Using a BlockRam in an async FIFO for bus width conversion ?

Discussion in 'VHDL' started by Arnaud, Jun 25, 2004.

  1. Arnaud

    Arnaud Guest

    Hi all,
    First of all, I'm a newbie in FPGA, so sorry if my questions are not very
    smart... :)
    In a larger design, I try to use a Xilinx BlockRam for a data width
    conversion between 2 clocks domains.
    I look through the different Xilinx example (xapp131, xapp258, ..). As my
    needs was much more simpler I try to make mine (mostly to understand).

    During behavioral or post-translate simulation everything is ok. But during
    Post-Place & Route Simulation. It doesn't work.
    I try 2 write 2 32bits words from one side and to get on the other side a
    64bits word.
    In my test bench, I write
    1st - 0x00000000 and 0x00000001
    and the read side I get 0x0000000100000000
    2nd - 0x00000002 and 0x00000003
    and the read side I get 0x0000000300000002
    and so on.

    BUT in place and route simulation I have
    In my test bench, I write
    1st - 0x00000000 and 0x00000001
    and the read side I get 0x0000000000000000
    2nd - 0x00000002 and 0x00000003
    and the read side I get 0x0000000200000001
    2nd - 0x00000004 and 0x00000005
    and the read side I get 0x0000000400000003
    and so on.


    Basically, I always miss the first value, as It is not taken into account,
    and the "word" are reordered (so with the wrong pair association).

    I saw on the newsgroups, that maybe I have to set the WriteEnable _before_
    the rising edge, but I don't understand how and why if it's the case ?

    I have isolated my problem in the two following file (testbench and
    "converter")

    Thanks a lot.

    Arnaud



    Converter
    ----------------------------------------------------------------------------
    ----------------------------
    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;

    -- Uncomment the following lines to use the declarations that are
    -- provided for instantiating Xilinx primitive components.
    library UNISIM;
    use UNISIM.VComponents.all;

    entity test_fifo is
    Port ( clk_wr_in : in std_logic;
    clk_rd_in : in std_logic;
    bus_in : in std_logic_vector(31 downto 0);
    bus_out : out std_logic_vector(63 downto 0);
    wr : in std_logic;
    rd : in std_logic;
    sr : in std_logic);
    end test_fifo;

    architecture Behavioral of test_fifo is

    component bram_w32_r64
    port (
    addra: IN std_logic_VECTOR(4 downto 0);
    addrb: IN std_logic_VECTOR(3 downto 0);
    clka: IN std_logic;
    clkb: IN std_logic;
    dina: IN std_logic_VECTOR(31 downto 0);
    doutb: OUT std_logic_VECTOR(63 downto 0);
    ena: IN std_logic;
    enb: IN std_logic;
    wea: IN std_logic);
    end component;


    signal addra: std_logic_VECTOR(4 downto 0);
    signal addrb: std_logic_VECTOR(3 downto 0);



    signal clk_rd: std_logic;
    signal clk_wr: std_logic;

    signal rst : std_logic;

    begin


    gclk1: BUFGP port map (I => clk_rd_in, O => clk_rd);
    gclk2: BUFGP port map (I => clk_wr_in, O => clk_wr);

    rst <= not sr;

    bram : bram_w32_r64
    port map (
    addra => addra,
    addrb => addrb,
    clka => clk_wr,
    clkb => clk_rd,
    dina => bus_in,
    doutb => bus_out,
    ena => wr,
    enb => rst,
    wea => '1');


    writer: process(sr, clk_wr)
    begin
    if ( sr = '1' ) then

    addra <= (others => '0');

    elsif (rising_edge(clk_wr)) then

    if ( wr = '1' ) then
    addra <= addra + 1 ;
    end if;

    end if;

    end process writer;



    reader: process(sr, clk_rd)
    begin
    if ( sr = '1' ) then

    addrb <= (others => '0');

    elsif (rising_edge(clk_rd)) then
    if (rd = '1') then
    addrb <= addrb + 1 ;
    end if;

    end if;

    end process reader;

    end Behavioral;


    TEST_BENCH
    ----------------------------------------------------------------------------
    ----------------------------
    LIBRARY ieee;
    USE ieee.std_logic_1164.ALL;
    USE ieee.numeric_std.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;


    ENTITY test_fifo_tb IS
    END test_fifo_tb;

    ARCHITECTURE behavior OF test_fifo_tb IS

    COMPONENT test_fifo
    PORT(
    clk_wr_in : IN std_logic;
    clk_rd_in : IN std_logic;
    bus_in : IN std_logic_vector(31 downto 0);
    bus_out : out std_logic_vector(63 downto 0);
    wr : IN std_logic;
    rd : IN std_logic;
    sr : IN std_logic
    );
    END COMPONENT;

    SIGNAL clk_wr : std_logic := '0';
    SIGNAL clk_rd : std_logic := '0';
    SIGNAL bus_in : std_logic_vector(31 downto 0):= (others => '0');
    SIGNAL bus_out : std_logic_vector(63 downto 0):= (others => '0');
    SIGNAL wr : std_logic :='0';
    SIGNAL rd : std_logic := '0';
    SIGNAL sr : std_logic := '1';

    BEGIN

    uut: test_fifo PORT MAP(
    clk_wr_in => clk_wr,
    clk_rd_in => clk_rd,
    bus_in => bus_in,
    bus_out => bus_out,
    wr => wr,
    rd => rd,
    sr => sr
    );


    -- *** Test Bench - User Defined Section ***

    clk_wr <= not clk_wr after 30 ns / 2;
    clk_rd <= not clk_rd after 15 ns / 2;
    sr <= transport '0' after 120 ns;

    tb : PROCESS
    BEGIN
    wait; -- will wait forever
    END PROCESS;
    -- *** End Test Bench - User Defined Section ***

    writer: process( clk_wr, sr)
    begin

    if ( sr ='1' ) then

    bus_in <= (others => '1');

    elsif (rising_edge(clk_wr)) then

    if ( bus_out /= 8 ) then
    rd <= '0';
    wr <= '1';
    bus_in <= bus_in + 1;
    else
    wr <= '0';
    rd <= '1';
    end if;

    end if;

    end process writer;
    END;
     
    Arnaud, Jun 25, 2004
    #1
    1. Advertising

  2. Arnaud

    Peter Alfke Guest

    Remember, all BlockRAM operations are synchronous, activated by the clock
    edge (your choice of clock polarity).
    That means all inputs must be there at least a set-up time before that clock
    edge.
    "All" means: Address, Data, Write Enable, and ENable.

    Peter Alfke, Xilinx Applications

    > From: "Arnaud" <>
    > Organization: Guest of ProXad - France
    > Newsgroups: comp.arch.fpga,comp.lang.vhdl
    > Date: Fri, 25 Jun 2004 22:11:03 +0200
    > Subject: Using a BlockRam in an async FIFO for bus width conversion ?
    >
    > Hi all,
    > First of all, I'm a newbie in FPGA, so sorry if my questions are not very
    > smart... :)
    > In a larger design, I try to use a Xilinx BlockRam for a data width
    > conversion between 2 clocks domains.
    > I look through the different Xilinx example (xapp131, xapp258, ..). As my
    > needs was much more simpler I try to make mine (mostly to understand).
    >
    > During behavioral or post-translate simulation everything is ok. But during
    > Post-Place & Route Simulation. It doesn't work.
    > I try 2 write 2 32bits words from one side and to get on the other side a
    > 64bits word.
    > In my test bench, I write
    > 1st - 0x00000000 and 0x00000001
    > and the read side I get 0x0000000100000000
    > 2nd - 0x00000002 and 0x00000003
    > and the read side I get 0x0000000300000002
    > and so on.
    >
    > BUT in place and route simulation I have
    > In my test bench, I write
    > 1st - 0x00000000 and 0x00000001
    > and the read side I get 0x0000000000000000
    > 2nd - 0x00000002 and 0x00000003
    > and the read side I get 0x0000000200000001
    > 2nd - 0x00000004 and 0x00000005
    > and the read side I get 0x0000000400000003
    > and so on.
    >
    >
    > Basically, I always miss the first value, as It is not taken into account,
    > and the "word" are reordered (so with the wrong pair association).
    >
    > I saw on the newsgroups, that maybe I have to set the WriteEnable _before_
    > the rising edge, but I don't understand how and why if it's the case ?
    >
    > I have isolated my problem in the two following file (testbench and
    > "converter")
    >
    > Thanks a lot.
    >
    > Arnaud
    >
    >
    >
    > Converter
    > ----------------------------------------------------------------------------
    > ----------------------------
    > library IEEE;
    > use IEEE.STD_LOGIC_1164.ALL;
    > use IEEE.STD_LOGIC_ARITH.ALL;
    > use IEEE.STD_LOGIC_UNSIGNED.ALL;
    >
    > -- Uncomment the following lines to use the declarations that are
    > -- provided for instantiating Xilinx primitive components.
    > library UNISIM;
    > use UNISIM.VComponents.all;
    >
    > entity test_fifo is
    > Port ( clk_wr_in : in std_logic;
    > clk_rd_in : in std_logic;
    > bus_in : in std_logic_vector(31 downto 0);
    > bus_out : out std_logic_vector(63 downto 0);
    > wr : in std_logic;
    > rd : in std_logic;
    > sr : in std_logic);
    > end test_fifo;
    >
    > architecture Behavioral of test_fifo is
    >
    > component bram_w32_r64
    > port (
    > addra: IN std_logic_VECTOR(4 downto 0);
    > addrb: IN std_logic_VECTOR(3 downto 0);
    > clka: IN std_logic;
    > clkb: IN std_logic;
    > dina: IN std_logic_VECTOR(31 downto 0);
    > doutb: OUT std_logic_VECTOR(63 downto 0);
    > ena: IN std_logic;
    > enb: IN std_logic;
    > wea: IN std_logic);
    > end component;
    >
    >
    > signal addra: std_logic_VECTOR(4 downto 0);
    > signal addrb: std_logic_VECTOR(3 downto 0);
    >
    >
    >
    > signal clk_rd: std_logic;
    > signal clk_wr: std_logic;
    >
    > signal rst : std_logic;
    >
    > begin
    >
    >
    > gclk1: BUFGP port map (I => clk_rd_in, O => clk_rd);
    > gclk2: BUFGP port map (I => clk_wr_in, O => clk_wr);
    >
    > rst <= not sr;
    >
    > bram : bram_w32_r64
    > port map (
    > addra => addra,
    > addrb => addrb,
    > clka => clk_wr,
    > clkb => clk_rd,
    > dina => bus_in,
    > doutb => bus_out,
    > ena => wr,
    > enb => rst,
    > wea => '1');
    >
    >
    > writer: process(sr, clk_wr)
    > begin
    > if ( sr = '1' ) then
    >
    > addra <= (others => '0');
    >
    > elsif (rising_edge(clk_wr)) then
    >
    > if ( wr = '1' ) then
    > addra <= addra + 1 ;
    > end if;
    >
    > end if;
    >
    > end process writer;
    >
    >
    >
    > reader: process(sr, clk_rd)
    > begin
    > if ( sr = '1' ) then
    >
    > addrb <= (others => '0');
    >
    > elsif (rising_edge(clk_rd)) then
    > if (rd = '1') then
    > addrb <= addrb + 1 ;
    > end if;
    >
    > end if;
    >
    > end process reader;
    >
    > end Behavioral;
    >
    >
    > TEST_BENCH
    > ----------------------------------------------------------------------------
    > ----------------------------
    > LIBRARY ieee;
    > USE ieee.std_logic_1164.ALL;
    > USE ieee.numeric_std.ALL;
    > use IEEE.STD_LOGIC_UNSIGNED.ALL;
    >
    >
    > ENTITY test_fifo_tb IS
    > END test_fifo_tb;
    >
    > ARCHITECTURE behavior OF test_fifo_tb IS
    >
    > COMPONENT test_fifo
    > PORT(
    > clk_wr_in : IN std_logic;
    > clk_rd_in : IN std_logic;
    > bus_in : IN std_logic_vector(31 downto 0);
    > bus_out : out std_logic_vector(63 downto 0);
    > wr : IN std_logic;
    > rd : IN std_logic;
    > sr : IN std_logic
    > );
    > END COMPONENT;
    >
    > SIGNAL clk_wr : std_logic := '0';
    > SIGNAL clk_rd : std_logic := '0';
    > SIGNAL bus_in : std_logic_vector(31 downto 0):= (others => '0');
    > SIGNAL bus_out : std_logic_vector(63 downto 0):= (others => '0');
    > SIGNAL wr : std_logic :='0';
    > SIGNAL rd : std_logic := '0';
    > SIGNAL sr : std_logic := '1';
    >
    > BEGIN
    >
    > uut: test_fifo PORT MAP(
    > clk_wr_in => clk_wr,
    > clk_rd_in => clk_rd,
    > bus_in => bus_in,
    > bus_out => bus_out,
    > wr => wr,
    > rd => rd,
    > sr => sr
    > );
    >
    >
    > -- *** Test Bench - User Defined Section ***
    >
    > clk_wr <= not clk_wr after 30 ns / 2;
    > clk_rd <= not clk_rd after 15 ns / 2;
    > sr <= transport '0' after 120 ns;
    >
    > tb : PROCESS
    > BEGIN
    > wait; -- will wait forever
    > END PROCESS;
    > -- *** End Test Bench - User Defined Section ***
    >
    > writer: process( clk_wr, sr)
    > begin
    >
    > if ( sr ='1' ) then
    >
    > bus_in <= (others => '1');
    >
    > elsif (rising_edge(clk_wr)) then
    >
    > if ( bus_out /= 8 ) then
    > rd <= '0';
    > wr <= '1';
    > bus_in <= bus_in + 1;
    > else
    > wr <= '0';
    > rd <= '1';
    > end if;
    >
    > end if;
    >
    > end process writer;
    > END;
    >
    >
    >
    >
     
    Peter Alfke, Jun 25, 2004
    #2
    1. Advertising

  3. Arnaud

    Arnaud Guest

    Thanks Peter,

    I was thinking,the behaviour was:
    - on the clock_write rising edge : I setup Address, data, Write Enable and
    ENable, as setup time is not valid, BlockRam doesn't take them into account
    - on the next clock_write rising edge, I setup the new value, and the
    BlockRam gets the previous value (line above), and set the memory cell
    - and so on..

    It works fine in behavioral not in post place and route, it seems, that some
    part of the value changed at the rising edge are taken from the "before
    rising edge" values, while others are taken from the "after rising edge"
    values, in post place and route.

    To do what you told me "at least a set-up time before", I changed my block
    Ram to react on FallingEdge, while my logical set all the values at the
    RisingEdge....
    But I don't know if it's the "good way"...

    I didn't succeed to find any trivial example about the use of DualPort
    BlockRam... if anyone has one, I would love to get it.

    Many thanks,

    Arnaud

    "Peter Alfke" <> a écrit dans le message de
    news:BD01EB55.71BA%...
    > Remember, all BlockRAM operations are synchronous, activated by the clock
    > edge (your choice of clock polarity).
    > That means all inputs must be there at least a set-up time before that

    clock
    > edge.
    > "All" means: Address, Data, Write Enable, and ENable.
    >
    > Peter Alfke, Xilinx Applications
    >
    > > From: "Arnaud" <>
    > > Organization: Guest of ProXad - France
    > > Newsgroups: comp.arch.fpga,comp.lang.vhdl
    > > Date: Fri, 25 Jun 2004 22:11:03 +0200
    > > Subject: Using a BlockRam in an async FIFO for bus width conversion ?
    > >
    > > Hi all,
    > > First of all, I'm a newbie in FPGA, so sorry if my questions are not

    very
    > > smart... :)
    > > In a larger design, I try to use a Xilinx BlockRam for a data width
    > > conversion between 2 clocks domains.
    > > I look through the different Xilinx example (xapp131, xapp258, ..). As

    my
    > > needs was much more simpler I try to make mine (mostly to understand).
    > >
    > > During behavioral or post-translate simulation everything is ok. But

    during
    > > Post-Place & Route Simulation. It doesn't work.
    > > I try 2 write 2 32bits words from one side and to get on the other side

    a
    > > 64bits word.
    > > In my test bench, I write
    > > 1st - 0x00000000 and 0x00000001
    > > and the read side I get 0x0000000100000000
    > > 2nd - 0x00000002 and 0x00000003
    > > and the read side I get 0x0000000300000002
    > > and so on.
    > >
    > > BUT in place and route simulation I have
    > > In my test bench, I write
    > > 1st - 0x00000000 and 0x00000001
    > > and the read side I get 0x0000000000000000
    > > 2nd - 0x00000002 and 0x00000003
    > > and the read side I get 0x0000000200000001
    > > 2nd - 0x00000004 and 0x00000005
    > > and the read side I get 0x0000000400000003
    > > and so on.
    > >
    > >
    > > Basically, I always miss the first value, as It is not taken into

    account,
    > > and the "word" are reordered (so with the wrong pair association).
    > >
    > > I saw on the newsgroups, that maybe I have to set the WriteEnable

    _before_
    > > the rising edge, but I don't understand how and why if it's the case ?
    > >
    > > I have isolated my problem in the two following file (testbench and
    > > "converter")
    > >
    > > Thanks a lot.
    > >
    > > Arnaud
    > >
    > >
    > >
    > > Converter

    >
    > --------------------------------------------------------------------------

    --
    > > ----------------------------
    > > library IEEE;
    > > use IEEE.STD_LOGIC_1164.ALL;
    > > use IEEE.STD_LOGIC_ARITH.ALL;
    > > use IEEE.STD_LOGIC_UNSIGNED.ALL;
    > >
    > > -- Uncomment the following lines to use the declarations that are
    > > -- provided for instantiating Xilinx primitive components.
    > > library UNISIM;
    > > use UNISIM.VComponents.all;
    > >
    > > entity test_fifo is
    > > Port ( clk_wr_in : in std_logic;
    > > clk_rd_in : in std_logic;
    > > bus_in : in std_logic_vector(31 downto 0);
    > > bus_out : out std_logic_vector(63 downto 0);
    > > wr : in std_logic;
    > > rd : in std_logic;
    > > sr : in std_logic);
    > > end test_fifo;
    > >
    > > architecture Behavioral of test_fifo is
    > >
    > > component bram_w32_r64
    > > port (
    > > addra: IN std_logic_VECTOR(4 downto 0);
    > > addrb: IN std_logic_VECTOR(3 downto 0);
    > > clka: IN std_logic;
    > > clkb: IN std_logic;
    > > dina: IN std_logic_VECTOR(31 downto 0);
    > > doutb: OUT std_logic_VECTOR(63 downto 0);
    > > ena: IN std_logic;
    > > enb: IN std_logic;
    > > wea: IN std_logic);
    > > end component;
    > >
    > >
    > > signal addra: std_logic_VECTOR(4 downto 0);
    > > signal addrb: std_logic_VECTOR(3 downto 0);
    > >
    > >
    > >
    > > signal clk_rd: std_logic;
    > > signal clk_wr: std_logic;
    > >
    > > signal rst : std_logic;
    > >
    > > begin
    > >
    > >
    > > gclk1: BUFGP port map (I => clk_rd_in, O => clk_rd);
    > > gclk2: BUFGP port map (I => clk_wr_in, O => clk_wr);
    > >
    > > rst <= not sr;
    > >
    > > bram : bram_w32_r64
    > > port map (
    > > addra => addra,
    > > addrb => addrb,
    > > clka => clk_wr,
    > > clkb => clk_rd,
    > > dina => bus_in,
    > > doutb => bus_out,
    > > ena => wr,
    > > enb => rst,
    > > wea => '1');
    > >
    > >
    > > writer: process(sr, clk_wr)
    > > begin
    > > if ( sr = '1' ) then
    > >
    > > addra <= (others => '0');
    > >
    > > elsif (rising_edge(clk_wr)) then
    > >
    > > if ( wr = '1' ) then
    > > addra <= addra + 1 ;
    > > end if;
    > >
    > > end if;
    > >
    > > end process writer;
    > >
    > >
    > >
    > > reader: process(sr, clk_rd)
    > > begin
    > > if ( sr = '1' ) then
    > >
    > > addrb <= (others => '0');
    > >
    > > elsif (rising_edge(clk_rd)) then
    > > if (rd = '1') then
    > > addrb <= addrb + 1 ;
    > > end if;
    > >
    > > end if;
    > >
    > > end process reader;
    > >
    > > end Behavioral;
    > >
    > >
    > > TEST_BENCH

    >
    > --------------------------------------------------------------------------

    --
    > > ----------------------------
    > > LIBRARY ieee;
    > > USE ieee.std_logic_1164.ALL;
    > > USE ieee.numeric_std.ALL;
    > > use IEEE.STD_LOGIC_UNSIGNED.ALL;
    > >
    > >
    > > ENTITY test_fifo_tb IS
    > > END test_fifo_tb;
    > >
    > > ARCHITECTURE behavior OF test_fifo_tb IS
    > >
    > > COMPONENT test_fifo
    > > PORT(
    > > clk_wr_in : IN std_logic;
    > > clk_rd_in : IN std_logic;
    > > bus_in : IN std_logic_vector(31 downto 0);
    > > bus_out : out std_logic_vector(63 downto 0);
    > > wr : IN std_logic;
    > > rd : IN std_logic;
    > > sr : IN std_logic
    > > );
    > > END COMPONENT;
    > >
    > > SIGNAL clk_wr : std_logic := '0';
    > > SIGNAL clk_rd : std_logic := '0';
    > > SIGNAL bus_in : std_logic_vector(31 downto 0):= (others => '0');
    > > SIGNAL bus_out : std_logic_vector(63 downto 0):= (others => '0');
    > > SIGNAL wr : std_logic :='0';
    > > SIGNAL rd : std_logic := '0';
    > > SIGNAL sr : std_logic := '1';
    > >
    > > BEGIN
    > >
    > > uut: test_fifo PORT MAP(
    > > clk_wr_in => clk_wr,
    > > clk_rd_in => clk_rd,
    > > bus_in => bus_in,
    > > bus_out => bus_out,
    > > wr => wr,
    > > rd => rd,
    > > sr => sr
    > > );
    > >
    > >
    > > -- *** Test Bench - User Defined Section ***
    > >
    > > clk_wr <= not clk_wr after 30 ns / 2;
    > > clk_rd <= not clk_rd after 15 ns / 2;
    > > sr <= transport '0' after 120 ns;
    > >
    > > tb : PROCESS
    > > BEGIN
    > > wait; -- will wait forever
    > > END PROCESS;
    > > -- *** End Test Bench - User Defined Section ***
    > >
    > > writer: process( clk_wr, sr)
    > > begin
    > >
    > > if ( sr ='1' ) then
    > >
    > > bus_in <= (others => '1');
    > >
    > > elsif (rising_edge(clk_wr)) then
    > >
    > > if ( bus_out /= 8 ) then
    > > rd <= '0';
    > > wr <= '1';
    > > bus_in <= bus_in + 1;
    > > else
    > > wr <= '0';
    > > rd <= '1';
    > > end if;
    > >
    > > end if;
    > >
    > > end process writer;
    > > END;
    > >
    > >
    > >
    > >

    >
     
    Arnaud, Jun 26, 2004
    #3
  4. Arnaud

    Peter Alfke Guest

    You can treat the inputs to the BlockRAM just as if it were a register.
    Give it all its information and then apply the right clock edge. It's as
    simple as that.

    But an asynchronous FIFO is not simple, especially if you are after high
    clock rates. The problem is detecting EMPTY reliably, and that involves the
    use of Gray counters etc.
    As you may have read in today's press announcement, we took care of that in
    Virtex-4, where we incorporated a FIFO controller with all the bells and
    whistles and impressive speed...
    Peter Alfke

    > From: "Arnaud" <>
    > Organization: Guest of ProXad - France
    > Newsgroups: comp.arch.fpga,comp.lang.vhdl
    > Date: Sat, 26 Jun 2004 09:34:40 +0200
    > Subject: Re: Using a BlockRam in an async FIFO for bus width conversion ?
    >
    > Thanks Peter,
    >
    > I was thinking,the behaviour was:
    > - on the clock_write rising edge : I setup Address, data, Write Enable and
    > ENable, as setup time is not valid, BlockRam doesn't take them into account
    > - on the next clock_write rising edge, I setup the new value, and the
    > BlockRam gets the previous value (line above), and set the memory cell
    > - and so on..
    >
    > It works fine in behavioral not in post place and route, it seems, that some
    > part of the value changed at the rising edge are taken from the "before
    > rising edge" values, while others are taken from the "after rising edge"
    > values, in post place and route.
    >
    > To do what you told me "at least a set-up time before", I changed my block
    > Ram to react on FallingEdge, while my logical set all the values at the
    > RisingEdge....
    > But I don't know if it's the "good way"...
    >
    > I didn't succeed to find any trivial example about the use of DualPort
    > BlockRam... if anyone has one, I would love to get it.
    >
    > Many thanks,
    >
    > Arnaud
    >
    > "Peter Alfke" <> a écrit dans le message de
    > news:BD01EB55.71BA%...
    >> Remember, all BlockRAM operations are synchronous, activated by the clock
    >> edge (your choice of clock polarity).
    >> That means all inputs must be there at least a set-up time before that

    > clock
    >> edge.
    >> "All" means: Address, Data, Write Enable, and ENable.
    >>
    >> Peter Alfke, Xilinx Applications
    >>
    >>> From: "Arnaud" <>
    >>> Organization: Guest of ProXad - France
    >>> Newsgroups: comp.arch.fpga,comp.lang.vhdl
    >>> Date: Fri, 25 Jun 2004 22:11:03 +0200
    >>> Subject: Using a BlockRam in an async FIFO for bus width conversion ?
    >>>
    >>> Hi all,
    >>> First of all, I'm a newbie in FPGA, so sorry if my questions are not

    > very
    >>> smart... :)
    >>> In a larger design, I try to use a Xilinx BlockRam for a data width
    >>> conversion between 2 clocks domains.
    >>> I look through the different Xilinx example (xapp131, xapp258, ..). As

    > my
    >>> needs was much more simpler I try to make mine (mostly to understand).
    >>>
    >>> During behavioral or post-translate simulation everything is ok. But

    > during
    >>> Post-Place & Route Simulation. It doesn't work.
    >>> I try 2 write 2 32bits words from one side and to get on the other side

    > a
    >>> 64bits word.
    >>> In my test bench, I write
    >>> 1st - 0x00000000 and 0x00000001
    >>> and the read side I get 0x0000000100000000
    >>> 2nd - 0x00000002 and 0x00000003
    >>> and the read side I get 0x0000000300000002
    >>> and so on.
    >>>
    >>> BUT in place and route simulation I have
    >>> In my test bench, I write
    >>> 1st - 0x00000000 and 0x00000001
    >>> and the read side I get 0x0000000000000000
    >>> 2nd - 0x00000002 and 0x00000003
    >>> and the read side I get 0x0000000200000001
    >>> 2nd - 0x00000004 and 0x00000005
    >>> and the read side I get 0x0000000400000003
    >>> and so on.
    >>>
    >>>
    >>> Basically, I always miss the first value, as It is not taken into

    > account,
    >>> and the "word" are reordered (so with the wrong pair association).
    >>>
    >>> I saw on the newsgroups, that maybe I have to set the WriteEnable

    > _before_
    >>> the rising edge, but I don't understand how and why if it's the case ?
    >>>
    >>> I have isolated my problem in the two following file (testbench and
    >>> "converter")
    >>>
    >>> Thanks a lot.
    >>>
    >>> Arnaud
    >>>
    >>>
    >>>
    >>> Converter

    >>
    >> --------------------------------------------------------------------------

    > --
    >>> ----------------------------
    >>> library IEEE;
    >>> use IEEE.STD_LOGIC_1164.ALL;
    >>> use IEEE.STD_LOGIC_ARITH.ALL;
    >>> use IEEE.STD_LOGIC_UNSIGNED.ALL;
    >>>
    >>> -- Uncomment the following lines to use the declarations that are
    >>> -- provided for instantiating Xilinx primitive components.
    >>> library UNISIM;
    >>> use UNISIM.VComponents.all;
    >>>
    >>> entity test_fifo is
    >>> Port ( clk_wr_in : in std_logic;
    >>> clk_rd_in : in std_logic;
    >>> bus_in : in std_logic_vector(31 downto 0);
    >>> bus_out : out std_logic_vector(63 downto 0);
    >>> wr : in std_logic;
    >>> rd : in std_logic;
    >>> sr : in std_logic);
    >>> end test_fifo;
    >>>
    >>> architecture Behavioral of test_fifo is
    >>>
    >>> component bram_w32_r64
    >>> port (
    >>> addra: IN std_logic_VECTOR(4 downto 0);
    >>> addrb: IN std_logic_VECTOR(3 downto 0);
    >>> clka: IN std_logic;
    >>> clkb: IN std_logic;
    >>> dina: IN std_logic_VECTOR(31 downto 0);
    >>> doutb: OUT std_logic_VECTOR(63 downto 0);
    >>> ena: IN std_logic;
    >>> enb: IN std_logic;
    >>> wea: IN std_logic);
    >>> end component;
    >>>
    >>>
    >>> signal addra: std_logic_VECTOR(4 downto 0);
    >>> signal addrb: std_logic_VECTOR(3 downto 0);
    >>>
    >>>
    >>>
    >>> signal clk_rd: std_logic;
    >>> signal clk_wr: std_logic;
    >>>
    >>> signal rst : std_logic;
    >>>
    >>> begin
    >>>
    >>>
    >>> gclk1: BUFGP port map (I => clk_rd_in, O => clk_rd);
    >>> gclk2: BUFGP port map (I => clk_wr_in, O => clk_wr);
    >>>
    >>> rst <= not sr;
    >>>
    >>> bram : bram_w32_r64
    >>> port map (
    >>> addra => addra,
    >>> addrb => addrb,
    >>> clka => clk_wr,
    >>> clkb => clk_rd,
    >>> dina => bus_in,
    >>> doutb => bus_out,
    >>> ena => wr,
    >>> enb => rst,
    >>> wea => '1');
    >>>
    >>>
    >>> writer: process(sr, clk_wr)
    >>> begin
    >>> if ( sr = '1' ) then
    >>>
    >>> addra <= (others => '0');
    >>>
    >>> elsif (rising_edge(clk_wr)) then
    >>>
    >>> if ( wr = '1' ) then
    >>> addra <= addra + 1 ;
    >>> end if;
    >>>
    >>> end if;
    >>>
    >>> end process writer;
    >>>
    >>>
    >>>
    >>> reader: process(sr, clk_rd)
    >>> begin
    >>> if ( sr = '1' ) then
    >>>
    >>> addrb <= (others => '0');
    >>>
    >>> elsif (rising_edge(clk_rd)) then
    >>> if (rd = '1') then
    >>> addrb <= addrb + 1 ;
    >>> end if;
    >>>
    >>> end if;
    >>>
    >>> end process reader;
    >>>
    >>> end Behavioral;
    >>>
    >>>
    >>> TEST_BENCH

    >>
    >> --------------------------------------------------------------------------

    > --
    >>> ----------------------------
    >>> LIBRARY ieee;
    >>> USE ieee.std_logic_1164.ALL;
    >>> USE ieee.numeric_std.ALL;
    >>> use IEEE.STD_LOGIC_UNSIGNED.ALL;
    >>>
    >>>
    >>> ENTITY test_fifo_tb IS
    >>> END test_fifo_tb;
    >>>
    >>> ARCHITECTURE behavior OF test_fifo_tb IS
    >>>
    >>> COMPONENT test_fifo
    >>> PORT(
    >>> clk_wr_in : IN std_logic;
    >>> clk_rd_in : IN std_logic;
    >>> bus_in : IN std_logic_vector(31 downto 0);
    >>> bus_out : out std_logic_vector(63 downto 0);
    >>> wr : IN std_logic;
    >>> rd : IN std_logic;
    >>> sr : IN std_logic
    >>> );
    >>> END COMPONENT;
    >>>
    >>> SIGNAL clk_wr : std_logic := '0';
    >>> SIGNAL clk_rd : std_logic := '0';
    >>> SIGNAL bus_in : std_logic_vector(31 downto 0):= (others => '0');
    >>> SIGNAL bus_out : std_logic_vector(63 downto 0):= (others => '0');
    >>> SIGNAL wr : std_logic :='0';
    >>> SIGNAL rd : std_logic := '0';
    >>> SIGNAL sr : std_logic := '1';
    >>>
    >>> BEGIN
    >>>
    >>> uut: test_fifo PORT MAP(
    >>> clk_wr_in => clk_wr,
    >>> clk_rd_in => clk_rd,
    >>> bus_in => bus_in,
    >>> bus_out => bus_out,
    >>> wr => wr,
    >>> rd => rd,
    >>> sr => sr
    >>> );
    >>>
    >>>
    >>> -- *** Test Bench - User Defined Section ***
    >>>
    >>> clk_wr <= not clk_wr after 30 ns / 2;
    >>> clk_rd <= not clk_rd after 15 ns / 2;
    >>> sr <= transport '0' after 120 ns;
    >>>
    >>> tb : PROCESS
    >>> BEGIN
    >>> wait; -- will wait forever
    >>> END PROCESS;
    >>> -- *** End Test Bench - User Defined Section ***
    >>>
    >>> writer: process( clk_wr, sr)
    >>> begin
    >>>
    >>> if ( sr ='1' ) then
    >>>
    >>> bus_in <= (others => '1');
    >>>
    >>> elsif (rising_edge(clk_wr)) then
    >>>
    >>> if ( bus_out /= 8 ) then
    >>> rd <= '0';
    >>> wr <= '1';
    >>> bus_in <= bus_in + 1;
    >>> else
    >>> wr <= '0';
    >>> rd <= '1';
    >>> end if;
    >>>
    >>> end if;
    >>>
    >>> end process writer;
    >>> END;
    >>>
    >>>
    >>>
    >>>

    >>

    >
    >
     
    Peter Alfke, Jun 28, 2004
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.

Share This Page