Question

I have an array of vectors that I want to be stored in Block RAM on a Virtex-5 using ISE 13.4. It is 32Kb which should fit in 1 BRAM but it is all being stored in logic. My system uses an AMBA APB bus so I check for a select line and an enable line. Please help me understand why this code isn't inferring a BRAM. Note: this is a dummy example which is simpler to understand and should help me with my other code.

architecture Behavioral of top is
type memory_array is array (63 downto 0) of std_logic_vector(31 downto 0);
signal memory : memory_array;

attribute ram_style: string;
attribute ram_style of memory : signal is "block";

begin

process(Clk)
begin
    if(rising_edge(Clk)) then
        if(Sel and Wr_en and Enable) = '1' then
            memory(to_integer(Paddr(5 downto 0))) <= Data_in;
        elsif(Sel and not Wr_en and Enable) = '1' then
            Data_out <= memory(to_integer(Paddr(5 downto 0)));
        end if;
    end if;
end process;

end Behavioral;

I declare the ram_style of the array as block but the XST report says: WARNING:Xst:3211 - Cannot use block RAM resources for signal <Mram_memory>. Please check that the RAM contents is read synchronously.

It appears that the problem lies in a read_enable condition, but the Virtex 5 User Guide makes it sound like there is an enable and a write_enable on the BRAM hard blocks. I could drive the output all the time, but I don't want to and that would waste power. Any other ideas?

Was it helpful?

Solution 3

I tried many different combinations and here is the only one I got to work:

en_BRAM <= Sel and Enable;

process(Clk)
begin
    if(rising_edge(Clk)) then       
        if(en_BRAM = '1')then
                if(Wr_en = '1') then
                    icap_memory(to_integer(Paddr(5 downto 0))) <= Data_in;
                else
                    Data_out <= icap_memory(to_integer(Paddr(5 downto 0)));         
                end if;
        end if;
    end if;
end process;

So I think the enable needs to be on the whole RAM and it can only be 1 signal. Then the write enable can also only be 1 signal and the read has to be only an else statement (not if/elsif). This instantiates a BRAM according to XST in ISE 13.3 on Windows 7 64-bit.

OTHER TIPS

Your logic may not match how your device's BRAM works (there are various limitations depending on the device). Usually, the data_out is updated on every clock cycle the RAM is enabled for, not just "when not writing" - try this:

process(Clk)
begin
    if(rising_edge(Clk)) then
        if(Sel and Enable) = '1' then
            Data_out <= memory(to_integer(Paddr(5 downto 0)));
            if wr_en = '1' then
                memory(to_integer(Paddr(5 downto 0))) <= Data_in;
            end if;
        end if;
    end if;
end process;

I moved the Data_out assignment "upwards" to make it clear that it gets the "old" value - that's the default behaviour of the BRAM, although other styles can also be set up.

Alternatively, the tools may be being confused by the sel and enable and write all in a single if statement - this is because they are mainly "template matching" rather than "function matching" when inferring BRAM. You may find that simply splitting out an "enable if" and a "write if" (as I did above) whilst keeping the rest of the functionality the same is sufficient to make the synthesiser do what is required.

If you are using Xilinx's XST then you can read all about inferring RAMs in the docs (page 204 onwards of my XST user guide - the chapter is called "RAM HDL Coding techniques")

Use the appropriate macro for the BRAM block on your device? I found that to work much better than relying on the synthesis tool not beeing stupid.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top