Fifo updated to more recent version to allow use of BlockRAM/FIFO hard blocks.
authorTerry Barnaby <terry.barnaby@beam.beam.ltd.uk>
Sat, 6 Jun 2020 09:01:33 +0000 (10:01 +0100)
committerTerry Barnaby <terry.barnaby@beam.beam.ltd.uk>
Sat, 6 Jun 2020 09:01:33 +0000 (10:01 +0100)
src/Fifo.vhd
src/NvmeWrite.vhd

index a388a6aa14dbdaf5bb3fad8771b83605bb66fce0..365f62c3e6153a006989cef2d589619fe95d4ad9 100644 (file)
 --! @details
 --! This is a simple single clock first word fall through FIFO.
 --! Its data storage memory will be implemented in registers for small Fifo's and
---! in BlockRAM for larger Fifos the FifoSize parameter defining the depth of the Fifo.
+--! in BlockRAM for larger Fifos (>= 32) the Size parameter defining the depth of the Fifo.
 --! The data width is defined by the DataWidth parameter.
---! It has a programmable fifoNearFull output that can be enabled by setting the
---! NearFull parameter to the appropriate Fifo level.
---! The RegisterOutputs parameter provides registered output of the data for better system timing
---! at the expense of one cycle of latency.
+--! It has a programmable nearFull output that can be enabled by setting the
+--! NearFullLevel parameter to the appropriate Fifo level.
+--! The module uses the Xilinx xpm_fifo_sync macro for larger Fifo sizes such that the
+--! RAM/FIFO hard blocks will be used in this case.
+--! The Simulate option disable the use of the Xilinx xpm_fifo_sync macro.
 --!
 --! @copyright GNU GPL License
 --! Copyright (c) Beam Ltd, All rights reserved. <br>
@@ -47,25 +48,25 @@ use work.NvmeStorageIntPkg.all;
 
 entity Fifo is
 generic (
+       Simulate        : boolean := False;                             --! Simulation
        DataWidth       : integer := 128;                               --! The data width of the Fifo in bits
-       FifoSize        : integer := 2;                                 --! The size of the fifo
-       NearFull        : integer := 0;                                 --! Nearly full level, 0 disables
-       RegisterOutputs : boolean := False                              --! Register the outputs
+       Size            : integer := 2;                                 --! The size of the fifo
+       NearFullLevel   : integer := 0                                  --! Nearly full level, 0 disables
 );
 port (
        clk             : in std_logic;                                 --! The interface clock line
        reset           : in std_logic;                                 --! The active high reset line
        
-       fifoNearFull    : out std_logic;                                --! Fifo is nearly full
+       nearFull        : out std_logic;                                --! Fifo is nearly full
 
-       fifoInReady     : out std_logic;                                --! Fifo is ready for input
-       fifoInValid     : in std_logic;                                 --! Data input is valid
-       fifoIn          : in std_logic_vector(DataWidth-1 downto 0);    --! The input data
+       inReady         : out std_logic;                                --! Fifo is ready for input
+       inValid         : in std_logic;                                 --! Data input is valid
+       inData          : in std_logic_vector(DataWidth-1 downto 0);    --! The input data
 
 
-       fifoOutReady    : in std_logic;                                 --! The external logic is ready for output
-       fifoOutValid    : out std_logic;                                --! The data output is available
-       fifoOut         : out std_logic_vector(DataWidth-1 downto 0)    --! The output data
+       outReady        : in std_logic;                                 --! The external logic is ready for output
+       outValid        : out std_logic;                                --! The data output is available
+       outData         : out std_logic_vector(DataWidth-1 downto 0)    --! The output data
 );
 end;
 
@@ -73,86 +74,196 @@ architecture Behavioral of Fifo is
 
 constant TCQ           : time := 1 ns;
 
-type MemoryType                is array(0 to FifoSize-1) of std_logic_vector(DataWidth-1 downto 0);
+component xpm_fifo_sync
+generic (
+       DOUT_RESET_VALUE        : string := "0";
+       ECC_MODE                : string :=  "no_ecc";
+       FIFO_MEMORY_TYPE        : string :=  "auto";
+       FIFO_READ_LATENCY       : integer :=  0;
+       FIFO_WRITE_DEPTH        : integer :=  Size;
+       FULL_RESET_VALUE        : integer :=  0;
+       PROG_EMPTY_THRESH       : integer :=  1;
+       PROG_FULL_THRESH        : integer :=  NearFullLevel;
+       RD_DATA_COUNT_WIDTH     : integer :=  1;
+       READ_DATA_WIDTH         : integer :=  DataWidth;
+       READ_MODE               : string :=  "fwft";
+       SIM_ASSERT_CHK          : integer :=  0;
+       USE_ADV_FEATURES        : string :=  "1002";
+       WAKEUP_TIME             : integer :=  0;
+       WRITE_DATA_WIDTH        : integer :=  DataWidth;
+       WR_DATA_COUNT_WIDTH     : integer :=  1
+);
+port (
+       wr_clk          : in std_logic;
+       rst             : in std_logic;
+
+       prog_full       : out std_logic;
+
+       full            : out std_logic;
+       wr_en           : in std_logic;
+       din             : in std_logic_vector(DataWidth-1 downto 0);
+
+       rd_en           : in std_logic;
+       data_valid      : out std_logic;
+       dout            : out std_logic_vector(DataWidth-1 downto 0);
+
+       sleep           : in std_logic;
+       injectdbiterr   : in std_logic;
+       injectsbiterr   : in std_logic
+
+       --empty         : out std_logic;
+       --almost_full   : out std_logic;
+       --almost_empty  : out std_logic;
+       --dbiterr       : out std_logic;
+       --overflow      : out std_logic;
+       --prog_empty    : out std_logic;
+       --rd_data_count : out std_logic;
+       --rd_rst_busy   : out std_logic;
+       --sbiterr       : out std_logic;
+       --underflow     : out std_logic;
+       --wr_ack        : out std_logic;
+       --wr_data_count : out std_logic;
+       --wr_rst_busy   : out std_logic;
+);
+end component;
+
+type MemoryType                is array(0 to Size-1) of std_logic_vector(DataWidth-1 downto 0);
 signal memory          : MemoryType := (others => (others => 'U'));
 
-signal count           : integer range 0 to FifoSize;                  --! Count of number of FIFO items.
-signal writePos                : integer range 0 to FifoSize-1;                --! The write position pointer
-signal readPos         : integer range 0 to FifoSize-1;                --! The read position pointer
+signal count           : integer range 0 to Size;                      --! Count of number of FIFO items.
+signal writePos                : integer range 0 to Size-1;                    --! The write position pointer
+signal readPos         : integer range 0 to Size-1;                    --! The read position pointer
 signal posLooped       : boolean := False;                             --! The write pointer has looped around behind the read pointer
 signal writeReady      : std_logic;                                    --! There is space to write to the FIFO
 signal writeEnable     : std_logic;                                    --! Write data to the FIFO
+signal readReady       : std_logic;                                    --! There is space to write to the FIFO
 signal readEnable      : std_logic;                                    --! Read data from the FIFO
 
+signal full            : std_logic;                                    --! There is no space to write to the FIFO
+signal empty           : std_logic;                                    --! Yhe FIFO is empty
+
+function features(nearLevel: integer) return string is
 begin
-       writeReady      <= '1' when(not posLooped or (readPos /= writePos)) else '0';
-       writeEnable     <= fifoInValid when(writeReady = '1') else '0';
-       fifoInReady     <= writeReady;
-       fifoNearFull    <= '1' when(count >= NearFull) else '0';
+       if(nearLevel > 0) then
+               return "1002";
+       else
+               return "1000";
+       end if;
+end;
 
-       readEnable      <= fifoOutReady when((posLooped) or (writePos /= readPos)) else '0';
-       fifoOutValid    <= '1' when((posLooped) or (writePos /= readPos)) else '0';
-       
-       -- Handle data output
-       noreg: if(RegisterOutputs = False) generate
-               fifoOut <= memory(readPos);
-       end generate;
+begin
+       simple: if((Simulate = True) or (Size <= 32)) generate
+               writeReady      <= '1' when(not posLooped or (readPos /= writePos)) else '0';
+               writeEnable     <= inValid when(writeReady = '1') else '0';
+               inReady         <= writeReady;
+               nearFull        <= '1' when(count >= NearFullLevel) else '0';
 
-       reg: if(RegisterOutputs = True) generate
-       process(clk)
-       begin
-               if(rising_edge(clk)) then
-                       -- Handle Fifo output
-                       if(readEnable = '1') then
-                               fifoOut <= memory(readPos);
-                       end if;
-               end if;
-       end process;
-       end generate;
+               readReady       <= '1' when((posLooped) or (writePos /= readPos)) else '0';
+               readEnable      <= outReady when(readReady = '1') else '0';
+               outData         <= memory(readPos);
+               outValid        <= '1' when((posLooped) or (writePos /= readPos)) else '0';
 
+               process(clk)
+               begin
+                       if(rising_edge(clk)) then
+                               if(reset = '1') then
+                                       writePos        <= 0;
+                                       readPos         <= 0;
+                                       posLooped       <= False;
+                                       count           <= 0;
 
-       process(clk)
-       begin
-               if(rising_edge(clk)) then
-                       if(reset = '1') then
-                               writePos        <= 0;
-                               readPos         <= 0;
-                               posLooped       <= False;
-                               count           <= 0;
-                               
-                       else
-                               -- Handle Fifo input
-                               if(writeEnable = '1') then
-                                       memory(writePos) <= fifoIn;
-
-                                       if(writePos = FifoSize-1) then
-                                               writePos        <= 0;
-                                               posLooped       <= True;
-                                       else 
-                                               writePos <= writePos + 1;
+                               else
+                                       -- Handle Fifo input
+                                       if(writeEnable = '1') then
+                                               memory(writePos) <= inData;
+
+                                               if(writePos = Size-1) then
+                                                       writePos        <= 0;
+                                                       posLooped       <= True;
+                                               else 
+                                                       writePos <= writePos + 1;
+                                               end if;
                                        end if;
-                               end if;
-                               
-                               -- Handle Fifo output
-                               if(readEnable = '1') then
-                                       if(readPos = FifoSize-1) then
-                                               readPos         <= 0;
-                                               posLooped       <= False;
-                                       else 
-                                               readPos <= readPos + 1;
+
+                                       -- Handle Fifo output
+                                       if(readEnable = '1') then
+                                               if(readPos = Size-1) then
+                                                       readPos         <= 0;
+                                                       posLooped       <= False;
+                                               else 
+                                                       readPos <= readPos + 1;
+                                               end if;
                                        end if;
-                               end if;
 
-                               -- Contents counter logic
-                               if(NearFull > 0) then
-                                       if((writeEnable = '1') and (readEnable = '0')) then
-                                               count <= count + 1;
-                                       elsif((writeEnable = '0') and (readEnable = '1')) then
-                                               count <= count - 1;
+                                       -- Contents counter logic
+                                       if(NearFullLevel > 0) then
+                                               if((writeEnable = '1') and (readEnable = '0')) then
+                                                       count <= count + 1;
+                                               elsif((writeEnable = '0') and (readEnable = '1')) then
+                                                       count <= count - 1;
+                                               end if;
                                        end if;
+
                                end if;
-                               
                        end if;
-               end if;
-       end process;
+               end process;
+       end generate;
+
+       xilinx: if((Simulate = False) and (Size > 32)) generate
+       
+               inReady <= not full;
+
+               -- xpm_fifo_sync: Synchronous FIFO
+               xpm_fifo_sync0 : xpm_fifo_sync
+               generic map (
+                       DOUT_RESET_VALUE        => "0",
+                       ECC_MODE                => "no_ecc",
+                       FIFO_MEMORY_TYPE        => "auto",
+                       FIFO_READ_LATENCY       => 0,
+                       FIFO_WRITE_DEPTH        => Size,
+                       FULL_RESET_VALUE        => 0,
+                       PROG_EMPTY_THRESH       => 1,
+                       PROG_FULL_THRESH        => NearFullLevel,
+                       RD_DATA_COUNT_WIDTH     => 1,
+                       READ_DATA_WIDTH         => DataWidth,
+                       READ_MODE               => "fwft",
+                       SIM_ASSERT_CHK          => 0,
+                       USE_ADV_FEATURES        => features(NearFullLevel),
+                       WAKEUP_TIME             => 0,
+                       WRITE_DATA_WIDTH        => DataWidth,
+                       WR_DATA_COUNT_WIDTH     => 1
+               )
+               port map (
+                       wr_clk          => clk,
+                       rst             => reset,
+
+                       prog_full       => nearFull,
+
+                       full            => full,
+                       wr_en           => inValid,
+                       din             => inData,
+                       
+                       rd_en           => outReady,
+                       data_valid      => outValid,
+                       dout            => outData,
+                       
+                       sleep           => '0',
+                       injectdbiterr   => '0',
+                       injectsbiterr   => '0'
+
+                       --empty         => empty,
+                       --almost_full   => nearFull,
+                       --almost_empty  => almost_empty,
+                       --dbiterr       => dbiterr,
+                       --overflow      => overflow,
+                       --prog_empty    => prog_empty,
+                       --rd_data_count => rd_data_count,
+                       --rd_rst_busy   => rd_rst_busy,
+                       --sbiterr       => sbiterr,
+                       --underflow     => underflow,
+                       --wr_ack        => wr_ack,
+                       --wr_data_count => wr_data_count,
+                       --wr_rst_busy   => wr_rst_busy,
+               );
+       end generate;
 end;
index b5c0ab3e810163d7944ca554e4a60beed351ed08..0ed66feef2700af65712c7727382585231e79c56 100644 (file)
@@ -142,23 +142,25 @@ end component;
 
 component Fifo is
 generic (
-       DataWidth       : integer := 128;                       --! The data width of the Fifo in bits
-       FifoSize        : integer := 8;                         --! The size of the fifo
-       NearFull        : integer := 6                          --! Nearly full level, 0 disables
+       Simulate        : boolean := False;                             --! Simulation
+       DataWidth       : integer := 128;                               --! The data width of the Fifo in bits
+       Size            : integer := 8;                                 --! The size of the fifo
+       NearFullLevel   : integer := 6                                  --! Nearly full level, 0 disables
 );
 port (
        clk             : in std_logic;                                 --! The interface clock line
        reset           : in std_logic;                                 --! The active high reset line
        
-       fifoNearFull    : out std_logic;
-       fifoInReady     : out std_logic;
-       fifoInValid     : in std_logic;
-       fifoIn          : in std_logic_vector(127 downto 0);
+       nearFull        : out std_logic;                                --! Fifo is nearly full
 
+       inReady         : out std_logic;                                --! Fifo is ready for input
+       inValid         : in std_logic;                                 --! Data input is valid
+       inData          : in std_logic_vector(DataWidth-1 downto 0);    --! The input data
 
-       fifoOutReady    : in std_logic;
-       fifoOutValid    : out std_logic;
-       fifoOut         : out std_logic_vector(127 downto 0)
+
+       outReady        : in std_logic;                                 --! The external logic is ready for output
+       outValid        : out std_logic;                                --! The data output is available
+       outData         : out std_logic_vector(DataWidth-1 downto 0)    --! The output data
 );
 end component;
 
@@ -699,14 +701,14 @@ begin
                clk             => clk,
                reset           => fifoReset,
 
-               fifoNearFull    => fifoNearFull,
-               fifoInReady     => fifoInReady,
-               fifoInValid     => readValid1,
-               fifoIn          => readData,
+               nearFull        => fifoNearFull,
+               inReady         => fifoInReady,
+               inValid         => readValid1,
+               indata          => readData,
 
-               fifoOutReady    => fifoOutReady,
-               fifoOutValid    => fifoOutValid,
-               fifoOut         => fifoData0
+               outReady        => fifoOutReady,
+               outValid        => fifoOutValid,
+               outdata         => fifoData0
        );
        
        process(clk)