Verilog Coding Tips and Tricks: Verilog code for a simple Sine Wave Generator

Tuesday, November 17, 2015

Verilog code for a simple Sine Wave Generator

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/10 : 2*pi ;  % for 20 values.
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(== 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

Simulation Waveform:

The following result was obtained in Xilinx ISE 13.1.


Synthesis Results:

The code was synthesised for a Virtex 4 device and a maximum clock frequency of 200 MHz was obtained.

2 comments:

  1. hi,
    you have a BUG: i=29 should be i=30.
    Thx!

    ReplyDelete
  2. how do i verify this on the board? do you need a DAC ?

    ReplyDelete