BlockROM inference in XST - This is just plain silly

Mar 26, 2006 6 Replies

What a waste of my time! (A cautionary rant)



As part of a re-engineering of a 15 year old product, I need a ROM with pre-settable output in a Spartan 3. It is company policy to try to write for vendor indepence, so the ROM has to be coded in VHDL, and I cannot use Coregen (even though I know this product will never be targeted to any other part, at least for another 10 years). The 8.1i release of ISE has support for "synchronously controlled initialization of the RAM data outputs" (pg 218 of XST User Guide) and for RAM initialization (pg 226). Thinking I can be clever about it, I code up a RAM with initial values and also with output initialization:



type ram_type is array (0 to 255) of std_logic_vector(7 downto 0); signal RAM : ram_type := ( X"12", X"34", yadda, yadda, yadda,



constant Init_Value : std_logic_vector( 7 downto 0 ) := x"FE"; ... process( Clk ) begin if RISING_EDGE( Clk ) then if CE = '1' then if WE = '1' then RAM (TO_INTEGER(Addr))


oh there are zillions of mockups, gotta get used to that.

for your case you may try using a "fake" 0 or 1, eg a signal that is constant but is not recognized as constant by xilinx flow, this is clever trick that helps in many different cases :)

Antti

Hi John, I have seen this message before when I successfully inferred Block ROM

256x72 for an instruction decoder. This message usually pops out when You don't follow the template carefully. Why don't You use template for ROM and just add preset? Something like this: (Warning, copying from the manual with some modifications)

entity rominfr is port ( clk : in std_logic; en : in std_logic; addr : in std_logic_vector(4 downto 0); data : out std_logic_vector(3 downto 0)); end rominfr; architecture syn of rominfr is type rom_type is array (31 downto 0) of std_logic_vector (3 downto 0); constant ROM : rom_type :=( "0001","0010","0011","0100","0101","0110","0111","1000","1001", "1010","1011","1100","1101","1110","1111","0001","0010","0011", "0100","0101","0110","0111","1000","1001","1010","1011","1100", "1101","1110","1111"); begin process (clk) begin if (clk'event and clk = '1') then if (en = '1') then if rst = '1' then -- optional reset do

Ahhh Maki, A thousand thanks to you! This does indeed synth down to a BRAM, with the desired synchronous reset. Of course I'd tried variations from the XST user guide, but it turned out that I'd blundered and used a formation of:

signal ROM : rom_type :=( "0001","0010","0011","0100","0101","0110","0111","1000","1001",

instead of "constant ROM", which was what impeded XST from doing it's impressive job. So my apologies to the XST developers, and I remain, Just John

Going back to my code, I actually did use the correct construction. It turns out that my PROM is 4K deep, and that produces the annoying message:

"Currently unable to implement this ROM as a read-only block RAM.",

While Maki's example, which is only 32 words deep, produces the unhappy result:

"The register is removed and the ROM is implemented as read-only block RAM."

Listen up Xilinx. This is the EXACT OPPOSITE of what almost any designer would want: Big PROMs should go into BRAM, small PROMs should go into distRAM. My apologies for being irked by this behavior, but it seems like such a simple thing...

While my dander is up, I'll also take this moment to gripe about the newest 8.1i ISE GUI. Who's idea was it to add the explicit left click "Set as top module"? This is as buggy as anything in the GUI. Has anybody else out there noticed that sometimes (often!) it gets recalcitrant, and refuses to put the Implement Design selection into the Process window sometimes? I just wasted 10 minutes trying to get the system to accept that I wanted to take a test design "Test_Maki" through to PAR. I could click on other modules, set them as top, but the particular one I wanted, it refused. Really bothersome. I far preferred the way 7.1 worked: single click - set as top; double click - open for edit. Was there a study group that decided on this particular change? How do I get into one of those?

(Always, my apologies for complaining, but it's Sunday and here I am at the office, instead of being out sailing on a nice sunny SoCal day).

On to Antti's suggestion.

Hey Antti,

(Thanks for your time!) Success at last. Sure, I'd thought of that, or tying off to an unused I/O pin, but this seemed so painfully convoluted. After mucking about with Maki's suggestion (see the other branch) I came back to yours. I used the RAM construct as posted at the start of this topic, and then produced a Dummy_Zero as follows:

signal Dummy_Ctr : UNSIGNED( 0 downto 0 ); signal Dummy_Sum : UNSIGNED( 0 downto 0 ); signal Dummy_Zero : std_logic; ... process( Clk ) begin if RISING_EDGE( Clk ) then Dummy_Ctr

JustJohn wrote: (See Google Groups if you want the history)

Back to being a cautionary tale... Thought I'd be clever, and fake a 4K x 8 PROM by coding a 4Kx8 RAM with initial values _and_ a set/reset value (code below). Looked like it worked, but then I opened FPGA Editor, and it reports that the S/R Val A is 0, rather than the value I coded. I guess that you only get either initial values or S/R value, but not both. I look forward to service pack 4...

Just John

This code produces erroneous bitstream for XST:

constant Init_Val : std_logic_vector( 7 downto 0 ) := x"06"; type RAM_Type is array ( 0 to 4095 ) of std_logic_vector (7 downto 0); signal RAM : RAM_Type :=(x"01", x"02", x"03", 4K of yadda, signal Dummy_Ctr : UNSIGNED( 0 downto 0 ); signal Dummy_Sum : UNSIGNED( 0 downto 0 ); signal Dummy_Zero : std_logic; signal Dummy_Input : UNSIGNED( 7 downto 0 ); ... begin -- Architecture process( Clk ) begin if RISING_EDGE( Clk ) then Dummy_Ctr

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required