- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic to the Top
- Bookmark
- Subscribe
- Printer Friendly Page
RAM synthesis in registers instead of LUT
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
06-04-2012 10:18 AM
Hi All,
I am having trouble synthesizing LUT RAM (16 deep by 48 bit wide) and instead the RAM gets built from registers. After experimenting I found I can get LUT RAM synthesis by commenting out some code I put in to help simulation. In the code I have two blocks, one for simulation and one for implementation. Which block gets used depends on an if (SIM_ENB=TRUE/FALSE) generate statement. The only difference is that the simulation code initializes the memory to zero on reset or startup. SIM_ENB is a generic boolean value. I am surprised that it impacts the synthesis method when I set SIM_ENB=FALSE since it shouldn't generate the conditional reset code.
So my questions are:
1) Why does the unused and not generated code affect the code I want? Does this sound like a 'bug' in Xilinx synthesis?
2) Is there a way to force the tools to use LUT RAM (or block RAM) instead of registers or make the tool fail if it can't do so?
Sorry if the answer is elsewhere in the forum or if it has already been asked. I searched but didn't find anything similar. I am getting around this for now by commenting out the simulation code.
Regards to all,
Tom Rounds
Here is the code--
-- RAM used for storing the old output values of the filter:
-- SIMULATION using RAM: inferring a single port, asynchronous READ, synchronous WRITE,
-- Includes self-clear code for simulation: if enabled in synthesis this will implement registers instead of RAM
-- Commenting out this section will correctly synthesize LUT RAM.
SIM_RESULT_RAM: if (SIM_ENB = TRUE) generate
Proc_SIM_RESULT_RAM :
process (MCLK)
variable STARTUP: boolean :=true; --temporary variable for simulation
begin
if (rising_edge(MCLK)) then
if (STARTUP or RESET = '1') then -- synchronous clear to initialize RAM contents
for i in 0 to (STAGE_NUM*CHANNELS-1) loop -- (RAM clear is needed for simulation)
LPF_RAM(i) <= (others => '0');
end loop;
STARTUP := FALSE;
-- Store the new output data when the stage data ready signal is asserted.
-- Should use some FPGA RAM for this.
elsif (STAGE_DRDY = '1') then
LPF_RAM(to_integer(unsigned(LPF_RAM_ADR))) <= std_logic_vector(OUTNEW);
end if;
end if;
end process Proc_SIM_RESULT_RAM;
end generate SIM_RESULT_RAM;
-- SYNTHESIS using RAM: single port, asynchronous READ, synchronous WRITE.
-- The intent is to infer LUT RAM and not registers.
SYN_RESULT_RAM: if (SIM_ENB = FALSE) generate
Proc_RESULT_RAM :
process (MCLK)
begin
if (rising_edge(MCLK)) then
if (STAGE_DRDY = '1') then -- synchronous write to RAM
LPF_RAM(to_integer(unsigned(LPF_RAM_ADR))) <= std_logic_vector(OUTNEW);
end if;
end if;
end process Proc_RESULT_RAM;
end generate SYN_RESULT_RAM;
-- STAGE_OUT RAM data output is the old data value. This is asynchronous read from the RAM and it forces
-- synthesis of LUT (distributed) RAM.
STAGE_RAM_DO <= signed(LPF_RAM(to_integer(unsigned(LPF_RAM_ADR))))
Solved! Go to Solution.
Re: RAM synthesis in registers instead of LUT
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
06-04-2012 10:19 AM
Tom,
If you specify an initial condition, or require a reset, LUTRAM can not be used (as it has no reset/set, and always starts out at 0's when configured).
Principal Engineer
Xilinx San Jose
Re: RAM synthesis in registers instead of LUT
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
06-04-2012 11:35 AM
Thanks for the quick response. I only specify an initial condition with this is generated as part of simulation. There is no initial condition for the code specific to synthesis. Why doesn't the software know this?
Clearing up incidental problems
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
06-04-2012 12:17 PM
This doesn't address the primary problem for trounds, but it does clear up what appears to be a mistaken representation which should not be left to stand.
Austin wrote:
If you specify an initial condition, or require a reset, LUTRAM can not be used (as it has no reset/set, and always starts out at 0's when configured).
A reset pin will indeed preclude LUT-RAM, but specifiying an initial condition should be no obstacle. What are all the logic LUTs in an FPGA design, if not LUT-RAM with a specified initial condition?
@trounds:
In the interest of removing a roadblock in your path, would a 16x48-bit distributed RAM with initialised state (but no reset-to-zero capability) satisfy both synthesis and simulation requirements, and possibly help you move forward with your design?
-- Bob Elkind
README for newbies is here: http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369
Summary:
1. Read the manual or user guide. Have you read the manual? Can you find the manual?
2. Search the forums (and search the web) for similar topics.
3. Do not post the same question on multiple forums.
4. Do not post a new topic or question on someone else's thread, start a new thread!
5. Students: Copying code is not the same as learning to design.
6 "It does not work" is not a question which can be answered. Provide useful details (with webpage, datasheet links, please).
7. You are not charged extra fees for comments in your code.
8. I am not paid for forum posts. If I write a good post, then I have been good for nothing.
Re: Clearing up incidental problems
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
06-04-2012 12:41 PM
Yes that would satisfy both conditions. I only need some sort of initial state for simulation. I don't care what the states are in synthesis since I'm using this for low pass filtering and it will eventually flush out in the real world application.
I'm just surprised that the tools are looking at the code related to simulation when I set SIM_ENB = FALSE. I would have thought it would disregard it. I have quite a few filters in this FPGA and correcting this problem reduced my utilization of an XC6SLX45 from 73% down to 31%.
I am using version 13.3 of the Webpack tools. I had neglected to mention that before. I know 13.4 is out but I haven't upgraded yet.
Re: RAM synthesis in registers instead of LUT
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
06-04-2012 12:52 PM
I have just tried getting rid of the RESET = '1' test for simulation and left in the variable for STARTUP. It didn't help.
To be sure, I'm not stuck. I'm just reporting that it isn't behaving like I think it should.
I know how to get around this problem; I have chosen to comment out the simulation section of code and add in an assert statement that warns me if SIM_ENB = TRUE so I remember to uncomment the code for simulation. I could also specifically instantiate a simple RAM from the Coregen tool. I prefer to infer this logic to be as flexible as possible for future changes.
Re: Clearing up incidental problems
[ Edited ]- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
06-04-2012 01:11 PM - edited 06-04-2012 01:15 PM
I only need some sort of initial state for simulation.
The initial state requirement is already met with no additional effort. A distributed RAM defaults to all locations containing zero after configuration is completed. For non-zero initial state of distributed RAM, you have (at least) three choices:
- The Distributed Memory Generator coregen wizard prompts you for a .COE (coefficients) file to define initial contents.
- Use somewhat generic HDL constructs for inferring RAM, combined with synthesis directives for specifying initial contents and synthesised style (e.g. distributed) of RAM.
- If you use a device primitive (for example the Spartan-3E RAM16x2S primitive), the initial contents may be specified in-line in your code where the primitive is instantiated, using .INIT attributes.
Examples from the ISE Language Templates (click on the light-bulb icon within ISE Navigator):
RAM16X2S #(
.INIT_00(16'h0000), // Initial contents of bit 0 of RAM
.INIT_01(16'h0000) // Initial contents of bit 1 of RAM
) RAM16X2S_inst (
.O0(O0), // RAM data[0] output
.O1(O1), // RAM data[1] output
.A0(A0), // RAM address[0] input
.A1(A1), // RAM address[1] input
.A2(A2), // RAM address[2] input
.A3(A3), // RAM address[3] input
.D0(D0), // RAM data[0] input
.D1(D1), // RAM data[1] input
.WCLK(WCLK), // Write clock input
.WE(WE) // Write enable input
);
parameter RAM_WIDTH = <ram_width>;
parameter RAM_ADDR_BITS = <ram_addr_bits>;
(* RAM_STYLE="{AUTO | DISTRIBUTED | PIPE_DISTRIBUTED}" *)
reg [RAM_WIDTH-1:0] <ram_name> [(2**RAM_ADDR_BITS)-1:0];
wire [RAM_WIDTH-1:0] <output_data>;
<reg_or_wire> [RAM_ADDR_BITS-1:0] <address>;
<reg_or_wire> [RAM_WIDTH-1:0] <input_data>;
always @(posedge <clock>)
if (<write_enable>)
<ram_name>[<address>] <= <input_data>;
assign <output_data> = <ram_name>[<address>];
Further reading: XST User Guide (UG627) has an entire section titled Initializing RAM Coding Examples.
-- Bob Elkind
README for newbies is here: http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369
Summary:
1. Read the manual or user guide. Have you read the manual? Can you find the manual?
2. Search the forums (and search the web) for similar topics.
3. Do not post the same question on multiple forums.
4. Do not post a new topic or question on someone else's thread, start a new thread!
5. Students: Copying code is not the same as learning to design.
6 "It does not work" is not a question which can be answered. Provide useful details (with webpage, datasheet links, please).
7. You are not charged extra fees for comments in your code.
8. I am not paid for forum posts. If I write a good post, then I have been good for nothing.
Re: RAM synthesis in registers instead of LUT
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
06-04-2012 01:36 PM
Yes, I agree, but the simulator doesn't seem to know about the initial/powerup configuration of zero states so it gives me undefined values in the RAM and so I cannot simulate the filter operation. The new values of the filter are based on previous values (it is an IIR filter) so it never settles out unless I force the simulation to some value.
Re: RAM synthesis in registers instead of LUT
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
06-04-2012 01:55 PM
For what it's worth, the following quick experiment successfully synthesised (ISE 13.4) a 16x48 single port SRAM with 24 Spartan-6 LUTs (2 bits per LUT, as Spartan-6 LUTs are either 64x1 or 32x2).
module s6_forum_top (
input inclk100m,
input [3:0] lut_addr,
input [47:0] lut_din,
input lut_we,
output [47:0] lut_dout
);
(* RAM_STYLE="DISTRIBUTED" *)
reg [47:0] forum_lutram [15:0]; // 16 words deep, 48 data bits wide
initial begin
forum_lutram[0] = 48’h0000_0000_0000;
forum_lutram[1] = 48’h0001_0000_0001;
forum_lutram[2] = 48’h0002_0000_0002;
forum_lutram[3] = 48’h0003_0000_0003;
forum_lutram[4] = 48’h0004_0000_0004;
forum_lutram[5] = 48’h0005_0000_0005;
forum_lutram[6] = 48’h0006_0000_0006;
forum_lutram[7] = 48’h0007_0000_0007;
forum_lutram[8] = 48’h0000_0008_0008;
forum_lutram[9] = 48’h0000_0009_0009;
forum_lutram[10] = 48’h0000_000A_000A;
forum_lutram[11] = 48’h0000_000B_000B;
forum_lutram[12] = 48’h0000_000C_000C;
forum_lutram[13] = 48’h0000_000D_000D;
forum_lutram[14] = 48’h0000_000E_000E;
forum_lutram[15] = 48’h0000_000F_000F;
end
always @(posedge inclk100m)
if (lut_we) forum_lutram[lut_addr] <= lut_din;
assign lut_dout = forum_lutram[lut_addr];
endmodule
I didn't bother with parameters for memory word depth and data width, but this should be no problem.
-- Bob Elkind
README for newbies is here: http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369
Summary:
1. Read the manual or user guide. Have you read the manual? Can you find the manual?
2. Search the forums (and search the web) for similar topics.
3. Do not post the same question on multiple forums.
4. Do not post a new topic or question on someone else's thread, start a new thread!
5. Students: Copying code is not the same as learning to design.
6 "It does not work" is not a question which can be answered. Provide useful details (with webpage, datasheet links, please).
7. You are not charged extra fees for comments in your code.
8. I am not paid for forum posts. If I write a good post, then I have been good for nothing.
Re: RAM synthesis in registers instead of LUT
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
06-04-2012 01:58 PM
Yes, I agree, but the simulator doesn't seem to know about the initial/powerup configuration of zero states so it gives me undefined values in the RAM and so I cannot simulate the filter operation.
This seems like odd behaviour. Have you tried both behavioural and structural simulation models with identical results? Just a wild guess....
-- Bob Elkind
README for newbies is here: http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369
Summary:
1. Read the manual or user guide. Have you read the manual? Can you find the manual?
2. Search the forums (and search the web) for similar topics.
3. Do not post the same question on multiple forums.
4. Do not post a new topic or question on someone else's thread, start a new thread!
5. Students: Copying code is not the same as learning to design.
6 "It does not work" is not a question which can be answered. Provide useful details (with webpage, datasheet links, please).
7. You are not charged extra fees for comments in your code.
8. I am not paid for forum posts. If I write a good post, then I have been good for nothing.











