--- /dev/null
+-------------------------------------------------------
+--! @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;
+--============================================================================--
+--############################################################################--
+--============================================================================--
--- /dev/null
+-------------------------------------------------------
+--! @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
--- /dev/null
+-------------------------------------------------------
+--! @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;
+--============================================================================--
+--############################################################################--
+--============================================================================--
--- /dev/null
+-------------------------------------------------------
+--! @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
--- /dev/null
+-------------------------------------------------------
+--! @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;
+--============================================================================--
+--############################################################################--
+--============================================================================--
--- /dev/null
+-------------------------------------------------------
+--! @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;
+--============================================================================--
+--############################################################################--
+--============================================================================--
--- /dev/null
+-------------------------------------------------------
+--! @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
--- /dev/null
+-------------------------------------------------------
+--! @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
--- /dev/null
+-------------------------------------------------------
+--! @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;
+--============================================================================--
+--############################################################################--
+--============================================================================--
--- /dev/null
+-------------------------------------------------------
+--! @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
--- /dev/null
+-------------------------------------------------------
+--! @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
--- /dev/null
+-------------------------------------------------------
+--! @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
--- /dev/null
+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;