- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The background: I'm working on QAM modulation from a Cyclone II dev board with a DAC board I made connected to it. Works great as a DDS and everything other than the QAM math.
The main QAM calculation is icos(t)-qsin(t). I implemented sin and cos as lookup tables in a module. The following simulates properly in iverilog:// leaving out standard stuff, only relevant lines shown (full paste at the end)
input signed i; // input values
input signed q;
output dacval; // output to the DAC
wire signed sin; // the values back from the lookup tables
wire signed cos;
reg signed dacfull; // holds the full size value
always @(negedge clk)
begin
dacfull=(i*cos)-(q*sin); // the qam value
dacval=(dacfull/64)+512; // scale down, then add to make positive
end
endmodule
Here's the problem: the above simulates great, but when I go to synthesize it with Altera, I get the following at the end: Warning (13410): Pin "dacval" is stuck at GND
Warning (13410): Pin "dacval" is stuck at GND
However, if I change the math section above to just: dacval=(sin*4)+512; // multiply to full range, then add to make positive
It synthesizes without error, and runs perfectly in hardware (outputting a beautiful sine). I spent hours today fooling with different ways to present the signed+unsigned math, but I can't get the Altera synth to like it. What's the proper way? The sin/cos LUT: http://paste.ubuntu.com/5763310 The IQ mod code: http://paste.ubuntu.com/5763316 Full output from synthesis: http://paste.ubuntu.com/5763317
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The problem is that a signed multiply effectively wastes one bit, which is necessary to avoid an overflow with -128*-128. To effectively utilize the result number range, dacfull must be resized to 15 bit with saturation logic applied, means 0x4000 (-16384) must be truncated to 0x3FFF (-16383).
ieee.fixed_pkg has a built-in saturation logic feature and is the most convient way to handle these problems. Or write your own functions to handle signed arithmetic with saturation.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You're right about the extra bit for a full-range multiply, but I handled that problem by generating the LUT to go from -127 to 127.
The problem gets weirder though... it synthesesizes and runs correctly in hardware if the input vars are registers:
reg signed ri;
reg signed rq;
dacfull=(ri*cos)-(rq*sin);
dacval=(dacfull/64)+512;
I set ri and rq in the initial to exactly the same values I set i and q to in the top-level module. Using the registers like that, the synth figures out that I need multiplication (which it never did without the registers):
Info (278003): Inferred multiplier megafunction ("lpm_mult") from the following logic: "iqmod:myiq|Mult0"
But here's the weird part: if I set ri and rq to i and q anywhere, it does the same thing it did before: no multiplier infered, and dacval is always 0. I tried "ri=i; rq=q;" just above the math lines, as well as adding a separate block @(i,q) where the registers are set, and both ways fail. I verified throughout the code that i+q are exactly the same type as ri and rq (signed 8-bit registers), except ri and rq are defined in this module and i and q are defined in the above level. What am I missing?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It looks like if the synth sees that ri and rq can change anywhere, it just gives up and decides the multiplication expression will always be 0. Whenever it decides they don't change (ie, when it works), it notes that one input to the multiplier is constant:
Info (278001): Inferred 1 megafunctions from design logic
Info (278003): Inferred multiplier megafunction ("lpm_mult") from the following logic: "iqmod:iq0|Mult0"
Info (12130): Elaborated megafunction instantiation "iqmod:iq0|lpm_mult:Mult0"
Info (12133): Instantiated megafunction "iqmod:iq0|lpm_mult:Mult0" with the following parameter:
Info (12134): Parameter "LPM_WIDTHA" = "8"
Info (12134): Parameter "LPM_WIDTHB" = "8"
Info (12134): Parameter "LPM_WIDTHP" = "16"
Info (12134): Parameter "LPM_WIDTHR" = "16"
Info (12134): Parameter "LPM_WIDTHS" = "1"
Info (12134): Parameter "LPM_REPRESENTATION" = "SIGNED"
Info (12134): Parameter "INPUT_A_IS_CONSTANT" = "YES"
Info (12134): Parameter "INPUT_B_IS_CONSTANT" = "NO"
Info (12134): Parameter "MAXIMIZE_SPEED" = "5"
Info (12131): Elaborated megafunction instantiation "iqmod:iq0|lpm_mult:Mult0|multcore:mult_core", which is child of megafunction instantiation "iqmod:iq0|lpm_mult:Mult0"
Info (12131): Elaborated megafunction instantiation "iqmod:iq0|lpm_mult:Mult0|multcore:mult_core|mpar_add:padder", which is child of megafunction instantiation "iqmod:iq0|lpm_mult:Mult0"
Info (12131): Elaborated megafunction instantiation "iqmod:iq0|lpm_mult:Mult0|multcore:mult_core|mpar_add:padder|lpm_add_sub:adder", which is child of megafunction instantiation "iqmod:iq0|lpm_mult:Mult0"
Info (12021): Found 1 design units, including 1 entities, in source file db/add_sub_qfh.tdf
Info (12023): Found entity 1: add_sub_qfh
Info (12131): Elaborated megafunction instantiation "iqmod:iq0|lpm_mult:Mult0|altshift:external_latency_ffs", which is child of megafunction instantiation "iqmod:iq0|lpm_mult:Mult0"
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page