----------------------------------------------------------------------------------
-- Company: IJS 
-- Engineer: Gasper Kojek
-- 
-- Create Date:    10:36:57 03/13/2014 
-- Last edit:      15:35    03/12/2014
-- Design Name: 
-- Module Name:    RX_TX_QUEUE - Behavioral 
-- Project Name: 
-- Target Devices:  Xilinx Virtex 5
-- Tool versions:   Xilinx ISE 14.7
-- Description: 
--
-- Dependencies: 
--
-- Revision: 1.0
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
use IEEE.STD_LOGIC_ARITH.ALL;

entity RX_TX_QUEUE is
port (
    clk                     : in std_logic;
    rst                     : in std_logic;

    -- from received TLP header - RX SIDE connections:
    req_tc_rx               : in std_logic_vector(2 downto 0);  -- Memory Read TC(traffic class field)
    req_td_rx               : in std_logic;                     -- Memory Read TD(TLP digest bit-ECRC)
    req_ep_rx               : in std_logic;                     -- Memory Read EP(poisoned bit)
    req_attr_rx             : in std_logic_vector(1 downto 0);  -- Memory Read Attribute
    req_len_rx              : in std_logic_vector(9 downto 0);  -- Memory Read Length (1DW)
    req_rid_rx              : in std_logic_vector(15 downto 0); -- Memory Read Requestor ID
    req_tag_rx              : in std_logic_vector(7 downto 0);  -- Memory Read Tag
    req_be_rx               : in std_logic_vector(7 downto 0);  -- Memory Read Byte Enables
    req_addr_rx             : in std_logic_vector(12 downto 0); -- Memory Read Address 
    req_compl_addr_err_rx   : in std_logic; -- requested completion with data: address error
    req_compl_with_data_rx  : in std_logic;  -- asserted indicates to generate a completion WITH data
                                              -- otherwise a completion WITHOUT data will be generated
    req_compl_rx            : in std_logic;                                                
    compl_done_rx           : out std_logic;
    rx_queue_full_n           : out std_logic;
    
    
    --  from DMA engine:
    
    --to TX:
    req_tc_tx               : out std_logic_vector(2 downto 0);  -- Memory Read TC(traffic class field)
    req_td_tx               : out std_logic;                     -- Memory Read TD(TLP digest bit-ECRC)
    req_ep_tx               : out std_logic;                     -- Memory Read EP(poisoned bit)
    req_attr_tx             : out std_logic_vector(1 downto 0);  -- Memory Read Attribute
    req_len_tx              : out std_logic_vector(9 downto 0);  -- Memory Read Length (1DW)
    req_rid_tx              : out std_logic_vector(15 downto 0); -- Memory Read Requestor ID
    req_tag_tx              : out std_logic_vector(7 downto 0);  -- Memory Read Tag
    req_be_tx               : out std_logic_vector(7 downto 0);  -- Memory Read Byte Enables
    req_addr_tx             : out std_logic_vector(12 downto 0); -- Memory Read Address 
    req_compl_addr_err_tx   : out std_logic;  -- requested completion with data: address error
    req_compl_with_data_tx  : out std_logic;  -- asserted indicates to generate a completion WITH data
                                              -- otherwise a completion WITHOUT data will be generated
    req_compl_tx            : out std_logic;    
    compl_done_tx           : in std_logic   

);
end RX_TX_QUEUE;

architecture Behavioral of RX_TX_QUEUE is

--RX BRAM 
    type   ram_type is array (15 downto 0) of std_logic_vector (63 downto 0);
    signal rx_RAM    : ram_type;
signal rx_addr1, rx_addr2      : std_logic_vector(3 downto 0):=x"0";
signal rx_out2         : std_logic_vector(63 downto 0);

signal req_out_vec, req_in_vec_rx      : std_logic_vector(63 downto 0):=x"0000000000000000";
--control signals
signal TX_round_robin   : std_logic := '1'; -- 0=last round was RX, 1=last round was DMA
signal RX_queue_cnt     : std_logic_vector(3 downto 0):=x"0"; --how much transactions requested by RX are in queue
signal DMA_queue_cnt    : std_logic_vector(3 downto 0):=x"0";

begin
compl_done_rx <= req_compl_rx;
req_out_vec <= rx_out2 when TX_round_robin='1' or DMA_queue_cnt=x"0" else 
                x"0000000000000000" when rst='1';
req_compl_tx <= '1' when (RX_queue_cnt/=x"0" or DMA_queue_cnt/=x"0") and compl_done_tx='0'  else '0';
rx_queue_full_n<= '0' when RX_queue_cnt=x"F" else '1';

control: process (rst, clk, req_compl_rx, compl_done_tx) 
begin
if rst='1' then
    RX_queue_cnt<=x"0";
    DMA_queue_cnt<=x"0";
    rx_addr1<=x"0";
    rx_addr2<=x"0";
    TX_round_robin<='1';
elsif rising_edge(clk) then
-- else
    if (req_compl_rx = '1') then
        rx_RAM(conv_integer(rx_addr1)) <= req_in_vec_rx;
    end if;
    rx_out2<=rx_RAM(conv_integer(rx_addr2));
    
    if req_compl_rx='1' then --requested completion from RX engine
        if rx_addr1=x"F" then
            rx_addr1<=x"0";
        else
            rx_addr1<=rx_addr1+1;
        end if;
        if compl_done_tx='0' and (TX_round_robin='0' or DMA_queue_cnt=x"0") then --FIXME - round robin!!
            RX_queue_cnt<=RX_queue_cnt+1;
        end if;
    end if;
    
    if compl_done_tx='1' then --request completed - from TX engine
        TX_round_robin <= not TX_round_robin;
        if TX_round_robin='0' or DMA_queue_cnt=x"0" then --completed RX request
            if rx_addr2=x"F" then
                rx_addr2<=x"0";
            else
                rx_addr2<=rx_addr2+1;
            end if;
            if req_compl_rx='0' then RX_queue_cnt<=RX_queue_cnt-1; end if;
        -- elsif TX_round_robin='1' or RX_queue_cnt=x"0" then
        end if;    
    end if;

end if;
end process;

--vector connections:
req_in_vec_rx <= req_tc_rx & req_td_rx & req_ep_rx & req_attr_rx & req_len_rx & req_rid_rx &
                req_tag_rx & req_be_rx & req_addr_rx & req_compl_addr_err_rx & req_compl_with_data_rx;
                
req_tc_tx <= req_out_vec (63 downto 61);
req_td_tx <= req_out_vec (60);
req_ep_tx <= req_out_vec (59);
req_attr_tx <= req_out_vec (58 downto 57);
req_len_tx <= req_out_vec (56 downto 47);
req_rid_tx <= req_out_vec (46 downto 31); 
req_tag_tx <= req_out_vec (30 downto 23);
req_be_tx <= req_out_vec (22 downto 15);
req_addr_tx <= req_out_vec (14 downto 2);
req_compl_addr_err_tx <= req_out_vec (1);
req_compl_with_data_tx <= req_out_vec (0);  
              
end Behavioral;

