--- /dev/null
+-- http://hades-wiki.gsi.de/cgi-bin/view/DaqSlowControl/TrbNetFifo
+
+-- taken example from xapp256, but rewritten most of the parts
+-- output fully synchonized with a "look-ahead" logic
+
+
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.std_logic_signed.ALL;
+use IEEE.numeric_std.ALL;
+use work.trb_net_std.all;
+
+
+architecture trb_net16_fifo_arch of trb_net16_fifo is
+
+component shift_lut_x16
+ generic (
+ ADDRESS_WIDTH : integer := 0
+ );
+ port (
+ D : in std_logic;
+ CE : in std_logic;
+ CLK : in std_logic;
+ A : in std_logic_vector (ADDRESS_WIDTH+3 downto 0);
+ Q : out std_logic
+ );
+end component;
+
+signal current_ADDRESS_SRL : std_logic_vector(DEPTH+1 downto 0);
+signal next_ADDRESS_SRL : std_logic_vector(DEPTH+1 downto 0);
+signal real_ADDRESS_SRL : std_logic_vector(DEPTH+1 downto 0);
+signal current_DOUT : std_logic_vector(WIDTH -1 downto 0);
+signal next_DOUT : std_logic_vector(WIDTH -1 downto 0);
+signal next_NUMOUT : std_logic_vector(NUM_WIDTH downto 0);
+signal current_NUMOUT : std_logic_vector(NUM_WIDTH downto 0);
+
+signal current_FULL, next_FULL : std_logic;
+signal current_EMPTY, next_EMPTY : std_logic;
+signal do_shift, do_shift_internal : std_logic;
+
+signal srl_in, srl_out : std_logic_vector(DATA_WDITH + BUS_WIDTH -1 downto 0);
+
+begin
+
+ FULL_OUT <= current_FULL;
+ EMPTY_OUT <= current_EMPTY;
+ do_shift <= do_shift_internal and CLK_EN;
+
+
+-- generate the shift registers
+ srl_in(DATA_WIDTH -1 downto 0) <= DATA_IN;
+ srl_in(DATA_WIDTH + BUS_WIDTH -1 downto DATA_WIDTH) <= PACKET_NUM_IN;
+
+ inst_SRLC256E_MACRO : for i in 0 to (DATA_WIDTH + NUM_WIDTH - 1) generate
+ U1 : shift_lut_x16
+ generic map (
+ ADDRESS_WIDTH => DEPTH - 3
+ )
+ port map (
+ D => srl_in(i),
+ CE => do_shift,
+ CLK => CLK,
+ A => real_ADDRESS_SRL(DEPTH downto 0),
+ Q => srl_out(i));
+ end generate;
+
+ next_DOUT <= srl_out(DATA_WIDTH downto 0);
+ next_NUMOUT <= srl_out(DATA_WIDTH + BUS_WIDTH -1 downto DATA_WIDTH);
+
+ reg_counter: process(CLK)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' then
+ current_ADDRESS_SRL <= (others => '0');
+ elsif CLK_EN = '1' then
+ current_ADDRESS_SRL <= next_ADDRESS_SRL;
+ else
+ current_ADDRESS_SRL <= current_ADDRESS_SRL;
+ end if;
+ end if;
+ end process;
+
+-- adress logic
+ comb_counter: process(WRITE_ENABLE_IN, READ_ENABLE_IN, current_ADDRESS_SRL,
+ current_EMPTY, current_FULL)
+ begin
+-- no activity
+ if WRITE_ENABLE_IN = '0' and READ_ENABLE_IN = '0' then
+ do_shift_internal <= '0';
+ next_ADDRESS_SRL <= current_ADDRESS_SRL;
+ real_ADDRESS_SRL <= current_ADDRESS_SRL - 1;
+-- read from FIFO
+ elsif WRITE_ENABLE_IN = '0' and READ_ENABLE_IN = '1' and current_EMPTY = '0' then
+ do_shift_internal <= '0';
+ next_ADDRESS_SRL <= current_ADDRESS_SRL - 1;
+ real_ADDRESS_SRL <= current_ADDRESS_SRL - 2;
+-- write into FIFO
+ elsif WRITE_ENABLE_IN = '1' and READ_ENABLE_IN = '0' and current_FULL = '0' then
+ do_shift_internal <= '1';
+ next_ADDRESS_SRL <= current_ADDRESS_SRL + 1;
+ real_ADDRESS_SRL <= current_ADDRESS_SRL - 1;
+-- read and write can be done in all cases
+ elsif WRITE_ENABLE_IN = '1' and READ_ENABLE_IN = '1' then
+ do_shift_internal <= '1';
+ next_ADDRESS_SRL <= current_ADDRESS_SRL;
+ real_ADDRESS_SRL <= current_ADDRESS_SRL - 2;
+ else
+ do_shift_internal <= '0';
+ next_ADDRESS_SRL <= current_ADDRESS_SRL;
+ real_ADDRESS_SRL <= current_ADDRESS_SRL - 1;
+ end if;
+ end process;
+
+-- registered read from FIFO
+ reg_output: process(CLK)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' then
+ current_DOUT <= (others => '0');
+ currrent_NUMOUT <= (others => '0');
+ elsif CLK_EN = '1' then
+ if current_EMPTY = '1' or real_ADDRESS_SRL(DEPTH+1) = '1' then
+ current_DOUT <= DATA_IN;
+ current_NUMOUT <= PACKET_NUM_IN
+ else
+ current_DOUT <= next_DOUT;
+ current_DOUT <= next_PACKET_NUM_OUT;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- Comparator Block
+ next_FULL <= next_ADDRESS_SRL(DEPTH+1);
+ -- Empty flag is generated when reading from the last location
+ next_EMPTY <= not or_all(next_ADDRESS_SRL(DEPTH+1 downto 0));
+
+ reg_empty: process(CLK)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' then
+ current_EMPTY <= '1';
+ current_FULL <= '0';
+ elsif CLK_EN = '1' then
+ current_EMPTY <= next_EMPTY;
+ current_FULL <= next_FULL;
+ else
+ current_EMPTY <= current_EMPTY;
+ current_FULL <= current_FULL;
+
+ end if;
+ end if;
+ end process;
+
+ FULL_OUT <= current_FULL;
+ EMPTY_OUT <= current_EMPTY;
+ DATA_OUT <= current_DOUT;
+ PACKET_NUM_OUT <= current_PACKET_NUM_OUT;
+
+
+ -- generate the real depth which is at least 3
+ -- 0 -> 2
+ -- 1 -> 4
+ -- 2 -> 8
+ -- 3 -> 16
+ CHECK_DEPTH1: if DEPTH>=3 generate
+ DEPTH_OUT <= std_logic_vector(to_unsigned(DEPTH,8));
+ end generate CHECK_DEPTH1;
+ CHECK_DEPTH2: if DEPTH<3 generate
+ DEPTH_OUT <= x"03";
+ end generate CHECK_DEPTH2;
+
+end trb_net16_fifo_arch;
\ No newline at end of file