From 507ef516aaa83b2e0119f25a17c40472b37fa9a8 Mon Sep 17 00:00:00 2001 From: Peter Lemmens Date: Thu, 12 Sep 2013 09:31:07 +0200 Subject: [PATCH] mediafiles added to repo. --- source/med_ecp3_sfp_sync_down.vhd | 499 ++++++++++++++++++++++++++++++ source/med_ecp3_sfp_sync_up.vhd | 498 +++++++++++++++++++++++++++++ source/trb3_periph_sodaclient.vhd | 18 +- source/trb3_periph_sodasource.vhd | 5 +- 4 files changed, 1009 insertions(+), 11 deletions(-) create mode 100644 source/med_ecp3_sfp_sync_down.vhd create mode 100644 source/med_ecp3_sfp_sync_up.vhd diff --git a/source/med_ecp3_sfp_sync_down.vhd b/source/med_ecp3_sfp_sync_down.vhd new file mode 100644 index 0000000..4198883 --- /dev/null +++ b/source/med_ecp3_sfp_sync_down.vhd @@ -0,0 +1,499 @@ +--Media interface for Lattice ECP3 using PCS at 2GHz + + +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 med_ecp3_sfp_sync is + generic( + SERDES_NUM : integer range 0 to 3 := 0; +-- MASTER_CLOCK_SWITCH : integer := c_NO; --just for debugging, should be NO + IS_SYNC_SLAVE : integer := c_NO --select slave mode + ); + port( + CLK : in std_logic; -- _internal_ 200 MHz reference clock + SYSCLK : in std_logic; -- 100 MHz main clock net, synchronous to RX clock + RESET : in std_logic; -- synchronous reset + CLEAR : in std_logic; -- asynchronous reset + --Internal Connection TX + 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'; + --Internal Connection RX + 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'; --received 100 MHz + CLK_RX_FULL_OUT : out std_logic := '0'; --received 200 MHz + + --Sync operation + 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; --not used + SD_REFCLK_N_IN : in std_logic; --not used + 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 entity; + + +architecture med_ecp3_sfp_sync_arch of med_ecp3_sfp_sync is + + -- Placer Directives + attribute HGROUP : string; + -- for whole architecture + attribute HGROUP of med_ecp3_sfp_sync_arch : architecture is "media_interface_group"; + attribute syn_sharing : string; + attribute syn_sharing of med_ecp3_sfp_sync_arch : architecture is "off"; + + +component DCS +-- synthesis translate_off +generic + ( +DCSMODE : string :=“POS” +); +-- synthesis translate_on + +port ( +CLK0 :in std_logic ; +CLK1 :in std_logic ; +SEL :in std_logic ; +DCSOUT :out std_logic) ; +end component; + + + +signal clk_200_i : std_logic; +signal clk_200_internal : std_logic; +signal clk_rx_full : std_logic; +signal clk_rx_half : std_logic; +signal clk_tx_full : std_logic; +signal clk_tx_half : std_logic; + +signal tx_data : std_logic_vector(7 downto 0); +signal tx_k : std_logic; +signal rx_data : std_logic_vector(7 downto 0); +signal rx_k : std_logic; +signal rx_error : std_logic; + +signal rst_n : std_logic; +signal rx_serdes_rst : std_logic; +signal tx_serdes_rst : std_logic; +signal tx_pcs_rst : std_logic; +signal rx_pcs_rst : std_logic; +signal rst_qd : std_logic; +signal serdes_rst_qd : std_logic; + +signal rx_los_low : std_logic; +signal lsm_status : std_logic; +signal rx_cdr_lol : std_logic; +signal tx_pll_lol : std_logic; + +signal sci_ch_i : std_logic_vector(3 downto 0); +signal sci_qd_i : std_logic; +signal sci_reg_i : std_logic; +signal sci_addr_i : std_logic_vector(8 downto 0); +signal sci_data_in_i : std_logic_vector(7 downto 0); +signal sci_data_out_i : std_logic_vector(7 downto 0); +signal sci_read_i : std_logic; +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 wa_position_rx : std_logic_vector(15 downto 0) := x"FFFF"; +signal tx_allow : std_logic; +signal rx_allow : std_logic; +signal tx_allow_q : std_logic; +signal rx_allow_q : 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 internal_make_link_reset_out : 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(18 downto 0) := (others => '0'); + +begin + +clk_200_internal <= CLK; +CLK_RX_HALF_OUT <= clk_rx_half; +CLK_RX_FULL_OUT <= clk_rx_full; + + + +SD_TXDIS_OUT <= '0'; --not (rx_allow_q or not IS_SLAVE); --slave only switches on when RX is ready + + +rst_n <= not CLEAR; + + +gen_slave_clock : if IS_SYNC_SLAVE = c_YES generate + clk_200_i <= clk_rx_full; +end generate; + +gen_master_clock : if IS_SYNC_SLAVE = c_NO generate + clk_200_i <= clk_200_internal; +end generate; + + +------------------------------------------------- +-- Serdes +------------------------------------------------- +THE_SERDES : entity work.serdes_sync_downstream + port map( + hdinp_ch0 => SD_RXD_P_IN, + hdinn_ch0 => SD_RXD_N_IN, + hdoutp_ch0 => SD_TXD_P_OUT, + hdoutn_ch0 => SD_TXD_N_OUT, + rxiclk_ch0 => clk_200_i, + txiclk_ch0 => clk_200_i, + rx_full_clk_ch0 => clk_rx_full, + rx_half_clk_ch0 => clk_rx_half, + tx_full_clk_ch0 => clk_tx_full, + tx_half_clk_ch0 => clk_tx_half, + fpga_rxrefclk_ch0 => clk_200_internal, + txdata_ch0 => tx_data, + tx_k_ch0 => tx_k, + tx_force_disp_ch0 => '0', + tx_disp_sel_ch0 => '0', + rxdata_ch0 => rx_data, + rx_k_ch0 => rx_k, + rx_disp_err_ch0 => open, + rx_cv_err_ch0 => rx_error, + rx_serdes_rst_ch0_c => rx_serdes_rst, + sb_felb_ch0_c => '0', + sb_felb_rst_ch0_c => '0', + tx_pcs_rst_ch0_c => tx_pcs_rst, + tx_pwrup_ch0_c => '1', + rx_pcs_rst_ch0_c => rx_pcs_rst, + rx_pwrup_ch0_c => '1', + rx_los_low_ch0_s => rx_los_low, + lsm_status_ch0_s => lsm_status, + rx_cdr_lol_ch0_s => rx_cdr_lol, + tx_div2_mode_ch0_c => '0', + rx_div2_mode_ch0_c => '0', + + SCI_WRDATA => sci_data_in_i, + SCI_RDDATA => sci_data_out_i, + SCI_ADDR => sci_addr_i(5 downto 0), + SCI_SEL_QUAD => sci_qd_i, + SCI_SEL_CH0 => sci_ch_i(0), + SCI_RD => sci_read_i, + SCI_WRN => sci_write_i, + + fpga_txrefclk => clk_200_i, + tx_serdes_rst_c => tx_serdes_rst, + tx_pll_lol_qd_s => tx_pll_lol, + rst_qd_c => rst_qd, + serdes_rst_qd_c => serdes_rst_qd + + ); + +------------------------------------------------- +-- Reset FSM & Link states +------------------------------------------------- +THE_RX_FSM : rx_reset_fsm + port map( + RST_N => rst_n, + RX_REFCLK => clk_200_i, + TX_PLL_LOL_QD_S => tx_pll_lol, + RX_SERDES_RST_CH_C => rx_serdes_rst, + 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_rx(3 downto 0), + STATE_OUT => rx_fsm_state + ); + +THE_TX_FSM : tx_reset_fsm + port map( + RST_N => rst_n, + TX_REFCLK => clk_200_internal, + TX_PLL_LOL_QD_S => tx_pll_lol, + RST_QD_C => rst_qd, + TX_PCS_RST_CH_C => tx_pcs_rst, + STATE_OUT => tx_fsm_state + ); + +-- Master does not do bit-locking +wa_position_rx <= wa_position when (IS_SYNC_SLAVE = 1) else x"0000"; + + +--Slave enables RX/TX when sync is done, Master waits additional time to make sure link is stable +PROC_ALLOW : process begin + wait until rising_edge(clk_200_i); + if rx_fsm_state = x"6" and (IS_SYNC_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" and (IS_SYNC_SLAVE = 1 or start_timer(start_timer'left) = '1') then + tx_allow <= '1'; + else + tx_allow <= '0'; + end if; +end process; + +rx_allow_q <= rx_allow when rising_edge(SYSCLK); +tx_allow_q <= tx_allow when rising_edge(SYSCLK); + + +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; + + +------------------------------------------------- +-- TX Data +------------------------------------------------- +THE_TX : tx_control + port map( + CLK_200 => clk_200_i, + CLK_100 => SYSCLK, + RESET_IN => CLEAR, + + 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 => request_retr_i, --TODO + REQUEST_POSITION_IN => request_retr_position_i, --TODO + + START_RETRANSMIT_IN => start_retr_i, --TODO + START_POSITION_IN => request_retr_position_i, --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 => 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 +------------------------------------------------- +--gives access to serdes config port from slow control and reads word alignment every ~ 40 us +PROC_SCI_CTRL: process + variable cnt : integer range 0 to 4 := 0; +begin + wait until rising_edge(SYSCLK); + 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(3 downto 0))))+7 downto 8*(to_integer(unsigned(SCI_ADDR(3 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 = 4 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_NACK <= '0'; + end if; + +end process; + + +------------------------------------------------- +-- Debug Registers +------------------------------------------------- +debug_reg(3 downto 0) <= rx_fsm_state; +debug_reg(4) <= rx_k; +debug_reg(5) <= rx_error; +debug_reg(6) <= rx_los_low; +debug_reg(7) <= rx_cdr_lol; + +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(35 downto 32) <= wa_position(3 downto 0); +debug_reg(36) <= debug_tx_control_i(6); +debug_reg(39 downto 37) <= "000"; +debug_reg(63 downto 40) <= debug_rx_control_i(23 downto 0); + + +STAT_DEBUG <= debug_reg; + +internal_make_link_reset_out <= make_link_reset_i when IS_SYNC_SLAVE = 1 else '0'; + + +STAT_OP(15) <= send_link_reset_i when rising_edge(SYSCLK); +STAT_OP(14) <= '0'; +STAT_OP(13) <= internal_make_link_reset_out 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"0" when rx_allow_q = '1' and tx_allow_q = '1' else x"7"; +end med_ecp3_sfp_sync_arch; + diff --git a/source/med_ecp3_sfp_sync_up.vhd b/source/med_ecp3_sfp_sync_up.vhd new file mode 100644 index 0000000..da28b0e --- /dev/null +++ b/source/med_ecp3_sfp_sync_up.vhd @@ -0,0 +1,498 @@ +--Media interface for Lattice ECP3 using PCS at 2GHz + + +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 med_ecp3_sfp_sync is + generic( + SERDES_NUM : integer range 0 to 3 := 0; +-- MASTER_CLOCK_SWITCH : integer := c_NO; --just for debugging, should be NO + IS_SYNC_SLAVE : integer := c_YES --select slave mode + ); + port( + CLK : in std_logic; -- _internal_ 200 MHz reference clock + SYSCLK : in std_logic; -- 100 MHz main clock net, synchronous to RX clock + RESET : in std_logic; -- synchronous reset + CLEAR : in std_logic; -- asynchronous reset + --Internal Connection TX + 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'; + --Internal Connection RX + 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'; --received 100 MHz + CLK_RX_FULL_OUT : out std_logic := '0'; --received 200 MHz + + --Sync operation + 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; --not used + SD_REFCLK_N_IN : in std_logic; --not used + 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 entity; + + +architecture med_ecp3_sfp_sync_arch of med_ecp3_sfp_sync is + + -- Placer Directives + attribute HGROUP : string; + -- for whole architecture + attribute HGROUP of med_ecp3_sfp_sync_arch : architecture is "media_interface_group"; + attribute syn_sharing : string; + attribute syn_sharing of med_ecp3_sfp_sync_arch : architecture is "off"; + + +component DCS +-- synthesis translate_off +generic + ( +DCSMODE : string :=“POS” +); +-- synthesis translate_on + +port ( +CLK0 :in std_logic ; +CLK1 :in std_logic ; +SEL :in std_logic ; +DCSOUT :out std_logic) ; +end component; + + + +signal clk_200_i : std_logic; +signal clk_200_internal : std_logic; +signal clk_rx_full : std_logic; +signal clk_rx_half : std_logic; +signal clk_tx_full : std_logic; +signal clk_tx_half : std_logic; + +signal tx_data : std_logic_vector(7 downto 0); +signal tx_k : std_logic; +signal rx_data : std_logic_vector(7 downto 0); +signal rx_k : std_logic; +signal rx_error : std_logic; + +signal rst_n : std_logic; +signal rx_serdes_rst : std_logic; +signal tx_serdes_rst : std_logic; +signal tx_pcs_rst : std_logic; +signal rx_pcs_rst : std_logic; +signal rst_qd : std_logic; +signal serdes_rst_qd : std_logic; + +signal rx_los_low : std_logic; +signal lsm_status : std_logic; +signal rx_cdr_lol : std_logic; +signal tx_pll_lol : std_logic; + +signal sci_ch_i : std_logic_vector(3 downto 0); +signal sci_qd_i : std_logic; +signal sci_reg_i : std_logic; +signal sci_addr_i : std_logic_vector(8 downto 0); +signal sci_data_in_i : std_logic_vector(7 downto 0); +signal sci_data_out_i : std_logic_vector(7 downto 0); +signal sci_read_i : std_logic; +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 wa_position_rx : std_logic_vector(15 downto 0) := x"FFFF"; +signal tx_allow : std_logic; +signal rx_allow : std_logic; +signal tx_allow_q : std_logic; +signal rx_allow_q : 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 internal_make_link_reset_out : 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(18 downto 0) := (others => '0'); + +begin + +clk_200_internal <= CLK; +CLK_RX_HALF_OUT <= clk_rx_half; +CLK_RX_FULL_OUT <= clk_rx_full; + + + +SD_TXDIS_OUT <= '0'; --not (rx_allow_q or not IS_SLAVE); --slave only switches on when RX is ready + + +rst_n <= not CLEAR; + + +gen_slave_clock : if IS_SYNC_SLAVE = c_YES generate + clk_200_i <= clk_rx_full; +end generate; + +gen_master_clock : if IS_SYNC_SLAVE = c_NO generate + clk_200_i <= clk_200_internal; +end generate; + + +------------------------------------------------- +-- Serdes +------------------------------------------------- +THE_SERDES : entity work.serdes_sync_upstream + port map( + hdinp_ch0 => SD_RXD_P_IN, + hdinn_ch0 => SD_RXD_N_IN, + hdoutp_ch0 => SD_TXD_P_OUT, + hdoutn_ch0 => SD_TXD_N_OUT, + txiclk_ch0 => clk_200_i, + rx_full_clk_ch0 => clk_rx_full, + rx_half_clk_ch0 => clk_rx_half, + tx_full_clk_ch0 => clk_tx_full, + tx_half_clk_ch0 => clk_tx_half, + fpga_rxrefclk_ch0 => clk_200_internal, + txdata_ch0 => tx_data, + tx_k_ch0 => tx_k, + tx_force_disp_ch0 => '0', + tx_disp_sel_ch0 => '0', + rxdata_ch0 => rx_data, + rx_k_ch0 => rx_k, + rx_disp_err_ch0 => open, + rx_cv_err_ch0 => rx_error, + rx_serdes_rst_ch0_c => rx_serdes_rst, + sb_felb_ch0_c => '0', + sb_felb_rst_ch0_c => '0', + tx_pcs_rst_ch0_c => tx_pcs_rst, + tx_pwrup_ch0_c => '1', + rx_pcs_rst_ch0_c => rx_pcs_rst, + rx_pwrup_ch0_c => '1', + rx_los_low_ch0_s => rx_los_low, + lsm_status_ch0_s => lsm_status, + rx_cdr_lol_ch0_s => rx_cdr_lol, + tx_div2_mode_ch0_c => '0', + rx_div2_mode_ch0_c => '0', + + SCI_WRDATA => sci_data_in_i, + SCI_RDDATA => sci_data_out_i, + SCI_ADDR => sci_addr_i(5 downto 0), + SCI_SEL_QUAD => sci_qd_i, + SCI_SEL_CH0 => sci_ch_i(0), + SCI_RD => sci_read_i, + SCI_WRN => sci_write_i, + + fpga_txrefclk => clk_200_i, + tx_serdes_rst_c => tx_serdes_rst, + tx_pll_lol_qd_s => tx_pll_lol, + rst_qd_c => rst_qd, + serdes_rst_qd_c => serdes_rst_qd + + ); + +------------------------------------------------- +-- Reset FSM & Link states +------------------------------------------------- +THE_RX_FSM : rx_reset_fsm + port map( + RST_N => rst_n, + RX_REFCLK => clk_200_internal, + TX_PLL_LOL_QD_S => tx_pll_lol, + RX_SERDES_RST_CH_C => rx_serdes_rst, + 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_rx(3 downto 0), + STATE_OUT => rx_fsm_state + ); + +THE_TX_FSM : tx_reset_fsm + port map( + RST_N => rst_n, + TX_REFCLK => clk_200_internal, + TX_PLL_LOL_QD_S => tx_pll_lol, + RST_QD_C => rst_qd, + TX_PCS_RST_CH_C => tx_pcs_rst, + STATE_OUT => tx_fsm_state + ); + +-- Master does not do bit-locking +wa_position_rx <= wa_position when (IS_SYNC_SLAVE = c_YES) else x"0000"; + + +--Slave enables RX/TX when sync is done, Master waits additional time to make sure link is stable +PROC_ALLOW : process begin + wait until rising_edge(clk_200_i); + if rx_fsm_state = x"6" and (IS_SYNC_SLAVE = c_YES or start_timer(start_timer'left) = '1') then + rx_allow <= '1'; + else + rx_allow <= '0'; + end if; + if rx_fsm_state = x"6" and (IS_SYNC_SLAVE = c_YES or start_timer(start_timer'left) = '1') then + tx_allow <= '1'; + else + tx_allow <= '0'; + end if; +end process; + +rx_allow_q <= rx_allow when rising_edge(SYSCLK); +tx_allow_q <= tx_allow when rising_edge(SYSCLK); + + +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; + + +------------------------------------------------- +-- TX Data +------------------------------------------------- +THE_TX : tx_control + port map( + CLK_200 => clk_200_i, + CLK_100 => SYSCLK, + RESET_IN => CLEAR, + + 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 => request_retr_i, --TODO + REQUEST_POSITION_IN => request_retr_position_i, --TODO + + START_RETRANSMIT_IN => start_retr_i, --TODO + START_POSITION_IN => request_retr_position_i, --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 => 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 +------------------------------------------------- +--gives access to serdes config port from slow control and reads word alignment every ~ 40 us +PROC_SCI_CTRL: process + variable cnt : integer range 0 to 4 := 0; +begin + wait until rising_edge(SYSCLK); + 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(3 downto 0))))+7 downto 8*(to_integer(unsigned(SCI_ADDR(3 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 = 4 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_NACK <= '0'; + end if; + +end process; + + +------------------------------------------------- +-- Debug Registers +------------------------------------------------- +debug_reg(3 downto 0) <= rx_fsm_state; +debug_reg(4) <= rx_k; +debug_reg(5) <= rx_error; +debug_reg(6) <= rx_los_low; +debug_reg(7) <= rx_cdr_lol; + +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(35 downto 32) <= wa_position(3 downto 0); +debug_reg(36) <= debug_tx_control_i(6); +debug_reg(39 downto 37) <= "000"; +debug_reg(63 downto 40) <= debug_rx_control_i(23 downto 0); + + +STAT_DEBUG <= debug_reg; + +internal_make_link_reset_out <= make_link_reset_i when IS_SYNC_SLAVE = c_YES else '0'; + + +STAT_OP(15) <= send_link_reset_i when rising_edge(SYSCLK); +STAT_OP(14) <= '0'; +STAT_OP(13) <= internal_make_link_reset_out 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"0" when rx_allow_q = '1' and tx_allow_q = '1' else x"7"; +end med_ecp3_sfp_sync_arch; + diff --git a/source/trb3_periph_sodaclient.vhd b/source/trb3_periph_sodaclient.vhd index 34eed6e..dfcb2e7 100644 --- a/source/trb3_periph_sodaclient.vhd +++ b/source/trb3_periph_sodaclient.vhd @@ -113,6 +113,7 @@ architecture trb3_periph_sodaclient_arch of trb3_periph_sodaclient is --Clock / Reset signal clk_sys_i : std_logic; --clock for main logic, 100 MHz, via Clock Manager and internal PLL + signal clk_soda_i : std_logic; --clock for main logic, 100 MHz, via Clock Manager and internal PLL -- signal clk_200_i : std_logic; --clock for logic at 200 MHz, via Clock Manager and bypassed PLL signal pll_lock : std_logic; --Internal PLL locked. E.g. used to reset all internal logic. signal clear_i : std_logic; @@ -261,13 +262,15 @@ gen_125 : if USE_125_MHZ = c_YES generate end generate; gen_sync_clocks : if SYNC_MODE = c_YES generate - clk_sys_i <= rx_clock_half; --- clk_200_i <= rx_clock_full; + clk_sys_i <= clk_sys_internal; + clk_soda_i <= rx_clock_full; +-- clk_200_i <= rx_clock_full; end generate; gen_local_clocks : if SYNC_MODE = c_NO generate - clk_sys_i <= clk_sys_internal; --- clk_200_i <= clk_raw_internal; + clk_sys_i <= clk_sys_internal; + clk_soda_i <= clk_sys_internal; +-- clk_200_i <= clk_raw_internal; end generate; @@ -512,7 +515,7 @@ THE_SPI_RELOAD : spi_flash_and_fpga_reload --.flash_reboot_arch THE_SYNC_LINK : med_ecp3_sfp_sync generic map( SERDES_NUM => 0, --number of serdes in quad - IS_SYNC_SLAVE => c_NO + IS_SYNC_SLAVE => c_YES ) port map( CLK => clk_raw_internal, --clk_200_i, @@ -562,12 +565,13 @@ THE_SYNC_LINK : med_ecp3_sfp_sync --------------------------------------------------------------------------- --- The Soda Central +-- The Soda Central --------------------------------------------------------------------------- A_SODA_CLIENT : soda_client port map( - SYSCLK => clk_sys_i, + SYSCLK => clk_sys_i, + SODACLK => clk_soda_i, RESET => reset_i, CLEAR => clear_i, CLK_EN => '1', diff --git a/source/trb3_periph_sodasource.vhd b/source/trb3_periph_sodasource.vhd index 1abcca7..32ca642 100644 --- a/source/trb3_periph_sodasource.vhd +++ b/source/trb3_periph_sodasource.vhd @@ -215,14 +215,11 @@ architecture trb3_periph_sodasource_arch of trb3_periph_sodasource is signal rx_dlm_word : std_logic_vector(7 downto 0); --SODA --- signal rst_S : std_logic; --- signal clk_S : std_logic; --- signal enable_S : std_logic := '0'; + signal SOB_S : std_logic := '0'; -- signal soda_cmd_word_S : std_logic_vector(31 downto 0) := (others => '0'); -- signal soda_cmd_strobe_S : std_logic := '0'; -- signal SOS_S : std_logic := '0'; -- signal super_burst_nr_S : std_logic_vector(30 downto 0) := (others => '0'); -- from super-burst-nr-generator --- signal SOB_S : std_logic := '0'; -- signal dlm_word_S : std_logic_vector(7 downto 0) := (others => '0'); -- signal dlm_valid_S : std_logic; -- 2.43.0