RESET_N : in std_logic;
CLEAR : in std_logic;
CLEAR_N : in std_logic;
- CLK_125 : in std_logic;
+ CLK_125 : in std_logic; -- this will be used as local reference, as needed
-- FIFO interface RX
FIFO_DATA_OUT : out std_logic_vector(4 * 9 - 1 downto 0);
FIFO_FULL_IN : in std_logic_vector(3 downto 0) := (others => '0');
LINK_ACTIVE_OUT : out std_logic_vector(3 downto 0); -- for internal SCTRL
TICK_MS_IN : in std_logic;
-- syntonous operation
--- MASTER_CLK_IN : in std_logic;
+ MASTER_CLK_IN : in std_logic; -- master clock for TX parts
+ MASTER_CLK_OUT : out std_logic; -- recovered RX clock from slave port, if any
+ TX_CLK_AVAIL_OUT : out std_logic; -- slave port has valid RX recovered clock
+ SYNC_TX_PLL_IN : in std_logic;
-- DLM
DLM_INJECT_IN : in std_logic_vector(3 downto 0) := (others => '0');
DLM_DATA_IN : in std_logic_vector(4 * 8 - 1 downto 0) := (others => '0');
signal sd_rx_kcntl_dst : std_logic_vector(3 downto 0);
signal sd_rx_clk : std_logic_vector(3 downto 0);
+ signal sd_tx_clk : std_logic_vector(3 downto 0);
signal xmit : std_logic_vector(3 downto 0);
signal sd_rx_disp_error : std_logic_vector(3 downto 0);
signal sd_rx_cv_error : std_logic_vector(3 downto 0);
signal idle_rx_int : std_logic_vector(3 downto 0);
signal cfg_rx_int : std_logic_vector(3 downto 0);
+ signal tx_clk_avail_i : std_logic;
+
-- attribute HGROUP : string;
-- attribute BBOX : string;
-- attribute HGROUP of gbe_med_fifo_arch : architecture is "gbe_med_fifo_group";
assert not ((quad_mode >= 1) and (quad_mode <= 4)) report "Note: QUAD with only master ports detected" severity note;
assert not (quad_mode = 8) report "Note: QUAD with one slave port detected" severity note;
assert not ((quad_mode >= 9) and (quad_mode <= 11)) report "Note: mixed master/slave QUAD detected" severity note;
-
+
+-------------------------------------------------
+-- TX ref clock
+-- output only if a slave port is available in QUAD
+-------------------------------------------------
+ MASTER_CLK_OUT <= sd_rx_clk(0) when (LINK_MODE(0) = c_IS_SLAVE) else
+ sd_rx_clk(1) when (LINK_MODE(1) = c_IS_SLAVE) else
+ sd_rx_clk(2) when (LINK_MODE(2) = c_IS_SLAVE) else
+ sd_rx_clk(3) when (LINK_MODE(3) = c_IS_SLAVE) else
+ '0';
+
+-------------------------------------------------
+-- stable RX recovered clock available
+-------------------------------------------------
+ TX_CLK_AVAIL_OUT <= tx_clk_avail_i;
+
+ tx_clk_avail_i <= link_rx_ready(0) when (LINK_MODE(0) = c_IS_SLAVE) else
+ link_rx_ready(1) when (LINK_MODE(1) = c_IS_SLAVE) else
+ link_rx_ready(2) when (LINK_MODE(2) = c_IS_SLAVE) else
+ link_rx_ready(3) when (LINK_MODE(3) = c_IS_SLAVE) else
+ '0';
+
-------------------------------------------------
-- SerDes quad
-------------------------------------------------
hdoutp_ch0 => SD_TXD_P_OUT(0),
hdoutn_ch0 => SD_TXD_N_OUT(0),
rxiclk_ch0 => sd_rx_clk(0),
- txiclk_ch0 => CLK_125,
+ txiclk_ch0 => MASTER_CLK_IN, --sd_tx_clk(0), -- CLK_125
rx_full_clk_ch0 => sd_rx_clk(0),
rx_half_clk_ch0 => open,
tx_full_clk_ch0 => open,
hdoutp_ch1 => SD_TXD_P_OUT(1),
hdoutn_ch1 => SD_TXD_N_OUT(1),
rxiclk_ch1 => sd_rx_clk(1),
- txiclk_ch1 => CLK_125,
+ txiclk_ch1 => MASTER_CLK_IN, --sd_tx_clk(1), -- CLK_125,
rx_full_clk_ch1 => sd_rx_clk(1),
rx_half_clk_ch1 => open,
tx_full_clk_ch1 => open,
hdoutp_ch2 => SD_TXD_P_OUT(2),
hdoutn_ch2 => SD_TXD_N_OUT(2),
rxiclk_ch2 => sd_rx_clk(2),
- txiclk_ch2 => CLK_125,
+ txiclk_ch2 => MASTER_CLK_IN, --sd_tx_clk(2), -- CLK_125,
rx_full_clk_ch2 => sd_rx_clk(2),
rx_half_clk_ch2 => open,
tx_full_clk_ch2 => open,
hdoutp_ch3 => SD_TXD_P_OUT(3),
hdoutn_ch3 => SD_TXD_N_OUT(3),
rxiclk_ch3 => sd_rx_clk(3),
- txiclk_ch3 => CLK_125,
+ txiclk_ch3 => MASTER_CLK_IN, --sd_tx_clk(3), -- CLK_125,
rx_full_clk_ch3 => sd_rx_clk(3),
rx_half_clk_ch3 => open,
tx_full_clk_ch3 => open,
lsm_status_ch3_s => lsm_status(3),
rx_cdr_lol_ch3_s => rx_cdr_lol(3),
---- Miscallaneous ports
- fpga_txrefclk => CLK_125,
+ fpga_txrefclk => MASTER_CLK_IN, --CLK_125,
tx_serdes_rst_c => '0',
tx_pll_lol_qd_s => tx_plol_lol,
rst_qd_c => CLEAR, -- ONLY ONCE
serdes_rst_qd_c => '0',
- tx_sync_qd_c => '0'
+ tx_sync_qd_c => SYNC_TX_PLL_IN --'0'
);
TX_PLOL_LOL_OUT <= tx_plol_lol;
+ -- workaround for clock domain problem
+-- sd_tx_clk(0) <= MASTER_CLK_IN;
+-- sd_tx_clk(1) <= MASTER_CLK_IN;
+-- sd_tx_clk(2) <= MASTER_CLK_IN;
+-- sd_tx_clk(3) <= MASTER_CLK_IN;
+
-- in case we have no uplink port...
NO_LOCAL_GEN: if (quad_mode < 8) generate
MAC_RX_DATA_OUT <= (others => '0');
THE_TX_PARSER: entity parser
port map(
- CLK => CLK_125,
+ CLK => MASTER_CLK_IN, --CLK_125,
RESET => CLEAR,
--
PHY_D_IN => sd_tx_data_dst((i + 1) * 8 - 1 downto i * 8),
DEBUG_OUT((i + 1) * 32 - 4) <= '0';
DEBUG_OUT((i + 1) * 32 - 5) <= '0';
DEBUG_OUT((i + 1) * 32 - 6) <= '0';
- DEBUG_OUT((i + 1) * 32 - 7) <= '0';
+ DEBUG_OUT((i + 1) * 32 - 7) <= tx_clk_avail_i;
DEBUG_OUT((i + 1) * 32 - 8) <= link_active(i);
DEBUG_OUT((i + 1) * 32 - 9) <= mac_ready_conf(i);
DEBUG_OUT((i + 1) * 32 - 10) <= mac_reconf(i);
THE_MAIN_RX_RST: main_rx_reset_RS
port map(
CLEAR => CLEAR,
- CLK_REF => CLK_125,
+ CLK_REF => CLK_125, -- needs always to run on local clock
CDR_LOL_IN => rx_cdr_lol(i),
CV_IN => sd_rx_cv_error(i),
LSM_IN => lsm_status(i),
TRUDY_AND_EVE: if INCLUDE_DLM(i) = 1 generate
THE_TRUDY: entity inserter
port map(
- CLK => CLK_125,
+ CLK => MASTER_CLK_IN, --sd_tx_clk(i), --CLK_125,
RESET => CLEAR,
-- PHY output
PHY_D_IN => sd_tx_data_src((i + 1) * 8 - 1 downto i * 8),
-- SGMII core
SGMII_GBE_PCS : sgmii_gbe_pcs42
port map(
- rst_n => CLEAR_N, --RESET_N,
+ rst_n => RESET_N, --CLEAR_N,
signal_detect => link_rx_ready(i),
gbe_mode => '1',
sgmii_mode => '0',
ctc_add_flag => open,
an_link_ok => open,
-- MAC interface
- tx_clk_125 => CLK_125,
+ tx_clk_125 => MASTER_CLK_IN, --CLK_125,
tx_clock_enable_source => tx_clk_en(i),
tx_clock_enable_sink => tx_clk_en(i),
tx_d => pcs_txd((i + 1) * 8 - 1 downto i * 8), -- TX data from MAC
tx_en => pcs_tx_en(i), -- TX data enable from MAC
tx_er => pcs_tx_er(i), -- TX error from MAC
- rx_clk_125 => CLK_125,
+ rx_clk_125 => MASTER_CLK_IN, --CLK_125,
rx_clock_enable_source => rx_clk_en(i),
rx_clock_enable_sink => rx_clk_en(i),
rx_d => pcs_rxd((i + 1 ) * 8 - 1 downto i * 8), -- RX data to MAC
mr_an_enable(i) <= link_rx_ready(i);
mr_adv_ability((i + 1) * 16 - 1 downto i * 16) <= x"0020";
- SYNC_PROC: process( CLK_125 )
+-- SYNC_PROC: process( CLK_125 )
+ SYNC_PROC: process( MASTER_CLK_IN )
begin
- if( rising_edge(CLK_125) ) then
+-- if( rising_edge(CLK_125) ) then
+ if( rising_edge(MASTER_CLK_IN) ) then
delay_q((i + 1) * 8 - 1 downto i * 8) <= delay_q((i + 1) * 8 - 2 downto i * 8) & link_rx_ready(i);
end if;
end process SYNC_PROC;
MAC: tsmac41
port map(
----------------- clock and reset port declarations ------------------
- hclk => CLK_125, -- BUG: can be CLK_125
- txmac_clk => CLK_125,
- rxmac_clk => CLK_125,
+ hclk => MASTER_CLK_IN, --CLK_125,
+ txmac_clk => MASTER_CLK_IN, --CLK_125,
+ rxmac_clk => MASTER_CLK_IN, --CLK_125,
reset_n => RESET_N,
------------------- Input signals to the GMII ----------------
rxd => pcs_rxd((i + 1) * 8 - 1 downto i * 8),
-- CAN BE OPTIMIZED
TSMAC_CONTROLLER : trb_net16_gbe_mac_control
port map(
- CLK => CLK_125,
+ CLK => MASTER_CLK_IN, --CLK_125,
RESET => RESET,
-- signals to/from main controller
MC_TSMAC_READY_OUT => mac_ready_conf(i),
-- initializes MAC after AN is complete
THE_FW_GBE_LSM: entity gbe_lsm
port map(
- CLK => CLK_125,
+ CLK => MASTER_CLK_IN, --CLK_125,
RESET => RESET,
--
MAC_AN_COMPLETE_IN => an_complete(i),
-- RX ringbuffer
THE_FW_RB: entity rx_rb
port map(
- CLK => CLK_125,
+ CLK => MASTER_CLK_IN, --CLK_125,
RESET => RESET,
-- MAC interface (RX)
MAC_RX_DATA_IN => mac_rx_data((i + 1) * 8 - 1 downto i * 8),
-- TX FIFO
THE_FW_FIFO: entity tx_fifo
port map(
- CLK => CLK_125,
+ CLK => MASTER_CLK_IN, --CLK_125,
RESET => RESET,
-- MAC interface
MAC_TX_DATA_OUT => mac_tx_data((i + 1) * 8 - 1 downto i * 8),
-- LED connections, can be simplified by CE signal, to get rid of local counter instances
led_activity_x(i) <= pcs_rx_en(i) or pcs_tx_en(i);
- THE_LED_ACT_PROC: process( CLK_125 )
+-- THE_LED_ACT_PROC: process( CLK_125 )
+ THE_LED_ACT_PROC: process( MASTER_CLK_IN )
begin
- if( rising_edge(CLK_125) ) then
+-- if( rising_edge(CLK_125) ) then
+ if( rising_edge(MASTER_CLK_IN) ) then
if( led_activity_x(i) = '1' ) then
led_activity((i + 1) * 2 - 2) <= '1';
end if;
end generate CHANNEL_GEN;
- THE_LED_TIMER_PROC: process( CLK_125 )
+-- THE_LED_TIMER_PROC: process( CLK_125 )
+ THE_LED_TIMER_PROC: process( MASTER_CLK_IN )
begin
- if( rising_edge(CLK_125) ) then
+-- if( rising_edge(CLK_125) ) then
+ if( rising_edge(MASTER_CLK_IN) ) then
led_timer_done <= led_timer_done_x;
led_timer <= led_timer + 1;
end if;