From 80791fb419b11d5b5d8cddad5bf4f8895f57d54a Mon Sep 17 00:00:00 2001 From: hadeshyp Date: Wed, 30 Jan 2013 17:32:38 +0000 Subject: [PATCH] new files for sync media interface --- media_interfaces/ecp3_sfp/sfp_0_200_int.vhd | 8 +- media_interfaces/med_ecp3_sfp_sync.vhd | 216 ++++++-- media_interfaces/sync/med_sync_define.vhd | 83 +++ media_interfaces/sync/rx_reset_fsm.vhd | 8 +- media_interfaces/sync/tb/tx_control_tb.vhd | 105 ++++ media_interfaces/sync/tx_control.vhd | 530 ++++++++++++++++++++ 6 files changed, 894 insertions(+), 56 deletions(-) create mode 100644 media_interfaces/sync/med_sync_define.vhd create mode 100644 media_interfaces/sync/tb/tx_control_tb.vhd create mode 100644 media_interfaces/sync/tx_control.vhd diff --git a/media_interfaces/ecp3_sfp/sfp_0_200_int.vhd b/media_interfaces/ecp3_sfp/sfp_0_200_int.vhd index 59f7a45..4fbccd9 100644 --- a/media_interfaces/ecp3_sfp/sfp_0_200_int.vhd +++ b/media_interfaces/ecp3_sfp/sfp_0_200_int.vhd @@ -9,7 +9,7 @@ library IEEE; use IEEE.std_logic_1164.all; entity PCSD is -GENERIC( +generic( CONFIG_FILE : String; QUAD_MODE : String; CH0_CDR_SRC : String := "REFCLK_EXT"; @@ -518,7 +518,7 @@ architecture PCSD_arch of PCSD is component PCSD_sim -GENERIC( +generic( CONFIG_FILE : String; QUAD_MODE : String; CH0_CDR_SRC : String; @@ -1881,7 +1881,7 @@ use IEEE.std_logic_1164.all; 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 -- @@ -1969,7 +1969,7 @@ end component; component PCSD --synopsys translate_off -GENERIC( +generic( CONFIG_FILE : String; QUAD_MODE : String; CH0_CDR_SRC : String := "REFCLK_EXT"; diff --git a/media_interfaces/med_ecp3_sfp_sync.vhd b/media_interfaces/med_ecp3_sfp_sync.vhd index ee186ce..d642153 100644 --- a/media_interfaces/med_ecp3_sfp_sync.vhd +++ b/media_interfaces/med_ecp3_sfp_sync.vhd @@ -8,6 +8,7 @@ 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 med_ecp3_sfp_sync is generic( @@ -48,7 +49,7 @@ entity med_ecp3_sfp_sync is 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'); @@ -117,32 +118,10 @@ component serdes_sync_0 is 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; @@ -181,10 +160,19 @@ 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); +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; @@ -265,6 +253,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), STATE_OUT => rx_fsm_state ); @@ -279,41 +268,166 @@ THE_TX_FSM : tx_reset_fsm ); +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 ------------------------------------------------- @@ -331,7 +445,9 @@ debug_reg(19) <= lsm_status; 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; diff --git a/media_interfaces/sync/med_sync_define.vhd b/media_interfaces/sync/med_sync_define.vhd new file mode 100644 index 0000000..793234e --- /dev/null +++ b/media_interfaces/sync/med_sync_define.vhd @@ -0,0 +1,83 @@ +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 diff --git a/media_interfaces/sync/rx_reset_fsm.vhd b/media_interfaces/sync/rx_reset_fsm.vhd index 9b7047f..a5d7131 100644 --- a/media_interfaces/sync/rx_reset_fsm.vhd +++ b/media_interfaces/sync/rx_reset_fsm.vhd @@ -15,6 +15,8 @@ entity rx_reset_fsm is 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 ; @@ -154,7 +156,7 @@ begin 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; @@ -184,6 +186,8 @@ begin end case; end process; - + + + 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 new file mode 100644 index 0000000..dbf9f8d --- /dev/null +++ b/media_interfaces/sync/tb/tx_control_tb.vhd @@ -0,0 +1,105 @@ +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; + diff --git a/media_interfaces/sync/tx_control.vhd b/media_interfaces/sync/tx_control.vhd new file mode 100644 index 0000000..8fe468d --- /dev/null +++ b/media_interfaces/sync/tx_control.vhd @@ -0,0 +1,530 @@ +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 -- 2.43.0