From fdd188abbb82c979047613b80c5c935f0064ba69 Mon Sep 17 00:00:00 2001 From: hadeshyp Date: Fri, 8 Feb 2013 14:25:56 +0000 Subject: [PATCH] added new syncmode files, JM --- media_interfaces/med_ecp3_sfp_sync.vhd | 164 ++++++----- media_interfaces/sync/med_sync_define.vhd | 105 ++++++- media_interfaces/sync/rx_control.vhd | 256 ++++++++++++++++++ media_interfaces/sync/tb/med_ecp3_sync_tb.vhd | 228 ++++++++++++++++ media_interfaces/sync/tb/tx_control_tb.vhd | 115 +++++++- media_interfaces/sync/tx_control.vhd | 49 +--- 6 files changed, 805 insertions(+), 112 deletions(-) create mode 100644 media_interfaces/sync/rx_control.vhd create mode 100644 media_interfaces/sync/tb/med_ecp3_sync_tb.vhd diff --git a/media_interfaces/med_ecp3_sfp_sync.vhd b/media_interfaces/med_ecp3_sfp_sync.vhd index 36104c1..9f8286d 100644 --- a/media_interfaces/med_ecp3_sfp_sync.vhd +++ b/media_interfaces/med_ecp3_sfp_sync.vhd @@ -29,9 +29,14 @@ entity med_ecp3_sfp_sync is MED_PACKET_NUM_OUT : out std_logic_vector(c_NUM_WIDTH-1 downto 0) := (others => '0'); MED_DATAREADY_OUT : out std_logic := '0'; MED_READ_IN : in std_logic; - REFCLK2CORE_OUT : out std_logic := '0'; CLK_RX_HALF_OUT : out std_logic := '0'; CLK_RX_FULL_OUT : out std_logic := '0'; + + IS_SLAVE : in std_logic := '0'; + RX_DLM : out std_logic := '0'; + RX_DLM_WORD : out std_logic_vector(7 downto 0) := x"00"; + TX_DLM : in std_logic := '0'; + TX_DLM_WORD : in std_logic_vector(7 downto 0) := x"00"; --SFP Connection SD_RXD_P_IN : in std_logic; SD_RXD_N_IN : in std_logic; @@ -160,18 +165,30 @@ signal sci_write_i : 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); +signal wa_position : std_logic_vector(15 downto 0) := x"FFFF"; +signal wa_position_rx : std_logic_vector(15 downto 0) := x"FFFF"; +signal tx_allow : std_logic; +signal rx_allow : std_logic; +signal request_retr_i : std_logic; +signal start_retr_i : std_logic; +signal request_retr_position_i : std_logic_vector(7 downto 0); +signal start_retr_position_i : std_logic_vector(7 downto 0); +signal send_link_reset_i : std_logic; +signal make_link_reset_i : std_logic; +signal got_link_ready_i : std_logic; + +signal stat_rx_control_i : std_logic_vector(31 downto 0); +signal stat_tx_control_i : std_logic_vector(31 downto 0); +signal debug_rx_control_i : std_logic_vector(31 downto 0); +signal debug_tx_control_i : std_logic_vector(31 downto 0); +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'); - +signal start_timer : unsigned(23 downto 0) := (others => '0'); begin clk_200_internal <= CLK; @@ -242,7 +259,7 @@ THE_SERDES : serdes_sync_0 ); ------------------------------------------------- --- Reset FSM +-- Reset FSM & Link states ------------------------------------------------- THE_RX_FSM : rx_reset_fsm port map( @@ -253,7 +270,7 @@ THE_RX_FSM : rx_reset_fsm 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), + WA_POSITION => wa_position_rx(3 downto 0), STATE_OUT => rx_fsm_state ); @@ -267,20 +284,32 @@ THE_TX_FSM : tx_reset_fsm STATE_OUT => tx_fsm_state ); +wa_position_rx <= wa_position when IS_SLAVE = '1' else x"0000"; PROC_ALLOW : process begin wait until rising_edge(clk_200_i); - if rx_fsm_state = x"6" then + if rx_fsm_state = x"6" and (IS_SLAVE = '1' or start_timer(start_timer'left) = '1') then rx_allow <= '1'; else rx_allow <= '0'; end if; - if rx_fsm_state = x"6" then --TODO: needs to be comma detection + if rx_fsm_state = x"6" and (IS_SLAVE = '1' or start_timer(start_timer'left) = '1') then tx_allow <= '1'; else tx_allow <= '0'; end if; end process; + +PROC_START_TIMER : process begin + wait until rising_edge(clk_200_i); + if got_link_ready_i = '1' then + if start_timer(start_timer'left) = '0' then + start_timer <= start_timer + 1; + end if; + else + start_timer <= (others => '0'); + end if; +end process; ------------------------------------------------- @@ -300,53 +329,62 @@ THE_TX : tx_control TX_DATA_OUT => tx_data, TX_K_OUT => tx_k, - REQUEST_RETRANSMIT_IN => open, --TODO - REQUEST_POSITION_IN => open, --TODO + REQUEST_RETRANSMIT_IN => request_retr_i, --TODO + REQUEST_POSITION_IN => request_retr_position_i, --TODO - START_RETRANSMIT_IN => open, --TODO - START_POSITION_IN => open, --TODO + START_RETRANSMIT_IN => start_retr_i, --TODO + START_POSITION_IN => request_retr_position_i, --TODO - SEND_DLM => open, --TODO - SEND_DLM_WORD => open, --TODO + SEND_DLM => TX_DLM, + SEND_DLM_WORD => TX_DLM_WORD, SEND_LINK_RESET_IN => CTRL_OP(15), TX_ALLOW_IN => tx_allow, RX_ALLOW_IN => rx_allow, - DEBUG_OUT => open, - STAT_REG_OUT => open + DEBUG_OUT => debug_tx_control_i, + STAT_REG_OUT => stat_tx_control_i ); + +------------------------------------------------- +-- RX Data +------------------------------------------------- +THE_RX_CONTROL : rx_control + port map( + CLK_200 => clk_200_i, + CLK_100 => SYSCLK, + RESET_IN => CLEAR, + + RX_DATA_OUT => MED_DATA_OUT, + RX_PACKET_NUMBER_OUT => MED_PACKET_NUM_OUT, + RX_WRITE_OUT => MED_DATAREADY_OUT, + RX_READ_IN => MED_READ_IN, + + RX_DATA_IN => rx_data, + RX_K_IN => rx_k, + + REQUEST_RETRANSMIT_OUT => request_retr_i, + REQUEST_POSITION_OUT => request_retr_position_i, + + START_RETRANSMIT_OUT => start_retr_i, + START_POSITION_OUT => start_retr_position_i, + + --send_dlm: 200 MHz, 1 clock strobe, data valid until next DLM + RX_DLM => RX_DLM, + RX_DLM_WORD => RX_DLM_WORD, + SEND_LINK_RESET_OUT => send_link_reset_i, + MAKE_RESET_OUT => make_link_reset_i, + RX_ALLOW_IN => rx_allow, + GOT_LINK_READY => got_link_ready_i, + + DEBUG_OUT => debug_rx_control_i, + STAT_REG_OUT => stat_rx_control_i + ); ------------------------------------------------- -- SCI ------------------------------------------------- --- 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 4 := 0; @@ -370,7 +408,7 @@ begin 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_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 @@ -436,31 +474,35 @@ debug_reg(4) <= rx_k; debug_reg(5) <= rx_error; debug_reg(6) <= rx_los_low; debug_reg(7) <= rx_cdr_lol; -debug_reg(15 downto 8) <= rx_data; -debug_reg(16) <= '0'; -debug_reg(17) <= tx_k; -debug_reg(18) <= tx_pll_lol; -debug_reg(19) <= lsm_status; -debug_reg(23 downto 20) <= tx_fsm_state; -debug_reg(31 downto 24) <= tx_data; +debug_reg(8) <= tx_k; +debug_reg(9) <= tx_pll_lol; +debug_reg(10) <= lsm_status; +debug_reg(11) <= make_link_reset_i; +debug_reg(15 downto 12) <= tx_fsm_state; +-- debug_reg(31 downto 24) <= tx_data; +debug_reg(16) <= '0'; +debug_reg(17) <= tx_allow; +debug_reg(18) <= RESET; +debug_reg(19) <= CLEAR; +debug_reg(31 downto 20) <= debug_rx_control_i(4) & debug_rx_control_i(2 downto 0) & debug_rx_control_i(15 downto 8); -debug_reg(47 downto 32) <= wa_position; - -debug_reg(63 downto 48) <= (others => '0'); +debug_reg(35 downto 32) <= wa_position(3 downto 0); +debug_reg(39 downto 36) <= x"0"; +debug_reg(63 downto 40) <= debug_rx_control_i(23 downto 0); STAT_DEBUG <= debug_reg; -STAT_OP(15) <= '0'; +STAT_OP(15) <= send_link_reset_i when rising_edge(SYSCLK); STAT_OP(14) <= '0'; -STAT_OP(13) <= not rx_allow when rising_edge(SYSCLK); --make trbnet reset +STAT_OP(13) <= ((make_link_reset_i and IS_SLAVE)) when rising_edge(SYSCLK); --make trbnet reset STAT_OP(12) <= '0'; STAT_OP(11) <= '0'; STAT_OP(10) <= rx_allow; STAT_OP(9) <= tx_allow; STAT_OP(8 downto 4) <= (others => '0'); -STAT_OP(3 downto 0) <= x"7"; +STAT_OP(3 downto 0) <= x"0" when rx_allow = '1' and tx_allow = '1' else x"7"; end architecture; diff --git a/media_interfaces/sync/med_sync_define.vhd b/media_interfaces/sync/med_sync_define.vhd index 793234e..4e17c4c 100644 --- a/media_interfaces/sync/med_sync_define.vhd +++ b/media_interfaces/sync/med_sync_define.vhd @@ -15,6 +15,39 @@ 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 rx_control is + port( + CLK_200 : in std_logic; + CLK_100 : in std_logic; + RESET_IN : in std_logic; + + RX_DATA_OUT : out std_logic_vector(15 downto 0); + RX_PACKET_NUMBER_OUT : out std_logic_vector(2 downto 0); + RX_WRITE_OUT : out std_logic; + RX_READ_IN : in std_logic; + + RX_DATA_IN : in std_logic_vector( 7 downto 0); + RX_K_IN : in std_logic; + + REQUEST_RETRANSMIT_OUT : out std_logic := '0'; + REQUEST_POSITION_OUT : out std_logic_vector( 7 downto 0) := (others => '0'); + + START_RETRANSMIT_OUT : out std_logic := '0'; + START_POSITION_OUT : out std_logic_vector( 7 downto 0) := (others => '0'); + + --send_dlm: 200 MHz, 1 clock strobe, data valid until next DLM + RX_DLM : out std_logic := '0'; + RX_DLM_WORD : out std_logic_vector( 7 downto 0) := (others => '0'); + + SEND_LINK_RESET_OUT : out std_logic := '0'; + MAKE_RESET_OUT : out std_logic := '0'; + RX_ALLOW_IN : in std_logic := '0'; + GOT_LINK_READY : out 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 tx_control is @@ -76,7 +109,77 @@ component tx_reset_fsm is STATE_OUT : out std_logic_vector(3 downto 0) ); end component; - + + +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; + +component med_ecp3_sfp_sync is + generic( + SERDES_NUM : integer range 0 to 3 := 0 + ); + port( + CLK : in std_logic; -- SerDes clock + SYSCLK : in std_logic; -- fabric clock + RESET : in std_logic; -- synchronous reset + CLEAR : in std_logic; -- asynchronous reset + CLK_EN : in std_logic; + --Internal Connection + MED_DATA_IN : in std_logic_vector(15 downto 0); + MED_PACKET_NUM_IN : in std_logic_vector(2 downto 0); + MED_DATAREADY_IN : in std_logic; + MED_READ_OUT : out std_logic := '0'; + MED_DATA_OUT : out std_logic_vector(15 downto 0) := (others => '0'); + MED_PACKET_NUM_OUT : out std_logic_vector(2 downto 0) := (others => '0'); + MED_DATAREADY_OUT : out std_logic := '0'; + MED_READ_IN : in std_logic; + REFCLK2CORE_OUT : out std_logic := '0'; + CLK_RX_HALF_OUT : out std_logic := '0'; + CLK_RX_FULL_OUT : out std_logic := '0'; + + IS_SLAVE : in std_logic := '0'; + RX_DLM : out std_logic := '0'; + RX_DLM_WORD : out std_logic_vector(7 downto 0) := x"00"; + TX_DLM : in std_logic := '0'; + TX_DLM_WORD : in std_logic_vector(7 downto 0) := x"00"; + --SFP Connection + SD_RXD_P_IN : in std_logic; + SD_RXD_N_IN : in std_logic; + SD_TXD_P_OUT : out std_logic; + SD_TXD_N_OUT : out std_logic; + SD_REFCLK_P_IN : in std_logic; + SD_REFCLK_N_IN : in std_logic; + SD_PRSNT_N_IN : in std_logic; -- SFP Present ('0' = SFP in place, '1' = no SFP mounted) + SD_LOS_IN : in std_logic; -- SFP Loss Of Signal ('0' = OK, '1' = no signal) + SD_TXDIS_OUT : out std_logic := '0'; -- SFP disable + --Control Interface + SCI_DATA_IN : in std_logic_vector(7 downto 0) := (others => '0'); + SCI_DATA_OUT : out std_logic_vector(7 downto 0) := (others => '0'); + SCI_ADDR : in std_logic_vector(8 downto 0) := (others => '0'); + 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); + STAT_DEBUG : out std_logic_vector (63 downto 0); + CTRL_DEBUG : in std_logic_vector (63 downto 0) + ); +end component; diff --git a/media_interfaces/sync/rx_control.vhd b/media_interfaces/sync/rx_control.vhd new file mode 100644 index 0000000..ab18a22 --- /dev/null +++ b/media_interfaces/sync/rx_control.vhd @@ -0,0 +1,256 @@ +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 rx_control is + port( + CLK_200 : in std_logic; + CLK_100 : in std_logic; + RESET_IN : in std_logic; + + RX_DATA_OUT : out std_logic_vector(15 downto 0); + RX_PACKET_NUMBER_OUT : out std_logic_vector(2 downto 0); + RX_WRITE_OUT : out std_logic; + RX_READ_IN : in std_logic; + + RX_DATA_IN : in std_logic_vector( 7 downto 0); + RX_K_IN : in std_logic; + + REQUEST_RETRANSMIT_OUT : out std_logic := '0'; + REQUEST_POSITION_OUT : out std_logic_vector( 7 downto 0) := (others => '0'); + + START_RETRANSMIT_OUT : out std_logic := '0'; + START_POSITION_OUT : out std_logic_vector( 7 downto 0) := (others => '0'); + + --send_dlm: 200 MHz, 1 clock strobe, data valid until next DLM + RX_DLM : out std_logic := '0'; + RX_DLM_WORD : out std_logic_vector( 7 downto 0) := (others => '0'); + + SEND_LINK_RESET_OUT : out std_logic := '0'; + MAKE_RESET_OUT : out std_logic := '0'; + RX_ALLOW_IN : in std_logic := '0'; + GOT_LINK_READY : out 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 rx_control_arch of rx_control is + +type rx_state_t is (SLEEP, WAIT_1, FIRST, GET_DATA, GET_IDLE, GET_DLM, MAKE_RESET, START_RETR); +signal rx_state : rx_state_t; +signal rx_state_bits : std_logic_vector(3 downto 0); + +signal rx_data : std_logic_vector(17 downto 0); +signal ct_fifo_write : std_logic := '0'; +signal ct_fifo_read : std_logic := '0'; +signal ct_fifo_reset : std_logic := '0'; +signal ct_fifo_data_out : std_logic_vector(17 downto 0); +signal ct_fifo_empty : std_logic; +signal ct_fifo_full : std_logic; +signal ct_fifo_afull : std_logic; +signal last_ct_fifo_empty : std_logic; +signal last_ct_fifo_read : std_logic; + +signal tmp_link_ready_i : std_logic := '0'; +signal got_link_ready_i : std_logic := '0'; +signal start_retr_i : std_logic; +signal start_retr_pos_i : std_logic_vector(7 downto 0); +signal rx_dlm_i : std_logic; +signal rx_dlm_word_i : std_logic_vector(7 downto 0); + +signal send_link_reset_i : std_logic; +signal make_reset_i : std_logic; +signal next_sop : std_logic; + +signal reg_rx_data_in : std_logic_vector(7 downto 0); +signal reg_rx_k_in : std_logic; + +begin + +---------------------------------------------------------------------- +-- Data to Endpoint +---------------------------------------------------------------------- +--note: no handshaking, read signal can be ignored! + +ct_fifo_read <= not ct_fifo_reset when rising_edge(CLK_100); + +RX_DATA_OUT <= ct_fifo_data_out(15 downto 0) ; +RX_WRITE_OUT <= last_ct_fifo_read and not last_ct_fifo_empty when rising_edge(CLK_100); + +last_ct_fifo_read <= ct_fifo_read when rising_edge(CLK_100); +last_ct_fifo_empty <= ct_fifo_empty when rising_edge(CLK_100); + +---------------------------------------------------------------------- +-- Clock Domain Transfer +---------------------------------------------------------------------- +THE_CT_FIFO : lattice_ecp3_fifo_18x16_dualport_oreg + port map( + Data => rx_data, + WrClock => CLK_200, + RdClock => CLK_100, + WrEn => ct_fifo_write, + RdEn => ct_fifo_read, + Reset => ct_fifo_reset, + RPReset => ct_fifo_reset, + Q(17 downto 0) => ct_fifo_data_out, + Empty => ct_fifo_empty, + Full => ct_fifo_full, + AlmostFull => ct_fifo_afull + ); + +ct_fifo_reset <= not RX_ALLOW_IN; + + + +---------------------------------------------------------------------- +-- Read incoming data +---------------------------------------------------------------------- +PROC_RX_FSM : process begin + wait until rising_edge(CLK_200); + ct_fifo_write <= '0'; + start_retr_i <= '0'; + rx_dlm_i <= '0'; + + case rx_state is + when SLEEP => + rx_state_bits <= x"1"; + got_link_ready_i <= '0'; + if RX_ALLOW_IN = '1' and reg_rx_k_in = '1' and reg_rx_data_in = x"BC" then + rx_state <= wAIT_1; + end if; + + when WAIT_1 => + rx_state <= FIRST; + + when FIRST => + rx_state_bits <= x"2"; + if reg_rx_k_in = '1' then + case reg_rx_data_in is + when K_IDLE => + rx_state <= GET_IDLE; + when K_RST => + rx_state <= MAKE_RESET; + when K_DLM => + rx_state <= GET_DLM; + when K_REQ => + rx_state <= START_RETR; + when others => null; + end case; + else + rx_data(7 downto 0) <= reg_rx_data_in; + rx_state <= GET_DATA; + end if; + + when GET_IDLE => + rx_state_bits <= x"3"; + rx_state <= FIRST; + next_sop <= '1'; + if reg_rx_k_in = '0' and reg_rx_data_in = D_IDLE0 then + tmp_link_ready_i <= '0'; + got_link_ready_i <= tmp_link_ready_i; + elsif reg_rx_k_in = '0' and reg_rx_data_in = D_IDLE1 then + got_link_ready_i <= '1'; + tmp_link_ready_i <= '1'; + else + rx_state <= SLEEP; + end if; + + when GET_DATA => + rx_state_bits <= x"4"; + if reg_rx_k_in = '0' then + next_sop <= '0'; + rx_data(15 downto 8)<= reg_rx_data_in; + rx_data(16) <= next_sop; + ct_fifo_write <= '1'; + else + rx_state <= SLEEP; + end if; + rx_state <= FIRST; + + when GET_DLM => + rx_state_bits <= x"5"; + rx_dlm_i <= '1'; + rx_dlm_word_i <= reg_rx_data_in; + rx_state <= FIRST; + + when START_RETR => + rx_state_bits <= x"6"; + start_retr_i <= '1'; + start_retr_pos_i <= reg_rx_data_in; + rx_state <= FIRST; + + when MAKE_RESET => + rx_state_bits <= x"F"; + if reg_rx_k_in = '1' and reg_rx_data_in = K_RST then + send_link_reset_i <= '1'; + make_reset_i <= '0'; + got_link_ready_i <= '0'; + else + send_link_reset_i <= '0'; + make_reset_i <= '1'; + rx_state <= SLEEP; + end if; + + end case; + + if RESET_IN = '1' then + rx_state <= SLEEP; + end if; +end process; + +reg_rx_data_in <= RX_DATA_IN when rising_edge(CLK_200); +reg_rx_k_in <= RX_K_IN when rising_edge(CLK_200); + + +---------------------------------------------------------------------- +-- Signals out +---------------------------------------------------------------------- +GOT_LINK_READY <= got_link_ready_i; + +START_RETRANSMIT_OUT <= start_retr_i; +START_POSITION_OUT <= start_retr_pos_i; + +RX_DLM <= rx_dlm_i; +RX_DLM_WORD <= rx_dlm_word_i; + +REQUEST_RETRANSMIT_OUT <= '0'; --TODO: check incoming data +REQUEST_POSITION_OUT <= x"00"; --TODO: check incoming data + +SEND_LINK_RESET_OUT <= send_link_reset_i; +MAKE_RESET_OUT <= make_reset_i; + + +---------------------------------------------------------------------- +-- Debug and Status +---------------------------------------------------------------------- +STAT_REG_OUT(3 downto 0) <= rx_state_bits; +STAT_REG_OUT(4) <= got_link_ready_i; +STAT_REG_OUT(5) <= ct_fifo_afull; +STAT_REG_OUT(6) <= ct_fifo_empty; +STAT_REG_OUT(7) <= ct_fifo_write; +STAT_REG_OUT(15 downto 8) <= reg_rx_data_in(7 downto 0); +STAT_REG_OUT(16) <= rx_data(16); +STAT_REG_OUT(31 downto 18) <= (others => '0'); + + +DEBUG_OUT(3 downto 0) <= rx_state_bits; +DEBUG_OUT(4) <= got_link_ready_i; +DEBUG_OUT(5) <= ct_fifo_afull; +DEBUG_OUT(6) <= ct_fifo_empty; +DEBUG_OUT(7) <= ct_fifo_write; +DEBUG_OUT(15 downto 8) <= reg_rx_data_in(7 downto 0); +DEBUG_OUT(16) <= rx_data(16); +DEBUG_OUT(31 downto 18) <= (others => '0'); + + + + +end architecture; \ No newline at end of file diff --git a/media_interfaces/sync/tb/med_ecp3_sync_tb.vhd b/media_interfaces/sync/tb/med_ecp3_sync_tb.vhd new file mode 100644 index 0000000..86c8757 --- /dev/null +++ b/media_interfaces/sync/tb/med_ecp3_sync_tb.vhd @@ -0,0 +1,228 @@ + +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 med_ecp3_sfp_sync_tb is +end entity; + +architecture arch of med_ecp3_sfp_sync_tb is + + + +component med_ecp3_sfp_sync is + generic( + SERDES_NUM : integer range 0 to 3 := 0 + ); + port( + CLK : in std_logic; -- SerDes clock + SYSCLK : in std_logic; -- fabric clock + RESET : in std_logic; -- synchronous reset + CLEAR : in std_logic; -- asynchronous reset + CLK_EN : 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 := '0'; + MED_DATA_OUT : out std_logic_vector(c_DATA_WIDTH-1 downto 0) := (others => '0'); + MED_PACKET_NUM_OUT : out std_logic_vector(c_NUM_WIDTH-1 downto 0) := (others => '0'); + MED_DATAREADY_OUT : out std_logic := '0'; + MED_READ_IN : in std_logic; + CLK_RX_HALF_OUT : out std_logic := '0'; + CLK_RX_FULL_OUT : out std_logic := '0'; + + IS_SLAVE : in std_logic := '0'; + RX_DLM : out std_logic := '0'; + RX_DLM_WORD : out std_logic_vector(7 downto 0) := x"00"; + TX_DLM : in std_logic := '0'; + TX_DLM_WORD : in std_logic_vector(7 downto 0) := x"00"; + --SFP Connection + SD_RXD_P_IN : in std_logic; + SD_RXD_N_IN : in std_logic; + SD_TXD_P_OUT : out std_logic; + SD_TXD_N_OUT : out std_logic; + SD_REFCLK_P_IN : in std_logic; + SD_REFCLK_N_IN : in std_logic; + SD_PRSNT_N_IN : in std_logic; -- SFP Present ('0' = SFP in place, '1' = no SFP mounted) + SD_LOS_IN : in std_logic; -- SFP Loss Of Signal ('0' = OK, '1' = no signal) + SD_TXDIS_OUT : out std_logic := '0'; -- SFP disable + --Control Interface + SCI_DATA_IN : in std_logic_vector(7 downto 0) := (others => '0'); + SCI_DATA_OUT : out std_logic_vector(7 downto 0) := (others => '0'); + SCI_ADDR : in std_logic_vector(8 downto 0) := (others => '0'); + 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'); + STAT_DEBUG : out std_logic_vector (63 downto 0); + CTRL_DEBUG : in std_logic_vector (63 downto 0) := (others => '0') + ); +end component; + + +signal clk_100_m, clk_100_s : std_logic := '1'; +signal clk_200_m, clk_200_s : std_logic := '1'; + +signal reset_m : std_logic := '1'; +signal clear_m : std_logic := '1'; +signal reset_s : std_logic := '1'; +signal clear_s : std_logic := '1'; + +signal med_data_in_m : std_logic_vector(15 downto 0) := (others => '0'); +signal med_packet_num_in_m : std_logic_vector(2 downto 0) := (others => '0'); +signal med_dataready_in_m : std_logic := '0'; +signal med_read_out_m : std_logic := '0'; +signal med_data_out_m : std_logic_vector(15 downto 0) := (others => '0'); +signal med_packet_num_out_m : std_logic_vector(2 downto 0) := (others => '0'); +signal med_dataready_out_m : std_logic := '0'; +signal med_read_in_m : std_logic := '0'; + +signal med_data_in_s : std_logic_vector(15 downto 0) := (others => '0'); +signal med_packet_num_in_s : std_logic_vector(2 downto 0) := (others => '0'); +signal med_dataready_in_s : std_logic := '0'; +signal med_read_out_s : std_logic := '0'; +signal med_data_out_s : std_logic_vector(15 downto 0) := (others => '0'); +signal med_packet_num_out_s : std_logic_vector(2 downto 0) := (others => '0'); +signal med_dataready_out_s : std_logic := '0'; +signal med_read_in_s : std_logic := '0'; + +signal tx_dlm_m : std_logic := '0'; +signal tx_dlm_word_m : std_logic_vector(7 downto 0) := (others => '0'); +signal rx_dlm_s : std_logic := '0'; +signal rx_dlm_word_s : std_logic_vector(7 downto 0) := (others => '0'); +signal tx_dlm_s : std_logic := '0'; +signal tx_dlm_word_s : std_logic_vector(7 downto 0) := (others => '0'); + +signal RX_P, RX_N, TX_P, TX_N : std_logic; +signal RX_P_S, RX_N_S, TX_P_S, TX_N_S : std_logic; + +signal clk_rxfull_s : std_logic; +signal clk_rxhalf_s : std_logic; + +begin + +reset_m <= '0' after 201 ns; +clear_m <= '0' after 51 ns; +reset_s <= '0' after 201 ns; +clear_s <= '0' after 51 ns; + +RX_P_S <= transport TX_P after 123 ns; +RX_N_S <= transport TX_N after 123 ns; +RX_P <= transport TX_P_S after 123 ns; +RX_N <= transport TX_N_S after 123 ns; + +clk_100_m <= not clk_100_m after 5 ns; +clk_200_m <= not clk_200_m after 2.5 ns; +clk_100_s <= clk_rxhalf_s; +clk_200_s <= not clk_200_s after 2.501 ns; + + +THE_MASTER : med_ecp3_sfp_sync + port map( + CLK => clk_200_m, + SYSCLK => clk_100_m, + RESET => reset_m, + CLEAR => clear_m, + CLK_EN => '1', + --Internal Connection + MED_DATA_IN => med_data_in_m, + MED_PACKET_NUM_IN => med_packet_num_in_m, + MED_DATAREADY_IN => med_dataready_in_m, + MED_READ_OUT => med_read_out_m, + MED_DATA_OUT => med_data_out_m, + MED_PACKET_NUM_OUT => med_packet_num_out_m, + MED_DATAREADY_OUT => med_dataready_out_m, + MED_READ_IN => med_read_in_m, + CLK_RX_HALF_OUT => open, + CLK_RX_FULL_OUT => open, + + IS_SLAVE => '0', + RX_DLM => open, + RX_DLM_WORD => open, + TX_DLM => tx_dlm_m, + TX_DLM_WORD => tx_dlm_word_m, + --SFP Connection + SD_RXD_P_IN => RX_P, + SD_RXD_N_IN => RX_N, + SD_TXD_P_OUT => TX_P, + SD_TXD_N_OUT => TX_N, + SD_REFCLK_P_IN => '0', + SD_REFCLK_N_IN => '0', + SD_PRSNT_N_IN => '0', + SD_LOS_IN => '0', + SD_TXDIS_OUT => open, + --Control Interface + SCI_DATA_IN => (others => '0'), + SCI_DATA_OUT => open, + SCI_ADDR => (others => '0'), + SCI_READ => '0', + SCI_WRITE => '0', + SCI_ACK => open, + SCI_NACK => open, + -- Status and control port + STAT_OP => open, + CTRL_OP => (others => '0'), + STAT_DEBUG => open, + CTRL_DEBUG => (others => '0') + ); + + +THE_SLAVE : med_ecp3_sfp_sync + port map( + CLK => clk_200_s, + SYSCLK => clk_100_s, + RESET => reset_s, + CLEAR => clear_s, + CLK_EN => '1', + --Internal Connection + MED_DATA_IN => med_data_in_s, + MED_PACKET_NUM_IN => med_packet_num_in_s, + MED_DATAREADY_IN => med_dataready_in_s, + MED_READ_OUT => med_read_out_s, + MED_DATA_OUT => med_data_out_s, + MED_PACKET_NUM_OUT => med_packet_num_out_s, + MED_DATAREADY_OUT => med_dataready_out_s, + MED_READ_IN => med_read_in_s, + CLK_RX_HALF_OUT => clk_rxhalf_s, + CLK_RX_FULL_OUT => clk_rxfull_s, + + IS_SLAVE => '1', + RX_DLM => rx_dlm_s, + RX_DLM_WORD => rx_dlm_word_s, + TX_DLM => tx_dlm_s, + TX_DLM_WORD => tx_dlm_word_s, + --SFP Connection + SD_RXD_P_IN => RX_P_S, + SD_RXD_N_IN => RX_N_S, + SD_TXD_P_OUT => TX_P_S, + SD_TXD_N_OUT => TX_N_S, + SD_REFCLK_P_IN => '0', + SD_REFCLK_N_IN => '0', + SD_PRSNT_N_IN => '0', + SD_LOS_IN => '0', + SD_TXDIS_OUT => open, + --Control Interface + SCI_DATA_IN => (others => '0'), + SCI_DATA_OUT => open, + SCI_ADDR => (others => '0'), + SCI_READ => '0', + SCI_WRITE => '0', + SCI_ACK => open, + SCI_NACK => open, + -- Status and control port + STAT_OP => open, + CTRL_OP => (others => '0'), + STAT_DEBUG => open, + CTRL_DEBUG => (others => '0') + ); + + +end architecture; \ No newline at end of file diff --git a/media_interfaces/sync/tb/tx_control_tb.vhd b/media_interfaces/sync/tb/tx_control_tb.vhd index dbf9f8d..90d6245 100644 --- a/media_interfaces/sync/tb/tx_control_tb.vhd +++ b/media_interfaces/sync/tb/tx_control_tb.vhd @@ -10,7 +10,6 @@ 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'; @@ -26,10 +25,26 @@ architecture tx_control_tb_arch of tx_control_tb is 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' ; + signal send_link_reset_out : std_logic := '0' ; + signal request_retransmit_out : std_logic := '0' ; + signal rx_dlm_word : std_logic_vector (7 downto 0) := (others => '0') ; + signal got_link_ready : std_logic := '0' ; + signal rx_write_out : std_logic ; + signal rx_read_in : std_logic ; + signal request_position_out : std_logic_vector (7 downto 0) := (others => '0') ; + signal start_retransmit_out : std_logic := '0' ; + signal rx_allow_in : std_logic := '0' ; + signal rx_packet_number_out : std_logic_vector (2 downto 0) ; + signal start_position_out : std_logic_vector (7 downto 0) := (others => '0') ; + signal rx_data_in : std_logic_vector (7 downto 0) ; + signal rx_data_out : std_logic_vector (15 downto 0) ; + signal rx_k_in : std_logic ; + signal rx_dlm : std_logic := '0' ; + signal make_reset_out : std_logic := '0' ; + component tx_control port ( @@ -54,11 +69,51 @@ architecture tx_control_tb_arch of tx_control_tb is REQUEST_RETRANSMIT_IN : in STD_LOGIC ); end component ; +component rx_control is + port( + CLK_200 : in std_logic; + CLK_100 : in std_logic; + RESET_IN : in std_logic; + + RX_DATA_OUT : out std_logic_vector(15 downto 0); + RX_PACKET_NUMBER_OUT : out std_logic_vector(2 downto 0); + RX_WRITE_OUT : out std_logic; + RX_READ_IN : in std_logic; + + RX_DATA_IN : in std_logic_vector( 7 downto 0); + RX_K_IN : in std_logic; + + REQUEST_RETRANSMIT_OUT : out std_logic := '0'; + REQUEST_POSITION_OUT : out std_logic_vector( 7 downto 0) := (others => '0'); + + START_RETRANSMIT_OUT : out std_logic := '0'; + START_POSITION_OUT : out std_logic_vector( 7 downto 0) := (others => '0'); + + --send_dlm: 200 MHz, 1 clock strobe, data valid until next DLM + RX_DLM : out std_logic := '0'; + RX_DLM_WORD : out std_logic_vector( 7 downto 0) := (others => '0'); + + SEND_LINK_RESET_OUT : out std_logic := '0'; + MAKE_RESET_OUT : out std_logic := '0'; + RX_ALLOW_IN : in std_logic := '0'; + GOT_LINK_READY : out std_logic := '0'; + + DEBUG_OUT : out std_logic_vector(31 downto 0); + STAT_REG_OUT : out std_logic_vector(31 downto 0) + ); +end component; begin - DUT : tx_control + +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; +RX_ALLOW_IN <= '0', '1' after 40 ns; + + DUTTX : tx_control port map ( - STAT_REG_OUT => STAT_REG_OUT , + STAT_REG_OUT => open , START_POSITION_IN => START_POSITION_IN , CLK_100 => CLK_100 , CLK_200 => CLK_200 , @@ -74,32 +129,68 @@ begin TX_WRITE_IN => TX_WRITE_IN , TX_DATA_OUT => TX_DATA_OUT , START_RETRANSMIT_IN => START_RETRANSMIT_IN , - DEBUG_OUT => DEBUG_OUT , + DEBUG_OUT => open , 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; + DUTRX : rx_control + port map ( + STAT_REG_OUT => open , + SEND_LINK_RESET_OUT => SEND_LINK_RESET_OUT , + REQUEST_RETRANSMIT_OUT => REQUEST_RETRANSMIT_OUT , + RX_DLM_WORD => RX_DLM_WORD , + CLK_100 => CLK_100 , + GOT_LINK_READY => GOT_LINK_READY , + CLK_200 => CLK_200 , + RX_WRITE_OUT => RX_WRITE_OUT , + RX_READ_IN => RX_READ_IN , + REQUEST_POSITION_OUT => REQUEST_POSITION_OUT , + START_RETRANSMIT_OUT => START_RETRANSMIT_OUT , + RX_ALLOW_IN => RX_ALLOW_IN , + RX_PACKET_NUMBER_OUT => RX_PACKET_NUMBER_OUT , + START_POSITION_OUT => START_POSITION_OUT , + RESET_IN => RESET_IN , + RX_DATA_IN => RX_DATA_IN , + RX_DATA_OUT => RX_DATA_OUT , + RX_K_IN => RX_K_IN , + DEBUG_OUT => open , + RX_DLM => RX_DLM , + MAKE_RESET_OUT => MAKE_RESET_OUT + ); + + +RX_K_IN <= TX_K_OUT; +RX_DATA_IN <= TX_DATA_OUT; 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'; + TX_DATA_IN <= x"2211"; 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'; + TX_DATA_IN <= x"4433"; 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'; + TX_DATA_IN <= x"6655"; 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'; + TX_DATA_IN <= x"8877"; 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; + +process begin + wait for 120 ns; + wait until rising_edge(clk_200); wait for 1 ns; + SEND_DLM_WORD <= x"85"; SEND_DLM <= '1'; + wait until rising_edge(clk_200); wait for 1 ns; + SEND_DLM_WORD <= x"85"; SEND_DLM <= '0'; + wait for 15 ns; +end process; + + end architecture; diff --git a/media_interfaces/sync/tx_control.vhd b/media_interfaces/sync/tx_control.vhd index 8fe468d..be7237e 100644 --- a/media_interfaces/sync/tx_control.vhd +++ b/media_interfaces/sync/tx_control.vhd @@ -26,7 +26,7 @@ entity tx_control is START_RETRANSMIT_IN : in std_logic := '0'; START_POSITION_IN : in std_logic_vector( 7 downto 0) := (others => '0'); - + --send_dlm: 200 MHz, 1 clock strobe, data valid until next DLM SEND_DLM : in std_logic := '0'; SEND_DLM_WORD : in std_logic_vector( 7 downto 0) := (others => '0'); @@ -43,34 +43,6 @@ 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, @@ -396,15 +368,16 @@ tx_allow_q <= tx_allow_qtx when rising_edge(CLK_100); 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_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 +-- ); + send_dlm_in_i <= SEND_DLM; THE_POSITION_REG : process(CLK_100) begin -- 2.43.0