From: Sidney Cadot on
Dear all,

Lately I have been trying to design and implement a synchronous FIFO
using a cyclic buffer, that can be synthesized by XST to use Block RAMs.

I now have a version that works (it does so in simulation using GHDL). I
have attached it below. However, since it doesn't follow the prescribed
pattern for BLOCK RAM inference, the code as shown synthesizes to an
implementation that uses "distributed RAM" instead.

Fortunately, I can easily get it in a form where BRAM can be inferred by
enabling the currently-commented-out line marked "ENABLE FOR BRAM",
around line 70.

The thing is that if I do this, the entity stops functioning as
intended. This is particularly strange since (as far as I can tell) the
change shouldn't affect the architecture's semantics in any way!

Any help/pointers by one of the VHDL gurus here would be much appreciated.

Best regards,

Sidney

------------- ramfifo.vhdl


library ieee;

use ieee.std_logic_1164.all,
ieee.numeric_std.all;

entity RAMFIFO is
port(
CLK : in std_logic;
data_in : in std_logic_vector(7 downto 0);
data_out : out std_logic_vector(7 downto 0);
status : out std_logic_vector(7 downto 0);
reset : in std_logic;
shift_in : in std_logic;
shift_out : in std_logic
);
end entity RAMFIFO;

architecture arch of RAMFIFO is

signal cur_address_r : unsigned(3 downto 0) := "0000";
signal cur_address_r2 : unsigned(3 downto 0) := "0000";
signal cur_num_entries : unsigned(3 downto 0) := "0000";
signal cur_address_w : unsigned(3 downto 0);

signal nxt_address_r : unsigned(3 downto 0);
signal nxt_num_entries : unsigned(3 downto 0);

signal sig_data_r : std_logic_vector(7 downto 0);

type RAMType is array(0 to 15) of std_logic_vector(7 downto 0);

-- initialize the ram below with sensible ascii values for debugging
signal ram : RAMType := (
x"30", x"31", x"32", x"33", x"34", x"35", x"36", x"37",
x"38", x"39", x"41", x"42", x"43", x"44", x"45", x"46"
);

signal shift_in_possible : std_logic;
signal shift_out_possible : std_logic;
signal shift_in_will_happen : std_logic;
signal shift_out_will_happen : std_logic;

begin

status <= std_logic_vector(cur_address_r) &
std_logic_vector(cur_num_entries);

process (CLK) is
begin
if rising_edge(CLK) then
if reset = '1' then
cur_num_entries <= "0000";
else
if shift_in_will_happen = '1' then
ram(to_integer(cur_address_w)) <= data_in;
end if;
cur_address_r <= nxt_address_r;
cur_num_entries <= nxt_num_entries;

-- if the line below is commented out,
-- XST generates DISTRIBUTED RAM,
-- and the FIFO works properly.
--
-- if the line below is enabled,
-- XST generates BLOCK RAM,
-- and the fifo does not work properly.

-- cur_address_r2 <= nxt_address_r; -- ENABLE FOR BRAM

end if;
end if;
end process;

sig_data_r <= ram(to_integer(cur_address_r));

with cur_num_entries select
data_out <= x"00" when "0000",
sig_data_r when others;

nxt_address_r <= cur_address_r + 1 when shift_out_will_happen = '1'
else cur_address_r;

nxt_num_entries <= cur_num_entries + 1 when shift_in_will_happen =
'1' and shift_out_will_happen = '0'
else cur_num_entries - 1 when shift_in_will_happen =
'0' and shift_out_will_happen = '1'
else cur_num_entries;

cur_address_w <= cur_address_r + cur_num_entries;

shift_in_will_happen <= shift_in and shift_in_possible;
shift_out_will_happen <= shift_out and shift_out_possible;

shift_in_possible <= '1' when (cur_num_entries /= "1111") or
shift_out = '1' else '0';
shift_out_possible <= '1' when (cur_num_entries /= "0000") else '0';

end architecture arch;
From: Peter Alfke on
Sidney. I am not a VHDL guru, but I claim to understand FIFOs.
There is an important difference between LUTRAM and BlockRAM:
In LUTRAM the reading is non-clocked (Change the read address, and the
new data appears immediately at the output), while the reading from a
BlockRAM is clocked (change the read address, and nothing happens at
the output until the next rising clock edge)

BTW, this is a long holoday weekend in the US.
Most people have better things to do than watching this ng. :-)
Peter Alfke

From: Mike Treseler on
Sidney Cadot wrote:

> Any help/pointers by one of the VHDL gurus here would be much appreciated.

http://groups-beta.google.com/groups?q=ram_dq_da


-- Mike Treseler
From: sidney on
Mike Treseler wrote:

> http://groups-beta.google.com/groups?q=ram_dq_da

I reviewed the results of this query, but I don't see anything that is
relevant to my problem I am afraid.

The example code I gave can be inferred as BRAMs by XST by the deletion
of 1 (semantically empty) line, as explained in my previous post. In
that case however, it ceases to work as expected. My only conclusion is
that either XST or my VHDL code must have a bug.

Regards, Sidney

From: sidney on
Peter Alfke wrote:

> Sidney. I am not a VHDL guru, but I claim to understand FIFOs.
> There is an important difference between LUTRAM and BlockRAM:
> In LUTRAM the reading is non-clocked (Change the read address, and the
> new data appears immediately at the output), while the reading from a
> BlockRAM is clocked (change the read address, and nothing happens at
> the output until the next rising clock edge)

Yes, I understand this. My FIFO design has a delay of at least one
clock cycle, I am not expecting the output to appear immediately.

Note, too, that my code carefully refrains from using any
Xilinx-specific components. If I enable the "ENABLE FOR BRAM" line in
the code I gave, XST is able to infer a Block-RAM implementation all by
itself (cf. the 'VHDL Coding Techniques' chapter of the XST User's
Guide), so it apparently 'thinks' that the BRAM can provide the VHDL
semantics of my code in that case.

> BTW, this is a long holoday weekend in the US.
> Most people have better things to do than watching this ng. :-)

Impossible ... :) Thanks for your help so far.

Regards, Sidney

 |  Next  |  Last
Pages: 1 2 3 4 5 6
Prev: errors during MAP
Next: NIOS II + USB 2.0 host