Есть ли способ, которым я могу использовать вход для определения тактового периода? - PullRequest
0 голосов
/ 27 апреля 2019

Эта программа должна иметь возможность выводить синусоидальную волну на испытательный стенд, где частота выходного сигнала должна указываться восьмибитным входом.Я понимаю, что мне нужно изменить тактовый период, который будет соответственно изменять частоту сигнала. Код приведен ниже:

module functionGenerator(Clk,data_out, freq);
//declare input and output
    input [7:0] freq;
    input Clk;
    output [9:0] data_out;
//declare the sine ROM - 30 registers each 8 bit wide.  
    reg [9:0] sine [0:99];
//Internal signals  
    integer i;  
    reg [9:0] data_out;
//Initialize the sine rom with samples. 
    initial begin
        i = 0;
        sine[0] = 0;        sine[1] = 10;        sine[2] = 20;        sine[3] = 29;        sine[4] = 39;   
        sine[5] = 48;       sine[6] = 58;        sine[7] = 67;        sine[8] = 75;        sine[9] = 84;
        sine[10] = 92;      sine[11] = 100;      sine[12] = 107;      sine[13] = 114;      sine[14] = 120;
        sine[15] = 126;     sine[16] = 132;      sine[17] = 137;      sine[18] = 141;      sine[19] = 145;   
        sine[20] = 149;     sine[21] = 151;      sine[22] = 153;      sine[23] = 155;      sine[24] = 156;
        sine[25] = 156;     sine[26] = 156;      sine[27] = 155;      sine[28] = 153;      sine[29] = 151;
        sine[30] = 149;     sine[31] = 145;      sine[32] = 141;      sine[33] = 137;      sine[34] = 132;   
        sine[35] = 126;     sine[36] = 120;      sine[37] = 114;      sine[38] = 107;      sine[39] = 100;
        sine[40] = 92;      sine[41] = 84;       sine[42] = 75;       sine[43] = 67;       sine[44] = 58;
        sine[45] = 48;      sine[46] = 39;       sine[47] = 29;       sine[48] = 20;       sine[49] = 10;   
        sine[50] = 0;       sine[51] = -10;      sine[52] = -20;      sine[53] = -29;      sine[54] = -39;
        sine[55] = -48;     sine[56] = -58;      sine[57] = -67;      sine[58] = -75;      sine[59] = -84;
        sine[60] = -92;     sine[61] = -100;     sine[62] = -107;     sine[63] = -114;     sine[64] = -120;   
        sine[65] = -126;    sine[66] = -132;     sine[67] = -137;     sine[68] = -141;     sine[69] = -145;
        sine[70] = -149;    sine[71] = -151;     sine[72] = -153;     sine[73] = -155;     sine[74] = -156;
        sine[75] = -156;    sine[76] = -156;     sine[77] = -155;     sine[78] = -153;     sine[79] = -151;   
        sine[80] = -149;    sine[81] = -145;     sine[82] = -141;     sine[83] = -137;     sine[84] = -132;
        sine[85] = -126;    sine[86] = -120;     sine[87] = -114;     sine[88] = -107;     sine[89] = -100;
        sine[90] = -92;     sine[91] = -84;      sine[92] = -75;      sine[93] = -67;      sine[94] = -58;
        sine[95] = -48;     sine[96] = -39;      sine[97] = -29;      sine[98] = -20;      sine[99] = -10;
    end

    //At every positive edge of the clock, output a sine wave sample.
    always@ (posedge(Clk))
    begin
        data_out = sine[i];
        i = i+ 1;
        if(i == 99)
            i = 0;
    end

endmodule

Testbench

module functionGeneratror_tb();

    // Inputs
    reg Clk;
    reg freq;

    // Outputs
    wire [9:0] data_out;

    // Instantiate the Unit Under Test (UUT)
    functionGenerator uut (
        .Clk(Clk), 
        .data_out(data_out),
        .freq(freq)
    );

    //Generate a clock with 10 ns clock period.
    initial Clk = 0;
    always #5 Clk = ~Clk; // CAN I PASS IN AN INPUT HERE INSTEAD OF 5?
    initial
    #10000 $finish;

endmodule

Ответы [ 2 ]

0 голосов
/ 28 апреля 2019

Это типичный случай, когда генератор фазы фазы используется для генерации адреса ПЗУ для вывода нового образца.

Примерно так: здесь накопитель фазы имеет ширину 14 бит, и мыиспользуют 6 старших разрядов, чтобы получить синусоидальную волну из 64 выборок.Выходная частота такой синусоидальной волны составляет CLK * freq / 16384

. На самом деле, ПЗУ имеет всего 16 ячеек, так как ему требуется только одна четверть синусоидальной волны.Биты с 3 по 0 из вычисленного адреса из фазового аккумулятора используются для адресации ПЗУ, а биты с 5 по 4 используются для определения того, в каком квадранте мы находимся, поэтому реальный адрес может потребоваться инвертировать и / или фактический выходможет потребоваться отрицать.

module FunctionGenerator (
  input wire clk,
  input wire [7:0] freq, // frequency of output signal is: clk * freq / 16384
  output reg signed [9:0] out
  );

  reg signed [9:0] quartersin[0:15];
  // Generate initial values with this little C program:
  //   #include <stdio.h>
  //   #include <math.h>
  // 
  //   #define PI 3.141592654
  // 
  //   int main()
  //   {
  //     int i;
  //     
  //     for (i=0;i<16;i++)
  //     {
  //         printf ("    quartersin[%2d] = %d;\n", i, (int)(511*sin(i*2*PI/64.0)));
  //     }
  //
  //     return 0;
  //   }
  initial begin
    quartersin[ 0] = 0;
    quartersin[ 1] = 50;
    quartersin[ 2] = 99;
    quartersin[ 3] = 148;
    quartersin[ 4] = 195;
    quartersin[ 5] = 240;
    quartersin[ 6] = 283;
    quartersin[ 7] = 324;
    quartersin[ 8] = 361;
    quartersin[ 9] = 395;
    quartersin[10] = 424;
    quartersin[11] = 450;
    quartersin[12] = 472;
    quartersin[13] = 488;
    quartersin[14] = 501;
    quartersin[15] = 508;
  end

  reg [13:0] phaseacum = 14'h0000;
  reg [3:0] indx;
  always @(posedge clk) begin
    phaseacum <= phaseacum + {6'b000000, freq};
    if (phaseacum[13] == 1'b0)  // if in quadrants 0 or 1, out as is
      out <= quartersin[indx];
    else
      out <= -quartersin[indx];  // if in quadrants 2 or 3, negate out
  end

  always @* begin
    if (phaseacum[12] == 1'b0)   // which quadrant am I ?
      indx = phaseacum[11:8];  // if in quadrant 0 or 2
    else
      indx = ~phaseacum[11:8]; // else, in quadrant 1 or 3
    endcase
  end
endmodule

Можно использовать минимальный тестовый стенд, чтобы позволить этому генератору функций работать около тысячи тактовых циклов, а затем перенести вывод в GTKWave и отобразить его как аналоговый выход.:

`timescale 1ns / 1ns

module tb;
  reg clk;
  reg [7:0] freq;
  wire [9:0] out;

  FunctionGenerator uut (
    .clk(clk),
    .freq(freq),
    .out(out)
  );

  initial begin
    $dumpfile("dump.vcd");
    $dumpvars(1,uut);

    clk = 1'b0;
    freq = 8'd16;  // aprox. 1 kHz sine wave for a 1 MHz clk

    repeat (2000) begin
      @(posedge clk);
    end
    $finish;
  end

  always begin
    clk = #500 ~clk;  // a 1 MHz clock
  end
endmodule

Это результат, смоделированный с iverilog / GTKWave:

GTKWave simulated output

0 голосов
/ 27 апреля 2019
always #5 Clk = ~Clk;

Это утверждение является частью вашего тестового стенда, а не частью проверяемого оборудования. Вы не должны менять это; ожидается, что тактовая частота останется постоянной.

Ваш модуль functionGenerator в настоящее время не использует вход freq. Вам нужно будет найти какой-то способ управления скоростью, с которой синтезатор будет проходить через массив sine, на основе значения freq. Это может включать в себя либо выполнение менее одного шага за период clk, либо выполнение нескольких шагов за период в зависимости от ваших требований.

...