In my other blog I have written the VHDL code for a sine wave generator, few years back.
In this post, I want to re-implement the same design in Verilog. The design uses look up table(LUT) method for generating the sine wave. The sine wave is sampled at a pre-fixed sample rate and the values are stored in a ROM. These values are read one by one and output to a DAC(digital to analog converter). Please note that I have not included the DAC interface code here.
In this particular design I have sampled and stored 30 values of a sine wave. But if you want a much more smoother sine wave, you can sample and store more values in the ROM at the cost of extra fpga resources.
To get the sample values, I used the following commands in Matlab.
t=0 : pi/50 : 2*pi ; % for 100 values etc..
(then type one of the following comment - to convert 't' into integer format)
int32(sin(t)*10000/128) %128 for 8 bit output.
int32(sin(t)*10000/512) %512 for 6 bit output etc...
The design can be modified for efficient use of memory. In that way, only the first (pi/2) values need to be stored in the ROM. That means the memory usage is reduced by a factor of 4.
If the frequency of your sine wave is very less, then it is better you increase the number of sample values. Otherwise there will be lot of high frequency components in your output wave.
Sine Wave Generator(SWG):
module sine_wave_gen(Clk,data_out);
//declare input and output
input Clk;
output [7:0] data_out;
//declare the sine ROM - 30 registers each 8 bit wide.
reg [7:0] sine [0:29];
//Internal signals
integer i;
reg [7:0] data_out;
//Initialize the sine rom with samples.
initial begin
i = 0;
sine[0] = 0;
sine[1] = 16;
sine[2] = 31;
sine[3] = 45;
sine[4] = 58;
sine[5] = 67;
sine[6] = 74;
sine[7] = 77;
sine[8] = 77;
sine[9] = 74;
sine[10] = 67;
sine[11] = 58;
sine[12] = 45;
sine[13] = 31;
sine[14] = 16;
sine[15] = 0;
sine[16] = -16;
sine[17] = -31;
sine[18] = -45;
sine[19] = -58;
sine[20] = -67;
sine[21] = -74;
sine[22] = -77;
sine[23] = -77;
sine[24] = -74;
sine[25] = -67;
sine[26] = -58;
sine[27] = -45;
sine[28] = -31;
sine[29] = -16;
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 == 29)
i = 0;
end
endmodule
//declare input and output
input Clk;
output [7:0] data_out;
//declare the sine ROM - 30 registers each 8 bit wide.
reg [7:0] sine [0:29];
//Internal signals
integer i;
reg [7:0] data_out;
//Initialize the sine rom with samples.
initial begin
i = 0;
sine[0] = 0;
sine[1] = 16;
sine[2] = 31;
sine[3] = 45;
sine[4] = 58;
sine[5] = 67;
sine[6] = 74;
sine[7] = 77;
sine[8] = 77;
sine[9] = 74;
sine[10] = 67;
sine[11] = 58;
sine[12] = 45;
sine[13] = 31;
sine[14] = 16;
sine[15] = 0;
sine[16] = -16;
sine[17] = -31;
sine[18] = -45;
sine[19] = -58;
sine[20] = -67;
sine[21] = -74;
sine[22] = -77;
sine[23] = -77;
sine[24] = -74;
sine[25] = -67;
sine[26] = -58;
sine[27] = -45;
sine[28] = -31;
sine[29] = -16;
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 == 29)
i = 0;
end
endmodule
Testbench Code:
module tb;
// Inputs
reg Clk;
// Outputs
wire [7:0] data_out;
// Instantiate the Unit Under Test (UUT)
sine_wave_gen uut (
.Clk(Clk),
.data_out(data_out)
);
//Generate a clock with 10 ns clock period.
initial Clk = 0;
always #5 Clk = ~Clk;
endmodule
// Inputs
reg Clk;
// Outputs
wire [7:0] data_out;
// Instantiate the Unit Under Test (UUT)
sine_wave_gen uut (
.Clk(Clk),
.data_out(data_out)
);
//Generate a clock with 10 ns clock period.
initial Clk = 0;
always #5 Clk = ~Clk;
endmodule
Simulation Waveform:
Synthesis Results:
The code was synthesised for a Virtex 4 device and a maximum clock frequency of 200 MHz was obtained.
hi,
ReplyDeleteyou have a BUG: i=29 should be i=30.
Thx!
how do i verify this on the board? do you need a DAC ?
ReplyDeleteCan't we generate a clean sine wave. I am not happy with the shape of wave.
ReplyDeletetake more samples r use filter
Deletei just want to know what is frequency of this sine wave in this given code
ReplyDeleteIt will be f_Clk/30
DeleteI could not get waveform in EDA playground. It is showing "Execution interrupted or reached maximum runtime". Plz help me
ReplyDeletemeasure the time period from the simulation of the one cycle wave and divide it by one or divide the clock by 1 and you will get the frequency
ReplyDeleteint32(sin(t)*10000/128) %128 for 8 bit output.
ReplyDeleteint32(sin(t)*10000/512) %512 for 6 bit output etc...
what is the significance of the fractions here in determining the bit of the output, what does that affect, and how does that affect the sine wave other than changes in amplitude?