1 -- Synchronous FIFO with a protocol similar to AXI
3 -- The outputs are generated combinationally from the inputs
4 -- in order to allow for back-to-back transfers with the type
5 -- of flow control used by busses lite AXI, pipelined WB or
6 -- LiteDRAM native port when the FIFO is full.
8 -- That means that care needs to be taken by the user not to
9 -- generate the inputs combinationally from the outputs otherwise
10 -- it would create a logic loop.
12 -- If breaking that loop is required, a stash buffer could be
13 -- added to break the flow control "loop" between the read and
17 use ieee.std_logic_1164.all;
24 -- Fifo depth in entries
25 DEPTH : natural := 64;
28 WIDTH : natural := 32;
30 -- When INIT_ZERO is set, the memory is pre-initialized to 0's
31 INIT_ZERO : boolean := false
36 reset : in std_ulogic;
39 wr_ready : out std_ulogic;
40 wr_valid : in std_ulogic;
41 wr_data : in std_ulogic_vector(WIDTH - 1 downto 0);
44 rd_ready : in std_ulogic;
45 rd_valid : out std_ulogic;
46 rd_data : out std_ulogic_vector(WIDTH - 1 downto 0)
50 architecture behaviour of sync_fifo is
52 subtype data_t is std_ulogic_vector(WIDTH - 1 downto 0);
53 type memory_t is array(0 to DEPTH - 1) of data_t;
55 function init_mem return memory_t is
56 variable m : memory_t;
59 for i in 0 to DEPTH - 1 loop
60 m(i) := (others => '0');
66 signal memory : memory_t := init_mem;
68 subtype index_t is integer range 0 to DEPTH - 1;
69 signal rd_idx : index_t;
70 signal rd_next : index_t;
71 signal wr_idx : index_t;
72 signal wr_next : index_t;
74 function next_index(idx : index_t) return index_t is
78 r := (idx + 1) mod DEPTH;
88 type op_t is (OP_POP, OP_PUSH);
89 signal op_prev : op_t := OP_POP;
90 signal op_next : op_t;
92 signal full, empty : std_ulogic;
93 signal push, pop : std_ulogic;
96 -- Current state at last clock edge
97 empty <= '1' when rd_idx = wr_idx and op_prev = OP_POP else '0';
98 full <= '1' when rd_idx = wr_idx and op_prev = OP_PUSH else '0';
100 -- We can accept new data if we aren't full or we are but
101 -- the read port is going to accept data this cycle
102 wr_ready <= rd_ready or not full;
104 -- We can provide data if we aren't empty or we are but
105 -- the write port is going to provide data this cycle
106 rd_valid <= wr_valid or not empty;
108 -- Internal control signals
109 push <= wr_ready and wr_valid;
110 pop <= rd_ready and rd_valid;
113 rd_next <= next_index(rd_idx) when pop = '1' else rd_idx;
114 wr_next <= next_index(wr_idx) when push = '1' else wr_idx;
115 with push & pop select op_next <=
121 rd_data <= memory(rd_idx) when empty = '0' else wr_data;
126 if rising_edge(clk) then
135 -- Write counter and memory write
136 producer: process(clk)
138 if rising_edge(clk) then
145 memory(wr_idx) <= wr_data;
151 -- Previous op latch used for generating empty/full
154 if rising_edge(clk) then
163 end architecture behaviour;