Forum Discussion
Quartus joins two RAMs?
In my design I deliberately designed two dual-port RAMs of single M9K block each, using them through both ports A and B in parallel.
I spent several days debugging the application I am designing failing in very strange way. Simulation and data captured from live system does not help to find the problem.
I started to dig into the deeps of Quartus reports (mostly out of desperation), and found that in fitter's RAM summary tab the location for both RAMs is the same (M9K_X15_Y19_N0) and that "Resource utilization per entity" list shows that one RAM is having 1 M9K assigned to it, and second does not!
Does it mean that Quartus "optimized" the design compacting two explicit memories into one physical memory?
This is technically fairly possible because I only use halves of these RAMs. However I can not understand how it can be done from interfacing point of view because I use ALL interfaces of both RAMs - are they time shared when combined?
How can I tell Quartus NOT to do it and leave separate M9K memories alone as they are designed?
11 Replies
- SyafieqS
Super Contributor
Hi Eugeny,
Noted and glad to hear the issue had been addressed. Let me know if you have any other concern on this.
- SyafieqS
Super Contributor
Hi Eugeny,
1. May I know what device you are targeting and Quartus version used?
2. I can see the code snippet provided, could you try to provide a design and achieve it here .qar. I will try to reproduce it at my end. You can email or private message me if it is confidential.
Thanks,
Regards
- EugenyB
Occasional Contributor
Hello, I am using Cyclone 3, Quartus versions tried are 12.0 SP2 and 13.0 SP1.
As a starting point I have put the definition of RAMs in one of my replies above, and briefly said how I used them. Putting code here is not appropriate as it is relatively big. The data being addressed through the address wires are in the first part of RAM, address MSb is always 0.
How can I send you a private message? Suspect that when I click your anonymous icon I must see something useful, but there's only progress indicator rotating.
Is your email address "SyafieqS_Intel@intel.com"? Who I am talking to?
- sstrell
Super Contributor
Did you add the RAMs through code inference or by adding them as IP through the IP Catalog? If it was code inference, that might be the issue. If you show your code, that could help diagnose the problem.
Also, if you are using code inference, check out the templates in the Quartus text editor (Edit menu -> Insert Template) to make sure you are following the coding guidelines to have your design synthesized the way you intend.
- EugenyB
Occasional Contributor
Hello, thank you for your reply.
I used MegaWizard.
Code as simple as this:
reg [8:0] r_fir_RAM_address = {9{1'b0}}; wire [15:0] w_fir_RAM_data_out_lo; wire [15:0] w_fir_RAM_data_out_hi; reg [15:0] r_fir_RAM_data_in_lo = {16{1'b0}}; reg [15:0] r_fir_RAM_data_in_hi = {16{1'b0}}; reg r_fir_RAM_we = 1'b0; fir_ram_lo fir_ram_lo ( .clock(FFCLK), // address - same for both channels, even/odd .address_a( { r_fir_RAM_address[8:0], 1'b0 } ),// even byte .address_b( { r_fir_RAM_address[8:0], 1'b1 } ),// odd byte // write enable .wren_a(r_fir_RAM_we), .wren_b(r_fir_RAM_we), // indata .data_a(r_fir_RAM_data_in_lo[7:0]), .data_b(r_fir_RAM_data_in_lo[15:8]), // outdata .q_a(w_fir_RAM_data_out_lo[7:0]), .q_b(w_fir_RAM_data_out_lo[15:8]) ); fir_ram_hi fir_ram_hi ( .clock(FFCLK), // address - same for both channels, even/odd .address_a( { r_fir_RAM_address[8:0], 1'b0 } ),// even byte .address_b( { r_fir_RAM_address[8:0], 1'b1 } ),// odd byte // write enable .wren_a(r_fir_RAM_we), .wren_b(r_fir_RAM_we), // indata .data_a(r_fir_RAM_data_in_hi[7:0]), .data_b(r_fir_RAM_data_in_hi[15:8]), // outdata .q_a(w_fir_RAM_data_out_hi[7:0]), .q_b(w_fir_RAM_data_out_hi[15:8]) );and then I set up common address and read 4 bytes in parallel into registers, or write 4 bytes in parallel to all RAMs. Address is really set up the way that its MSb is always zero, so Quartus knows that I do not use half of RAMs. Both RAMs are pre-initialized with their own data.- ak6dn
Regular Contributor
In reading your code snippet, for the instantiation of your two RAM blocks the **ONLY** difference is in the data input/output signals.
The address/data/control signals are IDENTICAL for each block.
So Quartus can easily (and validly) pack BOTH of your RAM blocks into a single M9K block that has a wide enough data port (of 32bits) and a deep enough depth (256 locations, as you indicate the upper address bit is always zero). 256*32 = 8192 < M9K size so it fits in one memory block.
Darn good optimization by Quartus. Why are you complaining?