HOW TO SAVE SINE AMPLITUDE VALUES IN A LUT/ROM FOR DDS - verilog

Status
Not open for further replies.

jubin007

Newbie level 4
Joined
Mar 10, 2015
Messages
7
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Visit site
Activity points
60
I am new in verilog but am getting used to it. My problem is how to store amplitude values of the sine wave. i am using a 14 bit resolution which means i have 2^14 no of values between 0 to 360 / 90 (doesn't matter) of sine. now the address will be linear but the corresponding sine amplitudes are nonlinear and theu have values like 0.00000123456. how to store these values.
i know the syntax for binary version but i need amplitudes here.
Code:
reg[13:0]mem [0:16384] ;
assign mem[0000] = 14'b00000000000011;
but that isn't gonna work here.
please help. hope the problem is understood
 

I think you can use a +Q0.14 format to store it in Fixed Point format. I used a simple taylor series to generate the quarter wave of the sinusoid. I just used the values in the simulations but you can write it in a text file and then generate some ROM with those initial values.

Once you have generated the quarter wave of the sinusoid, you can use 2 bits to decide which quarter of the sine wave you need to play.

Hope that helps.
MSBR
 

thanks for your reply but can you tell what is the +Q0.14 format and how to use it?
moreover it will be verymuch helpful if you explain the procedure to generate a rom and store a text file. thats what i have also been trying, but i see it stores hex values.
 

You have several options for setting the ROM up, are you planning to use an IP core for the ROM?

For info in initializing a ROM:
https://myfpgablog.blogspot.com/2011/12/memory-initialization-methods.html

You can write a script to generate the text file.

To deal with the decimal values, you should add a scaling factor. For DDS, this will either be a power of two (13'h1000), or a power of two minus one (13'h1FFF). The former gives "1.0" a representation that is a power of two, which is very convenient. The latter maximizes the dynamic range. For the 360 deg version, you would store 14b values in the LUT.
 
+Q0.14 is a fixed point format. The + sign indicates that it is an unsigned number and the 0.14 means that there are 0 bits integer bits and 14 mantissa bits. It is just a representation. For example, I have a floating point number 0.0255. In +Q0.14 format, the scaling factor is 2^14. So I need to multiply it with this scaling factor. The result would be 417.792. Now the mantissa part of this scaled number would be discarded (obviously, we lose some precision in Fixed Point Formats). So the end result would be 417. This could now be converted into binary, hex, oct or decimal.

Now coming to your second question that how to generate a ROM with these values? Well, in verilog you can write a simple task to evaluate the sine function using taylor series (lets say up to 5 or 7 iterations.) Now in your task, you can use file I/O functions to write the outputs to a text file. Then you can generate ROM from those values. Either you can infer the ROM or provide these values as init values to the IP Generator of Particular vendor. Like in Xilinx, Coregen allows you to give an initial value file to generate the ROM.

Hope that helps.
MSBR
 
thank you all for your valuable response. I have already implemented the LUT with scaling factor and then converting to binary representation. Now I have 90 degree symmetry. and I have to generate sine and cos wave simultaneously at the same clock. I have only one LUT. which means I have to access two different memory locations at the same clock.. which results in initialization of two RAMs.
suppose
Code:
a1= sin lut address (viz: 15 degree)  & a2 = (90-15 = 75 degree)
sin_out= sinelut[a1];
cos_out= sinelut[a2];
This is defining two block rams for a1 & a2.
Is it possible to define a single ROM and access two values at the same clock?
 
Last edited by a moderator:

Is it possible to define a single ROM and access two values at the same clock?
The question is asking for the hardware features of a specific FPGA family. It's possible with dual port block RAM. You need to refer to the vendor coding examples to know how it can be inferred from HDL code. In case of doubt instantiate it as vendor IP block.

- - - Updated - - -

As an example see the Altera dual port ROM template


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
module dual_port_rom
#(parameter DATA_WIDTH=8, parameter ADDR_WIDTH=8)
(
    input [(ADDR_WIDTH-1):0] addr_a, addr_b,
    input clk, 
    output reg [(DATA_WIDTH-1):0] q_a, q_b
);
 
    // Declare the ROM variable
    reg [DATA_WIDTH-1:0] rom[2**ADDR_WIDTH-1:0];
 
    // Initialize the ROM with $readmemb.  Put the memory contents
    // in the file dual_port_rom_init.txt.  Without this file,
    // this design will not compile.
    // See Verilog LRM 1364-2001 Section 17.2.8 for details on the
    // format of this file.
 
    initial
    begin
        $readmemb("dual_port_rom_init.txt", rom);
    end
 
    always @ (posedge clk)
    begin
        q_a <= rom[addr_a];
        q_b <= rom[addr_b];
    end
 
endmodule

 
Yes jubin007, you can read this way using dual port RAMs. I use Xilinx ISE, which automatically infers the dual port RAM when you assign two different outputs from a single LUT.

MSBR
 

thank you so much FvM, but MSBR, as you are telling you use Xilinx ISE, i am using the same xilinx 14.7 but it doesnot instantiate dual port ram. My target device is virtex 4 sx35 ff668. Might be this doesnot support dual port ram
 

thank you so much FvM, but MSBR, as you are telling you use Xilinx ISE, i am using the same xilinx 14.7 but it doesnot instantiate dual port ram. My target device is virtex 4 sx35 ff668. Might be this doesnot support dual port ram

Virtex 4 supports dual port RAM including for LUT RAM, but you have to adhere to the coding templates for inferring the dual port LUT RAM. Things like resets and clock enables will not let LUT RAM be inferred.

Here are a couple of links on the subject of LUT RAM inferrence.
http://www.xilinx.com/support/answers/39618.html
http://forums.xilinx.com/t5/Synthesis/Distributed-RAM-automatic-inference-in-XST/td-p/221553
 

thank you so much FvM, but MSBR, as you are telling you use Xilinx ISE, i am using the same xilinx 14.7 but it doesnot instantiate dual port ram. My target device is virtex 4 sx35 ff668. Might be this doesnot support dual port ram

Well, I said ISE infers Dual Port Ram, not instantiates. There is a difference between the two my friend. Once you have written the code for the RAM, you can check whether Dual Port RAM is inferred or not by the ISE by synthesizing your design and checking the module level Resource Utilization.

Hope that helps.
MSBR
 

Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…