--_________________________________________________________________________________________________
--                                                                                                |
--                                         |The nanoFIP|                                          |
--                                                                                                |
--                                         CERN,BE/CO-HT                                          |
--________________________________________________________________________________________________|

---------------------------------------------------------------------------------------------------
--                                                                                                |
--                                         masterfip_tx                                           |
--                                                                                                |
---------------------------------------------------------------------------------------------------
-- File         masterfip_tx.vhd                                                                  |
--                                                                                                |
-- Description  The unit groups the main actions that regard FIELDRIVE data transmission.         |
--              It instantiates the units/processes:                                              |
--                                                                                                |
--              o wf_tx_serializer: that receives bytes from the processor (Mock Turtle for       |
--                                  example) trough the tx_frame structure, encodes them          |
--                                  (Manchester 2), adds the FSS, FCS, FES fields and puts one by |
--                                  one bits to the FIELDRIVE output FD_TXD following the         |
--                                  synchronization signals from the wf_tx_osc unit.              |
--                                  Also generates the output FD_TXENA.                           |
--                                                                                                |
--              o wf_tx_osc       : that generates the output FD_TXCK and the array of pulses     |
--                                  tx_sched_p_buff, used for the synchronization of the          |
--                                  wf_tx_serializer's actions.                                   |
--                                                                                                |
--              o data_retrieval  : that copies the bytes provided by the processor upon the      |
--                                  activation of the signal tx_start.                            |
--                                                                                                |
--                                                      Mock Turtle                               |
--                      ___________________________________________________________               |
--                     |                       _______________________________     |              |
--                     |                      |                               |    |              |
--                     |                      |        data_retrieval         |    |              |
--                     |                      |_______________________________|    |              |
--                     |                            \/              \/             |              |
--                     |                         _________    _______________      |              |
--                     |                        |         |  |               |     |              |
--                     |                        | bytes_c |  |  select_byte  |     |              |
--                     |                        |_________|  |_______________|     |              |
--                     |                                            \/             |              |
--                     |   _____________      __________________________________   |              |
--                     |  |             |    |                                  |  |              |
--                     |  |  wf_tx_osc  |  > |          wf_tx_serializer        |  |              |
--                     |  |             |    |                                  |  |              |
--                     |  |_____________|    |__________________________________|  |              |
--                     |___________________________________________________________|              |
--                                                  \/                                            |
--                  ___________________________________________________________________           |
--                0_____________________________FIELDBUS______________________________O           |
--                                                                                                |
--                                                                                                |
-- Authors      Evangelia Gousiou     (Evangelia.Gousiou@cern.ch)                                 |
-- Date         30/09/2015                                                                        |
-- Version      v0.01                                                                             |
--                                                                                                |
----------------                                                                                  |
-- Last changes                                                                                   |
--     09/2015  v0.01  EG  First version                                                          |
---------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------
--                               GNU LESSER GENERAL PUBLIC LICENSE                                |
--                              ------------------------------------                              |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either     |
-- version 2.1 of the License, or (at your option) any later version.                             |
-- This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;       |
-- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.      |
-- See the GNU Lesser General Public License for more details.                                    |
-- You should have received a copy of the GNU Lesser General Public License along with this       |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html                     |
---------------------------------------------------------------------------------------------------



--=================================================================================================
--                                      Libraries & Packages
--=================================================================================================

-- Standard library
library IEEE;
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all;    -- conversion functions
-- Specific library
library work;
use work.masterFIP_pkg.all;  -- definitions of types, constants, entities
use work.wf_package.all;


--=================================================================================================
--                           Entity declaration for masterfip_tx
--=================================================================================================

entity masterfip_tx is port(
  -- INPUTS
   clk_i            : in std_logic;                     -- 100 MHz clock

   rst_i            : in std_logic;                     -- core rst, synched with clk_i

   speed_i          : in std_logic_vector(1 downto 0);  -- WorldFIP bit rate
   
   tx_frame_i       : in tx_frame_t;                    -- frame DATA bytes
                                                        -- structure with 66 words of 32-bit each
                                                        -- this represents the max length of a frame
                                                        -- upon tx_start_p_i only tx_bytes_num_i are read and transmitted

   tx_bytes_num_i   : in std_logic_vector(15 downto 0);  -- number of bytes to be serialized

   tx_ctrl_byte_i   : in std_logic_vector(7 downto 0);  -- frame CTRL byte

   tx_start_p_i     : in std_logic;                     -- indication for the start of the serialization

   
  -- OUTPUTS
   tx_byte_index_o  : out std_logic_vector(15 downto 0); -- index of the byte currently being serialized (0-262)

   tx_end_p_o       : out std_logic;                    -- pulse upon termination of a transmission (CRC & FES included)

   tx_data_o        : out std_logic;                    -- FIELDRIVE transmitter data

   tx_enable_o      : out std_logic;                    -- FIELDRIVE transmitter enable

   tx_clk_o         : out std_logic);                   -- FIELDRIVE transmitter line driver half bit clock

end entity masterfip_tx;


--=================================================================================================
--                                    architecture declaration
--=================================================================================================
architecture struc of masterfip_tx is

  -- frame bytes
  signal prod_bytes_c                         : unsigned(15 downto 0);
  signal ctrl_byte, tx_byte                   : std_logic_vector(7 downto 0);
  signal prod_frame                           : tx_frame_t;
  signal word32_num                           : integer range 0 to 66;
  signal word32                               : std_logic_vector(31 downto 0);
  -- bytes counter
  signal bytes_num                            : std_logic_vector(15 downto 0);
  signal prod_data_lgth_match                 : std_logic;
  signal last_data_byte_p, last_data_byte_p_d : std_logic;
  -- wf_tx_osc
  signal s_tx_clk_p_buff                      : std_logic_vector(c_TX_SCHED_BUFF_LGTH-1 downto 0);
  signal s_tx_osc_rst_p                       : std_logic;
  -- other signals
  signal byte_request_accept_p                : std_logic;
  signal byte_request_accept_p_d1             : std_logic;
  signal byte_request_accept_p_d2             : std_logic;
  signal tx_byte_request_p                    : std_logic;
  signal last_data_byte_p_tmp                 : std_logic;
  signal byte_request_accept_p_tmp            : std_logic;

--=================================================================================================
--                                       architecture begin
--=================================================================================================
begin

---------------------------------------------------------------------------------------------------
--                                    Copy of the frame data                                     --
---------------------------------------------------------------------------------------------------
-- Retrieval of the data bytes upon the tx_start_p_i.
-- All the frame bytes are copied to local registers; like this the frame data remain stable
-- until the next tx_start_p_i arrives.

  data_retrieval: process (clk_i)
  begin
    if rising_edge (clk_i) then
      if rst_i = '1' then
        prod_frame <= ((others => (others=>'0')));
        ctrl_byte  <= (others=>'0');
        bytes_num  <= (others=>'0');
      else
        if tx_start_p_i = '1' then
          prod_frame <= tx_frame_i;     -- copying of the data bytes
          ctrl_byte  <= tx_ctrl_byte_i; -- copying of the ctrl byte
          bytes_num  <= tx_bytes_num_i; -- num of bytes to serialize from the prod_frame
        end if;
		end if;
    end if;
  end process;

  
---------------------------------------------------------------------------------------------------
--                                Mux to select the right byte                                   --
---------------------------------------------------------------------------------------------------  
-- The process retrieves sequentially one by one the byte to be sent to the serializer.
  select_byte: process (clk_i)
  begin
    if rising_edge (clk_i) then
      if rst_i = '1' then
        word32_num   <= 0;
      else
        if prod_bytes_c mod 4 = 0 and tx_byte_request_p = '1' and prod_bytes_c > 0 then
          word32_num <= word32_num + 1;
        end if;
      end if;
    end if;
  end process;  

--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --
-- Instantiation of a wf_incr_counter for the counting of the number of the bytes that are
-- being serialized.
  cmp_tx_bytes_cnt: wf_incr_counter
  generic map(g_counter_lgth => 16)
  port map(
    uclk_i            => clk_i,
    counter_reinit_i  => tx_start_p_i,
    counter_incr_i    => tx_byte_request_p,
    counter_is_full_o => open,
    -------------------------------------------------------
    counter_o         => prod_bytes_c);
    -------------------------------------------------------
  tx_byte_index_o     <= std_logic_vector(prod_bytes_c);

--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --
  word32  <= prod_frame(word32_num);
  tx_byte <= ctrl_byte           when prod_bytes_c = "00000000" else
            word32(7 downto 0)   when prod_bytes_c mod 4 = 1    else 
            word32(15 downto 8)  when prod_bytes_c mod 4 = 2    else
            word32(23 downto 16) when prod_bytes_c mod 4 = 3    else
            word32(31 downto 24);


---------------------------------------------------------------------------------------------------
--                             Serializer as in the nanoFIP project                              --
---------------------------------------------------------------------------------------------------

  cmp_tx_serializer: wf_tx_serializer
  port map(
    uclk_i                  => clk_i,
    nfip_rst_i              => rst_i,
    byte_i                  => tx_byte,
    tx_start_p_i            => tx_start_p_i,
    byte_request_accept_p_i => byte_request_accept_p,
    last_byte_p_i           => last_data_byte_p,
    tx_sched_p_buff_i       => s_tx_clk_p_buff,
   -----------------------------------------------
    tx_byte_request_p_o     => tx_byte_request_p,
    tx_completed_p_o        => tx_end_p_o,
    tx_data_o               => tx_data_o,
    tx_osc_rst_p_o          => s_tx_osc_rst_p,
    tx_enable_o             => tx_enable_o);
   -----------------------------------------------

--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --
   cmp_tx_osc: wf_tx_osc
  port map(
    uclk_i                  => clk_i,
    rate_i                  => speed_i,
    nfip_rst_i              => rst_i,
    tx_osc_rst_p_i          => s_tx_osc_rst_p,
   -----------------------------------------------
    tx_clk_o                => tx_clk_o,
    tx_sched_p_buff_o       => s_tx_clk_p_buff);
   -----------------------------------------------

   
---------------------------------------------------------------------------------------------------
--                                         Other signals                                         --
---------------------------------------------------------------------------------------------------  

  -- when s_prod_data_lgth bytes have been counted,the signal prod_data_lgth_match is activated
  prod_data_lgth_match <= '1' when prod_bytes_c = unsigned(bytes_num) else '0';

--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --
  synch_signals: process (clk_i)
  begin
    if rising_edge (clk_i) then
      if rst_i = '1' then
        last_data_byte_p         <= '0'; -- indication of the last data byte (CRC, FES not included)
        last_data_byte_p_d       <= '0';
        byte_request_accept_p_d1 <= '0';
        byte_request_accept_p_d2 <= '0';

      else
        last_data_byte_p_d       <= last_data_byte_p_tmp;
        last_data_byte_p         <= last_data_byte_p_d;
        byte_request_accept_p_d1 <= byte_request_accept_p_tmp;
        byte_request_accept_p_d2 <= byte_request_accept_p_d1;
      end if;
    end if;
  end process;
  --  --  --  --  --  --  --  --  --  --  --
  byte_request_accept_p_tmp <= tx_byte_request_p or tx_start_p_i;
  last_data_byte_p_tmp      <= prod_data_lgth_match and tx_byte_request_p;
  byte_request_accept_p     <= byte_request_accept_p_d2; -- response to wf_tx_serializer request for a byte
  
   
end architecture struc;
--=================================================================================================
--                                        architecture end
--=================================================================================================
---------------------------------------------------------------------------------------------------
--                                      E N D   O F   F I L E
---------------------------------------------------------------------------------------------------