This program needs to be able to output a sinewave to the testbench, where the frequency of the output signal should be specified by an eight bit input. My understnading is that I need to change the clock period which will alter the frequency of the waveform accordingly.The code is provided below:
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
always #5 Clk = ~Clk;
This statement is part of your testbench, not part of the UUT. You aren't supposed to change it; the expectation is that the clock frequency remains constant.
Your functionGenerator
module currently doesn't make any use of the freq
input. You will need to come up with some way to control how quickly the synthesizer steps through the sine
array based on the value of freq
. This may involve either making less than one step per clk
period, or making multiple steps per period, depending on your requirements.
This is a typical case in which a phase-acummulator oscillator is used to generate the ROM address for the new sample to output.
Something like this: the phase accumulator here is 14 bits wide, and we are using the 6 most significant bits to have a sine wave of 64 samples. The output frequency of such sine wave is CLK * freq / 16384
Actually, the ROM has only 16 cells, as it needs only to store one quarter of a sine wave. Bits 3 to 0 from the calculated address from the phase accumulator are used to address the ROM, and bits 5 to 4 are used to find out which quadrant we are in, so the actual address may need to be inverted and/or the actual output may need to be negated.
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
A minimal testbench can be used to let this function generator to run for a thousand or so clock cycles, and then take the output to GTKWave and display it as an analog output:
`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
This is the result, simulated with iverilog / GTKWave:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.