-- SPDX-FileCopyrightText: 2016, MEN Mikro Elektronik GmbH
-- SPDX-License-Identifier: CERN-OHL-S-2.0+

--------------------------------------------------------------------------------
-- Title       : Tx Module
-- Project     : 16z091-01
--------------------------------------------------------------------------------
-- File        : tx_module.vhd
-- Author      : Susanne Reinfelder
-- Email       : susanne.reinfelder@men.de
-- Organization: MEN Mikro Elektronik Nuremberg GmbH
-- Created     : 13.12.2010
--------------------------------------------------------------------------------
-- Simulator   : ModelSim PE 6.6a / ModelSim AE 6.5e sp1
-- Synthesis   : 
--------------------------------------------------------------------------------
-- Description : 
-- combines the modules tx_put_data, tx_compl_timeout and tx_ctrl
--------------------------------------------------------------------------------
-- Hierarchy   : 
--    ip_16z091_01
--       rx_module
--          rx_ctrl
--          rx_get_data
--          rx_fifo
--          rx_len_cntr
--       wb_master
--       wb_slave
-- *     tx_module
--          tx_ctrl
--          tx_put_data
--          tx_compl_timeout
--          tx_fifo_data
--          tx_fifo_header
--       error
--          err_fifo
--       init
--       interrupt_core
--       interrupt_wb
--------------------------------------------------------------------------------
--
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity tx_module is
   generic(
      DEVICE_FAMILY        : string  := "unused";
      TX_HEADER_FIFO_DEPTH : natural := 32;                                      -- valid values are: 2^(TX_HEADER_LPM_WIDTHU-1) < TX_HEADER_FIFO_DEPTH <= 2^(TX_HEADER_LPM_WIDTHU) 
      TX_HEADER_LPM_WIDTHU : natural := 5;
      TX_DATA_FIFO_DEPTH   : natural := 1024;                                    -- valid values are: 2^(TX_DATA_LPM_WIDTHU-1) < TX_DATA_FIFO_DEPTH <= 2^(TX_DATA_LPM_WIDTHU) 
      TX_DATA_LPM_WIDTHU   : natural := 10
   );
   port(
      clk                    : in  std_logic;
      rst                    : in  std_logic;
      wb_clk                 : in  std_logic;
      wb_rst                 : in  std_logic;
      clk_500                : in  std_logic;                                    -- 500 Hz clock
      
      -- IP Core
      tx_st_ready0           : in  std_logic;
      tx_fifo_full0          : in  std_logic;
      tx_fifo_empty0         : in  std_logic;
      tx_fifo_rdptr0         : in  std_logic_vector(3 downto 0);
      tx_fifo_wrptr0         : in  std_logic_vector(3 downto 0);
      pme_to_sr              : in  std_logic;
      tx_st_err0             : out std_logic;
      tx_st_valid0           : out std_logic;
      tx_st_sop0             : out std_logic;
      tx_st_eop0             : out std_logic;
      tx_st_data0            : out std_logic_vector(63 downto 0);
      pme_to_cr              : out std_logic;
      
      -- Rx Module
      rx_tag_nbr             : in  std_logic_vector(7 downto 0);
      rx_tag_rcvd            : in  std_logic;
      
      -- Wishbone Master
      tx_fifo_c_data_clr     : in  std_logic;
      tx_fifo_c_head_clr     : in  std_logic;
      tx_fifo_c_head_enable  : in  std_logic;
      tx_fifo_c_data_enable  : in  std_logic;
      tx_fifo_c_head_in      : in  std_logic_vector(31 downto 0);
      tx_fifo_c_data_in      : in  std_logic_vector(31 downto 0);
      tx_fifo_c_head_full    : out std_logic;
      tx_fifo_c_data_full    : out std_logic;
      tx_fifo_c_data_usedw   : out std_logic_vector(9 downto 0);
      
      -- Wishbone Slave
      tx_fifo_wr_head_clr    : in  std_logic;
      tx_fifo_wr_head_enable : in  std_logic;
      tx_fifo_wr_head_in     : in  std_logic_vector(31 downto 0);
      tx_fifo_w_data_clr     : in  std_logic;
      tx_fifo_w_data_enable  : in  std_logic;
      tx_fifo_w_data_in      : in  std_logic_vector(31 downto 0);
      tx_fifo_wr_head_full   : out std_logic;
      tx_fifo_w_data_full    : out std_logic;
      tx_fifo_w_data_usedw   : out std_logic_vector(9 downto 0);
      tx_fifo_wr_head_usedw  : out std_logic_vector(6 downto 0);
      
      -- init
      bus_dev_func           : in  std_logic_vector(15 downto 0);
      max_payload            : in  std_logic_vector(2 downto 0);
      
      -- error
      tx_compl_abort         : out std_logic;
      tx_timeout             : out std_logic
   );
end entity tx_module;

-- ****************************************************************************

architecture tx_module_arch of tx_module is

-- internal signals -----------------------------------------------------------
signal aligned_int         : std_logic;
signal data_len_int        : std_logic_vector(9 downto 0);
signal wr_rd_int           : std_logic;                                          -- 0: write, 1: read
signal posted_int          : std_logic;                                          -- 0: non-posted, 1: posted
signal byte_count_int      : std_logic_vector(11 downto 0);
signal orig_addr_int       : std_logic_vector(31 downto 0);
signal tx_tag_nbr_int      : std_logic_vector(7 downto 0);
signal get_header_int      : std_logic;
signal make_header_int     : std_logic;
signal data_enable_int     : std_logic;
signal start_int           : std_logic;
signal start_tag_nbr_int   : std_logic_vector(4 downto 0);
signal c_wrrd_int          : std_logic;
signal completer_id_int    : std_logic_vector(15 downto 0);
signal own_id_int          : std_logic_vector(15 downto 0);
signal get_next_header_int : std_logic;
signal abort_compl_int     : std_logic;
signal send_len_int        : std_logic_vector(9 downto 0);
signal send_addr_int       : std_logic_vector(31 downto 0);
signal payload_loop_int    : std_logic;
signal first_last_full_int : std_logic_vector(1 downto 0);
signal io_write_int        : std_logic;

-- FIFO:
signal tx_fifo_c_head_empty_int   : std_logic;
signal tx_fifo_c_head_enable_int  : std_logic;
signal tx_fifo_c_head_out_int     : std_logic_vector(63 downto 0);
signal tx_fifo_c_data_empty_int   : std_logic;
signal tx_fifo_c_data_enable_int  : std_logic;
signal tx_fifo_c_data_out_int     : std_logic_vector(63 downto 0);
signal tx_fifo_wr_head_empty_int  : std_logic;
signal tx_fifo_wr_head_enable_int : std_logic;
signal tx_fifo_wr_head_out_int    : std_logic_vector(63 downto 0);
signal tx_fifo_w_data_enable_int  : std_logic;
signal tx_fifo_w_data_empty_int   : std_logic;
signal tx_fifo_w_data_out_int     : std_logic_vector(63 downto 0);

signal tx_wrusedw_c     : std_logic_vector (TX_DATA_LPM_WIDTHU+1 downto 0);
signal tx_wrusedw_w     : std_logic_vector (TX_DATA_LPM_WIDTHU+1 downto 0);

begin
-- instanciate components -----------------------------------------------------
   tx_ctrl_comp : entity work.tx_ctrl
      port map(
         clk               => clk,
         rst               => rst,
         
         -- IP core
         tx_st_ready0      => tx_st_ready0,
         tx_fifo_full0     => tx_fifo_full0,
         tx_fifo_empty0    => tx_fifo_empty0,
         tx_fifo_rdptr0    => tx_fifo_rdptr0,
         tx_fifo_wrptr0    => tx_fifo_wrptr0,
         pme_to_sr         => pme_to_sr,
         tx_st_err0        => tx_st_err0,
         tx_st_valid0      => tx_st_valid0,
         tx_st_sop0        => tx_st_sop0,
         tx_st_eop0        => tx_st_eop0,
         pme_to_cr         => pme_to_cr,
         
         -- FIFO
         tx_c_head_empty   => tx_fifo_c_head_empty_int,
         tx_wr_head_empty  => tx_fifo_wr_head_empty_int,
         tx_c_data_empty   => tx_fifo_c_data_empty_int,
         tx_wr_data_empty  => tx_fifo_w_data_empty_int,
         tx_c_head_enable  => tx_fifo_c_head_enable_int,
         tx_wr_head_enable => tx_fifo_wr_head_enable_int,
         tx_c_data_enable  => tx_fifo_c_data_enable_int,
         tx_wr_data_enable => tx_fifo_w_data_enable_int,
         
         -- tx_put_data
         aligned           => aligned_int,
         data_len          => data_len_int,
         wr_rd             => wr_rd_int,                                         -- 0: write, 1: read
         posted            => posted_int,                                        -- 0: non-posted, 1: posted
         byte_count        => byte_count_int,
         io_write          => io_write_int,
         orig_addr         => orig_addr_int,
         tx_tag_nbr        => tx_tag_nbr_int,
         get_header        => get_header_int,
         get_next_header   => get_next_header_int,
         make_header       => make_header_int,
         data_enable       => data_enable_int,
         c_wrrd            => c_wrrd_int,
         completer_id      => completer_id_int,
         own_id            => own_id_int,
         abort_compl       => abort_compl_int,
         send_len          => send_len_int,
         send_addr         => send_addr_int,
         payload_loop      => payload_loop_int,
         first_last_full   => first_last_full_int,
         
         -- tx_compl_timeout
         start             => start_int,
         start_tag_nbr     => start_tag_nbr_int,
         
         -- error
         compl_abort       => tx_compl_abort,
         
         -- init
         bus_dev_func      => bus_dev_func,
         max_payload       => max_payload
      );

    tx_put_data_comp : entity work.tx_put_data
      port map(
         clk             => clk,
         rst             => rst,
         
         -- IP Core
         tx_st_data0     => tx_st_data0,
         
         -- FIFO
         tx_c_head_out   => tx_fifo_c_head_out_int,
         tx_c_data_out   => tx_fifo_c_data_out_int,
         tx_wr_head_out  => tx_fifo_wr_head_out_int,
         tx_wr_data_out  => tx_fifo_w_data_out_int,
         
         -- tx_ctrl
         data_enable     => data_enable_int,
         tag_nbr         => tx_tag_nbr_int,
         req_id          => own_id_int,
         completer_id    => completer_id_int,
         c_wrrd          => c_wrrd_int,
         get_header      => get_header_int,
         get_next_header => get_next_header_int,
         make_header     => make_header_int,
         abort_compl     => abort_compl_int,
         send_len        => send_len_int,
         send_addr       => send_addr_int,
         payload_loop    => payload_loop_int,
         first_last_full => first_last_full_int,
         data_length     => data_len_int,
         aligned         => aligned_int,
         wr_rd           => wr_rd_int,
         posted          => posted_int,
         byte_count      => byte_count_int,
         io_write        => io_write_int,
         orig_addr       => orig_addr_int
      );

   tx_compl_timeout_comp : entity work.tx_compl_timeout
      generic map(
         CLOCK_TIME   => 8 ns,                                                   -- clock cycle time
         TIMEOUT_TIME => 25
      )
      port map(
         clk         => clk,
         clk_500     => clk_500,
         rst         => rst,
         
         -- tx_ctrl
         tag_nbr_in  => start_tag_nbr_int,
         start       => start_int,
         
         -- RxModule
         rx_tag_nbr  => rx_tag_nbr,
         rx_tag_rcvd => rx_tag_rcvd,
         
         -- error
         timeout     => tx_timeout
      );

   ------------------------------------------------
   tx_c_header_fifo : entity work.generic_dcfifo_mixedw
    generic map (
      g_device_family => DEVICE_FAMILY,
      g_fifo_depth    => TX_HEADER_FIFO_DEPTH,
      g_data_width    => 32,
      g_data_widthu   => TX_HEADER_LPM_WIDTHU+2,
      g_q_width       => 64,
      g_q_widthu      => TX_HEADER_LPM_WIDTHU-1,
      g_showahead     => "OFF")
    port map (
      aclr    => tx_fifo_c_head_clr,
      data    => tx_fifo_c_head_in,
      rdclk   => clk,
      rdreq   => tx_fifo_c_head_enable_int,
      wrclk   => wb_clk,
      wrreq   => tx_fifo_c_head_enable,
      q       => tx_fifo_c_head_out_int,
      rdempty => tx_fifo_c_head_empty_int,
      wrfull  => tx_fifo_c_head_full,
      wrusedw => open);

   tx_wr_header_fifo : entity work.generic_dcfifo_mixedw
    generic map (
      g_device_family => DEVICE_FAMILY,
      g_fifo_depth    => TX_HEADER_FIFO_DEPTH,
      g_data_width    => 32,
      g_data_widthu   => TX_HEADER_LPM_WIDTHU+2,
      g_q_width       => 64,
      g_q_widthu      => TX_HEADER_LPM_WIDTHU-1,
      g_showahead     => "OFF")
    port map (
      aclr    => tx_fifo_wr_head_clr,
      data    => tx_fifo_wr_head_in,
      rdclk   => clk,
      rdreq   => tx_fifo_wr_head_enable_int,
      wrclk   => wb_clk,
      wrreq   => tx_fifo_wr_head_enable,
      q       => tx_fifo_wr_head_out_int,
      rdempty => tx_fifo_wr_head_empty_int,
      wrfull  => tx_fifo_wr_head_full,
      wrusedw => tx_fifo_wr_head_usedw);

   ------------------------------------------------
   tx_c_data_fifo : entity work.generic_dcfifo_mixedw
    generic map (
      g_device_family => DEVICE_FAMILY,
      g_fifo_depth    => TX_DATA_FIFO_DEPTH,
      g_data_width    => 32,
      g_data_widthu   => TX_DATA_LPM_WIDTHU+2,
      g_q_width       => 64,
      g_q_widthu      => TX_DATA_LPM_WIDTHU-1,
      g_showahead     => "OFF")
    port map (
      aclr    => tx_fifo_c_data_clr,
      data    => tx_fifo_c_data_in,
      rdclk   => clk,
      rdreq   => tx_fifo_c_data_enable_int,
      wrclk   => wb_clk,
      wrreq   => tx_fifo_c_data_enable,
      q       => tx_fifo_c_data_out_int,
      rdempty => tx_fifo_c_data_empty_int,
      wrfull  => tx_fifo_c_data_full,
      wrusedw => tx_wrusedw_c);
   
   tx_w_data_fifo : entity work.generic_dcfifo_mixedw
    generic map (
      g_device_family => DEVICE_FAMILY,
      g_fifo_depth    => TX_DATA_FIFO_DEPTH,
      g_data_width    => 32,
      g_data_widthu   => TX_DATA_LPM_WIDTHU+2,
      g_q_width       => 64,
      g_q_widthu      => TX_DATA_LPM_WIDTHU-1,
      g_showahead     => "OFF")
    port map (
      aclr    => tx_fifo_w_data_clr,
      data    => tx_fifo_w_data_in,
      rdclk   => clk,
      rdreq   => tx_fifo_w_data_enable_int,
      wrclk   => wb_clk,
      wrreq   => tx_fifo_w_data_enable,
      q       => tx_fifo_w_data_out_int,
      rdempty => tx_fifo_w_data_empty_int,
      wrfull  => tx_fifo_w_data_full,
      wrusedw => tx_wrusedw_w);
-------------------------------------------------------------------------------
   tx_fifo_c_data_usedw <= "0" & tx_wrusedw_c(8 downto 0);
   tx_fifo_w_data_usedw <= "0" & tx_wrusedw_w(8 downto 0);
-------------------------------------------------------------------------------
end architecture tx_module_arch;
