该程序需要能够向测试台输出正弦波,其中输出信号的频率应由八位指定 输入。我的理解是,我需要更改时钟周期,这将相应地改变波形的频率。代码如下:
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
测试台
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
答案 0 :(得分:0)
always #5 Clk = ~Clk;
此语句是测试平台的一部分,而不是UUT的一部分。您不应该更改它;期望时钟频率保持恒定。
您的functionGenerator
模块当前未使用任何freq
输入。您将需要提出一些方法来基于sine
的值来控制合成器完成freq
数组的速度。根据您的要求,这可能涉及在每个clk
期间执行少于一个步骤,或在每个期间执行多个步骤。
答案 1 :(得分:0)
这是典型的情况,其中使用相位累加器振荡器生成ROM地址以供新样本输出。
类似这样的事情:这里的相位累加器为14位宽,我们使用6个最高有效位来产生64个采样的正弦波。这种正弦波的输出频率为CLK * freq / 16384
实际上,ROM只有16个单元,因为它只需要存储四分之一的正弦波。来自相位累加器的计算地址中的位3至0用于寻址ROM,而位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模拟的结果: