Forum Discussion
Verilog Synthesis Q
Am bumping into a synthesis problem inside of an always construct. Simplified code is
reg true_or_false[0:9999]; reg a; always (negedge clk) begin if (a <5000) true_or_false[a] <= 1 else if (a < 10000) true_or_false[a+5000] <= 1 end The error I get is "Cannot convert all sets of registers into RAM megafunctions when creating nodes. The resulting number of registers remaining in design exceeds the number of registers in device....." If I remove the if else construct, no allocations (register/memory/etc) are > 30%. I'm quite sure I'm violating an HDL paradigm. Could use a little guidance on why and thoughts on how I might implement it correctly. THNX, ME17 Replies
- Altera_Forum
Honored Contributor
Your simplified code isn't very clear.
But from the looks of the message, you're designing something that requires a huge number of register (more than the FPGA has) and can't be converted to use SRAM. What you need to do is to try and re-write your code in such a way that it uses SRAM and meets Quartus HDL SRAM templates. See the HDL coding guidelines handbook for details. - Altera_Forum
Honored Contributor
Besides observing the conditions for RAM inference, you should think about the data type of reg a. It's a bit variable, how can it address a memory array?
- Altera_Forum
Honored Contributor
Sorry for the confusion. Was trying to simplify the problem for brevity's sake.
Basically, I am capture the address bus on an old 80196 MPU using Cyclone 4 on a TerASIC DE2-115. Am using a NIOS II processor which preprocesses the 80196 list files to determine if a given address is a branch or not. If so, the branch offset is loaded into the TerASIC SRAM at an offset equal to the MPU address (so if MPU address 0x1234 represents a branch 0f 12, I store 12 at SRAM offset 0x1234). When a new address is available, I calculate the two addresses: one the represents the jump that occurs if the branch evaluates true, the other if false (I have to deal with a 5 byte prefetch on the false side). All of this synthesizes and fits quite well. My total logic element usage is 13% and my totoal memory bit usage is 53%. This 53% includes a 128k bit array that defines a true and false branch indication for each of the 64k addresses. So I don't think I'm running out of FPGA RAM due to the bit array. Once I determine that a given address represents a branch, I continue to collect addresses until either the true or false case is resolved. This is where I run into the RAM megafunction error. The code is in an always loop and looks like this (note branch_address is calculated earlier and is used as an index into the decision array): reg decision[0:128k-1] - Sorry too early in the morning to calculate 128 * 1024 - 1 if ((new_address > branch_false_address) && (new_address < branch_true_address)) decision[branch_address] <= 1; else if (new_address == branch_true_address) decision[branch_address+65536] <= 1 Adding this seeming innocuous code is where the problem lies. Am working to understand if it is the conditional logic statements or trying to set the decision array element that is causing me the problem. It seems that it is the conditionals that are causing the problem. BUt will confirm... Hope this clears it up some. Any more thoughts are greatly appreciated. - Altera_Forum
Honored Contributor
The post mainly shows that's it's useless to show small code snippets. It's even unclear, if you have synchronous (in an edge sensitive always block) or asynchronous writes to reg decision.
I suggest to try it the other way around. Understand about the hardware features of FPGA internal RAM and the requirements of RAM inference from behavioral code. Then write your code considering these informations. - Altera_Forum
Honored Contributor
SO I tried something a little different. Rather than creating the if else construct, I did something like this (inside a state machine):
branch_found: begin greater_than_false_address[0] <= (current_tdr_address >= branch_false_address[0]) ? 1 :0; less_than_true_address[0] <= (current_tdr_address < branch_true_address[0]) ? 1 : 0; equal_to_true_address[0] <= (current_tdr_address == branch_true_address[0]) ? 1 : 0; branch_processor_state[0] <= processing_branch; end processing_branch: begin decision[current_tdr_address] <= greater_than_false_address[0] & less_than_true_address[0]; end All synthesizes well with the same logic and memory usage statistics until I add the single assignment in the processing_branch case. I checked my settings and the max_number_of_uninferred_ram_logic is set to -1 (no max). Have attempted to read up on inferred/uninferred ram. It seems that the documentation would be quite helpful for someone that already understood the paradigm. However, I am having trouble converting that written academics to the practical problem that I have (I'm not the sharpest tool in the shed). Any help is greatly appreciated.... ME - Altera_Forum
Honored Contributor
one more thing after re-reading all the posts:
branch_address and current_tdr_address are defined as: reg [15:0] branch_address; reg [15:0] current_tdr_address; - Altera_Forum
Honored Contributor
FvM,
Thanks for the continued guidance. Am new to the FPGA world, so I'm sure my Q's are rather sophomoric. Not sure I understand you post about behavioral logic (I understand there is a difference between this and combinatorial logic). Could I ask for a VERY brief example of how you implement this as behavioral. ME - Altera_Forum
Honored Contributor
btw, it's in a synchronous always which contains a state machine...
thanks agagin - Altera_Forum
Honored Contributor
What FvM means is that you need to write your code while meeting Quartus templates for inferring RAM for your FPGA.
They are documented in the HDL coding guidelines handbook, but it's something like this
If your Verilog code describes something Quartus doesn't know or cannot map to RAM (M9K) blocks, Quartus will try to map it to registers. Since the FPGA in question only has ~115k registers, they're not enough to implement your 128 kbit table, plus all the remaining logic.// 1x128k memory reg memory; always @ (posedge clk) begin if (write) memory <= data_in; data_out <= memory; end - Altera_Forum
Honored Contributor
Thank to both of you. I'm starting to get there. Please bear with a couple more dumb questions.
Have been reading the HDL coding guidelines and I'm sure they will make sense once I solve the problem. One question. In your example, you specify a write signal. My understanding is that I don't need the write signal to access the array. Rather, since the always loop conforms to the standards you discuss, the synthesizer defines the array as ram rather than registers. A second question. In my example, if I remove the statement that actully attempts to write to the array, it synthesizes and appears to place the array in RAM. Thank you both for your continued patience as I learn.... ME