For portability and readability I strongly prefer infering memory, but I seem to be having a very hard time getting Quartus II 7.2 to work correctly.To prove I wasn't insane, I started a fresh empty project (1C20 FWIW), picked edit -> insert template -> single port ram and ended up with reasonably looking code (included below). However, when I translate it, I get this warning "Warning: Inferred RAM node "ram~0" from synchronous design logic. Pass-through logic has been added to match the read-during-write behavior of the original design." To make matters even more entertaining, the online help disagrees with this template. Notably, the memory update is using a non-blocking assignment if (we) ram[addr] <= data and that doesn't infer the pass-through logic. Unfortunately, both infers Simple Dual RAM according to the Analysis & Synthesis RAM Summary. Is it even possible to infer Single Port RAM? (I care because I want to pack two single port rams into one M4K block). Thanks Tommy .... code below .... // Quartus II Verilog Template // Single port RAM with single read/write address module single_port_ram ( input [(DATA_WIDTH-1):0] data, input [(ADDR_WIDTH-1):0] addr, input we, clk, output reg [(DATA_WIDTH-1):0] q ); parameter DATA_WIDTH = 8; parameter ADDR_WIDTH = 6; // Declare the RAM variable reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0]; always @ (posedge clk) begin // Write if (we) ram[addr] = data; // Read returns NEW data at addr if we == 1'b1. This is the // natural behavior of TriMatrix memory blocks in Single Port // mode q <= ram[addr]; end endmodule
I didn't try it, but there's a Quartus setting that might help. In the Quartus handbook, see "Turning Off Add Pass-Through Logic to Inferred RAMs/no_rw_check Attribute Setting" in Volume 1, Section III, Chapter 8.
Thanks, that would probably work as described, but it's not exactly portable and it means that Icarus Verilog would have different semantic behaviour here.I still don't understand why pure Verilog wouldn't be descriptive enough to express the semantics of the Cyclone RAM blocks.
Just a short follow up. Apparently, the template in Quartus II 7.2 is wrong. The one below works as expected. Now my next question is how to infer dual port memory without bypass. I suspect you can't (without messing with synthesizer settings which is not a portable solution).Thanks Tommy module single_port_ram ( input [(DATA_WIDTH-1):0] data, input [(ADDR_WIDTH-1):0] addr, input we, clk, output [(DATA_WIDTH-1):0] q ); parameter DATA_WIDTH = 8; parameter ADDR_WIDTH = 6; // Declare the RAM variable reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0]; reg [ADDR_WIDTH-1:0] addr_reg; always @ (posedge clk) begin // Write if (we) ram[addr] <= data; addr_reg <= addr; end // Read returns NEW data at addr if we == 1'b1. This is the // natural behavior of TriMatrix memory blocks in Single Port // mode assign q = ram[addr_reg]; endmodule
That works fine for me - but what if it needs clock enable ? putting 'if (en) begin .. end' around the contents of the 'always' will give the correct behaviour (i.e. en=0 supresses writes, and prevents address change for read).However, when I do that it turns into a bunch of flops.
I think there are some features you can use by instantiating a megafunction that RAM inference intentionally does not support in Quartus integrated synthesis. Clock enable might be one of those things (possibly because of the other control signals gregsmith tried to use at the same time). For a short-term solution, a third-party synthesis tool might have more capability than Quartus integrated synthesis for RAM inference. For a future solution, you can file a service request to ask that Quartus integrated synthesis support what you want to do.I recently had a design where I turned off "Allow Synchronous Control Signals" project wide in "More Analysis & Synthesis Settings". I needed it off on portions of the design and tried doing it on the whole project instead of doing it on individual blocks of hierarchy through the Assignment Editor. That setting prevented inference of some of the memories. If gregsmith ever changed anything in "More Analysis & Synthesis Settings", see whether that setting was turned off.
Thanks for the reply, but wasn't it, that option was on. According to the blurb it affects only sync clear/set, not an enable.I wasn't using anything else on the ram, it was exactly as described - I pasted the module out of tommythorn's nov-22 post into my code; it worked (but no ce), then I added the 'if ce' and it wasn't a RAM anymore.
Quartus II does not currently infer a RAM if the read address registers have a clock enable, so you need to instantiate your RAM through the MegaWizard. There are other cases where you must instantiate rather than infer, e.g. if you require byte enables. On the plus side, I'm told that Quartus II 8.0 will infer RAMs with clock enables on the read address registers.