]> jspc29.x-matter.uni-frankfurt.de Git - trb5sc.git/commitdiff
added GBT stuff
authorBenedikt Gutsche <b.gutsche@gsi.de>
Wed, 10 Jan 2024 10:30:46 +0000 (11:30 +0100)
committerBenedikt Gutsche <b.gutsche@gsi.de>
Wed, 10 Jan 2024 10:30:46 +0000 (11:30 +0100)
13 files changed:
vldb/code/GBT-SC/IC/ic_deserializer.vhd [new file with mode: 0644]
vldb/code/GBT-SC/IC/ic_rx.vhd [new file with mode: 0644]
vldb/code/GBT-SC/IC/ic_rx_fifo.vhd [new file with mode: 0644]
vldb/code/GBT-SC/IC/ic_top.vhd [new file with mode: 0644]
vldb/code/GBT-SC/IC/ic_tx.vhd [new file with mode: 0644]
vldb/code/GBT-SC/SCA/sca_deserializer.vhd [new file with mode: 0644]
vldb/code/GBT-SC/SCA/sca_pkg.vhd [new file with mode: 0644]
vldb/code/GBT-SC/SCA/sca_rx.vhd [new file with mode: 0644]
vldb/code/GBT-SC/SCA/sca_rx_fifo.vhd [new file with mode: 0644]
vldb/code/GBT-SC/SCA/sca_top.vhd [new file with mode: 0644]
vldb/code/GBT-SC/SCA/sca_tx.vhd [new file with mode: 0644]
vldb/code/GBT-SC/gbtsc_top.vhd [new file with mode: 0644]
vldb/code/gbt_core.vhd [new file with mode: 0644]

diff --git a/vldb/code/GBT-SC/IC/ic_deserializer.vhd b/vldb/code/GBT-SC/IC/ic_deserializer.vhd
new file mode 100644 (file)
index 0000000..62949f5
--- /dev/null
@@ -0,0 +1,147 @@
+-------------------------------------------------------
+--! @file
+--! @author Julian Mendez <julian.mendez@cern.ch> (CERN - EP-ESE-BE)
+--! @date April, 2017
+--! @version 1.0
+--! @brief IC control - IC Field deserializer/decoder
+-------------------------------------------------------
+
+--! Include the IEEE VHDL standard library
+library ieee;
+--! Use STD_Logic to define vector types
+use ieee.std_logic_1164.all;
+--! Used to convert std_logic_vector to integer and manage fifo pointer
+use ieee.numeric_std.all;
+
+--! @brief IC_Deserializer Entity - IC Field deserializer/decoder
+--! @details 
+--! The IC_Deserializer deserializes the data and removes the zeros
+--! inserted as specified by the HDLC standard (bit stuffing).
+--! Additionally, it detects the delimiter pattern to inform the
+--! core when a new frame is received.
+entity ic_deserializer is
+    generic (
+        g_WORD_SIZE     : integer := 8;                                     --! Size of the words to be stored
+        g_DELIMITER     : std_logic_vector(7 downto 0) := "01111110"        --! Delimiter pattern, defined by the HDLC standard ("01111110")
+    );
+    port (
+        clk_i           : in std_logic;                                     --! Rx clock (Rx_frameclk_o from GBT-FPGA IP): must be a multiple of the LHC frequency
+        rx_clk_en       : in std_logic;                                     --! Rx clock enable signal must be used in case of multi-cycle path(rx_clk_i > LHC frequency). By default: always enabled
+                 
+        reset_i         : in std_logic;                                     --! Reset all of the RX processes
+
+        -- Data
+        data_i          : in  std_logic_vector(1 downto 0);                 --! (RX) Array of bits from the GBT-Frame (bits 83/84) - IC line
+        data_o          : out std_logic_vector((g_WORD_SIZE-1) downto 0);   --! Deserialized/decoded data
+
+        -- Status
+        write_o         : out std_logic;                                    --! Write signal to the FIFO
+        new_word_o      : out std_logic                                     --! New frame received (Delimiter detected)
+    );
+end ic_deserializer;
+
+--! @brief IC_Deserializer Architecture - IC Field deserializer/decoder
+--! @details 
+--! The IC_Deserializer architecture describes the logic required to
+--! deserialize the input and decode the "HDLC" frame. The decoding
+--! consists in removing the '0' inserted every 5 consecutive high level bits
+--! bits and detecting/removing the delimiter packets (SOF/EOF).
+architecture behaviour of ic_deserializer is    
+begin                 --========####   Architecture Body   ####========-- 
+
+    --! @brief Deserializer process: manages the decoding/deserialization
+    --! @details 
+    --! The deserialization is based on a counter, used to control the write_o
+    --! signal (set to '1' when cnter value >= to the word size). The counter
+    --! is reseted when a delimiter is received to synchronize the system and
+    --! incremented when a valid bit is received (not a '0' to be removed).
+    --! Finally, because of the size of the serial frame (2 bits and not only one),
+    --! the logic of the process is duplicated once.
+    --! An on-going signal is used to know wether the delimiter packet received
+    --! is a start or end of frame.
+    deserializer: process(reset_i, clk_i)
+
+        variable reg                : std_logic_vector(g_WORD_SIZE-1 downto 0);
+        variable reg_no_destuffing  : std_logic_vector(g_WORD_SIZE-1 downto 0);
+        variable cnter              : integer range 0 to g_WORD_SIZE;
+        variable ongoing            : std_logic;
+
+    begin
+
+        if reset_i = '1' then
+            cnter                   := 0;
+            reg                     := (others => '0');
+            reg_no_destuffing       := (others => '0');
+            ongoing                 := '0';
+
+        elsif rising_edge(clk_i) then
+                 
+                       if rx_clk_en = '1' then
+                write_o         <= '0';
+                new_word_o        <= '0';
+    
+                -- Data(1)
+                reg(7 downto 0)     := data_i(1) & reg(7 downto 1);
+                reg_no_destuffing   := data_i(1) & reg_no_destuffing(7 downto 1);
+    
+                if reg_no_destuffing(7 downto 1) = "0111110" then
+                    reg(7 downto 0)    := reg(6 downto 0) & '0';
+    
+                elsif ongoing  = '1' then
+                    cnter           := cnter + 1;
+    
+                end if;
+    
+                if reg_no_destuffing = g_DELIMITER then
+                    cnter                       := 0;
+                    ongoing                     := '1';
+                    new_word_o                  <= '1';
+    
+                elsif reg_no_destuffing = x"FF" then
+                    ongoing                     := '0';
+    
+                end if;
+    
+                if cnter >= g_WORD_SIZE and ongoing  = '1' then
+                    cnter                       := 0;
+                    data_o                      <= reg;
+                    write_o                     <= '1';
+                end if;
+    
+                -- Data(0)
+                reg(7 downto 0)        := data_i(0) & reg(7 downto 1);
+                reg_no_destuffing   := data_i(0) & reg_no_destuffing(7 downto 1);
+    
+                if reg_no_destuffing(7 downto 1) = "0111110" then
+                    reg(7 downto 0)    := reg(6 downto 0) & '0';
+    
+                elsif ongoing  = '1' then
+                    cnter           := cnter + 1;
+    
+                end if;
+    
+                if reg_no_destuffing = g_DELIMITER then
+                    cnter                       := 0;
+                    ongoing                     := '1';
+                    new_word_o                  <= '1';
+    
+                elsif reg_no_destuffing = x"FF" then
+                    ongoing                     := '0';
+    
+                end if;
+    
+                if cnter >= g_WORD_SIZE and ongoing  = '1' then
+                    cnter                       := 0;
+                    data_o                      <= reg;
+                    write_o                     <= '1';
+                end if;
+
+                       end if;
+        end if;
+        
+    end process;
+    
+end behaviour;
+--============================================================================--
+--############################################################################--
+--============================================================================--
diff --git a/vldb/code/GBT-SC/IC/ic_rx.vhd b/vldb/code/GBT-SC/IC/ic_rx.vhd
new file mode 100644 (file)
index 0000000..504a37d
--- /dev/null
@@ -0,0 +1,156 @@
+-------------------------------------------------------
+--! @file
+--! @author Julian Mendez <julian.mendez@cern.ch> (CERN - EP-ESE-BE)
+--! @date April, 2017
+--! @version 1.0
+--! @brief IC control - Rx deserialization and decoding
+-------------------------------------------------------
+
+--! Include the IEEE VHDL standard library
+library ieee;
+--! Use STD_Logic to define vector types
+use ieee.std_logic_1164.all;
+--! Used to convert std_logic_vector to integer and manage fifo pointer
+use ieee.numeric_std.all;
+
+--! @brief IC_rx Entity - Rx deserialization and decoding
+--! @details
+--! The IC_rx entity handles the deserialization and decoding
+--! of the received frame on the couple of bits dedicated to
+--! the IC control.
+entity ic_rx is
+    generic (
+        g_FIFO_DEPTH:  integer := 10                            --! Depth of the internal FIFO used to improve the timming performance
+    );
+    port (
+        -- Clock and reset
+        rx_clk_i        : in  std_logic;                        --! Rx clock (Rx_frameclk_o from GBT-FPGA IP): must be a multiple of the LHC frequency
+        rx_clk_en       : in  std_logic;                        --! Rx clock enable signal must be used in case of multi-cycle path(rx_clk_i > LHC frequency). By default: always enabled
+
+        reset_i         : in  std_logic;                        --! Reset all of the RX processes
+
+        -- Status
+        rx_empty_o      : out std_logic;                        --! Rx FIFO is empty (no reply from GBTx)
+
+        -- Internal FIFO
+        rd_clk_i        : in  std_logic;
+        rd_i            : in  std_logic;                        --! Request a read operation of the internal FIFO (GBTx reply)
+        data_o          : out std_logic_vector(7 downto 0);     --! Data from the FIFO
+
+        -- IC lines
+        rx_data_i       : in std_logic_vector(1 downto 0)       --! (RX) Array of bits from the GBT-Frame (bits 83/84) - IC line
+   );
+end ic_rx;
+
+--! @brief IC_rx Architecture - Rx deserialization and decoding
+--! @details
+--! The IC_rx architecture implements the two components used to manage the IC line
+--! in order to decode the data received from the GBTx and store the information into
+--! a FIFO.
+architecture behaviour of ic_rx is
+
+    -- Signals
+    signal byte_des             : std_logic_vector(7 downto 0);     --! Decoded word from deserializer
+    signal wr                   : std_logic;                        --! Write request to saved decoded word into the FIFO (from deserializer)
+
+    -- Components
+    --! IC_deserializer component implements a state machine used to deserialize, decode and inform when a new command is received.
+    component ic_deserializer is
+        generic (
+            g_WORD_SIZE     : integer := 8;
+            g_DELIMITER     : std_logic_vector(7 downto 0) := "01111110"
+        );
+        port (
+            clk_i           : in std_logic;
+            rx_clk_en       : in std_logic;
+
+            reset_i         : in std_logic;
+
+            -- Data
+            data_i          : in  std_logic_vector(1 downto 0);
+            data_o          : out std_logic_vector((g_WORD_SIZE-1) downto 0);
+
+            -- Status
+            write_o         : out std_logic;
+            new_word_o      : out std_logic
+        );
+    end component ic_deserializer;
+
+    --! IC_rx_fifo contains the received data from the GBTx.
+    component ic_rx_fifo is
+        generic (
+            g_FIFO_DEPTH    : integer := 10;                                    --! Depth of the internal FIFO used to improve the timming performance
+            g_WORD_SIZE     : integer := 8                                      --! Size of the words to be stored
+        );
+        port (
+            wr_clk_i        : in  std_logic;                                    --! Rx clock (Rx_frameclk_o from GBT-FPGA IP): must be a multiple of the LHC frequency
+            wr_clk_en_i     : in  std_logic;                                    --! Rx clock enable signal must be used in case of multi-cycle path(rx_clk_i > LHC frequency). By default: always enabled
+            rd_clk_i        : in  std_logic;
+            reset_i         : in  std_logic;                                    --! Reset all of the RX processes
+
+            -- Data
+            data_i          : in  std_logic_vector((g_WORD_SIZE-1) downto 0);   --! Input data (from deserializer)
+            data_o          : out std_logic_vector((g_WORD_SIZE-1) downto 0);   --! Data from the FIFO (read by the user)
+
+            -- Control
+            write_i         : in  std_logic;                                    --! Request a write into the FIFO (from deserializer)
+            read_i          : in  std_logic;                                    --! Request a read (from user)
+
+            --Status
+            rx_empty_o      : out std_logic                                     --! Ready to be read, FIFO is not empty
+        );
+    end component ic_rx_fifo;
+
+begin                 --========####   Architecture Body   ####========--
+
+    -- RX Deserializer
+    --! Instantiation of the deserializer component
+    Deserializer_inst: ic_deserializer
+        generic map(
+            g_WORD_SIZE         => 8
+        )
+        port map(
+            clk_i               => rx_clk_i,
+            rx_clk_en           => rx_clk_en,
+
+            reset_i             => reset_i,
+
+            -- Data
+            data_i              => rx_data_i,
+            data_o              => byte_des,
+
+            -- Status
+            write_o             => wr,
+            new_word_o          => open
+        );
+
+    -- RX Fifo
+    --! Instantiation of the RX FIFO.
+    ic_rx_fifo_inst: ic_rx_fifo
+        generic map(
+            g_WORD_SIZE         => 8,
+            g_FIFO_DEPTH        => g_FIFO_DEPTH
+        )
+        port map(
+            wr_clk_i            => rx_clk_i,
+            wr_clk_en_i         => rx_clk_en,
+            rd_clk_i            => rd_clk_i,
+
+            reset_i             => reset_i,
+
+            -- Data
+            data_i              => byte_des,
+            data_o              => data_o,
+
+            -- Control
+            write_i             => wr,
+            read_i              => rd_i,
+
+            -- Status
+            rx_empty_o          => rx_empty_o
+        );
+
+end behaviour;
+--============================================================================--
+--############################################################################--
+--============================================================================--
\ No newline at end of file
diff --git a/vldb/code/GBT-SC/IC/ic_rx_fifo.vhd b/vldb/code/GBT-SC/IC/ic_rx_fifo.vhd
new file mode 100644 (file)
index 0000000..9b8fc89
--- /dev/null
@@ -0,0 +1,114 @@
+-------------------------------------------------------
+--! @file
+--! @author Julian Mendez <julian.mendez@cern.ch> (CERN - EP-ESE-BE)
+--! @date April, 2017
+--! @version 1.0
+--! @brief IC control - RX FIFO
+-------------------------------------------------------
+
+--! Include the IEEE VHDL standard library
+library ieee;
+--! Use STD_Logic to define vector types
+use ieee.std_logic_1164.all;
+--! Used to convert std_logic_vector to integer and manage fifo pointer
+use ieee.numeric_std.all;
+
+--! @brief IC_rx_fifo Entity - RX FIFO
+--! @details
+--! The IC_rx_fifo is used to store the reply from the GBTx
+--! following a read/write command. It extracts the header
+--! details (GBTx address, number of words, etc.) and provide
+--! a generic fifo interface to get the data.
+-- IEEE VHDL standard library:
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+--============================================================================--
+--############################   Entity   ####################################--
+--============================================================================--
+entity ic_rx_fifo is
+    generic (
+        g_FIFO_DEPTH    : integer := 10;                                    --! Depth of the internal FIFO used to improve the timming performance
+        g_WORD_SIZE     : integer := 8                                      --! Size of the words to be stored
+    );
+    port (
+        wr_clk_i        : in  std_logic;                                    --! Rx clock (Rx_frameclk_o from GBT-FPGA IP): must be a multiple of the LHC frequency
+        wr_clk_en_i     : in  std_logic;                                    --! Rx clock enable signal must be used in case of multi-cycle path(rx_clk_i > LHC frequency). By default: always enabled
+        rd_clk_i        : in  std_logic;
+        reset_i         : in  std_logic;                                    --! Reset all of the RX processes
+
+        -- Data
+        data_i          : in  std_logic_vector((g_WORD_SIZE-1) downto 0);   --! Input data (from deserializer)
+        data_o          : out std_logic_vector((g_WORD_SIZE-1) downto 0);   --! Data from the FIFO (read by the user)
+
+        -- Control
+        write_i         : in  std_logic;                                    --! Request a write into the FIFO (from deserializer)
+        read_i          : in  std_logic;                                    --! Request a read (from user)
+
+        --Status
+        rx_empty_o      : out std_logic                                     --! FIFO is empty
+    );
+end ic_rx_fifo;
+
+
+--! @brief IC_rx_fifo Architecture - RX FIFO
+--! @details
+--! The IC_rx_fifo architecture implements the logic to store the received byte
+--! and extract the header when a new_word_i flag is received.
+architecture behavioral of ic_rx_fifo is
+
+    -- Types
+    subtype reg_t   is std_logic_vector((g_WORD_SIZE-1) downto 0);
+    type ramreg_t   is array(integer range<>) of reg_t;
+    constant zero_ram_s   : std_logic_vector((g_WORD_SIZE-1) downto 0) := (others => '0');
+
+    -- Signals
+    signal mem_arr              : ramreg_t(g_FIFO_DEPTH downto 0);
+
+    signal wr_ptr               : integer range 0 to g_FIFO_DEPTH;
+    signal word_in_mem_size     : integer range 0 to g_FIFO_DEPTH;
+    signal rd_ptr               : integer range 0 to g_FIFO_DEPTH;
+
+begin                 --========####   Architecture Body   ####========--
+
+    ram_proc_rd: process(reset_i, rd_clk_i)
+    begin
+        if reset_i = '1' then
+            rd_ptr              <= 0;
+            rx_empty_o          <= '1';
+
+        elsif rising_edge(rd_clk_i) then
+            if read_i = '1' and rd_ptr < word_in_mem_size then
+                rd_ptr          <= rd_ptr + 1;
+            end if;
+
+            if word_in_mem_size > rd_ptr then
+                rx_empty_o         <= '0';
+            else
+                rx_empty_o         <= '1';
+            end if;
+
+            data_o          <= mem_arr(rd_ptr);
+        end if;
+    end process;
+
+    ram_proc_wr: process(reset_i, wr_clk_i)
+    begin
+        if reset_i = '1' then
+            wr_ptr              <= 0;
+            word_in_mem_size    <= 0;
+            mem_arr             <= (others => zero_ram_s);
+
+        elsif rising_edge(wr_clk_i) then
+            if write_i = '1' and wr_clk_en_i = '1' then
+                mem_arr(wr_ptr) <= data_i;
+                wr_ptr <= wr_ptr + 1;
+                word_in_mem_size  <= word_in_mem_size + 1;
+            end if;
+        end if;
+    end process;
+end architecture;
+--============================================================================--
+--############################################################################--
+--============================================================================--
diff --git a/vldb/code/GBT-SC/IC/ic_top.vhd b/vldb/code/GBT-SC/IC/ic_top.vhd
new file mode 100644 (file)
index 0000000..69d0239
--- /dev/null
@@ -0,0 +1,234 @@
+-------------------------------------------------------
+--! @file
+--! @author Julian Mendez <julian.mendez@cern.ch> (CERN - EP-ESE-BE)
+--! @date April, 2017
+--! @version 1.0
+--! @brief IC control - TOP level
+-------------------------------------------------------
+
+--! Include the IEEE VHDL standard library
+library ieee;
+--! Use STD_Logic to define vector types
+use ieee.std_logic_1164.all;
+
+--! @brief IC_top Entity - TOP Level of the IC component
+--! @details
+--! The IC_top entity handles the communication with the GBTx internal control
+--! module. It generates the 2 bits encoded with an HDLC subset encoding to
+--! read and write the internal register of the ASIC.
+entity ic_top is
+    generic (
+        g_ToLpGBT           : integer range 0 to 1 := 0;
+        g_FIFO_DEPTH        : integer := 20;                        --! Depth of the internal FIFO used to improve the timming performance
+        g_LPGBT_VERS        : std_logic := '1'                      --! Select lpGBT version ('0': 0, '1': 1)
+    );
+    port (
+        -- Clock and reset
+        tx_clk_i            : in  std_logic;                        --! Tx clock (Tx_frameclk_o from GBT-FPGA IP): must be a multiple of the LHC frequency
+        tx_clk_en           : in  std_logic;                        --! Tx clock enable signal must be used in case of multi-cycle path(tx_clk_i > LHC frequency). By default: always enabled
+
+        rx_clk_i            : in  std_logic;                        --! Rx clock (Rx_frameclk_o from GBT-FPGA IP): must be a multiple of the LHC frequency
+        rx_clk_en           : in  std_logic;                        --! Rx clock enable signal must be used in case of multi-cycle path(rx_clk_i > LHC frequency). By default: always enabled
+
+        rx_reset_i          : in  std_logic;                        --! Reset RX datapath
+        tx_reset_i          : in  std_logic;                        --! Reset TX datapath
+
+        -- Configuration
+        tx_GBTx_address_i   : in  std_logic_vector(7 downto 0);     --! I2C address of the GBTx
+        tx_register_addr_i  : in  std_logic_vector(15 downto 0);    --! Address of the first register to be accessed
+        tx_nb_to_be_read_i  : in  std_logic_vector(15 downto 0);    --! Number of words/bytes to be read (only for read transactions)
+
+        parity_err_mask_i   : in std_logic_vector(7 downto 0);
+
+        -- Internal FIFO
+        wr_clk_i            : in std_logic;                         --! Fifo's writing clock
+        tx_wr_i             : in  std_logic;                        --! Request a write operation into the internal FIFO (Data to GBTx)
+        tx_data_to_gbtx_i   : in  std_logic_vector(7 downto 0);     --! Data to be written into the internal FIFO
+
+        rd_clk_i            : in  std_logic;
+        rx_rd_i             : in  std_logic;                        --! Request a read operation of the internal FIFO (GBTx reply)
+        rx_data_from_gbtx_o : out std_logic_vector(7 downto 0);     --! Data from the FIFO
+
+        -- FSM Control
+        tx_start_write_i    : in  std_logic;                        --! Request a write config. to the GBTx
+        tx_start_read_i     : in  std_logic;                        --! Request a read config. to the GBTx
+
+        -- Status
+        tx_ready_o          : out std_logic;                        --! IC core ready for a transaction
+        rx_empty_o          : out std_logic;                        --! Rx FIFO is empty (no reply from GBTx)
+
+        -- IC lines
+        tx_data_o           : out std_logic_vector(1 downto 0);     --! (TX) Array of bits to be mapped to the TX GBT-Frame (bits 83/84)
+        rx_data_i           : in  std_logic_vector(1 downto 0)      --! (RX) Array of bits to be mapped to the RX GBT-Frame (bits 83/84)
+    );
+end ic_top;
+
+--! @brief IC_top architecture - TOP Level of the IC component
+--! @details
+--! Writting and/or reading register to/from the GBTx is made in two steps. To improve the performance
+--! and because the ASIC memory can be accessed by burst, an internal FIFO is implemented to store the
+--! data to be sent or received. Then the access from the outside looks like a FIFO interface with
+--! Read and write signals associated to their data busses. This file implements the TX and RX dedicated
+--! component and only a few logic elements to invert the MSB/LSB order of the IC line (2 bits).
+architecture behaviour of ic_top is
+
+    -- Signals
+    --! Tx line is inverted (MSB/LSB) to get the same order as for the SCA communication line
+    signal data_ic_tx_inv       : std_logic_vector(1 downto 0);
+    --! Tx line is inverted (MSB/LSB) to get the same order as for the SCA communication line
+    signal data_ic_rx_inv       : std_logic_vector(1 downto 0);
+
+    -- Components
+    --! @brief IC_tx Entity - Tx FIFO and encoding/serialization
+    --! @details
+    --! The IC_tx entity control the FIFO used to store the command to be sent
+    --! and perform the HDLC encoding in parallel of the serialization process.
+    component ic_tx
+        generic (
+            g_FIFO_DEPTH        : integer   := 10;
+            g_LPGBT_VERS        : std_logic := '1'
+        );
+        port (
+            -- Clock and reset
+            tx_clk_i            : in std_logic;
+            tx_clk_en           : in std_logic;
+
+            reset_i             : in std_logic;
+
+            -- Status
+            tx_ready_o          : out std_logic;
+
+            -- Configuration
+            GBTx_address_i      : in std_logic_vector(7 downto 0);
+            Register_addr_i     : in std_logic_vector(15 downto 0);
+            nb_to_be_read_i     : in std_logic_vector(15 downto 0);
+
+            parity_err_mask_i   : in std_logic_vector(7 downto 0);
+
+            -- Internal FIFO
+            wr_clk_i            : in std_logic;                         --! Fifo's writing clock
+            wr_i                : in std_logic;
+            data_i              : in std_logic_vector(7 downto 0);
+
+            -- FSM Control
+            start_write         : in std_logic;
+            start_read          : in std_logic;
+
+            -- IC line
+            tx_data_o           : out std_logic_vector(1 downto 0)
+        );
+    end component ic_tx;
+
+    --! @brief IC_rx Entity - Rx deserialization and decoding
+    --! @details
+    --! The IC_rx entity handles the deserialization and decoding
+    --! of the received frame on the couple of bits dedicated to
+    --! the IC control.
+    component ic_rx is
+        generic (
+            g_FIFO_DEPTH:  integer := 10
+        );
+        port (
+            -- Clock and reset
+            rx_clk_i        : in  std_logic;
+            rx_clk_en       : in  std_logic;
+
+            reset_i         : in  std_logic;
+
+            -- Status
+            rx_empty_o      : out std_logic;
+
+            -- Internal FIFO
+            rd_clk_i        : in  std_logic;
+            rd_i            : in  std_logic;
+            data_o          : out std_logic_vector(7 downto 0);
+
+            -- IC lines
+            rx_data_i       : in std_logic_vector(1 downto 0)
+       );
+    end component ic_rx;
+
+    signal ic_rst_rx_s   : std_logic;
+
+begin       --========####   Architecture Body   ####========--
+
+    gbtx_connectivity: if g_ToLpGBT = 0 generate
+        tx_data_o(0)            <= data_ic_tx_inv(1);
+        tx_data_o(1)            <= data_ic_tx_inv(0);
+        data_ic_rx_inv(0)       <= rx_data_i(1);
+        data_ic_rx_inv(1)       <= rx_data_i(0);
+    end generate;
+
+    lpgbt_connectivity: if g_ToLpGBT = 1 generate
+        tx_data_o       <= data_ic_tx_inv;
+        data_ic_rx_inv  <= rx_data_i;
+    end generate;
+
+    -- TX
+    tx_inst: ic_tx
+        generic map (
+            g_FIFO_DEPTH    => g_FIFO_DEPTH,
+            g_LPGBT_VERS    => g_LPGBT_VERS
+        )
+        port map (
+            -- Clock and reset
+            tx_clk_i        => tx_clk_i,
+            tx_clk_en       => tx_clk_en,
+
+            reset_i         => tx_reset_i,
+
+            -- Status
+            tx_ready_o      => tx_ready_o,
+
+            -- Configuration
+            GBTx_address_i  => tx_GBTx_address_i,
+            Register_addr_i => tx_register_addr_i,
+            nb_to_be_read_i => tx_nb_to_be_read_i,
+
+            parity_err_mask_i => parity_err_mask_i,
+
+
+            -- FSM Control
+            start_write     => tx_start_write_i,
+            start_read      => tx_start_read_i,
+
+            -- Internal FIFO
+            wr_clk_i        => wr_clk_i,
+            wr_i            => tx_wr_i,
+            data_i          => tx_data_to_gbtx_i,
+
+            -- IC line
+            tx_data_o       => data_ic_tx_inv
+        );
+
+    -- RX
+
+    ic_rst_rx_s   <= rx_reset_i or tx_start_write_i or tx_start_read_i;
+
+    rx_inst: entity work.ic_rx
+        generic map (
+            g_FIFO_DEPTH    => g_FIFO_DEPTH
+        )
+        port map (
+            -- Clock and reset
+            rx_clk_i        => rx_clk_i,
+            rx_clk_en       => rx_clk_en,
+
+            reset_i         => ic_rst_rx_s,
+
+            -- Status
+            rx_empty_o      => rx_empty_o,
+
+            -- Internal FIFO
+            rd_clk_i        => rd_clk_i,
+            rd_i            => rx_rd_i,
+            data_o          => rx_data_from_gbtx_o,
+
+            -- IC line
+            rx_data_i       => data_ic_rx_inv
+        );
+
+end behaviour;
+--============================================================================--
+--############################################################################--
+--============================================================================--
\ No newline at end of file
diff --git a/vldb/code/GBT-SC/IC/ic_tx.vhd b/vldb/code/GBT-SC/IC/ic_tx.vhd
new file mode 100644 (file)
index 0000000..d90d40d
--- /dev/null
@@ -0,0 +1,1057 @@
+-------------------------------------------------------
+--! @file
+--! @author Julian Mendez <julian.mendez@cern.ch> (CERN - EP-ESE-BE)
+--! @date April, 2017
+--! @version 1.0
+--! @brief IC control - Tx FIFO and encoding/serialization
+-------------------------------------------------------
+
+--! Include the IEEE VHDL standard library
+library ieee;
+--! Use STD_Logic to define vector types
+use ieee.std_logic_1164.all;
+--! Used to convert std_logic_vector to integer and manage fifo pointer
+use ieee.numeric_std.all;
+
+--! Include the work library
+library work;
+
+--! @brief IC_tx Entity - Tx FIFO and encoding/serialization
+--! @details
+--! The IC_tx entity control the FIFO used to store the command to be sent
+--! and perform the HDLC encoding in parallel of the serialization process.
+entity ic_tx is
+    generic (
+        g_FIFO_DEPTH        : integer   := 20;                      --! Depth of the internal FIFO used to improve the timming performance
+        g_LPGBT_VERS        : std_logic := '1'                      --! Select lpGBT version ('0': 0, '1': 1)
+    );
+   port (
+        -- Clock and reset
+        tx_clk_i            : in std_logic;                         --! Tx clock (Tx_frameclk_o from GBT-FPGA IP): must be a multiple of the LHC frequency
+        tx_clk_en           : in std_logic;                         --! Tx clock enable signal must be used in case of multi-cycle path(tx_clk_i > LHC frequency). By default: always enabled
+
+        reset_i             : in std_logic;                         --! Reset all of the TX processes
+
+        -- Status
+        tx_ready_o          : out std_logic;                        --! IC core ready for a transaction
+
+        -- Configuration
+        GBTx_address_i      : in std_logic_vector(7 downto 0);      --! I2C address of the GBTx
+        Register_addr_i     : in std_logic_vector(15 downto 0);     --! Address of the first register to be accessed
+        nb_to_be_read_i     : in std_logic_vector(15 downto 0);     --! Number of words/bytes to be read (only for read transactions)
+
+        parity_err_mask_i   : in std_logic_vector(7 downto 0);
+
+        -- Internal FIFO
+        wr_clk_i            : in std_logic;                         --! Fifo's writing clock
+        wr_i                : in std_logic;                         --! Request a write operation into the internal FIFO (Data to GBTx)
+        data_i              : in std_logic_vector(7 downto 0);      --! Data to be written into the internal FIFO
+
+        -- FSM Control
+        start_read          : in std_logic;                         --! Request a write config. to the GBTx
+        start_write         : in std_logic;                         --! Request a read config. to the GBTx
+
+        -- IC lines
+        tx_data_o           : out std_logic_vector(1 downto 0)      --! (TX) Array of bits to be mapped to the TX GBT-Frame (bits 83/84)
+   );
+end ic_tx;
+
+--! @brief IC_tx architecture - Tx FIFO and encoding/serialization
+--! @details
+--! The IC_tx architecture describes the behavior of the two components used to manage the IC line
+--! in order to send a specific command: write register/burst (consists of a specific header followed by the data)
+--! or read register/burst (consists of a specific header to inform the start register and the number of
+--! byte to be read).
+architecture behaviour of ic_tx is
+
+    -- Types & Subtypes
+    subtype reg2    is std_logic_vector(1 downto 0);           --! Subtype: bus of 2 bits (IC and EC lines)
+    subtype reg8    is std_logic_vector(7 downto 0);           --! Subtype: bus of 8 bits (Bytes)
+    subtype reg16   is std_logic_vector(15 downto 0);          --! Subtype: bus of 16 bits (Used for the CRC computing)
+    subtype reg32   is std_logic_vector(31 downto 0);          --! Subtype: bus of 32 bits (Used for the data)
+
+    type reg8_arr   is array(integer range <>) of reg8;                --! Type: array of bytes
+    type reg16_arr  is array(integer range <>) of reg16;       --! Type: array of 16 bits buses
+    type reg2_arr   is array(integer range <>) of reg2;                --! Type: array of 2 bits buses
+    type reg32_arr  is array(integer range <>) of reg32;       --! Type: array of 32 bits buses
+
+    -- Constant
+    constant DEL_PACKET     : std_logic_vector(7 downto 0)    := "01111110";
+
+    -- Types
+    --! The hdlcstate_t type defines the states available for the hdlcproc process
+    type hdlcstate_t is (s0_waitForStart,
+                            s2_sendSOF,
+                            s3_sendCommand,
+                            s4_sendCRC,
+                            s5_sendEOF);
+
+    -- Signals
+    signal word_cnt         : integer range 0 to g_FIFO_DEPTH;          --! Counter used to count the number of data written into the FIFO (write command)
+    signal word_cnt_v       : std_logic_vector(15 downto 0);            --! Same as word_cnt but with a std_logic_vector type
+    signal wr_ptr           : integer range 6 to (7+g_FIFO_DEPTH);      --! Write pointer to manage the write position into the FIFO (reset value: 7, after the header)
+
+    signal fifo             : reg8_arr(g_FIFO_DEPTH+7 downto 0);        --! FIFO memory: user defined depth + 7 bytes for the command header (GBTx documentation)
+    signal fifo_r           : reg8_arr(g_FIFO_DEPTH+7 downto 0);        --! FIFO memory: user defined depth + 7 bytes for the command header (GBTx documentation)
+
+    signal cmd_len          : integer range 0 to (7+g_FIFO_DEPTH);      --! Save command length in register
+    signal tx_parity        : std_logic_vector(7 downto 0);             --! Tx Data parity (xor between data words)
+    signal parity           : std_logic_vector(7 downto 0);             --! Final parity register (xor between header words and tx_parity signal)
+
+
+    signal hdlc_state       : hdlcstate_t := s0_waitForStart;           --! HDLC encoding FSM state register
+
+
+    signal start_write_s0   : std_logic    := '0';                      --! Register to detect start_write pulse
+    signal start_read_s0    : std_logic    := '0';                      --! Register to detect start_read pulse
+    signal reset_fifo       : std_logic := '0';                         --! Reset synchronization signal between FIFO and HDLC FSM. FIFO is reseted when the command has been fully sent.
+    signal reset_fifo_r     : std_logic := '0';                         --! Reset synchronization signal between FIFO and HDLC FSM. FIFO is reseted when the command has been fully sent.
+
+    signal ongoing_write_s  : std_logic;
+    signal ongoing_read_s   : std_logic;
+    signal ongoing_write_r  : std_logic;
+    signal ongoing_read_r   : std_logic;
+    signal ongoing_write_s0 : std_logic;
+    signal ongoing_read_s0  : std_logic;
+
+    signal start_wr_s0      : std_logic;
+    signal start_rd_s0      : std_logic;
+begin                 --========####   Architecture Body   ####========--
+
+    word_cnt_v <= std_logic_vector(to_unsigned((word_cnt), 16));
+
+    gen_vers1 : if g_LPGBT_VERS = '1' generate
+
+        -- TX Fifo
+        --! The wr_fifo process generate, create the command and store the data
+        --! to be sent. All of the signal are synchronous with the tx_clk_i
+        --! clock and can be managed at full speed (no use of the clk_en signal)
+        wr_fifo: process(wr_clk_i, reset_fifo_r)
+        begin
+            if reset_fifo_r = '1' then
+                ongoing_write_s   <= '0';
+                ongoing_read_s    <= '0';
+                word_cnt          <= 0;
+                wr_ptr            <= 6;
+                cmd_len           <= 6;
+
+                tx_parity         <= (others => '0');
+
+            elsif rising_edge(wr_clk_i) then
+
+                start_wr_s0 <= start_write;
+                start_rd_s0 <= start_read;
+
+                if ongoing_write_s = '1' or ongoing_read_s = '1' then
+                    null; -- Wait for end of transmission
+
+                elsif start_wr_s0 = '0' and start_write = '1' then
+                    fifo(0)          <= GBTx_address_i(6 downto 0) & '0';
+                    fifo(1)          <= "00000000";
+                    fifo(2)          <= (word_cnt_v(7 downto 0));
+                    fifo(3)          <= (word_cnt_v(15 downto 8));
+                    fifo(4)          <= (Register_addr_i(7 downto 0));
+                    fifo(5)          <= (Register_addr_i(15 downto 8));
+                    cmd_len          <= wr_ptr;
+
+                    ongoing_write_s  <= '1';
+
+                elsif start_rd_s0 = '0' and start_read = '1' then
+                    fifo(0)           <= GBTx_address_i(6 downto 0) & '1';
+                    fifo(1)           <= "00000000";
+                    fifo(2)           <= (nb_to_be_read_i(7 downto 0));
+                    fifo(3)           <= (nb_to_be_read_i(15 downto 8));
+                    fifo(4)           <= (Register_addr_i(7 downto 0));
+                    fifo(5)           <= (Register_addr_i(15 downto 8));
+
+                    cmd_len           <= 6;
+
+                    ongoing_read_s    <= '1';
+
+                elsif wr_i = '1' then
+
+                    fifo(wr_ptr)        <= data_i;
+                    tx_parity           <= tx_parity xor data_i;
+                    word_cnt            <= word_cnt + 1;
+                    wr_ptr              <= wr_ptr + 1;
+
+                end if;
+
+            end if;
+
+        end process;
+
+        -- TX Serializer
+        --! The hdlcproc process encodes and serializes the command into the two
+        --! bits of the IC line.
+        --! The process implements the following state machine:
+        --!     * *s0_waitForStart*: Wait for a start_write or start_read instruction and calculate the parity byte
+        --!     * *s2_sendSOF*: Send start of frame delimiter (serialization of the "01111110" byte)
+        --!     * *s3_sendCommand*: Read the FIFO and encode/serialize the data
+        --!     * *s4_sendCRC*: Send the parity byte
+        --!     * *s5_sendEOF*: Send end of frame delimiter (serialization of the "01111110" byte)
+        hdlcproc: process(tx_clk_i, reset_i)
+
+            variable offset_pos         : integer range 0 to 8;
+            variable reg_pos            : integer range 0 to 8+g_FIFO_DEPTH;
+            variable high_lvl_cnter     : integer range 0 to 6;
+
+        begin
+
+            if rising_edge(tx_clk_i) then
+
+                if reset_i = '1' then
+                    offset_pos          := 0;
+                    high_lvl_cnter      := 0;
+
+                    reset_fifo          <= '1';
+                    tx_ready_o          <= '0';
+                    tx_data_o           <= "11";
+
+                    hdlc_state          <= s0_waitForStart;
+                    reg_pos             := 0;
+
+                elsif tx_clk_en = '1' then
+
+                    tx_ready_o <= '0';
+
+                    ongoing_write_s0  <= ongoing_write_r;
+                    ongoing_read_s0   <= ongoing_read_r;
+
+                    case hdlc_state is
+
+                        when s0_waitForStart    =>
+
+                            reset_fifo <= '0';
+
+                            -- Send idle
+                            reg_pos             := 0;
+                            tx_ready_o          <= '1';
+
+                            tx_data_o(1)        <= '1';
+                            tx_data_o(0)        <= '1';
+
+                            -- Check start signal
+                            if ongoing_write_s0 = '0' and ongoing_write_r = '1' then
+
+                                tx_ready_o <= '0';
+
+                            -- Compute the parity word
+                                parity <=
+                                    (
+                                        tx_parity                        xor
+                                        GBTx_address_i(6 downto 0) & '0' xor
+                                        word_cnt_v(7 downto 0)           xor
+                                        word_cnt_v(15 downto 8)          xor
+                                        Register_addr_i(7 downto 0)      xor
+                                        Register_addr_i(15 downto 8)
+                                    ) xor parity_err_mask_i;
+
+                                tx_data_o(1)        <= DEL_PACKET(0);
+                                tx_data_o(0)        <= DEL_PACKET(1);
+                                offset_pos          := 2;
+
+                                hdlc_state <= s2_sendSOF;
+
+                            elsif ongoing_read_s0 = '0' and ongoing_read_r = '1' then
+
+                                tx_ready_o <= '0';
+
+                                -- Compute the parity word
+                                parity <=
+                                    (
+                                        GBTx_address_i(6 downto 0) & '1' xor
+                                        nb_to_be_read_i(7 downto 0)      xor
+                                        nb_to_be_read_i(15 downto 8)     xor
+                                        Register_addr_i(7 downto 0)      xor
+                                        Register_addr_i(15 downto 8)
+                                    ) xor parity_err_mask_i;
+    
+                                tx_data_o(1)        <= DEL_PACKET(0);
+                                tx_data_o(0)        <= DEL_PACKET(1);
+                                offset_pos          := 2;
+
+                                hdlc_state <= s2_sendSOF;
+
+                            end if;
+
+                        when s2_sendSOF         =>
+                            -- Data have been copied into the vector buffer
+                            --      -> The fifo can be reseted
+
+                            -- Send delimiter without bit stuffing
+                            tx_data_o(1)     <= DEL_PACKET(offset_pos);
+                            tx_data_o(0)     <= DEL_PACKET(offset_pos+1);
+
+                            offset_pos      := offset_pos + 2;
+
+                            --make sure that the bit stuffing counter is always zeroed at the beginning of the transaction
+                            high_lvl_cnter  := 0;
+
+                            -- Delimiter has been fully sent?
+                            if offset_pos > 7 then
+                                offset_pos  := 0;
+                                hdlc_state  <= s3_sendCommand;
+                            end if;
+
+                        when s3_sendCommand     =>
+
+
+                            -- Enough data to send 2 bits?
+                            if offset_pos < 7 then
+
+                                -- (MSB) Bit stuffing?
+                                if high_lvl_cnter >= 5 then
+
+                                    tx_data_o(1)        <= '0';
+                                    high_lvl_cnter     := 0;
+
+                                -- (MSB) Send data
+                                else
+
+                                    tx_data_o(1)        <= fifo_r(reg_pos)(offset_pos);
+                                    if fifo_r(reg_pos)(offset_pos) = '1' then
+                                        high_lvl_cnter := high_lvl_cnter + 1;
+                                    else
+                                        high_lvl_cnter := 0;
+                                    end if;
+
+                                    offset_pos         := offset_pos + 1;
+
+                                end if;
+
+                                -- (LSB) Bit stuffing?
+                                if high_lvl_cnter >= 5 then
+
+                                    tx_data_o(0)        <= '0';
+                                    high_lvl_cnter     := 0;
+
+                                -- (LSB) Send data
+                                else
+
+                                    tx_data_o(0)        <= fifo_r(reg_pos)(offset_pos);
+                                    if fifo_r(reg_pos)(offset_pos) = '1' then
+                                        high_lvl_cnter := high_lvl_cnter + 1;
+                                    else
+                                        high_lvl_cnter := 0;
+                                    end if;
+
+                                    offset_pos         := offset_pos + 1;
+
+                                end if;
+
+                                -- End of command?
+                                if offset_pos = 8 then
+
+                                    offset_pos      := 0;
+
+                                    if reg_pos < (cmd_len-1) then
+                                        reg_pos         := reg_pos + 1;
+                                    else
+                                        hdlc_state      <= s4_sendCRC;
+                                    end if;
+
+                                end if;
+
+                            -- 1 bit still have to been sent, then CRC
+                            elsif offset_pos < 8 then
+
+                                -- (MSB) Bit stuffing?
+                                if high_lvl_cnter >= 5 then
+
+                                    tx_data_o(1)     <= '0';
+                                    high_lvl_cnter   := 0;
+
+                                    tx_data_o(0)     <= fifo_r(reg_pos)(7);
+                                    if fifo_r(reg_pos)(offset_pos) = '1' then
+                                        high_lvl_cnter     := high_lvl_cnter + 1;
+                                    else
+                                        high_lvl_cnter     := 0;
+                                    end if;
+
+                                    offset_pos      := 0;
+
+                                    if reg_pos < (cmd_len-1) then
+                                        reg_pos         := reg_pos + 1;
+                                    else
+                                        hdlc_state      <= s4_sendCRC;
+                                    end if;
+
+                                -- (MSB) Send data
+                                else
+
+                                    tx_data_o(1)        <= fifo_r(reg_pos)(7);
+                                    if fifo_r(reg_pos)(offset_pos) = '1' then
+                                        high_lvl_cnter := high_lvl_cnter + 1;
+                                    else
+                                        high_lvl_cnter := 0;
+                                    end if;
+
+                                    -- (LSB) Bit stuffing?
+                                    if high_lvl_cnter >= 5 then
+                                        tx_data_o(0)     <= '0';
+                                        high_lvl_cnter  := 0;
+
+                                        offset_pos      := 0;
+
+                                        if reg_pos < (cmd_len-1) then
+                                            reg_pos         := reg_pos + 1;
+                                        else
+                                            hdlc_state      <= s4_sendCRC;
+                                        end if;
+
+                                    elsif reg_pos < (cmd_len-1) then
+
+                                        reg_pos         := reg_pos + 1;
+
+                                        tx_data_o(0)     <= fifo_r(reg_pos)(0);
+                                        if fifo_r(reg_pos)(0) = '1' then
+                                            high_lvl_cnter := high_lvl_cnter + 1;
+                                        else
+                                            high_lvl_cnter := 0;
+                                        end if;
+
+                                        offset_pos      := 1;
+
+                                    else
+                                        tx_data_o(0)     <= parity(0);
+                                        if parity(0) = '1' then
+                                            high_lvl_cnter := high_lvl_cnter + 1;
+                                        else
+                                            high_lvl_cnter := 0;
+                                        end if;
+
+                                        offset_pos      := 1;
+                                        hdlc_state      <= s4_sendCRC;
+
+                                    end if;
+
+                                end if;
+
+                            end if;
+
+                        when s4_sendCRC             =>
+
+                            -- Enough data to send 2 bits?
+                            if offset_pos < 7 then
+
+                                -- (MSB) Bit stuffing?
+                                if high_lvl_cnter >= 5 then
+
+                                    tx_data_o(1)        <= '0';
+                                    high_lvl_cnter     := 0;
+
+                                -- (MSB) Send data
+                                else
+
+                                    tx_data_o(1)         <= parity(offset_pos);
+                                    if parity(offset_pos) = '1' then
+                                        high_lvl_cnter := high_lvl_cnter + 1;
+                                    else
+                                        high_lvl_cnter := 0;
+                                    end if;
+
+                                    offset_pos          := offset_pos + 1;
+
+                                end if;
+
+                                -- (LSB) Bit stuffing?
+                                if high_lvl_cnter >= 5 then
+
+                                    tx_data_o(0)        <= '0';
+                                    high_lvl_cnter     := 0;
+
+                                -- (LSB) Send data
+                                else
+
+                                    tx_data_o(0)        <= parity(offset_pos);
+                                    if parity(offset_pos) = '1' then
+                                        high_lvl_cnter := high_lvl_cnter + 1;
+                                    else
+                                        high_lvl_cnter := 0;
+                                    end if;
+
+                                    offset_pos      := offset_pos + 1;
+
+                                end if;
+
+                                -- End of command?
+                                if offset_pos = 8 then
+
+                                    offset_pos      := 0;
+                                    reset_fifo      <= '1';
+                                    hdlc_state      <= s5_sendEOF;
+
+                                end if;
+
+                            -- 1 bit still have to been sent, then CRC
+                            elsif offset_pos < 8 then
+
+                                -- (MSB) Bit stuffing?
+                                if high_lvl_cnter >= 5 then
+
+                                    tx_data_o(1)     <= '0';
+                                    high_lvl_cnter   := 0;
+
+                                    tx_data_o(0)     <= parity(offset_pos);
+
+                                    if parity(offset_pos) = '1' then
+                                        high_lvl_cnter     := 1;
+                                    end if;
+
+                                    offset_pos      := 0;
+                                    reset_fifo      <= '1';
+                                    hdlc_state      <= s5_sendEOF;
+
+                                -- (MSB) Send data
+                                else
+
+                                    tx_data_o(1)        <= parity(offset_pos);
+                                    if parity(offset_pos) = '1' then
+                                        high_lvl_cnter := high_lvl_cnter + 1;
+                                    else
+                                        high_lvl_cnter := 0;
+                                    end if;
+
+                                    -- (LSB) Bit stuffing?
+                                    if high_lvl_cnter >= 5 then
+                                        tx_data_o(0)     <= '0';
+
+                                        high_lvl_cnter  := 0;
+                                        offset_pos      := 0;
+                                        reset_fifo      <= '1';
+                                        hdlc_state      <= s5_sendEOF;
+
+                                    else
+
+                                        tx_data_o(0)     <= DEL_PACKET(0);
+                                        offset_pos      := 1;
+                                        reset_fifo      <= '1';
+                                        hdlc_state      <= s5_sendEOF;
+
+                                    end if;
+                                end if;
+
+                            end if;
+
+                        when s5_sendEOF         =>
+
+                            -- (MSB) Send delimiter
+                            tx_data_o(1)            <= DEL_PACKET(offset_pos);
+                            offset_pos              := offset_pos + 1;
+
+                            -- Fully sent?
+                            if offset_pos > 7 then
+
+                                tx_data_o(0)        <= '1';
+                                hdlc_state          <= s0_waitForStart;
+
+                            else
+
+                                -- (LSB) Send delimiter
+                                tx_data_o(0)        <= DEL_PACKET(offset_pos);
+                                offset_pos          := offset_pos + 1;
+
+                                -- Fully sent?
+                                if offset_pos > 7 then
+                                    hdlc_state         <= s0_waitForStart;
+                                end if;
+
+                            end if;
+                    end case;
+
+                           end if;
+
+            end if;
+
+        end process;
+
+    end generate gen_vers1;
+
+    gen_vers0: if g_LPGBT_VERS = '0' generate
+
+        -- TX Fifo
+        --! The wr_fifo process generate, create the command and store the data
+        --! to be sent. All of the signal are synchronous with the tx_clk_i
+        --! clock and can be managed at full speed (no use of the clk_en signal)
+        wr_fifo: process(wr_clk_i, reset_fifo_r)
+        begin
+            if reset_fifo_r = '1' then
+                ongoing_write_s   <= '0';
+                ongoing_read_s    <= '0';
+                word_cnt          <= 0;
+                wr_ptr            <= 7;
+                cmd_len           <= 7;
+                tx_parity         <= (others => '0');
+
+            elsif rising_edge(wr_clk_i) then
+
+                start_wr_s0 <= start_write;
+                start_rd_s0 <= start_read;
+
+                if ongoing_write_s = '1' or ongoing_read_s = '1' then
+                    null; -- Wait for end of transmission
+
+                elsif start_wr_s0 = '0' and start_write = '1' then
+                    fifo(0)          <= GBTx_address_i(6 downto 0) & '0';
+                    fifo(1)          <= GBTx_address_i(6 downto 0) & '0';
+                    fifo(2)          <= "00000000";
+                    fifo(3)          <= (word_cnt_v(7 downto 0));
+                    fifo(4)          <= (word_cnt_v(15 downto 8));
+                    fifo(5)          <= (Register_addr_i(7 downto 0));
+                    fifo(6)          <= (Register_addr_i(15 downto 8));
+                    cmd_len          <= wr_ptr;
+
+                    ongoing_write_s  <= '1';
+
+                elsif start_rd_s0 = '0' and start_read = '1' then
+                    fifo(0)           <= GBTx_address_i(6 downto 0) & '1';
+                    fifo(1)           <= GBTx_address_i(6 downto 0) & '1';
+                    fifo(2)           <= "00000000";
+                    fifo(3)           <= (nb_to_be_read_i(7 downto 0));
+                    fifo(4)           <= (nb_to_be_read_i(15 downto 8));
+                    fifo(5)           <= (Register_addr_i(7 downto 0));
+                    fifo(6)           <= (Register_addr_i(15 downto 8));
+
+                    cmd_len           <= 7;
+
+                    ongoing_read_s    <= '1';
+
+                elsif wr_i = '1' then
+
+                    fifo(wr_ptr)        <= data_i;
+                    tx_parity           <= tx_parity xor data_i;
+                    word_cnt            <= word_cnt + 1;
+                wr_ptr              <= wr_ptr + 1;
+
+                end if;
+
+            end if;
+
+        end process;
+
+        -- TX Serializer
+        --! The hdlcproc process encodes and serializes the command into the two
+        --! bits of the IC line.
+        --! The process implements the following state machine:
+        --!     * *s0_waitForStart*: Wait for a start_write or start_read instruction and calculate the parity byte
+        --!     * *s2_sendSOF*: Send start of frame delimiter (serialization of the "01111110" byte)
+        --!     * *s3_sendCommand*: Read the FIFO and encode/serialize the data
+        --!     * *s4_sendCRC*: Send the parity byte
+        --!     * *s5_sendEOF*: Send end of frame delimiter (serialization of the "01111110" byte)
+        hdlcproc: process(tx_clk_i, reset_i)
+
+            variable offset_pos         : integer range 0 to 8;
+            variable reg_pos            : integer range 0 to 8+g_FIFO_DEPTH;
+            variable high_lvl_cnter     : integer range 0 to 6;
+
+        begin
+
+            if rising_edge(tx_clk_i) then
+
+                if reset_i = '1' then
+                    offset_pos          := 0;
+                    high_lvl_cnter      := 0;
+
+                    reset_fifo          <= '1';
+                    tx_ready_o          <= '0';
+                    tx_data_o           <= "11";
+
+                    hdlc_state          <= s0_waitForStart;
+                    reg_pos             := 0;
+
+                elsif tx_clk_en = '1' then
+
+                    tx_ready_o <= '0';
+
+                    ongoing_write_s0  <= ongoing_write_r;
+                    ongoing_read_s0   <= ongoing_read_r;
+
+                    case hdlc_state is
+
+                        when s0_waitForStart    =>
+
+                            reset_fifo <= '0';
+
+                            -- Send idle
+                            reg_pos             := 0;
+                            tx_ready_o          <= '1';
+
+                            tx_data_o(1)        <= '1';
+                            tx_data_o(0)        <= '1';
+
+                            -- Check start signal
+                            if ongoing_write_s0 = '0' and ongoing_write_r = '1' then
+
+                                tx_ready_o <= '0';
+
+                                -- Compute the parity word
+                                parity <=
+                                    (
+                                        tx_parity                       xor
+                                        word_cnt_v(7 downto 0)          xor
+                                        word_cnt_v(15 downto 8)         xor
+                                        Register_addr_i(7 downto 0)     xor
+                                        Register_addr_i(15 downto 8)
+                                    ) xor parity_err_mask_i;
+
+                                tx_data_o(1)        <= DEL_PACKET(0);
+                                tx_data_o(0)        <= DEL_PACKET(1);
+                                offset_pos          := 2;
+
+                                hdlc_state <= s2_sendSOF;
+
+                            elsif ongoing_read_s0 = '0' and ongoing_read_r = '1' then
+
+                                tx_ready_o <= '0';
+
+                            -- Compute the parity word
+                                parity <=
+                                    (
+                                        GBTx_address_i(6 downto 0) & '1' xor
+                                        nb_to_be_read_i(7 downto 0)      xor
+                                        nb_to_be_read_i(15 downto 8)     xor
+                                        Register_addr_i(7 downto 0)      xor
+                                        Register_addr_i(15 downto 8)
+                                    ) xor parity_err_mask_i;
+
+                                tx_data_o(1)        <= DEL_PACKET(0);
+                                tx_data_o(0)        <= DEL_PACKET(1);
+                                offset_pos          := 2;
+
+                                hdlc_state <= s2_sendSOF;
+
+                            end if;
+
+                        when s2_sendSOF         =>
+                            -- Data have been copied into the vector buffer
+                            --      -> The fifo can be reseted
+
+                            -- Send delimiter without bit stuffing
+                            tx_data_o(1)     <= DEL_PACKET(offset_pos);
+                            tx_data_o(0)     <= DEL_PACKET(offset_pos+1);
+
+                            offset_pos      := offset_pos + 2;
+
+                            --make sure that the bit stuffing counter is always zeroed at the beginning of the transaction
+                            high_lvl_cnter  := 0;
+
+                            -- Delimiter has been fully sent?
+                            if offset_pos > 7 then
+                                offset_pos  := 0;
+                                hdlc_state  <= s3_sendCommand;
+                            end if;
+
+                        when s3_sendCommand     =>
+
+                            -- Enough data to send 2 bits?
+                            if offset_pos < 7 then
+
+                                -- (MSB) Bit stuffing?
+                                if high_lvl_cnter >= 5 then
+
+                                    tx_data_o(1)        <= '0';
+                                    high_lvl_cnter     := 0;
+
+                                -- (MSB) Send data
+                                else
+
+                                    tx_data_o(1)        <= fifo_r(reg_pos)(offset_pos);
+                                    if fifo_r(reg_pos)(offset_pos) = '1' then
+                                        high_lvl_cnter := high_lvl_cnter + 1;
+                                    else
+                                        high_lvl_cnter := 0;
+                                    end if;
+
+                                    offset_pos         := offset_pos + 1;
+
+                                end if;
+
+                                -- (LSB) Bit stuffing?
+                                if high_lvl_cnter >= 5 then
+
+                                    tx_data_o(0)        <= '0';
+                                    high_lvl_cnter     := 0;
+
+                                -- (LSB) Send data
+                                else
+
+                                    tx_data_o(0)        <= fifo_r(reg_pos)(offset_pos);
+                                    if fifo_r(reg_pos)(offset_pos) = '1' then
+                                        high_lvl_cnter := high_lvl_cnter + 1;
+                                    else
+                                        high_lvl_cnter := 0;
+                                    end if;
+
+                                    offset_pos         := offset_pos + 1;
+
+                                end if;
+
+                                -- End of command?
+                                if offset_pos = 8 then
+
+                                    offset_pos      := 0;
+
+                                    if reg_pos < (cmd_len-1) then
+                                        reg_pos         := reg_pos + 1;
+                                    else
+                                        hdlc_state      <= s4_sendCRC;
+                                    end if;
+
+                                end if;
+
+                            -- 1 bit still have to been sent, then CRC
+                            elsif offset_pos < 8 then
+
+                                -- (MSB) Bit stuffing?
+                                if high_lvl_cnter >= 5 then
+
+                                    tx_data_o(1)     <= '0';
+                                    high_lvl_cnter   := 0;
+
+                                    tx_data_o(0)     <= fifo_r(reg_pos)(7);
+                                    if fifo_r(reg_pos)(offset_pos) = '1' then
+                                        high_lvl_cnter     := high_lvl_cnter + 1;
+                                    else
+                                        high_lvl_cnter     := 0;
+                                    end if;
+
+                                    offset_pos      := 0;
+
+                                    if reg_pos < (cmd_len-1) then
+                                        reg_pos         := reg_pos + 1;
+                                    else
+                                        hdlc_state      <= s4_sendCRC;
+                                    end if;
+
+                                -- (MSB) Send data
+                                else
+
+                                    tx_data_o(1)        <= fifo_r(reg_pos)(7);
+                                    if fifo_r(reg_pos)(offset_pos) = '1' then
+                                        high_lvl_cnter := high_lvl_cnter + 1;
+                                    else
+                                        high_lvl_cnter := 0;
+                                    end if;
+
+                                    -- (LSB) Bit stuffing?
+                                    if high_lvl_cnter >= 5 then
+                                        tx_data_o(0)     <= '0';
+                                        high_lvl_cnter  := 0;
+
+                                        offset_pos      := 0;
+
+                                        if reg_pos < (cmd_len-1) then
+                                            reg_pos         := reg_pos + 1;
+                                        else
+                                            hdlc_state      <= s4_sendCRC;
+                                        end if;
+
+                                    elsif reg_pos < (cmd_len-1) then
+
+                                        reg_pos         := reg_pos + 1;
+
+                                        tx_data_o(0)     <= fifo_r(reg_pos)(0);
+                                        if fifo_r(reg_pos)(0) = '1' then
+                                            high_lvl_cnter := high_lvl_cnter + 1;
+                                        else
+                                            high_lvl_cnter := 0;
+                                        end if;
+
+                                        offset_pos      := 1;
+
+                                    else
+                                        tx_data_o(0)     <= parity(0);
+                                        if parity(0) = '1' then
+                                            high_lvl_cnter := high_lvl_cnter + 1;
+                                        else
+                                            high_lvl_cnter := 0;
+                                        end if;
+
+                                        offset_pos      := 1;
+                                        hdlc_state      <= s4_sendCRC;
+
+                                    end if;
+
+                                end if;
+
+                            end if;
+
+                        when s4_sendCRC             =>
+
+                            -- Enough data to send 2 bits?
+                            if offset_pos < 7 then
+
+                                -- (MSB) Bit stuffing?
+                                if high_lvl_cnter >= 5 then
+
+                                    tx_data_o(1)        <= '0';
+                                    high_lvl_cnter     := 0;
+
+                                -- (MSB) Send data
+                                else
+
+                                    tx_data_o(1)         <= parity(offset_pos);
+                                    if parity(offset_pos) = '1' then
+                                        high_lvl_cnter := high_lvl_cnter + 1;
+                                    else
+                                        high_lvl_cnter := 0;
+                                    end if;
+
+                                    offset_pos          := offset_pos + 1;
+
+                                end if;
+
+                                -- (LSB) Bit stuffing?
+                                if high_lvl_cnter >= 5 then
+
+                                    tx_data_o(0)        <= '0';
+                                    high_lvl_cnter     := 0;
+
+                                -- (LSB) Send data
+                                else
+
+                                    tx_data_o(0)        <= parity(offset_pos);
+                                    if parity(offset_pos) = '1' then
+                                        high_lvl_cnter := high_lvl_cnter + 1;
+                                    else
+                                        high_lvl_cnter := 0;
+                                    end if;
+
+                                    offset_pos      := offset_pos + 1;
+
+                                end if;
+
+                                -- End of command?
+                                if offset_pos = 8 then
+
+                                    offset_pos      := 0;
+                                    reset_fifo      <= '1';
+                                    hdlc_state      <= s5_sendEOF;
+
+                                end if;
+
+                            -- 1 bit still have to been sent, then CRC
+                            elsif offset_pos < 8 then
+
+                                -- (MSB) Bit stuffing?
+                                if high_lvl_cnter >= 5 then
+
+                                    tx_data_o(1)     <= '0';
+                                    high_lvl_cnter   := 0;
+
+                                    tx_data_o(0)     <= parity(offset_pos);
+
+                                    if parity(offset_pos) = '1' then
+                                        high_lvl_cnter     := 1;
+                                    end if;
+
+                                    offset_pos      := 0;
+                                    reset_fifo      <= '1';
+                                    hdlc_state      <= s5_sendEOF;
+
+                                -- (MSB) Send data
+                                else
+
+                                    tx_data_o(1)        <= parity(offset_pos);
+                                    if parity(offset_pos) = '1' then
+                                        high_lvl_cnter := high_lvl_cnter + 1;
+                                    else
+                                        high_lvl_cnter := 0;
+                                    end if;
+
+                                    -- (LSB) Bit stuffing?
+                                    if high_lvl_cnter >= 5 then
+                                        tx_data_o(0)     <= '0';
+
+                                        high_lvl_cnter  := 0;
+                                        offset_pos      := 0;
+                                        reset_fifo      <= '1';
+                                        hdlc_state      <= s5_sendEOF;
+
+                                    else
+
+                                        tx_data_o(0)     <= DEL_PACKET(0);
+                                        offset_pos      := 1;
+                                        reset_fifo      <= '1';
+                                        hdlc_state      <= s5_sendEOF;
+
+                                    end if;
+                                end if;
+
+                            end if;
+
+                        when s5_sendEOF         =>
+
+                            -- (MSB) Send delimiter
+                            tx_data_o(1)            <= DEL_PACKET(offset_pos);
+                            offset_pos              := offset_pos + 1;
+
+                            -- Fully sent?
+                            if offset_pos > 7 then
+
+                                tx_data_o(0)        <= '1';
+                                hdlc_state          <= s0_waitForStart;
+
+                            else
+
+                                -- (LSB) Send delimiter
+                                tx_data_o(0)        <= DEL_PACKET(offset_pos);
+                                offset_pos          := offset_pos + 1;
+
+                                -- Fully sent?
+                                if offset_pos > 7 then
+                                    hdlc_state         <= s0_waitForStart;
+                                end if;
+
+                            end if;
+                    end case;
+
+                           end if;
+
+            end if;
+
+        end process;
+
+    end generate gen_vers0;
+
+    -- Clock domain crossing
+    clockDomainCrossing_tofifo: process(wr_clk_i, reset_fifo)
+    begin
+        if reset_fifo = '1' then
+            reset_fifo_r <= '1';
+
+        elsif rising_edge(wr_clk_i) then
+            reset_fifo_r <= '0';
+        end if;
+    end process;
+
+    clockDomainCrossing_tohdlc_rd: process(tx_clk_i, ongoing_read_s)
+    begin
+        if ongoing_read_s = '0' then
+            ongoing_read_r   <= '0';
+        elsif rising_edge(tx_clk_i) then
+            ongoing_read_r   <= '1';
+        end if;
+    end process;
+
+    clockDomainCrossing_tohdlc_wr: process(tx_clk_i, ongoing_write_s)
+    begin
+        if ongoing_write_s = '0' then
+            ongoing_write_r  <= '0';
+        elsif rising_edge(tx_clk_i) then
+            ongoing_write_r  <= '1';
+        end if;
+    end process;
+
+    clockDomainCrossing_tohdlc_fifo: process(tx_clk_i)
+    begin
+        if rising_edge(tx_clk_i) then
+            fifo_r           <= fifo;
+        end if;
+    end process;
+
+end behaviour;
+--============================================================================--
+--############################################################################--
+--============================================================================--
diff --git a/vldb/code/GBT-SC/SCA/sca_deserializer.vhd b/vldb/code/GBT-SC/SCA/sca_deserializer.vhd
new file mode 100644 (file)
index 0000000..0a86ec0
--- /dev/null
@@ -0,0 +1,148 @@
+-------------------------------------------------------
+--! @file
+--! @author Julian Mendez <julian.mendez@cern.ch> (CERN - EP-ESE-BE)
+--! @date April, 2017
+--! @version 1.0
+--! @brief SCA control - EC Field deserializer
+-------------------------------------------------------
+
+--! Include the IEEE VHDL standard library
+library ieee;
+--! Use STD_Logic to define vector types
+use ieee.std_logic_1164.all;
+--! Used to convert std_logic_vector to integer and manage fifo pointer
+use ieee.numeric_std.all;
+
+--! @brief SCA_Deserializer Entity - EC Field deserializer
+--! @details 
+--! The EC_Deserializer deserializes the data and removes the zeros
+--! inserted as specified by the HDLC standard (bit stuffing).
+--! Additionally, it detects the delimiter pattern to inform the
+--! core when a new frame is received.
+entity sca_deserializer is
+    generic (
+        g_WORD_SIZE         : integer := 8;                                     --! Size of the words to be stored into the external FIFO
+        g_DELIMITER         : std_logic_vector(7 downto 0) := "01111110";       --! Delimiter pattern
+        g_IDLE              : std_logic_vector(7 downto 0) := "01111111"        --! IDLE pattern
+    );
+    port (
+        rx_clk_i            : in  std_logic;                                    --! Rx clock (Rx_frameclk_o from GBT-FPGA IP): must be a multiple of the LHC frequency
+        clk_en              : in  std_logic;                                    --! Rx clock enable signal must be used in case of multi-cycle path(rx_clk_i > LHC frequency). By default: always enabled
+                 
+        reset_i             : in  std_logic;                                    --! Reset the deserializer
+
+        -- Data
+        data_i              : in  std_logic_vector(1 downto 0);                 --! (RX) Couple of bits from the GBT-Frame - EC line
+        data_o              : out std_logic_vector((g_WORD_SIZE-1) downto 0);   --! Deserialized/decoded data
+
+        -- Control & status
+        write_o             : out std_logic;                                    --! Write request to the external FIFO
+        delimiter_found_o   : out std_logic                                     --! Delimiter detected flag (new command received)
+    );
+end sca_deserializer;
+
+--! @brief SCA_Deserializer Architecture - SCA Field deserializer
+--! @details 
+--! The SCA_Deserializer architecture describes the logic required to
+--! deserialize the input and decode the "HDLC" frame. The decoding
+--! consists in removing the '0' inserted every 5 consecutive high level bits
+--! bits and detecting/removing the delimiter packets (SOF/EOF).
+architecture behavioral of sca_deserializer is    
+begin                 --========####   Architecture Body   ####========-- 
+
+    --! @brief Deserializer process: manages the decoding/deserialization
+    --! @details 
+    --! The deserialization is based on a counter, used to control the write_o
+    --! signal (set to '1' when cnter value >= to the word size). The counter
+    --! is reseted when a delimiter is received (to synchronize the system) and
+    --! incremented when a valid bit is received (not a '0' to be removed).
+    --! Finally, because of the size of the serial frame (2 bits and not only one),
+    --! the logic of the process is duplicated once.
+    --! An on-going signal is used to know wether the delimiter packet received
+    --! is a start or end of frame.
+    deserializer: process(reset_i, rx_clk_i)
+
+        variable reg                        : std_logic_vector(7 downto 0);    
+        variable reg_no_destuffing          : std_logic_vector(7 downto 0);    
+        variable cnter                      : integer;
+        variable ongoing                    : std_logic;
+        
+    begin
+
+        if rising_edge(rx_clk_i) then
+                 
+                               if reset_i = '1' then
+                                       cnter := 0;
+                                       reg := (others => '0');
+                                       reg_no_destuffing := (others => '0');
+                                       
+                          elsif clk_en = '1' then
+                         
+                                       write_o             <= '0';
+                                       delimiter_found_o    <= '0';
+                                       
+                                       -- Data(MSB)
+                                       reg(7 downto 0)     := data_i(1) & reg(7 downto 1);
+                                       reg_no_destuffing   := data_i(1) & reg_no_destuffing(7 downto 1);
+                                       
+                                       if reg_no_destuffing(7 downto 1) = "0111110" then
+                                                reg(7 downto 0) := reg(6 downto 0) & '0';
+                                                
+                                       elsif ongoing  = '1' then
+                                                cnter           := cnter + 1;
+                                                
+                                       end if;
+                                       
+                                       if reg_no_destuffing = g_DELIMITER then
+                                                cnter               := 0;
+                                                ongoing             := '1';
+                                                delimiter_found_o   <= '1';
+                                                
+                                       elsif reg_no_destuffing = x"FF" or reg_no_destuffing = g_IDLE then
+                                                ongoing             := '0';
+                                                
+                                       end if;
+                                       
+                                       if cnter >= 8 and ongoing  = '1' then
+                                                cnter               := 0;
+                                                data_o              <= reg;
+                                                write_o             <= '1';
+                                       end if;
+                                                                       
+                                       -- Data(LSB)
+                                       reg(7 downto 0)     := data_i(0) & reg(7 downto 1);
+                                       reg_no_destuffing   := data_i(0) & reg_no_destuffing(7 downto 1);
+                                       
+                                       if reg_no_destuffing(7 downto 1) = "0111110" then
+                                                reg(7 downto 0) := reg(6 downto 0) & '0';
+                                                
+                                       elsif ongoing  = '1' then
+                                                cnter           := cnter + 1;
+                                                
+                                       end if;
+                                       
+                                       if reg_no_destuffing = g_DELIMITER then
+                                                cnter               := 0;
+                                                ongoing             := '1';
+                                                delimiter_found_o   <= '1';
+                                                
+                                       elsif reg_no_destuffing = x"FF" or reg_no_destuffing = g_IDLE then
+                                                ongoing             := '0';
+                                                
+                                       end if;
+                                       
+                                       if cnter >= 8 and ongoing  = '1' then
+                                                cnter               := 0;
+                                                data_o              <= reg;
+                                                write_o             <= '1';
+                                       end if;
+                               end if; 
+            
+        end if;
+        
+    end process;
+    
+end behavioral;
+--============================================================================--
+--############################################################################--
+--============================================================================--
diff --git a/vldb/code/GBT-SC/SCA/sca_pkg.vhd b/vldb/code/GBT-SC/SCA/sca_pkg.vhd
new file mode 100644 (file)
index 0000000..68f907a
--- /dev/null
@@ -0,0 +1,111 @@
+-------------------------------------------------------
+--! @file
+--! @author Julian Mendez <julian.mendez@cern.ch> (CERN - EP-ESE-BE)
+--! @date April, 2017
+--! @version 1.0
+--! @brief SCA control - SCA Package (types and CRC func.)
+-------------------------------------------------------
+
+--! Include the IEEE VHDL standard library
+library ieee;
+--! Use STD_Logic to define vector types
+use ieee.std_logic_1164.all;
+
+--! @brief SCA control - SCA Package (types and CRC func.)
+--! @details 
+--! The SCA package defines new types and array required to
+--! handle the communication with the SCA. It defines also
+--! a couple of function needed to compute the HDLC frame
+--! CRC.
+package SCA_PKG is
+
+    -- Types & Subtypes
+    subtype reg2    is std_logic_vector(1 downto 0);           --! Subtype: bus of 2 bits (IC and EC lines)
+    subtype reg8    is std_logic_vector(7 downto 0);           --! Subtype: bus of 8 bits (Bytes)
+    subtype reg16   is std_logic_vector(15 downto 0);          --! Subtype: bus of 16 bits (Used for the CRC computing)
+    subtype reg32   is std_logic_vector(31 downto 0);          --! Subtype: bus of 32 bits (Used for the data)
+
+    type reg8_arr   is array(integer range <>) of reg8;                --! Type: array of bytes
+    type reg16_arr  is array(integer range <>) of reg16;       --! Type: array of 16 bits buses
+    type reg2_arr   is array(integer range <>) of reg2;                --! Type: array of 2 bits buses
+    type reg32_arr  is array(integer range <>) of reg32;       --! Type: array of 32 bits buses
+
+    -- Functions
+       --! Reverse function is used to reverse the CRC before sending it. The standard
+       --! requires to send the 16 bits from the LSB to the MSB.
+    function reverse_v (
+        a: in std_logic_vector)
+    return std_logic_vector;
+
+       --! nextCRC16_D8 function compute the 16 bits CRC, using the new byte to be sent
+       --! and the current CRC value.
+    function nextCRC16_D8 (
+        Data: std_logic_vector(7 downto 0);
+        crc:  std_logic_vector(15 downto 0))
+    return std_logic_vector;
+
+end SCA_PKG;
+
+--! @brief SCA control - SCA Package body (describes func.)
+--! @details 
+--! The SCA package body implements the reverse and nextCRC16_D8
+--! functions available via the SCA_PKG package.
+package body SCA_PKG is
+
+    -- Vector reverse function
+       --! Reverse function is used to reverse the CRC before sending it. The standard
+       --! requires to send the 16 bits from the LSB to the MSB.
+    function reverse_v (
+        a: in std_logic_vector)
+    return std_logic_vector is
+    
+        variable result: std_logic_vector(a'RANGE);
+        alias aa: std_logic_vector(a'REVERSE_RANGE) is a;
+      
+    begin    
+        for i in aa'RANGE loop
+            result(i) := aa(i);
+        end loop;
+      
+        return result;      
+    end;
+    
+    -- CRC16 - 8bits data
+       --! nextCRC16_D8 function compute the 16 bits CRC, using the new byte to be sent
+       --! and the current CRC value.
+    function nextCRC16_D8 (
+        Data: std_logic_vector(7 downto 0);
+        crc:  std_logic_vector(15 downto 0))
+    return std_logic_vector is
+    
+        variable d:      std_logic_vector(7 downto 0);
+        variable c:      std_logic_vector(15 downto 0);
+        variable newcrc: std_logic_vector(15 downto 0);
+        
+    begin
+    
+        d := Data;
+        c := crc;
+        
+        newcrc(0) := d(4) xor d(0) xor c(8) xor c(12);
+        newcrc(1) := d(5) xor d(1) xor c(9) xor c(13);
+        newcrc(2) := d(6) xor d(2) xor c(10) xor c(14);
+        newcrc(3) := d(7) xor d(3) xor c(11) xor c(15);
+        newcrc(4) := d(4) xor c(12);
+        newcrc(5) := d(5) xor d(4) xor d(0) xor c(8) xor c(12) xor c(13);
+        newcrc(6) := d(6) xor d(5) xor d(1) xor c(9) xor c(13) xor c(14);
+        newcrc(7) := d(7) xor d(6) xor d(2) xor c(10) xor c(14) xor c(15);
+        newcrc(8) := d(7) xor d(3) xor c(0) xor c(11) xor c(15);
+        newcrc(9) := d(4) xor c(1) xor c(12);
+        newcrc(10) := d(5) xor c(2) xor c(13);
+        newcrc(11) := d(6) xor c(3) xor c(14);
+        newcrc(12) := d(7) xor d(4) xor d(0) xor c(4) xor c(8) xor c(12) xor c(15);
+        newcrc(13) := d(5) xor d(1) xor c(5) xor c(9) xor c(13);
+        newcrc(14) := d(6) xor d(2) xor c(6) xor c(10) xor c(14);
+        newcrc(15) := d(7) xor d(3) xor c(7) xor c(11) xor c(15);
+        
+        return newcrc;
+        
+    end nextCRC16_D8;
+
+end SCA_PKG;
\ No newline at end of file
diff --git a/vldb/code/GBT-SC/SCA/sca_rx.vhd b/vldb/code/GBT-SC/SCA/sca_rx.vhd
new file mode 100644 (file)
index 0000000..343a812
--- /dev/null
@@ -0,0 +1,203 @@
+-------------------------------------------------------
+--! @file
+--! @author Julian Mendez <julian.mendez@cern.ch> (CERN - EP-ESE-BE)
+--! @date April, 2017
+--! @version 1.0
+--! @brief SCA control - SCA RX (HDLC decoder)
+-------------------------------------------------------
+
+--! Include the IEEE VHDL standard library
+library ieee;
+--! Use STD_Logic to define vector types
+use ieee.std_logic_1164.all;
+--! Used to convert std_logic_vector to integer and manage fifo pointer
+use ieee.numeric_std.all;
+
+--! @brief SCA_rx Entity - SCA RX (HDLC decoder)
+--! @details 
+--! The SCA_rx entity handles the deserialization and decoding
+--! of the received frame on the couple of bits dedicated to
+--! the EC control.
+entity sca_rx is
+    port (
+        -- Clock & reset
+        rx_clk_i        : in std_logic;                         --! Rx clock (Rx_frameclk_o from GBT-FPGA IP): must be a multiple of the LHC frequency
+        clk_en          : in std_logic;                         --! Rx clock enable signal must be used in case of multi-cycle path(rx_clk_i > LHC frequency). By default: always enabled
+                 
+        reset_i         : in std_logic;                         --! Reset RX datapath
+        
+        -- Satus
+        done_o          : out std_logic;                        --! Reply received flag (pulse)
+        crc_err_o       : out std_logic;                        --! CRC Error detected on received frame (not supported yet)
+        
+        -- RX data
+        address_o       : out std_logic_vector(7 downto 0);     --! Reply: address field (According to the SCA manual)
+        control_o       : out std_logic_vector(7 downto 0);     --! Reply: control field (According to the SCA manual)
+        transID_o       : out std_logic_vector(7 downto 0);     --! Reply: transaction ID field (According to the SCA manual)
+        channel_o       : out std_logic_vector(7 downto 0);     --! Reply: channel field (According to the SCA manual)
+        len_o           : out std_logic_vector(7 downto 0);     --! Reply: len field (According to the SCA manual)
+        error_o         : out std_logic_vector(7 downto 0);     --! Reply: error field (According to the SCA manual)
+        data_o          : out std_logic_vector(31 downto 0);    --! Reply: data field (According to the SCA manual)
+        
+        -- IC Line
+        rx_data_i       : in std_logic_vector(1 downto 0)       --! (RX) EC line from the RX GBT-Frame
+    );   
+end sca_rx;
+
+--! @brief SCA_rx Architecture - SCA RX (HDLC decoder)
+--! @details 
+--! The SCA_rx architecture implements the components and logic used to manage the EC line
+--! in order to decode the data received from the SCA and format the command received. The
+--! deserializer synchronize and control a FIFO. The deserialized bytes are saved and
+--! set in output of the FIFO when a delimiter packet is detected (EOF). Finally, a few
+--! logic elements are implemented to format the reply and to connect the data to the reply buses.
+architecture behaviour of sca_rx is
+
+    -- Signals
+    signal byte_from_des_s      : std_logic_vector(7 downto 0);     --! Deserialized word (from deserializer)
+    signal wr_command_s         : std_logic;                        --! Write command to the internal FIFO (from deserializer)
+    signal delimiter_detected_s : std_logic;                        --! Delimiter detected flag (from deserializer), used to generate reply received flag
+
+    signal cmd_v                : std_logic_vector(159 downto 0);   --! parallelized command (from FIFO)
+
+    signal data_word_s2         : std_logic_vector(31 downto 0);    --! Data word from the command when len = 2 bytes
+    signal data_word_s4         : std_logic_vector(31 downto 0);    --! Data word from the command when len = 4 bytes
+    signal len_s                : std_logic_vector(7 downto 0);     --! Computed length of the command (field value from the SCA is wrong)
+    
+    signal fifo_cnt             : std_logic_vector(7 downto 0);     --! Number of word in FIFO (std_logic_vector)
+    signal fifo_cnt_i           : integer range 0 to 15;            --! Number of word in FIFO (integer - used to compute the reply length)
+    signal len_from_fifo        : integer range 0 to 15;            --! Computed data length (number of word in FIFO - 8 bytes of header)  
+    
+    signal rx_received_s        : std_logic;                        --! Reply received flag (from FIFO)
+
+    -- Components
+    --! @brief SCA_Deserializer Entity - EC line deserializer
+    --! @details 
+    --! The SCA_Deserializer entity deserializes the EC line and control the FIFO
+    --! to save the 8bit words.
+    component sca_deserializer is
+        generic (
+            g_WORD_SIZE        : integer := 8;
+            g_DELIMITER        : std_logic_vector(7 downto 0) := "01111110";
+            g_IDLE             : std_logic_vector(7 downto 0) := "01111111"
+        );
+        port (
+            rx_clk_i           : in  std_logic;
+            clk_en             : in  std_logic;
+                 
+            reset_i            : in  std_logic;
+
+            -- Data
+            data_i             : in  std_logic_vector(1 downto 0);
+            data_o             : out std_logic_vector((g_WORD_SIZE-1) downto 0);
+
+            -- Control & status
+            write_o            : out std_logic;        
+            delimiter_found_o  : out std_logic
+        );
+    end component sca_deserializer;
+
+    --! @brief SCA_Rx_FIFO Entity - EC RX FIFO
+    --! @details 
+    --! The SCA_Rx_FIFO entity is used to save the deserialized word before
+    --! formating the command when the frame has been fully received.
+    component sca_rx_fifo is
+        generic (
+            g_DEPTH       : integer := 20;
+            g_SIZE        : integer := 8
+        );
+        port (
+            rx_clk_i      : in std_logic;
+            clk_en        : in  std_logic;
+                 
+            reset_i       : in std_logic;
+            
+            -- Data
+            data_i        : in  std_logic_vector((g_SIZE-1) downto 0);
+            data_o        : out std_logic_vector(((g_SIZE*g_DEPTH)-1) downto 0);
+
+            -- Control
+            new_word_i    : in  std_logic;
+            write_i       : in  std_logic;
+            
+            --Status
+            to_be_read_o  : out std_logic;
+            len_o         : out std_logic_vector(7 downto 0)
+        );
+    end component sca_rx_fifo;
+    
+begin          --========####   Architecture Body   ####========-- 
+
+    sca_deserializer_inst: sca_deserializer
+       port map(
+            rx_clk_i            => rx_clk_i,
+            clk_en              => clk_en,
+                               
+            reset_i             => reset_i,
+            
+            -- Data
+            data_i              => rx_data_i,
+            data_o              => byte_from_des_s,        
+            
+            -- Control & status
+            write_o             => wr_command_s,
+            delimiter_found_o   => delimiter_detected_s
+       );
+
+    sca_rx_fifo_inst: sca_rx_fifo
+       port map(
+            rx_clk_i            => rx_clk_i,
+            clk_en              => clk_en,
+            reset_i             => reset_i,
+            
+            -- Data
+            data_i              => byte_from_des_s,
+            data_o              => cmd_v,
+            
+            -- Control
+            write_i             => wr_command_s,
+            new_word_i          => delimiter_detected_s,
+            
+            -- Status
+            to_be_read_o        => rx_received_s,
+            len_o               => fifo_cnt
+       );
+
+    -- Filters SREJ replies
+    done_o         <= rx_received_s; -- when cmd_v(8) /= '1' else
+                    --'0';
+
+    -- Preparation
+    fifo_cnt_i      <= to_integer(unsigned(fifo_cnt));
+    
+    len_from_fifo   <= fifo_cnt_i - 8 when cmd_v(8) /= '1' and fifo_cnt_i > 8
+                       else 0;
+    
+    len_s           <= std_logic_vector(to_unsigned(len_from_fifo,8));
+    --cmd_v(47 downto 40) when cmd_v(8) /= '1' else
+    --                   x"00";
+
+    data_word_s2    <= cmd_v(63 downto 56) &    -- Dx
+                       cmd_v(55 downto 48) &    -- Dx
+                       x"0000";                 -- LSB (x"0000")
+
+    data_word_s4    <= cmd_v(63 downto 56) &    -- Dx
+                       cmd_v(55 downto 48) &    -- Dx
+                       cmd_v(79 downto 72) &    -- Dx
+                       cmd_v(71 downto 64);     -- Dx
+
+    -- Link the fields to the output
+    address_o       <= cmd_v(7 downto 0);
+    control_o       <= cmd_v(15 downto 8);
+    transID_o       <= cmd_v(23 downto 16) when cmd_v(8) /= '1' else x"00";
+    channel_o       <= cmd_v(31 downto 24) when cmd_v(8) /= '1' else x"00";
+    error_o         <= cmd_v(39 downto 32) when cmd_v(8) /= '1' else x"00";
+    len_o           <= std_logic_vector(to_unsigned(len_from_fifo,8));
+    data_o          <= data_word_s2 when (len_s = x"01" or len_s = x"02") else
+                       data_word_s4 when (len_s = x"03" or len_s = x"04") else
+                       x"00000000";
+
+end behaviour;
+--============================================================================--
+--############################################################################--
+--============================================================================--
\ No newline at end of file
diff --git a/vldb/code/GBT-SC/SCA/sca_rx_fifo.vhd b/vldb/code/GBT-SC/SCA/sca_rx_fifo.vhd
new file mode 100644 (file)
index 0000000..20dc341
--- /dev/null
@@ -0,0 +1,108 @@
+-------------------------------------------------------
+--! @file
+--! @author Julian Mendez <julian.mendez@cern.ch> (CERN - EP-ESE-BE)
+--! @date April, 2017
+--! @version 1.0
+--! @brief SCA Control - SCA RX FIFO
+-------------------------------------------------------
+
+--! Include the IEEE VHDL standard library
+library ieee;
+--! Use STD_Logic to define vector types
+use ieee.std_logic_1164.all;
+--! Used to convert std_logic_vector to integer and manage fifo pointer
+use ieee.numeric_std.all;
+
+--! @brief SCA_rx_fifo Entity - SCA RX FIFO
+--! @details
+--! The SCA_rx_fifo is used to store the deserialized bytes from
+--! the EC line. Then, the bytes are concatenate to provide one 
+--! word command when a delimiter (EOF) is received.
+entity sca_rx_fifo is
+    generic (
+        g_DEPTH         : integer := 20;                                        --! Depth of the FIFO
+        g_SIZE          : integer := 8                                          --! Size of the input vectors
+    );
+    port (
+        rx_clk_i        : in std_logic;                                         --! Rx clock (Rx_frameclk_o from GBT-FPGA IP): must be a multiple of the LHC frequency
+        clk_en          : in std_logic;                                         --! Rx clock enable signal must be used in case of multi-cycle path(rx_clk_i > LHC frequency). By default: always enabled
+                 
+        reset_i         : in std_logic;                                         --! Reset the FIFO
+        
+        -- Data
+        data_i          : in  std_logic_vector((g_SIZE-1) downto 0);            --! Input word (g_DEPTH length)
+        data_o          : out std_logic_vector(((g_SIZE*g_DEPTH)-1) downto 0);  --! Output word (g_DEPTH*g_SIZE length)
+
+        -- Control
+        new_word_i      : in  std_logic;                                        --! Equivalent to a read command. It reset the FIFO and concatanate all of the words of the memory to the data_o output register
+        write_i         : in  std_logic;                                        --! Request a write into the FIFO
+        
+        --Status
+        to_be_read_o    : out std_logic;                                        --! Flag generated when new_word command is received and FIFO len > 0
+        len_o           : out std_logic_vector(7 downto 0)                      --! Number of bytes stored into the FIFO
+    );
+end sca_rx_fifo;
+
+
+--! @brief SCA_rx_fifo Architecture - SCA RX FIFO
+--! @details 
+--! The SCA_rx_fifo architecture implements the logic to save data with a specific
+--! size and concatenate and the memory array to provide a unique word output when
+--! a new_word_i flag is received.
+architecture behaviour of sca_rx_fifo is
+
+    -- Types
+    subtype reg is std_logic_vector((g_SIZE-1) downto 0);
+    type ramreg_t is array(integer range<>) of reg;
+    
+    -- Signals
+    signal mem_arr: ramreg_t(g_DEPTH-1 downto 0);    
+    signal wr_ptr: integer range 0 to g_DEPTH-1;
+    
+begin                 --========####   Architecture Body   ####========-- 
+
+    ram_proc: process(reset_i, rx_clk_i)
+    begin
+
+        if rising_edge(rx_clk_i) then
+                 
+                     if reset_i = '1' then
+                                       wr_ptr                  <= 0;
+                                       data_o                  <= (others => '0');
+                                       
+                                       for i in 0 to g_DEPTH-1 loop
+                                                mem_arr(i)          <= (others => '0');
+                                       end loop;
+                                                
+                          elsif clk_en = '1' then
+
+                                       to_be_read_o            <= '0';
+                                       
+                                       if write_i = '1' then
+                                                mem_arr(wr_ptr)     <= data_i;
+                                                wr_ptr              <= wr_ptr + 1;
+                                       
+                                       elsif new_word_i = '1' and wr_ptr > 0 then
+
+                                                to_be_read_o        <= '1';
+                                                len_o               <= std_logic_vector(to_unsigned(wr_ptr,8));
+                                                wr_ptr              <= 0;
+                                                
+                                                for i in 0 to g_DEPTH-1 loop
+                                                         mem_arr(i)      <= (others => '0');
+                                                end loop;
+                                       
+                                                for i in 1 to g_DEPTH loop
+                                                         data_o(((8*i)-1) downto ((i-1)*8))  <= mem_arr(i-1);
+                                                end loop;
+
+                                       end if;
+                               end if; 
+        end if;
+        
+    end process;
+
+end behaviour;
+--============================================================================--
+--############################################################################--
+--============================================================================--
diff --git a/vldb/code/GBT-SC/SCA/sca_top.vhd b/vldb/code/GBT-SC/SCA/sca_top.vhd
new file mode 100644 (file)
index 0000000..9bb3499
--- /dev/null
@@ -0,0 +1,231 @@
+-------------------------------------------------------
+--! @file
+--! @author Julian Mendez <julian.mendez@cern.ch> (CERN - EP-ESE-BE)
+--! @date April, 2017
+--! @version 1.0
+--! @brief SCA control - SCA top level
+-------------------------------------------------------
+
+--! Include the IEEE VHDL standard library
+library ieee;
+--! Use STD_Logic to define vector types
+use ieee.std_logic_1164.all;
+
+--! Include the work library
+library work;
+--! Use SCA Package to define specific types (vector arrays)
+use work.SCA_PKG.all;
+
+--! @brief SCA_top Entity - SCA top level
+--! @details 
+--! The SCA_top entity handles the communication with the SCA modules. 
+--! It generates the couple of bits encoded with the HDLC standard to
+--! access the internal register of the ASIC.
+entity sca_top is
+    generic (
+        g_SCA_COUNT         : integer := 1                                      --! Number of SCAs to be controlled through the link (up to 41)
+    );
+    port (
+        tx_clk_i            : in  std_logic;                                    --! Tx clock (Tx_frameclk_o from GBT-FPGA IP): must be a multiple of the LHC frequency
+        tx_clk_en           : in  std_logic := '1';                             --! Tx clock enable signal must be used in case of multi-cycle path(tx_clk_i > LHC frequency). By default: always enabled
+                 
+        rx_clk_i            : in  std_logic;                                    --! Rx clock (Rx_frameclk_o from GBT-FPGA IP): must be a multiple of the LHC frequency
+        rx_clk_en           : in  std_logic := '1';                             --! Rx clock enable signal must be used in case of multi-cycle path(rx_clk_i > LHC frequency). By default: always enabled
+                 
+        rx_reset_i          : in  std_logic;                                    --! Reset RX datapath
+        tx_reset_i          : in  std_logic;                                    --! Reset TX datapath
+        
+        enable_i            : in  std_logic_vector((g_SCA_COUNT-1) downto 0);   --! Enable flag, bit position correspond to the SCA ID ('1': enabled / '0': Disabled)
+        start_reset_cmd_i   : in  std_logic;                                    --! Send a reset command to the enabled SCAs
+        start_connect_cmd_i : in  std_logic;                                    --! Send a connect command to the enabled SCAs
+        start_command_i     : in  std_logic;                                    --! Send the command set in input to the enabled SCAs
+        inject_crc_error    : in  std_logic;                                    --! Emulate a CRC error
+        
+        tx_address_i        : in  std_logic_vector(7 downto 0);                 --! Command: address field (According to the SCA manual)
+        tx_transID_i        : in  std_logic_vector(7 downto 0);                 --! Command: transaction ID field (According to the SCA manual)
+        tx_channel_i        : in  std_logic_vector(7 downto 0);                 --! Command: channel field (According to the SCA manual)
+        tx_len_i            : in  std_logic_vector(7 downto 0);                 --! Command: Len field (not used anymore, fixed to 4 bytes)
+        tx_command_i        : in  std_logic_vector(7 downto 0);                 --! Command: command field (According to the SCA manual)
+        tx_data_i           : in  std_logic_vector(31 downto 0);                --! Command: data field (According to the SCA manual)
+
+        rx_received_o       : out std_logic_vector((g_SCA_COUNT-1) downto 0);   --! Reply received flag (pulse), bit position correspond to the SCA ID
+        rx_address_o        : out reg8_arr((g_SCA_COUNT-1) downto 0);           --! Reply: address field (According to the SCA manual)
+        rx_control_o        : out reg8_arr((g_SCA_COUNT-1) downto 0);           --! Reply: control field (According to the SCA manual)
+        rx_transID_o        : out reg8_arr((g_SCA_COUNT-1) downto 0);           --! Reply: transaction ID field (According to the SCA manual)
+        rx_channel_o        : out reg8_arr((g_SCA_COUNT-1) downto 0);           --! Reply: channel field (According to the SCA manual)
+        rx_len_o            : out reg8_arr((g_SCA_COUNT-1) downto 0);           --! Reply: len field (According to the SCA manual)
+        rx_error_o          : out reg8_arr((g_SCA_COUNT-1) downto 0);           --! Reply: error field (According to the SCA manual)
+        rx_data_o           : out reg32_arr((g_SCA_COUNT-1) downto 0);          --! Reply: data field (According to the SCA manual)
+
+        tx_data_o           : out reg2_arr((g_SCA_COUNT-1) downto 0);           --! (TX) Array of 2 bits to be mapped to the TX GBT-Frame
+        rx_data_i           : in  reg2_arr((g_SCA_COUNT-1) downto 0)            --! (RX) Array of 2 bits to be mapped to the RX GBT-Frame
+        
+    );   
+end sca_top;
+
+
+--! @brief SCA control Architecture - SCA top level
+--! @details 
+--! The SCA top level architecture implements the TX and RX modules required
+--! to handle the communication with the ASIC. Because multiple chips can
+--! be controlled through one GBT link (using e-links), the instantiation is
+--! duplicated. As many SCA_tx and SCA_rx components as SCAs ASICs to be 
+--! controlled are instantiated. The SCA_gen instance multiplies the module 
+--! number using a generate for loop.
+architecture behaviour of sca_top is
+
+    -- Signals
+    signal tx_control_s     : reg8_arr((g_SCA_COUNT-1) downto 0);           --! Control field of the HDLC frame is used to acknowledge the command received. Then this field is managed internally, using the received value
+    signal rx_control_s     : reg8_arr((g_SCA_COUNT-1) downto 0);           --! Received control field value
+    
+    signal start_command_s  : std_logic_vector((g_SCA_COUNT-1) downto 0);   --! Used to detect a start_command request with enable = '1' for a specific SCA link
+    signal start_connect_s  : std_logic_vector((g_SCA_COUNT-1) downto 0);   --! Used to detect a start_connect request with enable = '1' for a specific SCA link
+    signal start_reset_s    : std_logic_vector((g_SCA_COUNT-1) downto 0);   --! Used to detect a start_reset request with enable = '1' for a specific SCA link
+    
+    -- Components
+    --! @brief SCA_rx Entity - RX deserializer/decoder
+    --! @details 
+    --! The SCA_rx entity handles the deserialization and decoding
+    --! of the received frame on the couple of bits dedicated to
+    --! the SCA control.
+    component sca_rx is
+        port (
+            -- Clock & reset
+            rx_clk_i        : in std_logic;
+            clk_en          : in  std_logic;
+                 
+            reset_i         : in std_logic;
+            
+            -- Satus
+            done_o          : out std_logic;
+            crc_err_o       : out std_logic;    -- Not supported yet
+            
+            -- RX data
+            address_o       : out std_logic_vector(7 downto 0);
+            control_o       : out std_logic_vector(7 downto 0);
+            transID_o       : out std_logic_vector(7 downto 0);
+            channel_o       : out std_logic_vector(7 downto 0);
+            len_o           : out std_logic_vector(7 downto 0);
+            error_o         : out std_logic_vector(7 downto 0);
+            data_o          : out std_logic_vector(31 downto 0);
+            
+            -- IC Line
+            rx_data_i       : in std_logic_vector(1 downto 0)
+        );   
+    end component sca_rx;
+    
+    --! @brief SCA_tx Entity - Tx encoding/serialization
+    --! @details 
+    --! The IC_tx entity performs the HDLC encoding in parallel 
+    --! of the serialization process.
+    component sca_tx is
+        port (
+            clock           : in  std_logic;
+            clk_en          : in  std_logic;
+                 
+            reset           : in  std_logic;
+        
+            start_input     : in  std_logic;
+            start_connect   : in  std_logic;
+            start_reset     : in  std_logic;
+        
+            address         : in  std_logic_vector(7 downto 0);
+            control         : in  std_logic_vector(7 downto 0);
+            transID         : in  std_logic_vector(7 downto 0);
+            channel         : in  std_logic_vector(7 downto 0);
+            len             : in  std_logic_vector(7 downto 0);
+            command         : in  std_logic_vector(7 downto 0);
+            data            : in  std_logic_vector(31 downto 0);
+            data_out        : out std_logic_vector(1 downto 0);
+
+            --Debug
+            crc_inj_err     : in  std_logic
+        
+        );
+    end component sca_tx;
+    
+begin           --========####   Architecture Body   ####========-- 
+
+    sca_gen: for i in 0 to (g_SCA_COUNT-1) generate
+
+        start_command_s(i)      <= enable_i(i) and start_command_i;
+        start_connect_s(i)      <= enable_i(i) and start_connect_cmd_i;
+        start_reset_s(i)        <= enable_i(i) and start_reset_cmd_i;
+
+        --! @brief Time domain crossing (control field)
+        --! @details
+        --! Clock domain crossing for the control field is managed inside
+        --! of the ctrl_timedomain_crossing process. It just consist in
+        --! clocking the rx_control_s signal with the tx_clock.
+        --! Because no command must be sent before receiving the reply of
+        --! the previous one, we do not have any timing issue with the control
+        --! register.
+        ctrl_timedomain_crossing: process(tx_reset_i, tx_clk_i)
+        begin
+        
+            if rising_edge(tx_clk_i) then
+                               
+                if tx_reset_i = '1' then
+                    tx_control_s(i)    <= x"00";
+                else
+                    tx_control_s(i)    <= rx_control_s(i);
+                end if;
+                
+            end if;
+            
+        end process;
+        
+        -- TX: The command is sent to all of the SCA enabled
+        tx_inst: sca_tx
+            port map (
+                clock           => tx_clk_i,
+                clk_en          => tx_clk_en,
+                                        
+                reset           => tx_reset_i,
+
+                start_input     => start_command_s(i),
+                start_connect   => start_connect_s(i),
+                start_reset     => start_reset_s(i),
+
+                address         => tx_address_i,
+                control         => tx_control_s(i),
+                transID         => tx_transID_i,
+                channel         => tx_channel_i,
+                len             => tx_len_i,
+                command         => tx_command_i,
+                data            => tx_data_i,
+
+                data_out        => tx_data_o(i),
+                
+                crc_inj_err     => inject_crc_error -- Used for test only
+            );
+        
+        -- RX: individual for each SCA
+        rx_inst: sca_rx
+            port map(
+                rx_clk_i        => rx_clk_i,
+                clk_en          => rx_clk_en,
+                                        
+                reset_i         => rx_reset_i,
+                
+                done_o          => rx_received_o(i),
+                
+                address_o       => rx_address_o(i),
+                control_o       => rx_control_s(i),
+                transID_o       => rx_transID_o(i),
+                channel_o       => rx_channel_o(i),
+                len_o           => rx_len_o(i),
+                error_o         => rx_error_o(i),
+                data_o          => rx_data_o(i),
+                
+                rx_data_i       => rx_data_i(i)
+            );
+   
+        rx_control_o(i)         <= rx_control_s(i);
+
+    end generate;
+    
+end behaviour;
+--============================================================================--
+--############################################################################--
+--============================================================================--'
\ No newline at end of file
diff --git a/vldb/code/GBT-SC/SCA/sca_tx.vhd b/vldb/code/GBT-SC/SCA/sca_tx.vhd
new file mode 100644 (file)
index 0000000..b9dafc2
--- /dev/null
@@ -0,0 +1,537 @@
+-------------------------------------------------------
+--! @file
+--! @author Julian Mendez <julian.mendez@cern.ch> (CERN - EP-ESE-BE)
+--! @date April, 2017
+--! @version 1.0
+--! @brief SCA control - SCA TX (HDLC encoder)
+-------------------------------------------------------
+
+--! Include the IEEE VHDL standard library
+library ieee;
+--! Use STD_Logic to define vector types
+use ieee.std_logic_1164.all;
+--! Used to convert std_logic_vector to integer and use math functions (adder)
+use ieee.numeric_std.all;
+
+--! Include the work library
+library work;
+--! Use SCA Package to define specific types (vector arrays)
+use work.SCA_PKG.all;
+
+--! @brief SCA_tx Entity - Tx encoding/serialization
+--! @details 
+--! The IC_tx entity performs the HDLC encoding in parallel 
+--! of the serialization process.
+entity sca_tx is
+    port (
+        clock           : in  std_logic;                        --! Tx clock (Tx_frameclk_o from GBT-FPGA IP): must be a multiple of the LHC frequency
+        clk_en          : in  std_logic;                        --! Tx clock enable signal must be used in case of multi-cycle path(tx_clk_i > LHC frequency). By default: always enabled
+                 
+        reset           : in  std_logic;                        --! Reset TX datapath
+        
+        start_input     : in  std_logic;                        --! Send the command set in input
+        start_connect   : in  std_logic;                        --! Send a connect command
+        start_reset     : in  std_logic;                        --! Send a reset command
+    
+        address         : in  std_logic_vector(7 downto 0);     --! Command: address field (According to the SCA manual)
+        control         : in  std_logic_vector(7 downto 0);     --! Command: control field (According to the SCA manual)
+        transID         : in  std_logic_vector(7 downto 0);     --! Command: transaction ID field (According to the SCA manual)
+        channel         : in  std_logic_vector(7 downto 0);     --! Command: channel field (According to the SCA manual)
+        len             : in  std_logic_vector(7 downto 0);     --! Command: Len field (not used anymore, fixed to 4 bytes)
+        command         : in  std_logic_vector(7 downto 0);     --! Command: command field (According to the SCA manual)
+        data            : in  std_logic_vector(31 downto 0);    --! Command: data field (According to the SCA manual)
+        data_out        : out std_logic_vector(1 downto 0);     --! (TX) Couple of bits to be connected to the SCA link
+    
+        --Debug
+        crc_inj_err     : in  std_logic                         --! Emulate a CRC error
+    
+    );   
+end sca_tx;
+
+--! @brief SCA_tx Architecture - Tx encoding/serialization
+--! @details 
+--! The SCA_tx architecture describes the logic used to generate the encoded frame
+--! defined by the SCA manual. It is based on a state machine running at the tx_clock
+--! frequency. Everytime the process is executed, two bits are generated and mapped
+--! to the EC line.
+architecture behaviour of sca_tx is
+
+    -- Constants
+    constant IDLE_PACKET        : std_logic_vector(7 downto 0)    := "01111111";    --! Idle pattern as defined by the HDLC standard
+    constant DELIMITER_PACKET   : std_logic_vector(7 downto 0)    := "01111110";    --! Delimiter packet as defined by the HDLC standard (SOF/EOF)
+    
+    -- Type
+    --! The hdlcstate_t type defines the states available for the hdlcproc process
+    type    hdlc_state_t    is  (   s0_waitForStart, 
+                                    s1_waitForIdleFinished, 
+                                    s2_sendSOF, 
+                                    s3_sendCommand, 
+                                    s4_sendCRC, 
+                                    s5_sendEOF
+                                );
+
+    -- Signals
+    signal hdlc_state           : hdlc_state_t := s0_waitForStart;                  --! HDLC encoding FSM state register
+    
+    signal cmd_reg              : reg8_arr(9 downto 0);                             --! Set of 8bit register that contains the command to be sent
+    signal cmd_len              : integer range 0 to 10;                            --! Register to save the length of the command
+    
+    signal crc                  : std_logic_vector(15 downto 0);                    --! Register used to generate the CRC                   
+    signal rev_crc              : std_logic_vector(15 downto 0);                    --! Inverted CRC
+    
+    signal ctrl_cnt             : unsigned(2 downto 0);                             --! Internal control counter used to number the packet (must be incremented everytime a new command is sent)
+
+begin                 --========####   Architecture Body   ####========-- 
+    
+    rev_crc     <= reverse_v(crc);
+
+    -- HDLC process
+    --! The hdlcproc process encodes and serializes the command into the two
+    --! bits of the EC line.
+    --! The process implements the following state machine:
+    --!     * *s0_waitForStart*: Serializes the IDLE_PACKET word until a start command. Upon a start, the cmd_reg set of register is filled out and the encoding start.
+    --!     * *s1_waitForIdleFinished*: Sends the end of the IDLE_PACKET word.
+    --!     * *s2_sendSOF*: Sends the SOF DELIMITER_PACKET word.
+    --!     * *s3_sendCommand*: Sends the command registered into the cmd_reg with '0' insertion and CRC computing.
+    --!     * *s4_sendCRC*: Sends the CRC computed during the previous stage (incl. '0' insertion).
+    --!     * *s5_sendEOF*: Sends the EOF DELIMITER_PACKET word.
+    hdlcproc: process(clock, reset)
+    
+        variable offset_pos         : integer range 0 to 17 := 0;
+        variable reg_pos            : integer range 0 to 11 := 0;
+        variable high_lvl_cnter     : integer range 0 to 6  := 0;
+        
+    begin
+    
+        if rising_edge(clock) then
+                 
+                       if reset = '1' then
+                               data_out        <= "11";
+                               offset_pos      := 0;
+                               reg_pos         := 0;
+                               ctrl_cnt        <= (others => '0');
+                               cmd_len         <= 0;
+            
+                       elsif clk_en = '1' then
+            
+                               case hdlc_state is
+
+                                       when s0_waitForStart        =>    
+                                               -- Generate tx_data_o
+                                               if offset_pos <= 6 then
+                                                       data_out(1) <= IDLE_PACKET(offset_pos);
+                                                       data_out(0) <= IDLE_PACKET(offset_pos+1);
+                                                       
+                                                       offset_pos  := offset_pos + 2;
+                                               
+                                                       if offset_pos > 7 then
+                                                               offset_pos  := 0;
+                                                       end if;                        
+                                                       
+                                               elsif offset_pos > 6 then                    
+                                                       data_out(1) <= IDLE_PACKET(7);
+                                                       data_out(0) <= IDLE_PACKET(0);
+                                                       
+                                                       offset_pos  := 1;
+                                               end if;
+                                               
+                                               -- First word is always the address
+                                               cmd_reg(0) <= (address);
+                                               
+                                               -- Send command asked
+                                               if start_input = '1' then
+
+                                                       -- Control field computing
+                                                       if crc_inj_err = '0' then
+                                                               ctrl_cnt                <= ctrl_cnt + 1;
+                                                       end if;
+                                                       
+                                                       cmd_reg(1)(7)           <= control(3) and not(control(0));
+                                                       cmd_reg(1)(6)           <= control(2) and not(control(0));
+                                                       cmd_reg(1)(5)           <= control(1) and not(control(0));
+                                                       cmd_reg(1)(4)           <= '0';
+                                                       cmd_reg(1)(3 downto 1)  <= std_logic_vector(ctrl_cnt);
+                                                       cmd_reg(1)(0)           <= '0';
+
+                                                       -- Save in register
+                                                       cmd_reg(2)              <= (transID);
+                                                       cmd_reg(3)              <= (channel);
+                                                       cmd_reg(4)              <= (len);
+                                                       cmd_reg(5)              <= (command);    
+
+                                                       -- JM: Not supported anymore because of SCA's issues
+                                                       
+                                                       --if len = x"01" or len = x"02" then
+                                                       --    cmd_reg(6)          <= (data(23 downto 16));
+                                                       --    cmd_reg(7)          <= (data(31 downto 24));
+                                                       --    cmd_reg(8)          <= x"00";
+                                                       --    cmd_reg(9)          <= x"00";
+                                                       --    
+                                                       --    cmd_len             <= 8;
+                                                               
+                                                       --elsif len = x"03" or len = x"04" then
+                                                               cmd_reg(6)          <= (data(23 downto 16));
+                                                               cmd_reg(7)          <= (data(31 downto 24));
+                                                               cmd_reg(8)          <= (data(7 downto 0));
+                                                               cmd_reg(9)          <= (data(15 downto 8));
+                                                               
+                                                               cmd_len             <= 10;
+                                                       
+                                                       --else
+                                                       --    cmd_reg(6)          <= (others => '0');
+                                                       --    cmd_reg(7)          <= (others => '0');
+                                                       --    cmd_reg(8)          <= (others => '0');
+                                                       --    cmd_reg(9)          <= (others => '0');
+                                                       --    
+                                                       --    cmd_len             <= 10;
+                                                       --
+                                                       --end if;
+                                                       
+                                                       offset_pos              := 0;
+                                                       hdlc_state              <= s1_waitForIdleFinished;
+
+                                               -- Send connect asked
+                                               elsif start_connect = '1' then    
+                                                       cmd_reg(1)              <= x"2F";
+                                                       cmd_reg(2)              <= (others => '0');
+                                                       cmd_len                 <= 2;
+                                                       
+                                                       offset_pos              := 0;
+                                                       hdlc_state              <= s1_waitForIdleFinished;
+
+                                               -- Send reset asked
+                                               elsif start_reset = '1' then    
+                                                       cmd_reg(1)              <= x"8F";
+                                                       cmd_reg(2)              <= (others => '0');
+                                                       cmd_len                 <= 2;
+                                                       
+                                                       offset_pos              := 0;
+                                                       hdlc_state              <= s1_waitForIdleFinished;
+                                                       
+                                               end if;
+                                               
+                                       when s1_waitForIdleFinished =>    
+                                               -- Send 8 times '1'
+                                               data_out        <= "11";
+                                               offset_pos      := offset_pos + 2;
+                                               
+                                               if offset_pos > 7 then
+                                                       hdlc_state  <= s2_sendSOF;
+                                                       offset_pos  := 0;
+                                               end if;
+                                       
+                                       when s2_sendSOF             =>    
+                                               
+                                               -- Send 8 times '1'
+                                               data_out(1)        <= DELIMITER_PACKET(offset_pos);
+                                               data_out(0)        <= DELIMITER_PACKET(offset_pos+1);
+                                               offset_pos         := offset_pos + 2;
+                                               
+                                               if offset_pos > 7 then
+                                                       hdlc_state  <= s3_sendCommand;
+                                                       reg_pos     := 0;
+                                                       offset_pos  := 0;
+                                                       
+                                                       if crc_inj_err = '1' then
+                                                               crc         <= x"0000";
+                                                               
+                                                       else
+                                                               crc         <=  nextCRC16_D8(
+                                                                                                       reverse_v(cmd_reg(0)), 
+                                                                                                       x"FFFF"
+                                                                                               );
+                                                       end if;
+                                                       
+                                               end if;
+                                       
+                                               high_lvl_cnter     := 0;
+                                       
+                                       when s3_sendCommand         =>                  
+                                       
+                                               -- Enough data to send 2 bits?
+                                               if offset_pos < 7 then
+                                               
+                                                       -- (MSB) Bit stuffing?
+                                                       if high_lvl_cnter >= 5 then
+                                                       
+                                                               data_out(1)        <= '0';
+                                                               high_lvl_cnter     := 0;
+                                                       
+                                                       -- (MSB) Send data
+                                                       else
+                                                       
+                                                               data_out(1)        <= cmd_reg(reg_pos)(offset_pos);
+                                                               if cmd_reg(reg_pos)(offset_pos) = '1' then
+                                                                       high_lvl_cnter := high_lvl_cnter + 1;
+                                                               else
+                                                                       high_lvl_cnter := 0;
+                                                               end if;
+                                                               
+                                                               offset_pos         := offset_pos + 1;
+                                                       
+                                                       end if;
+                                               
+                                                       -- (LSB) Bit stuffing?
+                                                       if high_lvl_cnter >= 5 then
+                                                       
+                                                               data_out(0)        <= '0';
+                                                               high_lvl_cnter     := 0;
+                                                       
+                                                       -- (LSB) Send data
+                                                       else
+                                                       
+                                                               data_out(0)        <= cmd_reg(reg_pos)(offset_pos);
+                                                               if cmd_reg(reg_pos)(offset_pos) = '1' then
+                                                                       high_lvl_cnter := high_lvl_cnter + 1;
+                                                               else
+                                                                       high_lvl_cnter := 0;
+                                                               end if;
+                                                               
+                                                               offset_pos         := offset_pos + 1;
+                                                       
+                                                       end if;
+                                                       
+                                                       -- End of command?
+                                                       if offset_pos = 8 then
+                                                       
+                                                               offset_pos      := 0;
+                                                               
+                                                               if reg_pos < (cmd_len-1) then
+                                                                       reg_pos         :=  reg_pos + 1;
+                                                                       crc             <=  nextCRC16_D8(
+                                                                                                                       reverse_v(
+                                                                                                                               cmd_reg(reg_pos)
+                                                                                                                       ),
+                                                                                                                       crc
+                                                                                                               );
+                                                               else
+                                                                       hdlc_state      <= s4_sendCRC;
+                                                               end if;
+                                                               
+                                                       end if;
+                                               
+                                               -- 1 bit still have to been sent, then CRC
+                                               elsif offset_pos < 8 then
+                                               
+                                                       -- (MSB) Bit stuffing?
+                                                       if high_lvl_cnter >= 5 then
+                                                       
+                                                               high_lvl_cnter  := 0;
+                                                               
+                                                               data_out(1)     <= '0';
+                                                               data_out(0)     <= cmd_reg(reg_pos)(7);
+                                                               
+                                                               if cmd_reg(reg_pos)(offset_pos) = '1' then
+                                                                       high_lvl_cnter     := high_lvl_cnter + 1;
+                                                               else
+                                                                       high_lvl_cnter     := 0;
+                                                               end if;
+                                                               
+                                                               offset_pos      := 0;
+                                                               
+                                                               if reg_pos < (cmd_len-1) then
+                                                                       reg_pos         :=  reg_pos + 1;
+                                                                       crc             <=  nextCRC16_D8(
+                                                                                                                       reverse_v(
+                                                                                                                               cmd_reg(reg_pos)
+                                                                                                                       ), 
+                                                                                                                       crc
+                                                                                                               );
+                                                               else
+                                                                       hdlc_state      <= s4_sendCRC;
+                                                               end if;
+                                                               
+                                                       -- (MSB) Send data
+                                                       else
+                                                       
+                                                               data_out(1)        <= cmd_reg(reg_pos)(7);
+                                                               if cmd_reg(reg_pos)(offset_pos) = '1' then
+                                                                       high_lvl_cnter := high_lvl_cnter + 1;
+                                                               else
+                                                                       high_lvl_cnter := 0;
+                                                               end if;
+                                                               
+                                                       
+                                                               -- (LSB) Bit stuffing?
+                                                               if reg_pos < (cmd_len-1) then
+                                                               
+                                                                       reg_pos         :=  reg_pos + 1;
+                                                                       crc             <=  nextCRC16_D8(
+                                                                                                                       reverse_v(
+                                                                                                                               cmd_reg(reg_pos)
+                                                                                                                       ), 
+                                                                                                                       crc
+                                                                                                               );
+                                                                       
+                                                                       if high_lvl_cnter >= 5 then
+                                                                               data_out(0)     <= '0';
+                                                                               high_lvl_cnter  := 0;
+                                                                               offset_pos      := 0;
+                                                                               
+                                                                       else
+                                                                               data_out(0)     <= cmd_reg(reg_pos)(0);
+                                                                               if cmd_reg(reg_pos)(0) = '1' then
+                                                                                       high_lvl_cnter := high_lvl_cnter + 1;
+                                                                               else
+                                                                                       high_lvl_cnter := 0;
+                                                                               end if;
+                                                                               
+                                                                               offset_pos      := 1;
+                                                                       end if;
+                                                                               
+                                                               else
+                                                                       if high_lvl_cnter >= 5 then
+                                                                               data_out(0)     <= '0';
+                                                                               high_lvl_cnter  := 0;
+                                                                               offset_pos      := 0;
+                                                                       
+                                                                       else
+                                                                               data_out(0)     <= rev_crc(0);
+                                                                               if rev_crc(0) = '1' then
+                                                                                       high_lvl_cnter := high_lvl_cnter + 1;
+                                                                               else
+                                                                                       high_lvl_cnter := 0;
+                                                                               end if;
+
+                                                                               offset_pos      := 1;    
+                                                                               
+                                                                       end if;
+                                                                       
+                                                                       hdlc_state      <= s4_sendCRC;
+                                                               
+                                                               end if;
+                                                               
+                                                       end if;
+                                               
+                                               end if;
+                                       
+                                       when s4_sendCRC             =>
+                                       
+                                               -- Enough data to send 2 bits?
+                                               if offset_pos < 15 then
+                                               
+                                                       -- (MSB) Bit stuffing?
+                                                       if high_lvl_cnter >= 5 then
+                                                       
+                                                               data_out(1)        <= '0';
+                                                               high_lvl_cnter     := 0;
+                                                       
+                                                       -- (MSB) Send data
+                                                       else
+                                                       
+                                                               data_out(1)         <= rev_crc(offset_pos);
+                                                               if rev_crc(offset_pos) = '1' then
+                                                                       high_lvl_cnter := high_lvl_cnter + 1;
+                                                               else
+                                                                       high_lvl_cnter := 0;
+                                                               end if;
+                                                               
+                                                               offset_pos          := offset_pos + 1;
+                                                       
+                                                       end if;
+                                               
+                                                       -- (LSB) Bit stuffing?
+                                                       if high_lvl_cnter >= 5 then
+                                                       
+                                                               data_out(0)        <= '0';
+                                                               high_lvl_cnter     := 0;
+                                                       
+                                                       -- (LSB) Send data
+                                                       else
+                                                       
+                                                               data_out(0)        <= rev_crc(offset_pos);
+                                                               if rev_crc(offset_pos) = '1' then
+                                                                       high_lvl_cnter := high_lvl_cnter + 1;
+                                                               else
+                                                                       high_lvl_cnter := 0;
+                                                               end if;
+                                                               
+                                                               offset_pos      := offset_pos + 1;
+                                                       
+                                                       end if;
+                                                       
+                                                       -- End of command?
+                                                       if offset_pos = 16 then
+                                                       
+                                                               offset_pos      := 0;
+                                                               hdlc_state      <= s5_sendEOF;
+                                                               
+                                                       end if;
+                                               
+                                               -- 1 bit still have to been sent, then CRC
+                                               elsif offset_pos < 16 then
+                                               
+                                                       -- (MSB) Bit stuffing?
+                                                       if high_lvl_cnter >= 5 then
+                                                       
+                                                               high_lvl_cnter  := 0;
+                                                               
+                                                               data_out(1)     <= '0';
+                                                               data_out(0)     <= rev_crc(offset_pos);
+                                                               
+                                                               if rev_crc(offset_pos) = '1' then
+                                                                       high_lvl_cnter     := 0;
+                                                               end if;
+                                                               
+                                                               offset_pos      := 0;
+                                                               hdlc_state      <= s5_sendEOF;
+                                                               
+                                                       -- (MSB) Send data
+                                                       else
+                                                       
+                                                               data_out(1)        <= rev_crc(offset_pos);
+                                                               if rev_crc(offset_pos) = '1' then
+                                                                       high_lvl_cnter := high_lvl_cnter + 1;
+                                                               else
+                                                                       high_lvl_cnter := 0;
+                                                               end if;
+                                                       
+                                                               -- (LSB) Bit stuffing?
+                                                               if high_lvl_cnter >= 5 then
+                                                                       data_out(0)     <= '0';
+                                                                       
+                                                                       high_lvl_cnter  := 0;
+                                                                       offset_pos      := 0;
+                                                                       hdlc_state      <= s5_sendEOF;
+
+                                                               else
+                                                                       
+                                                                       data_out(0)     <= DELIMITER_PACKET(0);
+                                                                       offset_pos      := 1;
+                                                                       hdlc_state      <= s5_sendEOF;
+                                                                       
+                                                               end if;
+                                                       end if;
+                                               
+                                               end if;    
+                                       
+                                       when s5_sendEOF             =>  
+                                       
+                                               if offset_pos <= 6 then
+                                                       data_out(1) <= DELIMITER_PACKET(offset_pos);
+                                                       data_out(0) <= DELIMITER_PACKET(offset_pos+1);
+                                                       
+                                                       offset_pos  := offset_pos + 2;
+                                                       
+                                                       if offset_pos > 7 then
+                                                               offset_pos      := 0;
+                                                               hdlc_state      <= s0_waitForStart;
+                                                       end if;
+                                                       
+                                               elsif offset_pos > 6 then                    
+                                                       data_out(1) <= DELIMITER_PACKET(7);
+                                                       data_out(0) <= IDLE_PACKET(0);
+                                                       
+                                                       offset_pos      := 1;
+                                                       hdlc_state      <= s0_waitForStart;
+                                               end if;
+                                               
+                               end case;
+                       end if;
+        end if;
+    end process;
+    
+end behaviour;
+--============================================================================--
+--############################################################################--
+--============================================================================--
\ No newline at end of file
diff --git a/vldb/code/GBT-SC/gbtsc_top.vhd b/vldb/code/GBT-SC/gbtsc_top.vhd
new file mode 100644 (file)
index 0000000..b6a876a
--- /dev/null
@@ -0,0 +1,301 @@
+-------------------------------------------------------
+--! @file
+--! @author Julian Mendez <julian.mendez@cern.ch> (CERN - EP-ESE-BE)
+--! @date April, 2017
+--! @version 1.0
+--! @brief IC and EC control - TOP level
+-------------------------------------------------------
+
+--! Include the IEEE VHDL standard library
+library ieee;
+--! Use STD_Logic to define vector types
+use ieee.std_logic_1164.all;
+
+--! Include the work library
+library work;
+--! Use SCA Package to define specific types (vector arrays)
+use work.SCA_PKG.all;
+
+--! @brief GBTSC_top Entity - TOP Level
+--! @details
+--! The gbtsc_top module implements the required blocks to carry out Internal (GBTx)
+--! and external (SCA) slow control. Its purpose is to handle the communication
+--! with up to 41 SCAs and 1 GBTx (max. capability of a GBT link).
+entity gbtsc_top is
+    generic (
+        -- IC configuration
+        g_IC_FIFO_DEPTH     : integer := 20;                                    --! Defines the depth of the FIFO used to handle the Internal control (Max. number of words/bytes can be read/write from/to a GBTx)
+        g_ToLpGBT           : integer range 0 to 1 := 0;                        --! 1 to use LpGBT. Otherwise, it should be 0
+        g_LPGBT_VERS        : std_logic := '1';                                 --! Select lpGBT version ('0': 0, '1': 1)
+
+        -- EC configuration
+        g_SCA_COUNT         : integer := 1                                      --! Defines the maximum number of SCA that can be connected to this module
+    );
+    port (
+        -- Clock & reset
+        tx_clk_i            : in  std_logic;                                    --! Tx clock (Tx_frameclk_o from GBT-FPGA IP): must be a multiple of the LHC frequency
+               tx_clk_en           : in  std_logic := '1';                             --! Tx clock enable signal must be used in case of multi-cycle path(tx_clk_i > LHC frequency). By default: always enabled
+
+        rx_clk_i            : in  std_logic;                                    --! Rx clock (Rx_frameclk_o from GBT-FPGA IP): must be a multiple of the LHC frequency
+               rx_clk_en           : in  std_logic := '1';                             --! Rx clock enable signal must be used in case of multi-cycle path(rx_clk_i > LHC frequency). By default: always enabled
+
+        rx_reset_i          : in  std_logic;                                    --! Reset RX datapath
+        tx_reset_i          : in  std_logic;                                    --! Reset TX datapath
+
+        -- IC control
+        tx_start_write_i    : in  std_logic;                                    --! Request a write config. to the GBTx (IC)
+        tx_start_read_i     : in  std_logic;                                    --! Request a read config. to the GBTx (IC)
+
+        -- IC configuration
+        tx_GBTx_address_i   : in  std_logic_vector(7 downto 0);                 --! I2C address of the GBTx
+        tx_register_addr_i  : in  std_logic_vector(15 downto 0);                --! Address of the first register to be accessed
+        tx_nb_to_be_read_i  : in  std_logic_vector(15 downto 0);                --! Number of words/bytes to be read (only for read transactions)
+
+        -- IC FIFO control
+        wr_clk_i            : in std_logic;                                     --! Fifo's writing clock
+        tx_wr_i             : in  std_logic;                                    --! Request a write operation into the internal FIFO (Data to GBTx)
+        tx_data_to_gbtx_i   : in  std_logic_vector(7 downto 0);                 --! Data to be written into the internal FIFO
+
+        rd_clk_i            : in  std_logic;
+        rx_rd_i             : in  std_logic;                                    --! Request a read operation of the internal FIFO (GBTx reply)
+        rx_data_from_gbtx_o : out std_logic_vector(7 downto 0);                 --! Data from the FIFO
+
+        -- IC Status
+        tx_ready_o          : out std_logic;                                    --! IC core ready for a transaction
+        rx_empty_o          : out std_logic;                                    --! Rx FIFO is empty (no reply from GBTx)
+
+        -- SCA control
+        sca_enable_i        : in  std_logic_vector((g_SCA_COUNT-1) downto 0);   --! Enable flag to select SCAs
+        start_reset_cmd_i   : in  std_logic;                                    --! Send a reset command to the enabled SCAs
+        start_connect_cmd_i : in  std_logic;                                    --! Send a connect command to the enabled SCAs
+        start_command_i     : in  std_logic;                                    --! Send the command set in input to the enabled SCAs
+        inject_crc_error    : in  std_logic;                                    --! Emulate a CRC error
+
+        -- SCA command
+        tx_address_i        : in  std_logic_vector(7 downto 0);                 --! Command: address field (According to the SCA manual)
+        tx_transID_i        : in  std_logic_vector(7 downto 0);                 --! Command: transaction ID field (According to the SCA manual)
+        tx_channel_i        : in  std_logic_vector(7 downto 0);                 --! Command: channel field (According to the SCA manual)
+        tx_command_i        : in  std_logic_vector(7 downto 0);                 --! Command: command field (According to the SCA manual)
+        tx_data_i           : in  std_logic_vector(31 downto 0);                --! Command: data field (According to the SCA manual)
+
+        rx_received_o       : out std_logic_vector((g_SCA_COUNT-1) downto 0);   --! Reply received flag (pulse)
+        rx_address_o        : out reg8_arr((g_SCA_COUNT-1) downto 0);           --! Reply: address field (According to the SCA manual)
+        rx_control_o        : out reg8_arr((g_SCA_COUNT-1) downto 0);           --! Reply: control field (According to the SCA manual)
+        rx_transID_o        : out reg8_arr((g_SCA_COUNT-1) downto 0);           --! Reply: transaction ID field (According to the SCA manual)
+        rx_channel_o        : out reg8_arr((g_SCA_COUNT-1) downto 0);           --! Reply: channel field (According to the SCA manual)
+        rx_len_o            : out reg8_arr((g_SCA_COUNT-1) downto 0);           --! Reply: len field (According to the SCA manual)
+        rx_error_o          : out reg8_arr((g_SCA_COUNT-1) downto 0);           --! Reply: error field (According to the SCA manual)
+        rx_data_o           : out reg32_arr((g_SCA_COUNT-1) downto 0);          --! Reply: data field (According to the SCA manual)
+
+        -- EC line
+        ec_data_o           : out reg2_arr((g_SCA_COUNT-1) downto 0);           --! (TX) Array of bits to be mapped to the TX GBT-Frame
+        ec_data_i           : in  reg2_arr((g_SCA_COUNT-1) downto 0);           --! (RX) Array of bits to be mapped to the RX GBT-Frame
+
+        -- IC lines
+        ic_data_o           : out std_logic_vector(1 downto 0);                 --! (TX) Array of bits to be mapped to the TX GBT-Frame (bits 83/84)
+        ic_data_i           : in  std_logic_vector(1 downto 0)                  --! (RX) Array of bits to be mapped to the RX GBT-Frame (bits 83/84)
+
+    );
+end gbtsc_top;
+
+--! @brief GBTSC_top architecture - TOP Level
+--! @details GBTSC_top architecture instantiates the modules used to handle the IC and EC slow control. It maps all of the signal from
+--! its entity to the sca_top and ic_top components. No additional logic is added in this block.
+architecture behaviour of gbtsc_top is
+
+    -- Signals
+    signal tx_start_write_s     : std_logic;   --! Used to simulate a write command request to the GBTx
+    signal tx_start_read_s      : std_logic;   --! Used to simulate a read command request to the GBTx
+
+    --! SCA_top component - TOP Level of the SCA-EC module
+    component sca_top is
+        generic (
+            g_SCA_COUNT         : integer := 1
+        );
+        port (
+            tx_clk_i            : in  std_logic;
+            tx_clk_en           : in  std_logic;
+
+            rx_clk_i            : in  std_logic;
+            rx_clk_en           : in  std_logic;
+
+            rx_reset_i          : in  std_logic;
+            tx_reset_i          : in  std_logic;
+
+            enable_i            : in  std_logic_vector(g_SCA_COUNT-1 downto 0);
+            start_reset_cmd_i   : in  std_logic;
+            start_connect_cmd_i : in  std_logic;
+            start_command_i     : in  std_logic;
+            inject_crc_error    : in  std_logic;
+
+            tx_address_i        : in  std_logic_vector(7 downto 0);
+            tx_transID_i        : in  std_logic_vector(7 downto 0);
+            tx_channel_i        : in  std_logic_vector(7 downto 0);
+            tx_len_i            : in  std_logic_vector(7 downto 0);
+            tx_command_i        : in  std_logic_vector(7 downto 0);
+            tx_data_i           : in  std_logic_vector(31 downto 0);
+
+            rx_received_o       : out std_logic_vector(g_SCA_COUNT-1 downto 0);
+            rx_address_o        : out reg8_arr(g_SCA_COUNT-1 downto 0);
+            rx_control_o        : out reg8_arr(g_SCA_COUNT-1 downto 0);
+            rx_transID_o        : out reg8_arr(g_SCA_COUNT-1 downto 0);
+            rx_channel_o        : out reg8_arr(g_SCA_COUNT-1 downto 0);
+            rx_len_o            : out reg8_arr(g_SCA_COUNT-1 downto 0);
+            rx_error_o          : out reg8_arr(g_SCA_COUNT-1 downto 0);
+            rx_data_o           : out reg32_arr(g_SCA_COUNT-1 downto 0);
+
+            tx_data_o           : out reg2_arr(g_SCA_COUNT-1 downto 0);
+            rx_data_i           : in  reg2_arr(g_SCA_COUNT-1 downto 0)
+
+        );
+    end component sca_top;
+
+    --! IC_top component - TOP Level of the IC module
+    component ic_top is
+        generic (
+            g_ToLpGBT           : integer range 0 to 1 := 0;
+            g_FIFO_DEPTH        : integer := 20;                        --! Depth of the internal FIFO used to improve the timming performance
+            g_LPGBT_VERS        : std_logic := '1'                      --! Select lpGBT version ('0': 0, '1': 1)
+        );
+        port (
+            -- Clock and reset
+            tx_clk_i            : in  std_logic;                        --! Tx clock (Tx_frameclk_o from GBT-FPGA IP): must be a multiple of the LHC frequency
+            tx_clk_en           : in  std_logic;                        --! Tx clock enable signal must be used in case of multi-cycle path(tx_clk_i > LHC frequency). By default: always enabled
+
+            rx_clk_i            : in  std_logic;                        --! Rx clock (Rx_frameclk_o from GBT-FPGA IP): must be a multiple of the LHC frequency
+            rx_clk_en           : in  std_logic;                        --! Rx clock enable signal must be used in case of multi-cycle path(rx_clk_i > LHC frequency). By default: always enabled
+
+            rx_reset_i          : in  std_logic;                        --! Reset RX datapath
+            tx_reset_i          : in  std_logic;                        --! Reset TX datapath
+
+            -- Configuration
+            tx_GBTx_address_i   : in  std_logic_vector(7 downto 0);     --! I2C address of the GBTx
+            tx_register_addr_i  : in  std_logic_vector(15 downto 0);    --! Address of the first register to be accessed
+            tx_nb_to_be_read_i  : in  std_logic_vector(15 downto 0);    --! Number of words/bytes to be read (only for read transactions)
+
+            parity_err_mask_i   : in std_logic_vector(7 downto 0);
+
+            -- Internal FIFO
+            wr_clk_i            : in std_logic;                         --! Fifo's writing clock
+            tx_wr_i             : in  std_logic;                        --! Request a write operation into the internal FIFO (Data to GBTx)
+            tx_data_to_gbtx_i   : in  std_logic_vector(7 downto 0);     --! Data to be written into the internal FIFO
+
+            rd_clk_i            : in  std_logic;
+            rx_rd_i             : in  std_logic;                        --! Request a read operation of the internal FIFO (GBTx reply)
+            rx_data_from_gbtx_o : out std_logic_vector(7 downto 0);     --! Data from the FIFO
+
+            -- FSM Control
+            tx_start_write_i    : in  std_logic;                        --! Request a write config. to the GBTx
+            tx_start_read_i     : in  std_logic;                        --! Request a read config. to the GBTx
+
+            -- Status
+            tx_ready_o          : out std_logic;                        --! IC core ready for a transaction
+            rx_empty_o          : out std_logic;                        --! Rx FIFO is empty (no reply from GBTx)
+
+            -- IC lines
+            tx_data_o           : out std_logic_vector(1 downto 0);     --! (TX) Array of bits to be mapped to the TX GBT-Frame (bits 83/84)
+            rx_data_i           : in  std_logic_vector(1 downto 0)      --! (RX) Array of bits to be mapped to the RX GBT-Frame (bits 83/84)
+
+        );
+    end component ic_top;
+
+begin           --========####   Architecture Body   ####========--
+
+
+    --! Instantiation of the SCA_top component
+   sca_inst: sca_top
+        generic map(
+            g_SCA_COUNT         => g_SCA_COUNT
+        )
+        port map(
+            tx_clk_i            => tx_clk_i,
+            tx_clk_en           => tx_clk_en,
+
+            rx_clk_i            => rx_clk_i,
+            rx_clk_en           => rx_clk_en,
+
+            rx_reset_i          => rx_reset_i,
+            tx_reset_i          => tx_reset_i,
+
+            enable_i            => sca_enable_i,
+            start_reset_cmd_i   => start_reset_cmd_i,
+            start_connect_cmd_i => start_connect_cmd_i,
+            start_command_i     => start_command_i,
+            inject_crc_error    => inject_crc_error,
+
+            tx_address_i        => tx_address_i,
+            tx_transID_i        => tx_transID_i,
+            tx_channel_i        => tx_channel_i,
+            tx_len_i            => x"04", -- tx_len_i, -- Fixed (BUG)
+            tx_command_i        => tx_command_i,
+            tx_data_i           => tx_data_i,
+
+            rx_received_o       => rx_received_o,
+            rx_address_o        => rx_address_o,
+            rx_control_o        => rx_control_o,
+            rx_transID_o        => rx_transID_o,
+            rx_channel_o        => rx_channel_o,
+            rx_len_o            => rx_len_o,
+            rx_error_o          => rx_error_o,
+            rx_data_o           => rx_data_o,
+
+            tx_data_o           => ec_data_o,
+            rx_data_i           => ec_data_i
+
+        );
+        
+    tx_start_write_s <= tx_start_write_i ;
+    tx_start_read_s <= tx_start_read_i ;
+
+    --! Instantiation of the IC_top component
+    ic_inst: ic_top
+        generic map(
+            g_ToLpGBT           => g_ToLpGBT,
+            g_FIFO_DEPTH        => g_IC_FIFO_DEPTH,
+            g_LPGBT_VERS        => g_LPGBT_VERS
+        )
+        port map(
+        
+            -- Clock and reset
+            tx_clk_i            => tx_clk_i,
+            tx_clk_en           => tx_clk_en,
+            
+            rx_clk_i            => rx_clk_i,
+            rx_clk_en           => rx_clk_en,
+            
+            rx_reset_i          => rx_reset_i,
+            tx_reset_i          => tx_reset_i,
+            
+            -- Configuration
+            tx_GBTx_address_i   => tx_GBTx_address_i,
+            tx_register_addr_i  => tx_register_addr_i,
+            tx_nb_to_be_read_i  => tx_nb_to_be_read_i,
+
+            parity_err_mask_i   => (others => '0'),
+            
+            -- Internal FIFO
+            wr_clk_i            => wr_clk_i,
+            tx_wr_i             => tx_wr_i,
+            tx_data_to_gbtx_i   => tx_data_to_gbtx_i,
+            
+            rd_clk_i            => rd_clk_i,
+            rx_rd_i             => rx_rd_i,
+            rx_data_from_gbtx_o => rx_data_from_gbtx_o,
+            
+            -- FSM Control
+            tx_start_write_i    => tx_start_write_s,
+            tx_start_read_i     => tx_start_read_s,
+            
+            -- Status
+            tx_ready_o          => tx_ready_o,
+            rx_empty_o          => rx_empty_o,
+            
+            -- IC lines
+            tx_data_o           => ic_data_o,
+            rx_data_i           => ic_data_i
+        );
+
+end behaviour;
+--============================================================================--
+--############################################################################--
+--============================================================================--
\ No newline at end of file
diff --git a/vldb/code/gbt_core.vhd b/vldb/code/gbt_core.vhd
new file mode 100644 (file)
index 0000000..a7d33b6
--- /dev/null
@@ -0,0 +1,265 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.trb_net_std.all;
+
+
+entity gbt_core is
+  port(
+    CLK_SYS : in std_logic;
+    CLK  : in std_logic;
+    RESET   : in std_logic;
+
+    BUS_RX  : in  CTRLBUS_RX;
+    BUS_TX  : out CTRLBUS_TX;
+
+    ELINK_RX : in std_logic;
+    ELINK_TX : out std_logic
+    );
+end entity;
+
+
+architecture arch of gbt_core is
+
+  -- Clock & reset
+  signal gbtsc_tx_clk_en           : std_logic := '0';                             --! Tx clock enable signal must be used in case of multi-cycle path(tx_clk_i > LHC frequency). By default: always enabled
+  signal gbtsc_rx_clk_en           : std_logic := '0';                             --! Rx clock enable signal must be used in case of multi-cycle path(rx_clk_i > LHC frequency). By default: always enabled
+
+  -- SCA control
+  signal gbtsc_sca_enable_i        : std_logic := '1';                                    --! Enable flag to select SCAs
+  signal gbtsc_start_reset_cmd_i   : std_logic := '0';                                    --! Send a reset command to the enabled SCAs
+  signal gbtsc_start_connect_cmd_i : std_logic := '0';                                    --! Send a connect command to the enabled SCAs
+  signal gbtsc_start_command_i     : std_logic := '0';                                    --! Send the command set in input to the enabled SCAs
+  signal gbtsc_start_reset_cmd_raw :std_logic  := '0';
+  signal gbtsc_start_connect_cmd_raw :std_logic  := '0';
+  signal gbtsc_start_command_raw   :std_logic  := '0';
+  signal gbtsc_reset_go            : std_logic := '0';
+  signal gbtsc_connect_go          : std_logic := '0';
+  signal gbtsc_go                  : std_logic := '0';
+  -- SCA command
+  signal gbtsc_tx_address_i        : std_logic_vector(7 downto 0) := x"00";                 --! Command: address field (According to the SCA manual)
+  signal gbtsc_tx_transID_i        : std_logic_vector(7 downto 0) := x"01";                 --! Command: transaction ID field (According to the SCA manual)
+  signal gbtsc_tx_channel_i        : std_logic_vector(7 downto 0) := x"00";                 --! Command: channel field (According to the SCA manual)
+  signal gbtsc_tx_command_i        : std_logic_vector(7 downto 0) := x"02";                 --! Command: command field (According to the SCA manual)
+  signal gbtsc_tx_data_i           : std_logic_vector(31 downto 0) := x"0000FF00";          --! Command: data field (According to the SCA manual)
+
+  signal gbtsc_rx_received_o       : std_logic := '0';                       --! Reply received flag (pulse)
+  signal gbtsc_rx_address_o        : std_logic_vector(7 downto 0);           --! Reply: address field (According to the SCA manual)
+  signal gbtsc_rx_control_o        : std_logic_vector(7 downto 0);           --! Reply: control field (According to the SCA manual)
+  signal gbtsc_rx_transID_o        : std_logic_vector(7 downto 0);           --! Reply: transaction ID field (According to the SCA manual)
+  signal gbtsc_rx_channel_o        : std_logic_vector(7 downto 0);           --! Reply: channel field (According to the SCA manual)
+  signal gbtsc_rx_len_o            : std_logic_vector(7 downto 0);           --! Reply: len field (According to the SCA manual)
+  signal gbtsc_rx_error_o          : std_logic_vector(7 downto 0);           --! Reply: error field (According to the SCA manual)
+  signal gbtsc_rx_data_o           : std_logic_vector(31 downto 0);          --! Reply: data field (According to the SCA manual)
+
+  -- EC line
+  signal hdlc_from_gbtsc           : std_logic_vector(1 downto 0) := "11";           --! (TX) Array of bits to be mapped to the TX GBT-Frame
+  signal hdlc_to_gbtsc             : std_logic_vector(1 downto 0) := "11";           --! (RX) Array of bits to be mapped to the RX GBT-Frame
+
+begin
+
+  THE_GBTSC_TOP : entity work.gbtsc_top
+    generic map(
+      -- IC configuration
+      g_IC_FIFO_DEPTH     => 20,                  --! Defines the depth of the FIFO used to handle the Internal control (Max. number of words/bytes can be read/write from/to a GBTx)
+
+      -- EC configuration
+      g_SCA_COUNT         => 1                    --! Defines the maximum number of SCA that can be connected to this module
+      )
+    port map(
+
+      -- Clock & reset
+      tx_clk_i            => CLK,                 -- gbtsc_tx_clk_i,    --! Tx clock (Tx_frameclk_o from GBT-FPGA IP): must be a multiple of the LHC frequency
+      tx_clk_en           => gbtsc_tx_clk_en,     --! Tx clock enable signal must be used in case of multi-cycle path(tx_clk_i > LHC frequency). By default: always enabled
+      tx_reset_i          => RESET,               -- gbtsc_tx_reset_i,    --! Reset TX datapath
+
+      rx_clk_i            => CLK,                 -- gbtsc_rx_clk_i,    --! Rx clock (Rx_frameclk_o from GBT-FPGA IP): must be a multiple of the LHC frequency
+      rx_clk_en           => gbtsc_rx_clk_en,     --! Rx clock enable signal must be used in case of multi-cycle path(rx_clk_i > LHC frequency). By default: always enabled
+      rx_reset_i          => RESET,               -- gbtsc_rx_reset_i,    --! Reset RX datapath
+
+      -- IC control
+      tx_start_write_i    => '0',                 -- gbtsc_tx_start_write_i,    --! Request a write config. to the GBTx (IC)
+      tx_start_read_i     => '0',                 -- gbtsc_tx_start_read_i,   --! Request a read config. to the GBTx (IC)
+
+      -- IC configuration
+      tx_GBTx_address_i   => (others => '0'),     -- gbtsc_tx_GBTx_address_i,   --! I2C address of the GBTx
+      tx_register_addr_i  => (others => '0'),     -- gbtsc_tx_register_addr_i,    --! Address of the first register to be accessed
+      tx_nb_to_be_read_i  => (others => '0'),     -- gbtsc_tx_nb_to_be_read_i,    --! Number of words/bytes to be read (only for read transactions)
+
+      -- IC FIFO control
+      wr_clk_i            => CLK,                 --! Fifo's writing clock
+      tx_wr_i             => '0',                 -- gbtsc_tx_wr_i,   --! Request a write operation into the internal FIFO (Data to GBTx)
+      tx_data_to_gbtx_i   => (others => '0'),     -- gbtsc_tx_data_to_gbtx_i,   --! Data to be written into the internal FIFO
+
+      rd_clk_i            => CLK,
+      rx_rd_i             => '0',                 -- gbtsc_rx_rd_i,   --! Request a read operation of the internal FIFO (GBTx reply)
+      rx_data_from_gbtx_o => open,                -- gbtsc_rx_data_from_gbtx_o,   --! Data from the FIFO
+
+      -- IC Status
+      tx_ready_o          => open,                -- gbtsc_tx_ready_o,    --! IC core ready for a transaction
+      rx_empty_o          => open,                -- gbtsc_rx_empty_o,    --! Rx FIFO is empty (no reply from GBTx)
+
+      -- SCA control
+      sca_enable_i(0)     => gbtsc_sca_enable_i,    --! Enable flag to select SCAs
+      start_reset_cmd_i   => gbtsc_start_reset_cmd_i, --! Send a reset command to the enabled SCAs
+      start_connect_cmd_i => gbtsc_start_connect_cmd_i, --! Send a connect command to the enabled SCAs
+      start_command_i     => gbtsc_start_command_i, --! Send the command set in input to the enabled SCAs
+      inject_crc_error    => '0',                   --! Emulate a CRC error
+
+      -- SCA command
+      tx_address_i        => gbtsc_tx_address_i,    --! Command: address field (According to the SCA manual)
+      tx_transID_i        => gbtsc_tx_transID_i,    --! Command: transaction ID field (According to the SCA manual)
+      tx_channel_i        => gbtsc_tx_channel_i,    --! Command: channel field (According to the SCA manual)
+      tx_command_i        => gbtsc_tx_command_i,    --! Command: command field (According to the SCA manual)
+      tx_data_i           => gbtsc_tx_data_i,       --! Command: data field (According to the SCA manual)
+
+      rx_received_o(0)    => gbtsc_rx_received_o,   --! Reply: received flag (pulse)
+      rx_address_o(0)     => gbtsc_rx_address_o,    --! Reply: address field (According to the SCA manual)
+      rx_control_o(0)     => gbtsc_rx_control_o,    --! Reply: control field (According to the SCA manual)
+      rx_transID_o(0)     => gbtsc_rx_transID_o,    --! Reply: transaction ID field (According to the SCA manual)
+      rx_channel_o(0)     => gbtsc_rx_channel_o,    --! Reply: channel field (According to the SCA manual)
+      rx_len_o(0)         => gbtsc_rx_len_o,        --! Reply: len field (According to the SCA manual)
+      rx_error_o(0)       => gbtsc_rx_error_o,      --! Reply: error field (According to the SCA manual)
+      rx_data_o(0)        => gbtsc_rx_data_o,       --! Reply: data field (According to the SCA manual)
+
+      -- EC line
+      ec_data_o(0)        => hdlc_from_gbtsc,       --! (TX) Array of bits to be mapped to the TX GBT-Frame
+      ec_data_i(0)        => hdlc_to_gbtsc,         --! (RX) Array of bits to be mapped to the RX GBT-Frame
+
+      -- IC lines
+      ic_data_o           => open,    --! (TX) Array of bits to be mapped to the TX GBT-Frame (bits 83/84)
+      ic_data_i           => "00"     --! (RX) Array of bits to be mapped to the RX GBT-Frame (bits 83/84)
+      );
+
+  -- -- shift signals to the next high enable
+  -- PROC_SHIFT_TO_EN : process
+  --     variable reg_res : std_logic_vector(1 downto 0) := "00";
+  --     variable reg_con : std_logic_vector(1 downto 0) := "00";
+  --     variable reg_cmd : std_logic_vector(1 downto 0) := "00";
+  --   begin
+  --     wait until rising_edge(CLK);
+  --       reg_res := reg_res(0) & gbtsc_start_reset_cmd_raw;
+  --       reg_con := reg_con(0) & gbtsc_start_connect_cmd_raw;
+  --       reg_cmd := reg_cmd(0) & gbtsc_start_command_raw;
+  --       gbtsc_start_reset_cmd_i <= (reg_res(0) and not gbtsc_tx_clk_en ) or (reg_res(1) and not gbtsc_tx_clk_en);
+  --       gbtsc_start_connect_cmd_i <= (reg_con(0) and not gbtsc_tx_clk_en ) or (reg_con(1) and not gbtsc_tx_clk_en);
+  --       gbtsc_start_command_i <= (reg_cmd(0) and not gbtsc_tx_clk_en ) or (reg_cmd(1) and not gbtsc_tx_clk_en);
+  --   end process;
+
+  -- HDLC serializer
+  hdlcser_proc: process(CLK)
+  begin
+    if rising_edge(CLK) then
+      gbtsc_tx_clk_en <= gbtsc_tx_clk_en xor '1';
+      if gbtsc_tx_clk_en = '1' then
+        ELINK_TX <= hdlc_from_gbtsc(0);
+      elsif gbtsc_tx_clk_en = '0' then
+        ELINK_TX <= hdlc_from_gbtsc(1);
+      end if;
+    end if;
+  end process;
+
+  -- HDLC deserializer
+  hdlcdes_proc: process(CLK)
+  begin
+    if rising_edge(CLK) then
+      gbtsc_rx_clk_en <= gbtsc_rx_clk_en xor '1';
+      if gbtsc_rx_clk_en = '1' then
+        hdlc_to_gbtsc(1) <= ELINK_RX;
+      elsif gbtsc_rx_clk_en = '0' then
+        hdlc_to_gbtsc(0) <= ELINK_RX;
+      end if;
+    end if;
+  end process;
+
+  PROC_GBTSCA_REG_CMDS : process
+  begin
+    wait until rising_edge(CLK_SYS);
+    BUS_TX.ack  <= '0';
+    BUS_TX.unknown <= '0';
+    BUS_TX.nack <= '0';
+    BUS_TX.data <= (others => '0');
+    -- reset start flags
+    gbtsc_reset_go <= '0';
+    gbtsc_connect_go <= '0';
+    gbtsc_go <= '0';
+
+    if BUS_RX.write = '1' then
+      BUS_TX.ack <= '1';
+
+      if BUS_RX.addr(3 downto 0) = x"0" then
+        gbtsc_tx_address_i      <= BUS_RX.data(7 downto 0);
+        -- gbtsc_sca_enable_i      <= BUS_RX.data(8);
+        gbtsc_reset_go          <= BUS_RX.data(9);
+        gbtsc_connect_go        <= BUS_RX.data(10);
+        gbtsc_go                <= BUS_RX.data(11);
+      elsif BUS_RX.addr(3 downto 0) = x"1" then
+        gbtsc_tx_transID_i <= BUS_RX.data(7 downto 0);
+        gbtsc_tx_channel_i <= BUS_RX.data(15 downto 8);
+        -- gbtsc_tx_len_i     <= BUS_RX.data(23 downto 16);
+        gbtsc_tx_command_i <= BUS_RX.data(31 downto 24);
+      elsif BUS_RX.addr(3 downto 0) = x"2" then
+        gbtsc_tx_data_i <= BUS_RX.data(31 downto 0);
+      else
+        BUS_TX.ack <= '0';
+        BUS_TX.unknown <= '1';
+      end if;
+
+    elsif BUS_RX.read = '1' and gbtsc_rx_received_o = '1' then
+      BUS_TX.ack <= '1';
+
+      if BUS_RX.addr(3 downto 0) = x"0" then
+        BUS_TX.data(7 downto 0) <= gbtsc_rx_address_o;
+      elsif BUS_RX.addr(3 downto 0) = x"1" then
+        BUS_TX.data( 7 downto 0 ) <= gbtsc_rx_transID_o;
+        BUS_TX.data(15 downto 8 ) <= gbtsc_rx_channel_o;
+        BUS_TX.data(23 downto 16) <= gbtsc_rx_len_o;
+      elsif BUS_RX.addr(3 downto 0) = x"2" then
+        BUS_TX.data(31 downto 0) <= gbtsc_rx_data_o;
+      elsif BUS_RX.addr(3 downto 0) = x"3" then
+        BUS_TX.data(7 downto 0)  <= gbtsc_rx_control_o;
+        BUS_TX.data(15 downto 8) <= gbtsc_rx_error_o;
+      else
+        BUS_TX.ack  <= '0';
+        BUS_TX.unknown <= '1';
+      end if;
+
+    end if;
+  end process;
+
+
+
+  THE_CMD_SYNC : entity work.pulse_sync
+    port map(
+      CLK_A_IN        => CLK_SYS,
+      RESET_A_IN      => RESET,
+      PULSE_A_IN      => gbtsc_go,
+      CLK_B_IN        => gbtsc_tx_clk_en,
+      RESET_B_IN      => RESET,
+      PULSE_B_OUT     => gbtsc_start_command_i
+      );
+
+  THE_RESET_SYNC : entity work.pulse_sync
+    port map(
+      CLK_A_IN        => CLK_SYS,
+      RESET_A_IN      => RESET,
+      PULSE_A_IN      => gbtsc_reset_go,
+      CLK_B_IN        => gbtsc_tx_clk_en,
+      RESET_B_IN      => RESET,
+      PULSE_B_OUT     => gbtsc_start_reset_cmd_i
+      );
+
+  THE_CONNECT_SYNC : entity work.pulse_sync
+    port map(
+      CLK_A_IN        => CLK_SYS,
+      RESET_A_IN      => RESET,
+      PULSE_A_IN      => gbtsc_connect_go,
+      CLK_B_IN        => gbtsc_tx_clk_en,
+      RESET_B_IN      => RESET,
+      PULSE_B_OUT     => gbtsc_start_connect_cmd_i
+      );
+
+
+end architecture;