xilinx block ram synthesis

Hi

Since Version 7.x xilinx xst is able to infer block ram out of appropriate vhdl statements. Unfortunately it is not working in the example given below. Does anybody have an idea why the code below gives the following warning:

WARNING:Xst:1440 - Cannot use block RAM resources. Please check that the RAM contents is read synchronously.

Thanks ST

library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all;

entity BRAM_test is port (CLOCK : in std_logic; reset : in std_logic; di : in std_logic_vector(15 downto 0); do : out std_logic_vector(15 downto 0)); end BRAM_test;

architecture syn of BRAM_test is

type ram_type is array (1023 downto 0) of std_logic_vector (15 downto 0); signal RAM : ram_type; attribute ram_style : string; attribute ram_style of RAM: signal is "block";

type STATE_TYPE is (P1, P2, P3); signal STATE : STATE_TYPE;

signal addr : std_logic_vector(9 downto 0);

begin main : process (CLOCK, RESET) begin if (RESET = '1') then STATE

Reply to
S.T.
Loading thread data ...

The way I interpret your code as written, if the clock event happens and the reset is one, the RAM is not to be read or written. While this can be assembled manually into a memory through correct ENA usage, it probably doesn't fit the synthesis template.

Consider separating the memory read/write into a separate process that has no reset. Resets - even this one which isn't "intended" to affect the memory - tend to diffuse any attempts to infer a good BlockRAM.

Reply to
John_H

hi,

I think there can be no reset to the block ram....

remove it and try.

and i believe u r using ur RAM in write first mode. i think the following modification to your code should work.

ibrary ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all;

entity BRAM_test is port (CLOCK : in std_logic; -- reset : in std_logic; di : in std_logic_vector(15 downto 0); do : out std_logic_vector(15 downto 0)); end BRAM_test;

architecture syn of BRAM_test is

type ram_type is array (1023 downto 0) of std_logic_vector (15 downto

0); signal RAM : ram_type; attribute ram_style : string; attribute ram_style of RAM: signal is "block";

type STATE_TYPE is (P1, P2, P3); signal STATE : STATE_TYPE;

signal addr : std_logic_vector(9 downto 0);

begin main : process (CLOCK) begin -- if (RESET = '1') then -- STATE

Reply to
nagaraj

Hi

Thanks for your feedback. Unfortunately both suggestions didn't work :-(. When removing the Reset path the synthesized ram will get dual ported instead of single ported (see below). I tried to rewrite it and make the read and write enable signals explicit and decoupling the reset from ram. It also doesn't work i.e. it still gives distributed instead of block ram :-(.

Any other suggestions? ST

rewritten part: main : process (CLOCK, reset) begin if (RESET = '1') then STATE

Reply to
S.T.

Oh, you wanted a single port?

Look at the BlockRAM operation in single port mode. You can have an ENA that will allow a read and write. You can have a WE that - combined with ENA - will allow a write.

There is no read enable.

If you want a read enable - rather than a global enable - it will be a dual port.

- John_H

S.T. wrote:

Reply to
John_H

Hi!

I have also been quite frustrated by XST BRAM inference in the past... and have yet to get XST to do what I want.

If you go check the XST "coding style guide" which contains VHDL templates for inferring most of the supported BRAM types, you might find exactly what you want.

In my case, I wanted to infer "True dual-port BRAMs" but copy-pasting the guide's template (ISE 8.1/8.2) consistently resulted in XST crashes. After wasting a week trying to work this out last summer, I decided to give up and used a coregen RAM.

More details about my experience with the true dual-port BRAM template:

- pasting the code in the module's VHDL causes unrecognized BRAM inference warnings, causing XST to attempt implementation with distributed RAM

- whipping up the template into its own module and synthesizing it as a top module works as advertised/expected

- instantiating the BRAM template module in an actual design crashes XST

S.T. wrote:

Reply to
Daniel S.

Try this piece of code.....

library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all;

entity BRAM_test is port (CLOCK : in std_logic; -- reset : in std_logic; di : in std_logic_vector(15 downto 0); do : out std_logic_vector(15 downto 0)); end BRAM_test;

architecture syn of BRAM_test is

type ram_type is array (1023 downto 0) of std_logic_vector (15 downto

0); signal RAM : ram_type; attribute ram_style : string; attribute ram_style of RAM: signal is "block";

type STATE_TYPE is (P1, P2, P3); signal STATE : STATE_TYPE;

signal addr : std_logic_vector(9 downto 0);

begin main : process (CLOCK) begin -- if (RESET = '1') then -- STATE

Reply to
nagaraj

The code above looks like it would infer a single-RW-port BRAM but the intended functionality is unclear: DO is assigned DI at P1, unchanged at P2 since the RAM location is P1's DI already assigned to DO, P3 has no effect... the code's net effect appears to be "do

Reply to
Daniel S.

Some things:

a) don't do this as a state machine -- you need to make the write process(es) separate from the read process(es) (or at least keep the read logic in a process separate from the write logic). One important point is that an FPGA's "single-port RAM" still has separate data-in and data-out ports (unlike a regular RAM chip, which has one bidirectional data port). This means that you don't have to worry about bus contention, etc., and you don't need a read enable. The read side code is simply

do

Reply to
Andy Peters

Hi Andy and all the nice guys who answered

I cought a bad cold and was mainly listening to my pillow. Sorry for this delay, i really appreaciate this feedback!

I am aiming for the synthesis of dual-ported block ram. Am i right that your comments aim at single ported ram?

But in my book the read is synchronous?

I have rewritten the stuff with your suggestions, still no success. Any more ideeas, why the code below is not synthesized as block ram from xilinx xst but as distributed ram?

Thanks ST

library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all;

entity BRAM_test is port (CLOCK : in std_logic; reset : in std_logic; di : in std_logic_vector(15 downto 0); do : out std_logic_vector(15 downto 0)); end BRAM_test;

architecture syn of BRAM_test is

type ram_type is array (1023 downto 0) of std_logic_vector (15 downto 0); signal RAM : ram_type; attribute ram_style : string; attribute ram_style of RAM: signal is "block";

type STATE_TYPE is (P1, P2, P3 ); signal STATE : STATE_TYPE; signal we: std_logic; signal re: std_logic;

signal addr : std_logic_vector(9 downto 0);

begin main : process (CLOCK, reset) begin if (CLOCK'event and CLOCK = '1') then if (RESET = '1') then STATE

Reply to
S.T.

ST,

Since you want a dual-port rather than a single port, try defining two addresses (I'd use syn_keep attributes in Synplify) rather than using "addr" for both the read and the write.

I would hardly be surprised to find the synthesizer seeing a single port design is appropriate but then discovering that the write and read enables don't fit the "ENA" and "WE" scheme of a single port BlockRAM.

Also, is ramstyle "block" as opposed to "BlockRAM"?

- John_H

S.T. wrote:

Reply to
John_H

Does the code synthesize any sort of memory at all?

To me, it looks like XST may have analyzed the code, determined that the memory was unnecessary and either optimized it away or replaced it by a few FFs. This is usually caused by undriven, unused and constant-value nets. XST also has a tendency of being quite overzealous with reorganizing pipelines and I have seen it manage to optimize away large chunks of nets and logic I had plugged on pseudo-random generators to prevent trivial optimization while sizing partial design implementations. If you want to prevent such optimizations, you have to make your controls and data depend on IOBs.

When I infer BRAMs, my processes look like this:

---------------------- process(clk) begin if(rising_edge(clk)) then doA

Reply to
Daniel S.

Hi John

You really made my day :-)! Tell me if you are around Darmstadt, Germany and i will get you an drink of your choice ;-). (Yes, i know it's improbable, but sometimes the world is a small place...)

I just hit the nail on the head. I am really happy that there is no need now to explicitly instanticate block ram. After finding out that it's working i tried removing the read and write processes. It didn't work. So i think both suggestions:

  • doing seperate processes for read and write access
  • using seperate adresses (even if identical) for the read and write access lead to the success.

It works for me (tm). I think copied this statement right out of the xst manual.

Thanks to all who have taken time to help out. ST

XST output: Found 1024x16-bit dual-port block RAM for signal . ----------------------------------------------------------------------- | ram_style | block | | ----------------------------------------------------------------------- | Port A | | aspect ratio | 1024-word x 16-bit | | | mode | write-first | | | clkA | connected to signal | rise | | weA | connected to signal | high | | addrA | connected to signal | | | diA | connected to signal | | ----------------------------------------------------------------------- | Port B | | aspect ratio | 1024-word x 16-bit | | | clkB | connected to signal | rise | | enB | connected to signal | high | | addrB | connected to signal | | | doB | connected to signal | | -----------------------------------------------------------------------

corresponding test code:

entity BRAM_test is port (CLOCK : in std_logic; reset : in std_logic; di : in std_logic_vector(15 downto 0); do : out std_logic_vector(15 downto 0)); end BRAM_test;

architecture syn of BRAM_test is

type ram_type is array (1023 downto 0) of std_logic_vector (15 downto 0); signal RAM : ram_type; attribute ram_style : string; attribute ram_style of RAM: signal is "block";

type STATE_TYPE is (P1, P2, P3 ); signal STATE : STATE_TYPE; signal we: std_logic; signal re: std_logic;

signal w_addr : std_logic_vector(9 downto 0); signal r_addr : std_logic_vector(9 downto 0);

begin main : process (CLOCK, reset) begin if (CLOCK'event and CLOCK = '1') then if (RESET = '1') then STATE

Reply to
S.T.

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.