03-03-2009 07:46 AM
My project uses lookup ROMs which are synthesized into BRAM resources. Because I need to repeatedly change the ROM content without re-synthesizing the logic, I am using data2mem in my design flow to load and modify the contents of my ROMs. This means that my verilog source has no specific ROM content and I want to declare it as blank (all 0s or all 1s) memory
This works fine with XST correctly inferring all my ROMs until it gets to the "Low Level Synthesis" pass when it apparently spots duplications in BRAM content and optimizes some or all the BRAMs away with a message like this:
"INFO:Xst:2399 - RAMs <Mram_phaserom2>, <Mram_phaserom1> are equivalent, second RAM is removed"
This leaves me with a design which data2mem cannot work with. How can I prevent this optimization so that the BRAMs get preserved in the NGC file?
Solved! Go to Solution.
03-04-2009 03:53 AM
Take a look at http://www.xilinx.com/itp/xilinx10/books/docs/xst/
03-05-2009 02:56 AM
Thanks Jim, I thought there must be a switch like this but had not found it.
Unfortunately though it does not work! Am I missing something obvious?
I have tried setting EQUIVALENT_REGISTER_REMOVAL to NO on the ROM register declaration, on the module containing the ROM, on the top level module and as a command switch to XST. It shows up as set to NO in the synthesis log, but I still get the following in low level synthesis:
WARNING:Xst:1989 - Unit <lookup>: instances <phaseroms.phdat>, <phaseroms.phdat> of unit <phaserom> are equivalent, second instance is removed
INFO:Xst:2399 - RAMs <phlookup/phaseroms.phdat/Mram_phaserom2>, <lookup/phaseroms.phdat/Mram_phaserom1> are equivalent, second RAM is removed
I am using XST Release 10.1.02 - xst K.37 (lin)
My ROMS are logically organized as four ROMS of 2048 words by 36
bits - each logical ROM is initially synthesized as 4xRAMB16_S9. This
should use 16 out of the 20 BRAMs on a Spartan 3E (3s500efg320-4). After the unwanted optimizations I end up with just one BRAM!
It may be unconnected but I have found this which relates to an earlier version of ISE?
03-05-2009 10:44 AM
If you can post your code, it would help see what's going on. I tried the code in the link you mentioned. The code as it is had the same problem you mentioned. I then added equivalent_register_removal attribute to the ROM address signal (see bolded lines below) , the problem went away (i.e. no inferred RAM optimized out).
entity mc8051_rom is
port (clk : in std_logic; -- clock signal
reset : in std_logic; -- reset signal
rom_data_o : out std_logic_vector(7 downto 0); -- data output
rom_adr_i : in std_logic_vector(15 downto 0)); -- adresses
architecture behav of mc8051_rom is
attribute equivalent_register_removal: string;
-- we use a RAM that is initialized via data2mem with the hexfile.
type rom_type is array (16383 downto 0) of std_logic_vector(7 downto 0);
constant c : rom_type := (16383 downto 20 => x"01",
-- using 4Kbyte works?!
-- type rom_type is array (4095 downto 0) of std_logic_vector(7 downto 0);
-- constant extrom : rom_type := (4095 downto 20 => x"01",
19 downto 6 => x"00",
5 downto 0 => x"23"
); -- to avoid optimalizing out? Needed?
signal rom_adr : std_logic_vector(13 downto 0);
attribute equivalent_register_removal of rom_adr : signal is "no";
rom_adr <= rom_adr_i(13 downto 0);
rom_read : process (clk)
if rising_edge(clk) then
rom_data_o <= c(conv_integer(unsigned(rom_adr)));
end process rom_read;
03-06-2009 05:09 AM
Problem partially solved! Thanks to your post, I applied equivalent_register_removal="NO" to the address lines of my ROM and it worked like a charm. This sorts out my immediate problem.
However, I am surprised that it does not work if I turn equivalent_register_removal off globally (command line option -equivalent_register_removal NO) even though the setting appears clearly in the synthesis report.
It does not work either if I attach the attribute to the ROM registers declaration, to the entire module containing the ROM or to the top-level module in the design. It only seems to work if I attach it to the address lines.
Here is my code with the attribute on the entire module::
(* equivalent_register_removal = "NO" *) module phaserom(phasedata, phaseaddr, clk);
parameter ROMWIDTH = 36;
parameter ADDRBITS = 11;
output reg [ROMWIDTH - 1 : 0] phasedata;
input wire [ADDRBITS - 1 : 0] phaseaddr;
input wire clk;
localparam WORDCOUNT = 1 << ADDRBITS;
reg [ROMWIDTH - 1 : 0] phaserom [WORDCOUNT - 1 : 0];
$readmemh("rom-blank.mem", phaserom, 0, WORDCOUNT - 1);
/* Dummy write lines improve synthesis */
wire dummywen = 0;
wire [ROMWIDTH - 1 : 0] dummydat = 0;
always @(posedge clk) begin
if (dummywen) begin /* dummy write to satisfy XST */
phaserom[phaseaddr] <= dummydat;
phasedata <= dummydat;
else phasedata <= phaserom[phaseaddr];