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