use IEEE.std_logic_1164.all;
entity PCSD is
-GENERIC(
+generic(
CONFIG_FILE : String;
QUAD_MODE : String;
CH0_CDR_SRC : String := "REFCLK_EXT";
component PCSD_sim
-GENERIC(
+generic(
CONFIG_FILE : String;
QUAD_MODE : String;
CH0_CDR_SRC : String;
use STD.TEXTIO.all;
entity sfp_0_200_int is
- GENERIC (USER_CONFIG_FILE : String := "sfp_0_200_int.txt");
+ generic (USER_CONFIG_FILE : String := "sfp_0_200_int.txt");
port (
------------------
-- CH0 --
component PCSD
--synopsys translate_off
-GENERIC(
+generic(
CONFIG_FILE : String;
QUAD_MODE : String;
CH0_CDR_SRC : String := "REFCLK_EXT";
library work;
use work.trb_net_std.all;
use work.trb_net_components.all;
+use work.med_sync_define.all;
entity med_ecp3_sfp_sync is
generic(
SCI_READ : in std_logic := '0';
SCI_WRITE : in std_logic := '0';
SCI_ACK : out std_logic := '0';
-
+ SCI_NACK : out std_logic := '0';
-- Status and control port
STAT_OP : out std_logic_vector (15 downto 0);
CTRL_OP : in std_logic_vector (15 downto 0) := (others => '0');
serdes_rst_qd_c : in std_logic
);
end component;
-
-component rx_reset_fsm is
- port (
- RST_N : in std_logic;
- RX_REFCLK : in std_logic;
- TX_PLL_LOL_QD_S : in std_logic;
- RX_SERDES_RST_CH_C: out std_logic;
- RX_CDR_LOL_CH_S : in std_logic;
- RX_LOS_LOW_CH_S : in std_logic;
- RX_PCS_RST_CH_C : out std_logic;
- STATE_OUT : out std_logic_vector(3 downto 0)
- );
-end component;
-component tx_reset_fsm is
- port (
- RST_N : in std_logic;
- TX_REFCLK : in std_logic;
- TX_PLL_LOL_QD_S : in std_logic;
- RST_QD_C : out std_logic;
- TX_PCS_RST_CH_C : out std_logic;
- STATE_OUT : out std_logic_vector(3 downto 0)
- );
-end component;
-
-constant K_IDLE : std_logic_vector(7 downto 0) := x"BC";
+
+
+
signal clk_200_i : std_logic;
signal clk_200_internal : std_logic;
signal sci_write_shift_i : std_logic_vector(2 downto 0);
signal sci_read_shift_i : std_logic_vector(2 downto 0);
+signal wa_position : std_logic_vector(15 downto 0) := x"FFFF";
+signal tx_allow : std_logic;
+signal rx_allow : std_logic;
+
signal rx_fsm_state : std_logic_vector(3 downto 0);
signal tx_fsm_state : std_logic_vector(3 downto 0);
signal debug_reg : std_logic_vector(63 downto 0);
+type sci_ctrl is (IDLE, SCTRL, SCTRL_WAIT, SCTRL_WAIT2, SCTRL_FINISH, GET_WA, GET_WA_WAIT, GET_WA_WAIT2, GET_WA_FINISH);
+signal sci_state : sci_ctrl;
+signal sci_timer : unsigned(12 downto 0) := (others => '0');
+
+
begin
clk_200_internal <= CLK;
clk_200_i <= clk_rx_full;
RX_CDR_LOL_CH_S => rx_cdr_lol,
RX_LOS_LOW_CH_S => rx_los_low,
RX_PCS_RST_CH_C => rx_pcs_rst,
+ WA_POSITION => wa_position(3 downto 0),
STATE_OUT => rx_fsm_state
);
);
+PROC_ALLOW : process begin
+ wait until rising_edge(clk_200_i);
+ if rx_fsm_state = x"6" then
+ rx_allow <= '1';
+ else
+ rx_allow <= '0';
+ end if;
+ if rx_fsm_state = x"6" then --TODO: needs to be comma detection
+ tx_allow <= '1';
+ else
+ tx_allow <= '0';
+ end if;
+end process;
+
+
-------------------------------------------------
-- TX Data
-------------------------------------------------
- tx_data <= x"BC";
- tx_k <= '1';
+THE_TX : tx_control
+ port map(
+ CLK_200 => clk_200_i,
+ CLK_100 => SYSCLK,
+ RESET_IN => RESET,
+
+ TX_DATA_IN => MED_DATA_IN,
+ TX_PACKET_NUMBER_IN => MED_PACKET_NUM_IN,
+ TX_WRITE_IN => MED_DATAREADY_IN,
+ TX_READ_OUT => MED_READ_OUT,
+
+ TX_DATA_OUT => tx_data,
+ TX_K_OUT => tx_k,
+
+ REQUEST_RETRANSMIT_IN => open, --TODO
+ REQUEST_POSITION_IN => open, --TODO
+
+ START_RETRANSMIT_IN => open, --TODO
+ START_POSITION_IN => open, --TODO
+
+ SEND_DLM => open, --TODO
+ SEND_DLM_WORD => open, --TODO
+
+ SEND_LINK_RESET_IN => CTRL_OP(15),
+ TX_ALLOW_IN => tx_allow,
+ RX_ALLOW_IN => rx_allow,
+
+ DEBUG_OUT => open,
+ STAT_REG_OUT => open
+ );
+
-------------------------------------------------
-- SCI
-------------------------------------------------
-PROC_SCI : process begin
+-- PROC_SCI : process begin
+-- wait until rising_edge(SYSCLK);
+-- if SCI_READ = '1' or SCI_WRITE = '1' then
+-- sci_ch_i(0) <= not SCI_ADDR(6) and not SCI_ADDR(7) and not SCI_ADDR(8);
+-- sci_ch_i(1) <= SCI_ADDR(6) and not SCI_ADDR(7) and not SCI_ADDR(8);
+-- sci_ch_i(2) <= not SCI_ADDR(6) and SCI_ADDR(7) and not SCI_ADDR(8);
+-- sci_ch_i(3) <= SCI_ADDR(6) and SCI_ADDR(7) and not SCI_ADDR(8);
+-- sci_qd_i <= not SCI_ADDR(6) and not SCI_ADDR(7) and SCI_ADDR(8);
+-- sci_reg_i <= SCI_ADDR(6) and not SCI_ADDR(7) and SCI_ADDR(8);
+-- sci_addr_i <= SCI_ADDR;
+-- sci_data_in_i <= SCI_DATA_IN;
+-- end if;
+-- sci_read_shift_i <= sci_read_shift_i(1 downto 0) & SCI_READ;
+-- sci_write_shift_i <= sci_write_shift_i(1 downto 0) & SCI_WRITE;
+-- if sci_reg_i = '1' then
+-- SCI_DATA_OUT <= debug_reg(8*(to_integer(unsigned(SCI_ADDR(2 downto 0))))+7 downto 8*(to_integer(unsigned(SCI_ADDR(2 downto 0)))));
+-- sci_read_shift_i(2) <= '1';
+-- else
+-- SCI_DATA_OUT <= sci_data_out_i;
+-- end if;
+-- end process;
+
+-- sci_write_i <= or_all(sci_write_shift_i);
+-- sci_read_i <= or_all(sci_read_shift_i);
+-- SCI_ACK <= sci_write_shift_i(2) or sci_read_shift_i(2);
+
+
+PROC_SCI_CTRL: process
+ variable cnt : integer range 0 to 3 := 0;
+begin
wait until rising_edge(SYSCLK);
- if SCI_READ = '1' or SCI_WRITE = '1' then
- sci_ch_i(0) <= not SCI_ADDR(6) and not SCI_ADDR(7) and not SCI_ADDR(8);
- sci_ch_i(1) <= SCI_ADDR(6) and not SCI_ADDR(7) and not SCI_ADDR(8);
- sci_ch_i(2) <= not SCI_ADDR(6) and SCI_ADDR(7) and not SCI_ADDR(8);
- sci_ch_i(3) <= SCI_ADDR(6) and SCI_ADDR(7) and not SCI_ADDR(8);
- sci_qd_i <= not SCI_ADDR(6) and not SCI_ADDR(7) and SCI_ADDR(8);
- sci_reg_i <= SCI_ADDR(6) and not SCI_ADDR(7) and SCI_ADDR(8);
- sci_addr_i <= SCI_ADDR;
- sci_data_in_i <= SCI_DATA_IN;
- end if;
- sci_read_shift_i <= sci_read_shift_i(1 downto 0) & SCI_READ;
- sci_write_shift_i <= sci_write_shift_i(1 downto 0) & SCI_WRITE;
- if sci_reg_i = '1' then
- SCI_DATA_OUT <= debug_reg(8*(to_integer(unsigned(SCI_ADDR(2 downto 0))))+7 downto 8*(to_integer(unsigned(SCI_ADDR(2 downto 0)))));
- sci_read_shift_i(2) <= '1';
+ SCI_ACK <= '0';
+ case sci_state is
+ when IDLE =>
+ sci_ch_i <= x"0";
+ sci_qd_i <= '0';
+ sci_reg_i <= '0';
+ sci_read_i <= '0';
+ sci_write_i <= '0';
+ sci_timer <= sci_timer + 1;
+ if SCI_READ = '1' or SCI_WRITE = '1' then
+ sci_ch_i(0) <= not SCI_ADDR(6) and not SCI_ADDR(7) and not SCI_ADDR(8);
+ sci_ch_i(1) <= SCI_ADDR(6) and not SCI_ADDR(7) and not SCI_ADDR(8);
+ sci_ch_i(2) <= not SCI_ADDR(6) and SCI_ADDR(7) and not SCI_ADDR(8);
+ sci_ch_i(3) <= SCI_ADDR(6) and SCI_ADDR(7) and not SCI_ADDR(8);
+ sci_qd_i <= not SCI_ADDR(6) and not SCI_ADDR(7) and SCI_ADDR(8);
+ sci_reg_i <= SCI_ADDR(6) and not SCI_ADDR(7) and SCI_ADDR(8);
+ sci_addr_i <= SCI_ADDR;
+ sci_data_in_i <= SCI_DATA_IN;
+ sci_read_i <= SCI_READ and not (SCI_ADDR(6) and not SCI_ADDR(7) and SCI_ADDR(8));
+ sci_write_i <= SCI_WRITE and not (SCI_ADDR(6) and not SCI_ADDR(7) and SCI_ADDR(8));
+ sci_state <= SCTRL;
+ elsif sci_timer(sci_timer'left) = '1' then
+ sci_timer <= (others => '0');
+ sci_state <= GET_WA;
+ end if;
+ when SCTRL =>
+ if sci_reg_i = '1' then
+ SCI_DATA_OUT <= debug_reg(8*(to_integer(unsigned(SCI_ADDR(2 downto 0))))+7 downto 8*(to_integer(unsigned(SCI_ADDR(2 downto 0)))));
+ SCI_ACK <= '1';
+ sci_write_i <= '0';
+ sci_read_i <= '0';
+ sci_state <= IDLE;
+ else
+ sci_state <= SCTRL_WAIT;
+ end if;
+ when SCTRL_WAIT =>
+ sci_state <= SCTRL_WAIT2;
+ when SCTRL_WAIT2 =>
+ sci_state <= SCTRL_FINISH;
+ when SCTRL_FINISH =>
+ SCI_DATA_OUT <= sci_data_out_i;
+ SCI_ACK <= '1';
+ sci_write_i <= '0';
+ sci_read_i <= '0';
+ sci_state <= IDLE;
+
+ when GET_WA =>
+ if cnt = 3 then
+ cnt := 0;
+ sci_state <= IDLE;
+ else
+ sci_state <= GET_WA_WAIT;
+ sci_addr_i <= '0' & x"22";
+ sci_ch_i <= x"0";
+ sci_ch_i(cnt) <= '1';
+ sci_read_i <= '1';
+ end if;
+ when GET_WA_WAIT =>
+ sci_state <= GET_WA_WAIT2;
+ when GET_WA_WAIT2 =>
+ sci_state <= GET_WA_FINISH;
+ when GET_WA_FINISH =>
+ wa_position(cnt*4+3 downto cnt*4) <= sci_data_out_i(3 downto 0);
+ sci_state <= GET_WA;
+ cnt := cnt + 1;
+ end case;
+
+ if (SCI_READ = '1' or SCI_WRITE = '1') and sci_state /= IDLE then
+ SCI_NACK <= '1';
else
- SCI_DATA_OUT <= sci_data_out_i;
+ SCI_NACK <= '0';
end if;
+
end process;
-sci_write_i <= or_all(sci_write_shift_i);
-sci_read_i <= or_all(sci_read_shift_i);
-SCI_ACK <= sci_write_shift_i(2) or sci_read_shift_i(2);
-
+
-------------------------------------------------
-- Debug Registers
-------------------------------------------------
debug_reg(23 downto 20) <= tx_fsm_state;
debug_reg(31 downto 24) <= tx_data;
-debug_reg(63 downto 32) <= (others => '0');
+
+debug_reg(47 downto 32) <= wa_position;
+debug_reg(63 downto 48) <= (others => '0');
STAT_DEBUG <= debug_reg;
--- /dev/null
+library ieee;
+USE IEEE.std_logic_1164.ALL;
+USE IEEE.std_logic_ARITH.ALL;
+USE IEEE.std_logic_UNSIGNED.ALL;
+
+package med_sync_define is
+
+constant K_IDLE : std_logic_vector(7 downto 0) := x"BC";
+constant D_IDLE0 : std_logic_vector(7 downto 0) := x"C5";
+constant D_IDLE1 : std_logic_vector(7 downto 0) := x"50";
+constant K_SOP : std_logic_vector(7 downto 0) := x"FB";
+constant K_EOP : std_logic_vector(7 downto 0) := x"FD";
+constant K_BGN : std_logic_vector(7 downto 0) := x"1C";
+constant K_REQ : std_logic_vector(7 downto 0) := x"7C";
+constant K_RST : std_logic_vector(7 downto 0) := x"FE";
+constant K_DLM : std_logic_vector(7 downto 0) := x"DC";
+
+
+
+component tx_control is
+ port(
+ CLK_200 : in std_logic;
+ CLK_100 : in std_logic;
+ RESET_IN : in std_logic;
+
+ TX_DATA_IN : in std_logic_vector(15 downto 0);
+ TX_PACKET_NUMBER_IN : in std_logic_vector( 2 downto 0);
+ TX_WRITE_IN : in std_logic;
+ TX_READ_OUT : out std_logic;
+
+ TX_DATA_OUT : out std_logic_vector( 7 downto 0);
+ TX_K_OUT : out std_logic;
+
+ REQUEST_RETRANSMIT_IN : in std_logic := '0';
+ REQUEST_POSITION_IN : in std_logic_vector( 7 downto 0) := (others => '0');
+
+ START_RETRANSMIT_IN : in std_logic := '0';
+ START_POSITION_IN : in std_logic_vector( 7 downto 0) := (others => '0');
+
+ SEND_DLM : in std_logic := '0';
+ SEND_DLM_WORD : in std_logic_vector( 7 downto 0) := (others => '0');
+
+ SEND_LINK_RESET_IN : in std_logic := '0';
+ TX_ALLOW_IN : in std_logic := '0';
+ RX_ALLOW_IN : in std_logic := '0';
+
+ DEBUG_OUT : out std_logic_vector(31 downto 0);
+ STAT_REG_OUT : out std_logic_vector(31 downto 0)
+ );
+end component;
+
+
+
+component rx_reset_fsm is
+ port (
+ RST_N : in std_logic;
+ RX_REFCLK : in std_logic;
+ TX_PLL_LOL_QD_S : in std_logic;
+ RX_SERDES_RST_CH_C: out std_logic;
+ RX_CDR_LOL_CH_S : in std_logic;
+ RX_LOS_LOW_CH_S : in std_logic;
+ RX_PCS_RST_CH_C : out std_logic;
+ --fix word alignment position to 0 for non-slave links!
+ WA_POSITION : in std_logic_vector(3 downto 0) := x"0";
+ STATE_OUT : out std_logic_vector(3 downto 0)
+ );
+end component;
+
+component tx_reset_fsm is
+ port (
+ RST_N : in std_logic;
+ TX_REFCLK : in std_logic;
+ TX_PLL_LOL_QD_S : in std_logic;
+ RST_QD_C : out std_logic;
+ TX_PCS_RST_CH_C : out std_logic;
+ STATE_OUT : out std_logic_vector(3 downto 0)
+ );
+end component;
+
+
+
+
+end package;
\ No newline at end of file
RX_CDR_LOL_CH_S : in std_logic;
RX_LOS_LOW_CH_S : in std_logic;
RX_PCS_RST_CH_C : out std_logic;
+ --fix word alignment position to 0 for non-slave links!
+ WA_POSITION : in std_logic_vector(3 downto 0) := x"0";
STATE_OUT : out std_logic_vector(3 downto 0)
);
end entity ;
rx_serdes_rst_ch_c_int <= '0';
if rx_lol_los_int = rx_lol_los_del then --NO RISING OR FALLING EDGES
if timer2 = '1' then
- if rx_lol_los_int = '1' then
+ if rx_lol_los_int = '1' or WA_POSITION /= x"0" then
ns <= WAIT_FOR_PLOL;
else
ns <= NORMAL;
end case;
end process;
-
+
+
+
end architecture;
\ No newline at end of file
--- /dev/null
+LIBRARY ieee ;
+LIBRARY work ;
+USE ieee.NUMERIC_STD.all ;
+USE ieee.std_logic_1164.all ;
+USE work.med_sync_define.all ;
+USE work.trb_net_components.all ;
+USE work.trb_net_std.all ;
+
+entity tx_control_tb is
+end entity;
+
+architecture tx_control_tb_arch of tx_control_tb is
+ signal stat_reg_out : std_logic_vector (31 downto 0) ;
+ signal start_position_in : std_logic_vector (7 downto 0) := (others => '0') ;
+ signal clk_100 : std_logic := '1';
+ signal clk_200 : std_logic := '1';
+ signal request_position_in : std_logic_vector (7 downto 0) := (others => '0') ;
+ signal tx_k_out : std_logic ;
+ signal send_dlm : std_logic := '0' ;
+ signal tx_read_out : std_logic ;
+ signal tx_allow_in : std_logic := '1' ;
+ signal send_dlm_word : std_logic_vector (7 downto 0) := (others => '0') ;
+ signal reset_in : std_logic := '0' ;
+ signal tx_packet_number_in : std_logic_vector (2 downto 0) ;
+ signal tx_data_in : std_logic_vector (15 downto 0) := (others => '0') ;
+ signal tx_write_in : std_logic := '0';
+ signal tx_data_out : std_logic_vector (7 downto 0) ;
+ signal start_retransmit_in : std_logic := '0' ;
+ signal debug_out : std_logic_vector (31 downto 0) ;
+ signal send_link_reset_in : std_logic := '0' ;
+ signal request_retransmit_in : std_logic := '0' ;
+
+
+ component tx_control
+ port (
+ STAT_REG_OUT : out std_logic_vector (31 downto 0) ;
+ START_POSITION_IN : in std_logic_vector (7 downto 0) ;
+ CLK_100 : in STD_LOGIC ;
+ CLK_200 : in STD_LOGIC ;
+ REQUEST_POSITION_IN : in std_logic_vector (7 downto 0) ;
+ TX_K_OUT : out STD_LOGIC ;
+ SEND_DLM : in STD_LOGIC ;
+ TX_READ_OUT : out STD_LOGIC ;
+ TX_ALLOW_IN : in STD_LOGIC ;
+ SEND_DLM_WORD : in std_logic_vector (7 downto 0) ;
+ RESET_IN : in STD_LOGIC ;
+ TX_PACKET_NUMBER_IN : in std_logic_vector (2 downto 0) ;
+ TX_DATA_IN : in std_logic_vector (15 downto 0) ;
+ TX_WRITE_IN : in STD_LOGIC ;
+ TX_DATA_OUT : out std_logic_vector (7 downto 0) ;
+ START_RETRANSMIT_IN : in STD_LOGIC ;
+ DEBUG_OUT : out std_logic_vector (31 downto 0) ;
+ SEND_LINK_RESET_IN : in STD_LOGIC ;
+ REQUEST_RETRANSMIT_IN : in STD_LOGIC );
+ end component ;
+
+
+begin
+ DUT : tx_control
+ port map (
+ STAT_REG_OUT => STAT_REG_OUT ,
+ START_POSITION_IN => START_POSITION_IN ,
+ CLK_100 => CLK_100 ,
+ CLK_200 => CLK_200 ,
+ REQUEST_POSITION_IN => REQUEST_POSITION_IN ,
+ TX_K_OUT => TX_K_OUT ,
+ SEND_DLM => SEND_DLM ,
+ TX_READ_OUT => TX_READ_OUT ,
+ TX_ALLOW_IN => TX_ALLOW_IN ,
+ SEND_DLM_WORD => SEND_DLM_WORD ,
+ RESET_IN => RESET_IN ,
+ TX_PACKET_NUMBER_IN => TX_PACKET_NUMBER_IN ,
+ TX_DATA_IN => TX_DATA_IN ,
+ TX_WRITE_IN => TX_WRITE_IN ,
+ TX_DATA_OUT => TX_DATA_OUT ,
+ START_RETRANSMIT_IN => START_RETRANSMIT_IN ,
+ DEBUG_OUT => DEBUG_OUT ,
+ SEND_LINK_RESET_IN => SEND_LINK_RESET_IN ,
+ REQUEST_RETRANSMIT_IN => REQUEST_RETRANSMIT_IN
+ );
+
+CLK_100 <= not CLK_100 after 5 ns;
+CLK_200 <= not CLK_200 after 2.5 ns;
+
+TX_ALLOW_IN <= '0', '1' after 50 ns;
+
+
+process begin
+ wait for 100 ns;
+ wait until rising_edge(clk_100); wait for 1 ns;
+ TX_DATA_IN <= x"0038"; TX_PACKET_NUMBER_IN <= "100"; TX_WRITE_IN <= '1';
+ wait until rising_edge(clk_100); wait for 1 ns;
+ TX_DATA_IN <= x"1111"; TX_PACKET_NUMBER_IN <= "000"; TX_WRITE_IN <= '1';
+ wait until rising_edge(clk_100); wait for 1 ns;
+ TX_DATA_IN <= x"2222"; TX_PACKET_NUMBER_IN <= "001"; TX_WRITE_IN <= '1';
+ wait until rising_edge(clk_100); wait for 1 ns;
+ TX_DATA_IN <= x"3333"; TX_PACKET_NUMBER_IN <= "010"; TX_WRITE_IN <= '1';
+ wait until rising_edge(clk_100); wait for 1 ns;
+ TX_DATA_IN <= x"4444"; TX_PACKET_NUMBER_IN <= "011"; TX_WRITE_IN <= '1';
+ wait until rising_edge(clk_100); wait for 1 ns;
+ TX_DATA_IN <= x"0000"; TX_PACKET_NUMBER_IN <= "100"; TX_WRITE_IN <= '0';
+end process;
+
+end architecture;
+
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.trb_net_std.all;
+use work.trb_net_components.all;
+use work.med_sync_define.all;
+
+entity tx_control is
+ port(
+ CLK_200 : in std_logic;
+ CLK_100 : in std_logic;
+ RESET_IN : in std_logic;
+
+ TX_DATA_IN : in std_logic_vector(15 downto 0);
+ TX_PACKET_NUMBER_IN : in std_logic_vector(2 downto 0);
+ TX_WRITE_IN : in std_logic;
+ TX_READ_OUT : out std_logic;
+
+ TX_DATA_OUT : out std_logic_vector( 7 downto 0);
+ TX_K_OUT : out std_logic;
+
+ REQUEST_RETRANSMIT_IN : in std_logic := '0';
+ REQUEST_POSITION_IN : in std_logic_vector( 7 downto 0) := (others => '0');
+
+ START_RETRANSMIT_IN : in std_logic := '0';
+ START_POSITION_IN : in std_logic_vector( 7 downto 0) := (others => '0');
+
+ SEND_DLM : in std_logic := '0';
+ SEND_DLM_WORD : in std_logic_vector( 7 downto 0) := (others => '0');
+
+ SEND_LINK_RESET_IN : in std_logic := '0';
+ TX_ALLOW_IN : in std_logic := '0';
+ RX_ALLOW_IN : in std_logic := '0';
+
+ DEBUG_OUT : out std_logic_vector(31 downto 0);
+ STAT_REG_OUT : out std_logic_vector(31 downto 0)
+ );
+end entity;
+
+
+
+architecture arch of tx_control is
+
+-- gk 05.10.10
+ component lattice_ecp3_fifo_18x16_dualport_oreg
+ port (
+ Data: in std_logic_vector(17 downto 0);
+ WrClock: in std_logic;
+ RdClock: in std_logic;
+ WrEn: in std_logic;
+ RdEn: in std_logic;
+ Reset: in std_logic;
+ RPReset: in std_logic;
+ Q: out std_logic_vector(17 downto 0);
+ Empty: out std_logic;
+ Full: out std_logic;
+ AlmostFull: out std_logic
+ );
+ end component;
+
+-- gk 05.10.10
+component trb_net_CRC8 is
+ port(
+ CLK : in std_logic;
+ RESET : in std_logic;
+ CLK_EN : in std_logic;
+ DATA_IN : in std_logic_vector(7 downto 0);
+ CRC_OUT : out std_logic_vector(7 downto 0);
+ CRC_match : out std_logic
+ );
+end component;
+
+ type state_t is (SEND_IDLE_L, SEND_IDLE_H, SEND_DATA_L, SEND_DATA_H, SEND_DLM_L, SEND_DLM_H,
+ SEND_START_L, SEND_START_H, SEND_REQUEST_L, SEND_REQUEST_H,
+ SEND_RESET, SEND_CHKSUM_L, SEND_CHKSUM_H); -- gk 05.10.10
+ signal current_state : state_t;
+
+ type ram_t is array(0 to 255) of std_logic_vector(17 downto 0);
+ signal ram : ram_t;
+
+ signal ram_write : std_logic := '0';
+ signal ram_write_addr : unsigned(7 downto 0) := (others => '0');
+ signal ram_read : std_logic := '0';
+ signal ram_read_addr : unsigned(7 downto 0) := (others => '0');
+ signal ram_dout : std_logic_vector(17 downto 0);
+ signal next_ram_dout : std_logic_vector(17 downto 0);
+ signal ram_fill_level : unsigned(7 downto 0);
+ signal ram_empty : std_logic;
+ signal ram_afull : std_logic;
+
+ signal request_position_q : std_logic_vector( 7 downto 0);
+ signal restart_position_q : std_logic_vector( 7 downto 0);
+ signal request_position_i : std_logic_vector( 7 downto 0);
+ signal restart_position_i : std_logic_vector( 7 downto 0);
+ signal make_request_i : std_logic;
+ signal make_restart_i : std_logic;
+ signal load_read_pointer_i : std_logic;
+ signal send_dlm_in_i : std_logic;
+ signal send_dlm_i : std_logic;
+ signal start_retransmit_i : std_logic;
+ signal request_retransmit_i : std_logic;
+
+ signal buf_tx_read_out : std_logic;
+ signal tx_data_200 : std_logic_vector(17 downto 0);
+ signal tx_allow_qtx : std_logic;
+ signal rx_allow_qtx : std_logic;
+ signal tx_allow_q : std_logic;
+ signal send_link_reset_qtx : std_logic;
+ signal ct_fifo_empty : std_logic;
+ signal ct_fifo_write : std_logic := '0';
+ signal ct_fifo_read : std_logic := '0';
+ signal ct_fifo_full : std_logic;
+ signal ct_fifo_afull : std_logic;
+ signal ct_fifo_reset : std_logic;
+ signal last_ct_fifo_empty : std_logic;
+ signal last_ct_fifo_read : std_logic;
+
+ -- gk 05.10.10
+ signal save_sop : std_logic;
+ signal save_eop : std_logic;
+ signal load_sop : std_logic;
+ signal load_eop : std_logic;
+ signal crc_reset : std_logic;
+ signal crc_q : std_logic_vector(7 downto 0);
+ signal crc_en : std_logic;
+ signal crc_data : std_logic_vector(7 downto 0);
+
+begin
+
+----------------------------------------------------------------------
+-- Clock Domain Transfer
+----------------------------------------------------------------------
+-- gk 05.10.10
+ THE_CT_FIFO : lattice_ecp3_fifo_18x16_dualport_oreg
+ port map(
+ Data(15 downto 0) => TX_DATA_IN,
+ Data(16) => save_sop,
+ Data(17) => save_eop,
+ WrClock => CLK_100,
+ RdClock => CLK_200,
+ WrEn => ct_fifo_write,
+ RdEn => ct_fifo_read,
+ Reset => ct_fifo_reset,
+ RPReset => ct_fifo_reset,
+ Q(17 downto 0) => tx_data_200,
+ Empty => ct_fifo_empty,
+ Full => ct_fifo_full,
+ AlmostFull => ct_fifo_afull
+ );
+
+ THE_RD_PROC : process(CLK_100)
+ begin
+ if rising_edge(CLK_100) then
+ buf_tx_read_out <= tx_allow_q and not ct_fifo_afull ;
+ end if;
+ end process;
+
+ ct_fifo_reset <= not tx_allow_qtx;
+ TX_READ_OUT <= buf_tx_read_out;
+
+ ct_fifo_write <= buf_tx_read_out and TX_WRITE_IN;
+ ct_fifo_read <= tx_allow_qtx and not ram_afull and not ct_fifo_empty;
+
+ last_ct_fifo_read <= ct_fifo_read when rising_edge(CLK_200);
+ last_ct_fifo_empty <= ct_fifo_empty when rising_edge(CLK_200);
+
+ save_sop <= '1' when (TX_PACKET_NUMBER_IN = c_H0) else '0';
+ save_eop <= '1' when (TX_PACKET_NUMBER_IN = c_F3) else '0';
+
+----------------------------------------------------------------------
+-- RAM
+----------------------------------------------------------------------
+
+
+ THE_RAM_WR_PROC : process(CLK_200, RESET_IN)
+ begin
+ if RESET_IN = '1' then
+ ram_write <= '0';
+ elsif rising_edge(CLK_200) then
+ ram_write <= last_ct_fifo_read and not last_ct_fifo_empty;
+ end if;
+ end process;
+
+--RAM
+ THE_RAM_PROC : process(CLK_200)
+ begin
+ if rising_edge(CLK_200) then
+ if ram_write = '1' then
+ ram((to_integer(ram_write_addr))) <= tx_data_200;
+ end if;
+ next_ram_dout <= ram(to_integer(ram_read_addr));
+ ram_dout <= next_ram_dout;
+ end if;
+ end process;
+
+--RAM read pointer
+ THE_READ_CNT : process(CLK_200, RESET_IN)
+ begin
+ if RESET_IN = '1' then
+ ram_read_addr <= (others => '0');
+ elsif rising_edge(CLK_200) then
+ if tx_allow_qtx = '0' then
+ ram_read_addr <= (others => '0');
+ elsif load_read_pointer_i = '1' then
+ ram_read_addr <= unsigned(restart_position_i);
+ elsif ram_read = '1' then
+ ram_read_addr <= ram_read_addr + to_unsigned(1,1);
+ end if;
+ end if;
+ end process;
+
+--RAM write pointer
+ THE_WRITE_CNT : process(CLK_200, RESET_IN)
+ begin
+ if RESET_IN = '1' then
+ ram_write_addr <= (others => '0');
+ elsif rising_edge(CLK_200) then
+ if tx_allow_qtx = '0' then
+ ram_write_addr <= (others => '0');
+ elsif ram_write = '1' then
+ ram_write_addr <= ram_write_addr + to_unsigned(1,1);
+ end if;
+ end if;
+ end process;
+
+
+--RAM fill level counter
+ THE_FILL_CNT : process(CLK_200, RESET_IN)
+ begin
+ if RESET_IN = '1' then
+ ram_fill_level <= (others => '0');
+ elsif rising_edge(CLK_200) then
+ if tx_allow_qtx = '0' then
+ ram_fill_level <= (others => '0');
+ else
+ ram_fill_level <= ram_write_addr - ram_read_addr;
+ end if;
+ end if;
+ end process;
+
+
+--RAM empty
+-- ram_empty <= not or_all(std_logic_vector(ram_write_addr) xor std_logic_vector(ram_read_addr)) and not RESET_IN;
+ ram_empty <= '1' when (ram_write_addr = ram_read_addr) or RESET_IN = '1' else '0';
+ ram_afull <= '1' when ram_fill_level >= 4 else '0';
+
+
+
+----------------------------------------------------------------------
+-- TX control state machine
+----------------------------------------------------------------------
+
+ THE_DATA_CONTROL_FSM : process(CLK_200, RESET_IN)
+ begin
+ if rising_edge(CLK_200) then
+-- ram_read <= '0';
+ TX_K_OUT <= '0';
+
+ case current_state is
+ when SEND_IDLE_L =>
+ TX_DATA_OUT <= K_IDLE;
+ TX_K_OUT <= '1';
+ current_state <= SEND_IDLE_H;
+
+ when SEND_IDLE_H =>
+ if rx_allow_qtx = '1' then
+ TX_DATA_OUT <= D_IDLE1;
+ else
+ TX_DATA_OUT <= D_IDLE0;
+ end if;
+
+ when SEND_DATA_L =>
+ TX_DATA_OUT <= ram_dout(7 downto 0);
+ load_sop <= ram_dout(16);
+ load_eop <= ram_dout(17);
+ current_state <= SEND_DATA_H;
+
+ when SEND_DATA_H =>
+ TX_DATA_OUT <= ram_dout(15 downto 8);
+
+ when SEND_CHKSUM_L =>
+ TX_DATA_OUT <= K_EOP;
+ TX_K_OUT <= '1';
+ load_sop <= '0';
+ load_eop <= '0';
+ current_state <= SEND_CHKSUM_H;
+
+ when SEND_CHKSUM_H =>
+ TX_DATA_OUT <= crc_q;
+
+ when SEND_START_L =>
+ TX_DATA_OUT <= K_BGN;
+ TX_K_OUT <= '1';
+ current_state <= SEND_START_H;
+
+ when SEND_START_H =>
+ TX_DATA_OUT <= std_logic_vector(ram_read_addr);
+
+ when SEND_REQUEST_L =>
+ TX_DATA_OUT <= K_REQ;
+ TX_K_OUT <= '1';
+ current_state <= SEND_REQUEST_H;
+
+ when SEND_DLM_L =>
+ TX_DATA_OUT <= K_DLM;
+ TX_K_OUT <= '1';
+ current_state <= SEND_DLM_H;
+
+ when SEND_DLM_H =>
+ TX_DATA_OUT <= SEND_DLM_WORD;
+
+ when SEND_REQUEST_H =>
+ TX_DATA_OUT <= request_position_i;
+
+ when SEND_RESET =>
+ TX_DATA_OUT <= K_RST;
+ TX_K_OUT <= '1';
+ if send_link_reset_qtx = '0' then
+ current_state <= SEND_IDLE_L;
+ end if;
+
+ when others =>
+ current_state <= SEND_IDLE_L;
+ end case;
+
+ if current_state = SEND_START_H or
+ current_state = SEND_IDLE_H or
+ current_state = SEND_DATA_H or
+ current_state = SEND_DLM_H or
+ current_state = SEND_REQUEST_H or
+ current_state = SEND_CHKSUM_H then
+ if tx_allow_qtx = '0' then
+ current_state <= SEND_IDLE_L;
+ elsif send_link_reset_qtx = '1' then
+ current_state <= SEND_RESET;
+ elsif make_request_i = '1' then
+ current_state <= SEND_REQUEST_L;
+ elsif make_restart_i = '1' then
+ current_state <= SEND_START_L;
+ elsif send_dlm_i = '1' then
+ current_state <= SEND_DLM_L;
+-- elsif (load_eop = '1') then
+-- current_state <= SEND_CHKSUM_L;
+ elsif ram_empty = '0' then
+-- ram_read <= '1';
+ current_state <= SEND_DATA_L;
+ else
+ current_state <= SEND_IDLE_L;
+ end if;
+
+ end if;
+ end if;
+ --async because of oreg.
+ if (current_state = SEND_START_H or current_state = SEND_IDLE_H or current_state = SEND_DATA_H or
+ current_state = SEND_DLM_H or current_state = SEND_REQUEST_H or current_state = SEND_CHKSUM_H)
+ and ram_empty = '0' and tx_allow_qtx = '1' and send_link_reset_qtx = '0'
+ and make_request_i = '0' and make_restart_i = '0' and send_dlm_i = '0' then
+ ram_read <= '1';
+ else
+ ram_read <= '0';
+ end if;
+ if RESET_IN = '1' then
+ ram_read <= '0';
+ end if;
+ end process;
+
+----------------------------------------------------------------------
+--
+----------------------------------------------------------------------
+
+tx_allow_qtx <= TX_ALLOW_IN when rising_edge(CLK_200);
+rx_allow_qtx <= RX_ALLOW_IN when rising_edge(CLK_200);
+
+send_link_reset_qtx <= SEND_LINK_RESET_IN when rising_edge(CLK_200);
+tx_allow_q <= tx_allow_qtx when rising_edge(CLK_100);
+
+ THE_RETRANSMIT_PULSE_SYNC_1 : pulse_sync
+ port map(
+ CLK_A_IN => CLK_100,
+ RESET_A_IN => RESET_IN,
+ PULSE_A_IN => REQUEST_RETRANSMIT_IN,
+ CLK_B_IN => CLK_200,
+ RESET_B_IN => RESET_IN,
+ PULSE_B_OUT => request_retransmit_i
+ );
+
+ THE_RETRANSMIT_PULSE_SYNC_2 : pulse_sync
+ port map(
+ CLK_A_IN => CLK_100,
+ RESET_A_IN => RESET_IN,
+ PULSE_A_IN => START_RETRANSMIT_IN,
+ CLK_B_IN => CLK_200,
+ RESET_B_IN => RESET_IN,
+ PULSE_B_OUT => start_retransmit_i
+ );
+
+ THE_RETRANSMIT_PULSE_SYNC_3 : pulse_sync
+ port map(
+ CLK_A_IN => CLK_100,
+ RESET_A_IN => RESET_IN,
+ PULSE_A_IN => SEND_DLM,
+ CLK_B_IN => CLK_200,
+ RESET_B_IN => RESET_IN,
+ PULSE_B_OUT => send_dlm_in_i
+ );
+
+ THE_POSITION_REG : process(CLK_100)
+ begin
+ if rising_edge(CLK_100) then
+ if REQUEST_RETRANSMIT_IN = '1' then
+ request_position_q <= REQUEST_POSITION_IN;
+ end if;
+ if START_RETRANSMIT_IN = '1' then
+ restart_position_q <= START_POSITION_IN;
+ end if;
+ end if;
+ end process;
+
+
+--Store Request Retransmit position
+ THE_STORE_REQUEST_PROC : process(CLK_200, RESET_IN)
+ begin
+ if RESET_IN = '1' then
+ make_request_i <= '0';
+ request_position_i <= (others => '0');
+ elsif rising_edge(CLK_200) then
+ if tx_allow_qtx = '0' then
+ make_request_i <= '0';
+ request_position_i <= (others => '0');
+ elsif request_retransmit_i = '1' then
+ make_request_i <= '1';
+ request_position_i <= request_position_q;
+ elsif current_state = SEND_REQUEST_L then
+ make_request_i <= '0';
+ elsif current_state = SEND_REQUEST_H then
+ request_position_i <= (others => '0');
+ end if;
+ end if;
+ end process;
+
+
+--Store Restart position
+ THE_STORE_RESTART_PROC : process(CLK_200, RESET_IN)
+ begin
+ if RESET_IN = '1' then
+ make_restart_i <= '0';
+ restart_position_i <= (others => '0');
+ elsif rising_edge(CLK_200) then
+ if tx_allow_qtx = '0' then
+ make_restart_i <= '0';
+ restart_position_i <= (others => '0');
+ elsif start_retransmit_i = '1' then
+ make_restart_i <= '1';
+ restart_position_i <= restart_position_q;
+ elsif current_state = SEND_START_L then
+ make_restart_i <= '0';
+ elsif current_state = SEND_START_H then
+ restart_position_i <= (others => '0');
+ end if;
+ end if;
+ end process;
+
+--Store Restart position
+ THE_STORE_DLM_PROC : process(CLK_200, RESET_IN)
+ begin
+ if RESET_IN = '1' then
+ send_dlm_i <= '0';
+ elsif rising_edge(CLK_200) then
+ if tx_allow_qtx = '0' then
+ send_dlm_i <= '0';
+ elsif send_dlm_in_i = '1' then
+ send_dlm_i <= '1';
+ elsif current_state = SEND_DLM_L then
+ send_dlm_i <= '0';
+ end if;
+ end if;
+ end process;
+
+ load_read_pointer_i <= '1' when current_state = SEND_START_L else '0';
+
+ -- gk 05.10.10
+ crc_reset <= '1' when ((RESET_IN = '1') or (current_state = SEND_CHKSUM_H) or (current_state = SEND_START_H)) else '0';
+ crc_en <= '1' when ((current_state = SEND_DATA_L) or (current_state = SEND_DATA_H)) else '0';
+ crc_data <= ram_dout(15 downto 8) when (current_state = SEND_DATA_H) else ram_dout(7 downto 0);
+
+ -- gk 05.10.10
+ CRC_CALC : trb_net_CRC8
+ port map(
+ CLK => CLK_200,
+ RESET => crc_reset,
+ CLK_EN => crc_en,
+ DATA_IN => crc_data,
+ CRC_OUT => crc_q,
+ CRC_match => open
+ );
+
+
+----------------------------------------------------------------------
+-- Debug
+----------------------------------------------------------------------
+ DEBUG_OUT(0) <= ram_read;
+ DEBUG_OUT(1) <= ct_fifo_write;
+ DEBUG_OUT(2) <= ct_fifo_read;
+ DEBUG_OUT(3) <= tx_allow_qtx;
+ DEBUG_OUT(4) <= ram_empty;
+ DEBUG_OUT(5) <= ram_afull;
+
+
+ process(CLK_100)
+ begin
+ if rising_edge(CLK_100) then
+ STAT_REG_OUT(7 downto 0) <= std_logic_vector(ram_fill_level);
+ STAT_REG_OUT(15 downto 8) <= std_logic_vector(ram_read_addr);
+ STAT_REG_OUT(16) <= ram_afull;
+ STAT_REG_OUT(17) <= ram_empty;
+ STAT_REG_OUT(18) <= tx_allow_qtx;
+ STAT_REG_OUT(19) <= TX_ALLOW_IN;
+ STAT_REG_OUT(20) <= make_restart_i;
+ STAT_REG_OUT(21) <= make_request_i;
+ STAT_REG_OUT(22) <= load_eop;
+ STAT_REG_OUT(31 downto 23) <= (others => '0');
+ end if;
+ end process;
+
+
+
+
+end architecture;
\ No newline at end of file