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 <= P1; addr <= (others => '0'); elsif (CLOCK'event and CLOCK = '1') then case STATE is when P1 => RAM(conv_integer(addr)) <= di; STATE <= P2; when P2 => do <= RAM(conv_integer(addr)); STATE <= P3; when P3 => addr <= addr + '1'; STATE <= P1; end case; end if; end process main; end syn;
xilinx block ram synthesis
Started by ●March 1, 2007
Reply by ●March 1, 20072007-03-01
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. "S.T." <st@iss.tu-darmstadt.de> wrote in message news:es6uu7$7ul$1@lnx107.hrz.tu-darmstadt.de...> 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 <= P1; > addr <= (others => '0'); > elsif (CLOCK'event and CLOCK = '1') then > case STATE is > when P1 => > RAM(conv_integer(addr)) <= di; > STATE <= P2; > when P2 => > do <= RAM(conv_integer(addr)); > STATE <= P3; > when P3 => > addr <= addr + '1'; > STATE <= P1; > end case; > end if; > end process main; > end syn; >
Reply by ●March 2, 20072007-03-02
> > > 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 <= P1; > > addr <= (others => '0');> > elsif (CLOCK'event and CLOCK = '1') then > > case STATE is > > when P1 => > > RAM(conv_integer(addr)) <= di; > > STATE <= P2; > > when P2 => > > do <= RAM(conv_integer(addr)); > > STATE <= P3; > > when P3 => > > addr <= addr + '1'; > > STATE <= P1; > > end case; > > end if; > > end process main; > > end syn;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 <= P1; -- addr <= (others => '0'); if (CLOCK'event and CLOCK = '1') then case STATE is when P1 => RAM(conv_integer(addr)) <= di; do<=di; STATE <= P2; when P2 => do <= RAM(conv_integer(addr)); STATE <= P3; when P3 => addr <= addr + '1'; STATE <= P1; end case; end if; end process main; end syn; -
Reply by ●March 2, 20072007-03-02
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 <= P1;
addr <= (others => '0');
we <= '0';
re <= '0';
elsif (CLOCK'event and CLOCK = '1') then
case STATE is
when P1 =>
we<='1';
STATE <= P2;
when P2 =>
we<='0';
re<='1';
STATE <= P3;
when P3 =>
addr <= addr + '1';
STATE <= P1;
end case;
end if;
end process main;
ram_ctl: process (CLOCK)
begin
if (CLOCK'event and CLOCK='1') then
if(we='1') then
RAM(conv_integer(addr)) <= di;
end if;
if(re='1') then
do <= RAM(conv_integer(addr));
end if;
end if;
end process ram_ctl;
Version with no reset path:
Found 1024x16-bit dual-port distributed RAM for signal <RAM>.
-----------------------------------------------------------------------
| ram_style | block | |
-----------------------------------------------------------------------
| Port A |
| aspect ratio | 1024-word x 16-bit | |
| clkA | connected to signal <CLOCK> | rise |
| weA | connected to internal node | high |
| addrA | connected to signal <addr> | |
| diA | connected to signal <di> | |
-----------------------------------------------------------------------
| Port B |
| aspect ratio | 1024-word x 16-bit | |
| enB | connected to internal node | high |
| addrB | connected to signal <addr> | |
| doB | connected to internal node | |
-----------------------------------------------------------------------
WARNING:Xst:1440 - Cannot use block RAM resources. Please check that the RAM
contents is read synchronously.
original version:
Synthesizing Unit <BRAM_test>.
Related source file
is "/amd/iss1/users/ma/tstone/georg/bram/BRAM_test.vhd".
Found 1024x16-bit single-port distributed RAM for signal <RAM>.
-----------------------------------------------------------------------
| ram_style | block | |
-----------------------------------------------------------------------
| Port A |
| aspect ratio | 1024-word x 16-bit | |
| clkA | connected to signal <CLOCK> | rise |
| weA | connected to internal node | high |
| addrA | connected to signal <addr> | |
| diA | connected to signal <di> | |
| doA | connected to internal node | |
-----------------------------------------------------------------------
WARNING:Xst:1440 - Cannot use block RAM resources. Please check that the RAM
contents is read synchronously.
Reply by ●March 2, 20072007-03-02
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:> 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 <= P1; > addr <= (others => '0'); > we <= '0'; > re <= '0'; > elsif (CLOCK'event and CLOCK = '1') then > case STATE is > when P1 => > we<='1'; > STATE <= P2; > when P2 => > we<='0'; > re<='1'; > STATE <= P3; > when P3 => > addr <= addr + '1'; > STATE <= P1; > end case; > end if; > end process main; > ram_ctl: process (CLOCK) > begin > if (CLOCK'event and CLOCK='1') then > if(we='1') then > RAM(conv_integer(addr)) <= di; > end if; > if(re='1') then > do <= RAM(conv_integer(addr)); > end if; > end if; > end process ram_ctl; > > > Version with no reset path: > Found 1024x16-bit dual-port distributed RAM for signal <RAM>. > ----------------------------------------------------------------------- > | ram_style | block | | > ----------------------------------------------------------------------- > | Port A | > | aspect ratio | 1024-word x 16-bit | | > | clkA | connected to signal <CLOCK> | rise | > | weA | connected to internal node | high | > | addrA | connected to signal <addr> | | > | diA | connected to signal <di> | | > ----------------------------------------------------------------------- > | Port B | > | aspect ratio | 1024-word x 16-bit | | > | enB | connected to internal node | high | > | addrB | connected to signal <addr> | | > | doB | connected to internal node | | > ----------------------------------------------------------------------- > WARNING:Xst:1440 - Cannot use block RAM resources. Please check that the RAM > contents is read synchronously. > > original version: > > Synthesizing Unit <BRAM_test>. > Related source file > is "/amd/iss1/users/ma/tstone/georg/bram/BRAM_test.vhd". > Found 1024x16-bit single-port distributed RAM for signal <RAM>. > ----------------------------------------------------------------------- > | ram_style | block | | > ----------------------------------------------------------------------- > | Port A | > | aspect ratio | 1024-word x 16-bit | | > | clkA | connected to signal <CLOCK> | rise | > | weA | connected to internal node | high | > | addrA | connected to signal <addr> | | > | diA | connected to signal <di> | | > | doA | connected to internal node | | > ----------------------------------------------------------------------- > WARNING:Xst:1440 - Cannot use block RAM resources. Please check that the RAM > contents is read synchronously.
Reply by ●March 4, 20072007-03-04
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:> 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 :-(.> Synthesizing Unit <BRAM_test>. > Related source file > is "/amd/iss1/users/ma/tstone/georg/bram/BRAM_test.vhd". > Found 1024x16-bit single-port distributed RAM for signal <RAM>. > ----------------------------------------------------------------------- > | ram_style | block | | > ----------------------------------------------------------------------- > | Port A | > | aspect ratio | 1024-word x 16-bit | | > | clkA | connected to signal <CLOCK> | rise | > | weA | connected to internal node | high | > | addrA | connected to signal <addr> | | > | diA | connected to signal <di> | | > | doA | connected to internal node | | > ----------------------------------------------------------------------- > WARNING:Xst:1440 - Cannot use block RAM resources. Please check that the RAM > contents is read synchronously. > > >
Reply by ●March 5, 20072007-03-05
On Mar 5, 2:57 am, "Daniel S." <digitalmastrmind_no_s...@hotmail.com> wrote:> 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: > > 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 :-(. > > Synthesizing Unit <BRAM_test>. > > Related source file > > is "/amd/iss1/users/ma/tstone/georg/bram/BRAM_test.vhd". > > Found 1024x16-bit single-port distributed RAM for signal <RAM>. > > ----------------------------------------------------------------------- > > | ram_style | block | | > > ----------------------------------------------------------------------- > > | Port A | > > | aspect ratio | 1024-word x 16-bit | | > > | clkA | connected to signal <CLOCK> | rise | > > | weA | connected to internal node | high | > > | addrA | connected to signal <addr> | | > > | diA | connected to signal <di> | | > > | doA | connected to internal node | | > > ----------------------------------------------------------------------- > > WARNING:Xst:1440 - Cannot use block RAM resources. Please check that the RAM > > contents is read synchronously.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 <= P1; -- addr <= (others => '0'); if (CLOCK'event and CLOCK = '1') then case STATE is when P1 => RAM(conv_integer(addr)) <= di; do<=di; STATE <= P2; when P2 => do <= RAM(conv_integer(addr)); STATE <= P3; when P3 => addr <= addr + '1'; STATE <= P1; end case; end if; end process main; end syn;
Reply by ●March 5, 20072007-03-05
nagaraj wrote:> On Mar 5, 2:57 am, "Daniel S." <digitalmastrmind_no_s...@hotmail.com> > wrote: >> >> 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 >> > > 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 <= P1; > -- addr <= (others => '0'); > if (CLOCK'event and CLOCK = '1') then > case STATE is > when P1 => > RAM(conv_integer(addr)) <= di; > do<=di; > STATE <= P2; > when P2 => > do <= RAM(conv_integer(addr)); > STATE <= P3; > when P3 => > addr <= addr + '1'; > STATE <= P1; > end case; > end if; > end process main; > end syn;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 <= di;" every third cycle and thus fails to demonstrate any sort of BRAM functionality. Inferring a BRAM with two independent synchronous read and write ports (as one would for FIFO applications) is pretty straight-forward with ISE/VHDL and has worked well enough at least since 7.1. Where things get complicated is with true dual-port BRAMs - the ones with one RW port and a second R/W/RW one. The XST Coding Style guide has a template for them but it causes XST (ISE 8.1/8.2 - I have yet to try with 9.1) to crash when used in an actual design. This has forced me to use either coregen or explicit primitive instantiation. Coregen is slow, buggy and often inconvenient while primitives lack flexibility - so I would like to find out how to make XST (8.1/8.2) digest true dual-port (and not spit them out as distributed RAM) without having it crash. Until I find out (or get an opportunity to upgrade ISE to a version that has this bug fixed), at least I can still use coregen and primitives.
Reply by ●March 6, 20072007-03-06
On Mar 1, 9:27 am, "S.T." <s...@iss.tu-darmstadt.de> wrote:> 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 <= P1; > addr <= (others => '0'); > elsif (CLOCK'event and CLOCK = '1') then > case STATE is > when P1 => > RAM(conv_integer(addr)) <= di; > STATE <= P2; > when P2 => > do <= RAM(conv_integer(addr)); > STATE <= P3; > when P3 => > addr <= addr + '1'; > STATE <= P1; > end case; > end if; > end process main; > end syn;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 <= memarray(address); b) The read has to be synchronous; otherwise it won't use block RAMs. c) Don't use an async reset, which are not allowed for block RAMs. d) std_logic_arith is deprecated and should be replaced with numeric_std. -a
Reply by ●March 13, 20072007-03-13
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!> 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 simplyI am aiming for the synthesis of dual-ported block ram. Am i right that your comments aim at single ported ram?> b) The read has to be synchronous; otherwise it won't use block RAMs.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 <= P1; addr <= (others => '0'); we <= '0'; re <= '0'; else case STATE is when P1 => we<='1'; STATE <= P2; when P2 => we<='0'; re<='1'; STATE <= P3; when P3 => re<='0'; addr <= addr + '1'; STATE <= P1; end case; end if; end if; end process main; ram_write: process (CLOCK) begin if (CLOCK'event and CLOCK='1') then if(we='1') then RAM(conv_integer(addr)) <= di; end if; end if; end process ram_write; ram_read: process (CLOCK) begin if (CLOCK'event and CLOCK='1') then if(re='1') then do <= RAM(conv_integer(addr)); end if; end if; end process ram_read; end syn;





