--- /dev/null
+-- A 16bit data interface between two devices using a common clock, 32 data lines and 4 control lines
+
+
+LIBRARY ieee;
+use ieee.std_logic_1164.all;
+USE IEEE.numeric_std.ALL;
+USE IEEE.std_logic_UNSIGNED.ALL;
+
+library work;
+use work.trb_net_std.all;
+
+entity trb_net16_med_16_CC is
+ port(
+ CLK : in std_logic;
+ CLK_EN : in std_logic;
+ RESET : in std_logic;
+
+ --Internal Connection
+ MED_DATA_IN : in std_logic_vector(c_DATA_WIDTH-1 downto 0);
+ MED_PACKET_NUM_IN : in std_logic_vector(c_NUM_WIDTH-1 downto 0);
+ MED_DATAREADY_IN : in std_logic;
+ MED_READ_OUT : out std_logic;
+ MED_DATA_OUT : out std_logic_vector(c_DATA_WIDTH-1 downto 0);
+ MED_PACKET_NUM_OUT : out std_logic_vector(c_NUM_WIDTH-1 downto 0);
+ MED_DATAREADY_OUT : out std_logic;
+ MED_READ_IN : in std_logic;
+
+ DATA_OUT : out std_logic_vector(15 downto 0);
+ DATA_VALID_OUT : out std_logic;
+ DATA_CTRL_OUT : out std_logic;
+ DATA_IN : in std_logic_vector(15 downto 0);
+ DATA_VALID_IN : in std_logic;
+ DATA_CTRL_IN : in std_logic;
+
+ STAT_OP : out std_logic_vector(15 downto 0);
+ CTRL_OP : in std_logic_vector(15 downto 0);
+ STAT_DEBUG : out std_logic_vector(63 downto 0)
+ );
+end entity;
+
+architecture trb_net16_med_16_CC_arch of trb_net16_med_16_CC is
+
+ component signal_sync is
+ generic(
+ WIDTH : integer := 18;
+ DEPTH : integer := 3
+ );
+ port(
+ RESET : in std_logic;
+ CLK0 : in std_logic;
+ CLK1 : in std_logic;
+ D_IN : in std_logic_vector(WIDTH-1 downto 0);
+ D_OUT : out std_logic_vector(WIDTH-1 downto 0)
+ );
+ end component;
+
+
+ signal reg_DATA_IN : std_logic_vector(15 downto 0);
+ signal reg_DATA_VALID_IN : std_logic;
+ signal reg_DATA_CTRL_IN : std_logic;
+
+ signal last_DATA_CTRL_IN : std_logic;
+ signal link_running_counter : unsigned(3 downto 0);
+ signal link_running : std_logic;
+
+ signal buf_DATA_VALID_OUT : std_logic;
+ signal buf_DATA_CTRL_OUT : std_logic;
+ signal buf_DATA_OUT : std_logic_vector(15 downto 0);
+ signal PRESENT_SIG : std_logic;
+ signal led_counter : unsigned(18 downto 0);
+
+ signal link_led : std_logic;
+ signal tx_led : std_logic;
+ signal rx_led : std_logic;
+ signal resync : std_logic;
+ signal resync_counter : unsigned(4 downto 0);
+ signal rx_mismatch : std_logic;
+
+ signal rx_counter : std_logic_vector(c_NUM_WIDTH-1 downto 0);
+ signal buf_MED_READ_OUT : std_logic;
+ signal buf_MED_DATAREADY_OUT : std_logic;
+ signal buf_MED_PACKET_NUM_OUT : std_logic_vector(c_NUM_WIDTH-1 downto 0);
+ signal buf_MED_DATA_OUT : std_logic_vector(c_DATA_WIDTH-1 downto 0);
+
+begin
+
+-----------------------
+--Receiver
+-----------------------
+ THE_RX_SIGNAL_SYNC: signal_sync
+ generic map(
+ DEPTH => 2,
+ WIDTH => 18
+ )
+ port map(
+ RESET => RESET,
+ D_IN(15 downto 0) => DATA_IN,
+ D_IN(16) => DATA_VALID_IN,
+ D_IN(17) => DATA_CTRL_IN,
+ CLK0 => CLK,
+ CLK1 => CLK,
+ D_OUT(15 downto 0) => reg_DATA_IN,
+ D_OUT(16) => reg_DATA_VALID_IN,
+ D_OUT(17) => reg_DATA_CTRL_IN
+ );
+
+
+ PROC_RX_COUNTER : process(CLK)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' then
+ rx_counter <= c_H0;
+ elsif buf_MED_DATAREADY_OUT = '1' and CLK_EN = '1' then
+ if rx_counter = c_max_word_number then
+ rx_counter <= (others => '0');
+ else
+ rx_counter <= rx_counter + 1;
+ end if;
+ end if;
+ end if;
+ end process;
+
+
+ buf_MED_PACKET_NUM_OUT <= rx_counter;
+ buf_MED_DATAREADY_OUT <= reg_DATA_VALID_IN and link_running;
+ buf_MED_DATA_OUT <= reg_DATA_IN;
+ buf_MED_READ_OUT <= link_running;
+ MED_READ_OUT <= buf_MED_READ_OUT;
+
+ PROC_REG_MED_OUT : process(CLK)
+ begin
+ if rising_edge(CLK) then
+ MED_DATA_OUT <= buf_MED_DATA_OUT;
+ MED_DATAREADY_OUT <= buf_MED_DATAREADY_OUT;
+ MED_PACKET_NUM_OUT<= buf_MED_PACKET_NUM_OUT;
+ end if;
+ end process;
+
+
+-----------------------
+--Link detection & Status & Control signals
+-----------------------
+
+--during idle phases, the ctrl signal changes every clock cycle
+--if no change is seen within 2 cycles, the link is broken
+--if it changes for 16 cycles, the link is running
+ PROC_DETECT_SIGNAL : process(CLK)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' then
+ link_running_counter <= to_unsigned(0,4);
+ link_running <= '0';
+ else
+ if link_running_counter = x"F" and rx_mismatch = '0' then
+ link_running <= '1';
+ else
+ link_running <= '0';
+ end if;
+ if reg_DATA_VALID_IN = '0' then
+ last_DATA_CTRL_IN <= reg_DATA_CTRL_IN;
+ if last_DATA_CTRL_IN /= reg_DATA_CTRL_IN and link_running_counter /= x"F" then
+ link_running_counter <= link_running_counter + to_unsigned(1,1);
+ elsif last_DATA_CTRL_IN = reg_DATA_CTRL_IN and link_running_counter /= 0 then
+ link_running_counter <= link_running_counter - to_unsigned(1,1);
+ end if;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ PROC_CHECK_RX_COUNTER : process(CLK)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' or CTRL_OP(15) = '1' then
+ rx_mismatch <= '0';
+ elsif link_running = '1' then
+ if (reg_DATA_CTRL_IN = '1' and reg_DATA_VALID_IN = '1' and rx_counter /= c_H0)
+ or (reg_DATA_CTRL_IN = '0' and reg_DATA_VALID_IN = '1' and rx_counter = c_H0)
+ or (buf_MED_DATAREADY_OUT = '1' and MED_READ_IN = '0') then
+ rx_mismatch <= '1';
+ end if;
+ end if;
+ end if;
+ end process;
+
+ STAT_OP(8 downto 3) <= (others => '0');
+ STAT_OP(9) <= link_led;
+ STAT_OP(10) <= rx_led;
+ STAT_OP(11) <= tx_led;
+ STAT_OP(12) <= '0';
+ STAT_OP(13) <= '0';
+ STAT_OP(14) <= '1' when link_running_counter > x"1" and link_running_counter < x"A" else '0';
+ STAT_OP(15) <= rx_mismatch;
+
+
+ PROC_ERROR : process(CLK)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' then
+ STAT_OP(2 downto 0) <= ERROR_NC;
+ else
+ if link_running = '1' then
+ STAT_OP(2 downto 0) <= ERROR_OK;
+ else
+ STAT_OP(2 downto 0) <= ERROR_NC;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ PROC_LED : process(CLK)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' then
+ led_counter <= (others => '0');
+ rx_led <= '0';
+ tx_led <= '0';
+ link_led <= '0';
+ else
+ led_counter <= led_counter + 1;
+ link_led <= link_running;
+ if led_counter(18) = '1' then
+ led_counter <= (others => '0');
+ rx_led <= '0';
+ tx_led <= '0';
+ end if;
+ if buf_MED_DATAREADY_OUT = '1' then
+ rx_led <= '1';
+ end if;
+ if MED_DATAREADY_IN = '1' and buf_MED_READ_OUT = '1' then
+ tx_led <= '1';
+ end if;
+ end if;
+ end if;
+ end process;
+
+ PROC_GEN_RESYNC : process(CLK)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' then
+ resync_counter <= (others => '0');
+ resync <= '0';
+ else
+ if CTRL_OP(15) = '1' or resync_counter /= 0 then
+ resync_counter <= resync_counter + 1;
+ resync <= '1';
+ else
+ resync_counter <= (others => '0');
+ resync <= '0';
+ end if;
+ end if;
+ end if;
+ end process;
+
+-----------------------
+--Sender
+-----------------------
+
+
+--Generate tx signals
+ PROC_SEND_DATA : process(CLK)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' then
+ buf_DATA_VALID_OUT <= '0';
+ buf_DATA_CTRL_OUT <= '0';
+ buf_DATA_OUT <= (others => '0');
+ PRESENT_SIG <= '0';
+ elsif resync = '1' then
+ buf_DATA_VALID_OUT <= '0';
+ buf_DATA_CTRL_OUT <= '1';
+ buf_DATA_OUT <= x"EEEE";
+ elsif MED_DATAREADY_IN = '1' and buf_MED_READ_OUT = '1' then
+ buf_DATA_VALID_OUT <= '1';
+ buf_DATA_OUT <= MED_DATA_IN;
+ if MED_PACKET_NUM_IN = c_H0 then
+ buf_DATA_CTRL_OUT <= '1';
+ else
+ buf_DATA_CTRL_OUT <= '0';
+ end if;
+ else
+ buf_DATA_OUT <= x"AAAA";
+ buf_DATA_CTRL_OUT <= PRESENT_SIG;
+ buf_DATA_VALID_OUT <= '0';
+ PRESENT_SIG <= not PRESENT_SIG;
+ end if;
+ end if;
+ end process;
+
+--Generate O-FF
+ PROC_OUTPUT : process(CLK)
+ begin
+ if rising_edge(CLK) then
+ DATA_VALID_OUT <= buf_DATA_VALID_OUT;
+ DATA_CTRL_OUT <= buf_DATA_CTRL_OUT;
+ DATA_OUT <= buf_DATA_OUT;
+ end if;
+ end process;
+
+
+
+
+-----------------------
+--Debug
+-----------------------
+
+STAT_DEBUG(15 downto 0) <= reg_DATA_IN;
+STAT_DEBUG(16) <= reg_DATA_VALID_IN;
+STAT_DEBUG(17) <= reg_DATA_CTRL_IN;
+STAT_DEBUG(18) <= rx_mismatch;
+STAT_DEBUG(22 downto 19)<= link_running_counter(3 downto 0);
+STAT_DEBUG(23) <= resync;
+
+
+STAT_DEBUG(63 downto 24) <= (others => '0');
+
+end architecture;
\ No newline at end of file