Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Honored Contributor I
1,176 Views

Quartus' own Single Port RAM template infers Dual Port RAM with pass-through logic

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
0 Kudos
7 Replies
Highlighted
Honored Contributor I
25 Views

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.

0 Kudos
Highlighted
Honored Contributor I
25 Views

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.
0 Kudos
Highlighted
Honored Contributor I
25 Views

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
0 Kudos
Highlighted
Honored Contributor I
25 Views

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.
0 Kudos
Highlighted
Honored Contributor I
25 Views

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.
0 Kudos
Highlighted
Honored Contributor I
25 Views

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.
0 Kudos
Highlighted
Honored Contributor I
25 Views

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.

0 Kudos