--- /dev/null
+library ieee;
+ use ieee.std_logic_1164.all;
+ use ieee.numeric_std.all;
+
+package cbmnet_interface_pkg is
+ constant K280 : std_logic_vector(7 downto 0) := "00011100";
+ constant K281 : std_logic_vector(7 downto 0) := "00111100";
+ constant K282 : std_logic_vector(7 downto 0) := "01011100";
+ constant K283 : std_logic_vector(7 downto 0) := "01111100";
+ constant K284 : std_logic_vector(7 downto 0) := "10011100";
+ constant K285 : std_logic_vector(7 downto 0) := "10111100";
+ constant K286 : std_logic_vector(7 downto 0) := "11011100";
+ constant K287 : std_logic_vector(7 downto 0) := "11111100";
+ constant K237 : std_logic_vector(7 downto 0) := "11111110";
+ constant K277 : std_logic_vector(7 downto 0) := "11111011";
+ constant K297 : std_logic_vector(7 downto 0) := "11111101";
+ constant K307 : std_logic_vector(7 downto 0) := "11111110";
+
+ component gtp_rx_ready_module is
+ generic (
+ READY_CHAR0 : std_logic_vector(7 downto 0) := K284;
+ READY_CHAR1 : std_logic_vector(7 downto 0) := K287;
+ ALIGN_CHAR : std_logic_vector(7 downto 0) := K285;
+ DATAWIDTH : integer := 16;
+ WORDS : integer := 2; --DATAWIDTH/8;
+
+ INCL_8B10B_DEC : integer range 0 to 1 := 1
+ );
+ port (
+ clk : in std_logic;
+ res_n : in std_logic;
+ ready_MGT2RM : in std_logic;
+ rxdata_in : in std_logic_vector((WORDS*10)-1 downto 0);
+
+ tx_ready : in std_logic;
+ tx_almost_ready : in std_logic;
+
+ ready_RM2LP : out std_logic;
+ almost_ready_OUT : out std_logic;
+ rxdata_out : out std_logic_vector((DATAWIDTH-1) downto 0);
+ charisk_out : out std_logic_vector((WORDS-1) downto 0);
+ see_ready0 : out std_logic;
+ saw_ready1 : out std_logic;
+ valid_char : out std_logic;
+ reset_rx : out std_logic
+ );
+ end component;
+
+ component gtp_tx_ready_module is
+ generic (
+ READY_CHAR0 : std_logic_vector(7 downto 0) := K284;
+ READY_CHAR1 : std_logic_vector(7 downto 0) := K287;
+ ALIGN_CHAR : std_logic_vector(7 downto 0) := K285;
+ DATAWIDTH : integer := 16;
+ WORDS :integer := 2 --DATAWIDTH/8;
+ );
+ port (
+ clk : in std_logic;
+ res_n : in std_logic;
+ restart_link : in std_logic;
+ ready_MGT2RM : in std_logic;
+ txdata_in : in std_logic_vector((DATAWIDTH-1) downto 0);
+ txcharisk_in : in std_logic_vector((WORDS-1) downto 0);
+
+ see_ready0 : in std_logic;
+ saw_ready1 : in std_logic;
+ valid_char : in std_logic;
+ rx_rm_ready : in std_logic;
+
+ ready_RM2LP : out std_logic;
+ txdata_out : out std_logic_vector((WORDS*9)-1 downto 0);
+ almost_ready : out std_logic;
+ gt11_reinit : out std_logic
+ );
+ end component;
+
+ component lp_top is
+ generic (
+ NUM_LANES : integer := 1; -- Number of data lanes
+ TX_SLAVE : integer := 0 -- If set; module will act as TX slave; otherwise as RX slave
+ -- If only one lane is used; parameter does not matter
+ );
+ port (
+ clk : in std_logic; -- Main clock
+ res_n : in std_logic; -- Active low reset; can be changed by define
+ link_active : out std_logic; -- link is active and can send and receive data
+
+ ctrl2send_stop : out std_logic; -- send control interface
+ ctrl2send_start : in std_logic;
+ ctrl2send_end : in std_logic;
+ ctrl2send : in std_logic_vector(15 downto 0);
+
+ data2send_stop : out std_logic_vector(NUM_LANES-1 downto 0); -- send data interface
+ data2send_start : in std_logic_vector(NUM_LANES-1 downto 0);
+ data2send_end : in std_logic_vector(NUM_LANES-1 downto 0);
+ data2send : in std_logic_vector((16*NUM_LANES)-1 downto 0);
+
+ dlm2send_va : in std_logic; -- send dlm interface
+ dlm2send : in std_logic_vector(3 downto 0);
+
+ dlm_rec_type : out std_logic_vector(3 downto 0); -- receive dlm interface
+ dlm_rec_va : out std_logic;
+
+ data_rec : out std_logic_vector((16*NUM_LANES)-1 downto 0); -- receive data interface
+ data_rec_start : out std_logic_vector(NUM_LANES-1 downto 0);
+ data_rec_end : out std_logic_vector(NUM_LANES-1 downto 0);
+ data_rec_stop : in std_logic_vector(NUM_LANES-1 downto 0);
+
+ ctrl_rec : out std_logic_vector(15 downto 0); -- receive control interface
+ ctrl_rec_start : out std_logic;
+ ctrl_rec_end : out std_logic;
+ ctrl_rec_stop : in std_logic;
+
+ data_from_link : in std_logic_vector((18*NUM_LANES)-1 downto 0); -- interface from the PHY
+ data2link : out std_logic_vector((18*NUM_LANES)-1 downto 0); -- interface to the PHY
+
+ link_activeovr : in std_logic; -- Overrides; set 0 by default
+ link_readyovr : in std_logic;
+
+ SERDES_ready : in std_logic -- signalize when PHY ready
+ );
+ end component;
+
+
+
+end package cbmnet_interface_pkg;
+
+package body cbmnet_interface_pkg is
+end package body;
\ No newline at end of file
attribute syn_sharing : string;
attribute syn_sharing of cbmnet_phy_ecp3_arch : architecture is "off";
+ constant WA_FIXATION : integer := c_YES;
+
signal clk_125_i : std_logic;
- signal clk_125_internal : std_logic;
+ signal clk_125_local : std_logic;
signal clk_rx_full : std_logic;
signal clk_rx_half : std_logic;
signal tx_data_i : std_logic_vector(17 downto 0);
- signal tx_data_buf_i : std_logic_vector(17 downto 0);
+
signal rx_data_i : std_logic_vector(17 downto 0);
+ signal rx_data_buf_i : std_logic_vector(17 downto 0);
signal rx_error : std_logic_vector(1 downto 0);
signal sd_los_i : std_logic;
signal rx_pcs_rst : std_logic;
- signal rx_fsm_pcs_rst : std_logic:= '0';
- signal rx_init_pcs_rst : std_logic:= '0';
-
signal rx_serdes_rst : std_logic;
- signal rx_fsm_serdes_rst : std_logic := '0';
- signal rx_init_serdes_rst : std_logic := '0';
-
-
-
+ signal rx_reset_from_rm_i: std_logic;
signal rx_los_low : std_logic;
signal rx_cdr_lol : std_logic;
signal tx_pll_lol : std_logic;
signal serdes_ready_i : std_logic;
+ signal serdes_rx_ready_i : std_logic;
+ signal serdes_tx_ready_i : std_logic;
signal sci_ch_i : std_logic_vector(3 downto 0);
signal sci_qd_i : std_logic;
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 wa_position_buf : std_logic_vector(3 downto 0);
-
- 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 := '0';
- signal got_link_ready_i : std_logic;
-
- signal stat_rx_control_i : std_logic_vector(31 downto 0);
- signal stat_tx_control_i : std_logic_vector(31 downto 0);
- signal debug_rx_control_i : std_logic_vector(31 downto 0);
- signal debug_tx_control_i : std_logic_vector(31 downto 0);
signal rx_fsm_state : std_logic_vector(3 downto 0);
signal tx_fsm_state : std_logic_vector(3 downto 0);
- signal debug_reg : std_logic_vector(63 downto 0);
- type sci_ctrl is (IDLE, SCTRL, SCTRL_WAIT, SCTRL_WAIT2, SCTRL_FINISH, GET_WA, GET_WA_WAIT, GET_WA_WAIT2, GET_WA_FINISH);
+ type sci_ctrl is (IDLE, 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 sci_timer : unsigned(7 downto 0) := (others => '0');
signal start_timer : unsigned(18 downto 0) := (others => '0');
signal led_ok : std_logic;
signal led_tx, last_led_tx : std_logic;
signal led_rx, last_led_rx : std_logic;
- signal timer : unsigned(20 downto 0);
-
- signal lsm_status_i : std_logic;
+ signal led_timer : unsigned(20 downto 0);
+ signal proper_byte_align_i : std_logic;
+ signal proper_word_align_i : std_logic;
+
-- RX READY MODULE
signal rx_ready_i : std_logic;
signal rx_valid_char_i : std_logic;
signal link_init_rx_reset_i : std_logic;
- signal rx_rm_rst_n :std_logic;
-
+ signal rx_rm_rst_n, tx_rm_rst_n :std_logic;
-- TX READY MODULE
signal tx_ready_i : std_logic;
signal tx_almost_ready_i : std_logic;
begin
- clk_125_internal <= CLK;
+ clk_125_local <= CLK;
CLK_RX_HALF_OUT <= clk_rx_half;
CLK_RX_FULL_OUT <= clk_rx_full;
SD_TXDIS_OUT <= '0';
- rst_n <= not (CLEAR or sd_los_i or CTRL_OP(0));
- rst <= (CLEAR or sd_los_i or CTRL_OP(0));
-
+ rst <= (CLEAR or CTRL_OP(0));
+ rst_n <= not rst;
gen_slave_clock : if IS_SYNC_SLAVE = c_YES generate
clk_125_i <= clk_rx_half;
end generate;
gen_master_clock : if IS_SYNC_SLAVE = c_NO generate
- clk_125_i <= clk_125_internal;
+ clk_125_i <= clk_125_local;
end generate;
-------------------------------------------------
tx_full_clk_ch0 => open,
tx_half_clk_ch0 => open,
- fpga_rxrefclk_ch0 => clk_125_internal,
+ fpga_rxrefclk_ch0 => clk_125_local,
-- RESETS
fpga_txrefclk => clk_125_i,
rx_pwrup_ch0_c => '1',
-- TX DATA PORT
- txdata_ch0 => tx_data_buf_i(15 downto 0),
- tx_k_ch0 => tx_data_buf_i(17 downto 16),
+ txdata_ch0 => tx_data_i(15 downto 0),
+ tx_k_ch0 => tx_data_i(17 downto 16),
tx_force_disp_ch0 => "00",
tx_disp_sel_ch0 => "00",
tx_pll_lol_qd_s => tx_pll_lol,
rx_los_low_ch0_s => rx_los_low,
rx_cdr_lol_ch0_s => rx_cdr_lol,
- lsm_status_ch0_s => lsm_status_i,
+ lsm_status_ch0_s => open,
SCI_WRDATA => sci_data_in_i,
SCI_RDDATA => sci_data_out_i,
SCI_WRN => sci_write_i
);
- wa_position_buf <= x"1" when (rx_init_pcs_rst = '1' and CTRL_OP(2) = '0') or (CTRL_OP(4) = '1') else
- wa_position_rx(3 downto 0);
-
- tx_data_buf_i <=
- ("01" & x"009c") when CTRL_OP(9 downto 8) = "01" else
- ("01" & x"00bc") when CTRL_OP(9 downto 8) = "11" else
- tx_data_i;
-
- rx_pcs_rst <= rx_fsm_pcs_rst;
- rx_serdes_rst <= rx_fsm_serdes_rst;
-
tx_serdes_rst <= '0'; --no function
serdes_rst_qd <= '0'; --included in rst_qd
- DEBUG_OUT(17 downto 0) <= tx_data_i;
- DEBUG_OUT(22 downto 20) <= tx_pll_lol & rx_los_low & rx_cdr_lol;
+ DEBUG_OUT(19 downto 0) <= "00" & tx_data_i;
+ DEBUG_OUT(23 downto 20) <= "0" & tx_pll_lol & rx_los_low & rx_cdr_lol;
+ DEBUG_OUT(27 downto 24) <= proper_word_align_i & proper_byte_align_i & SD_PRSNT_N_IN & SD_LOS_IN;
+ DEBUG_OUT(31 downto 28) <= rst_qd & rx_serdes_rst & tx_pcs_rst & rx_pcs_rst;
- DEBUG_OUT(17+32 downto 32) <= rx_data_i;
+ DEBUG_OUT(51 downto 32) <= "00" & rx_data_buf_i;
+ DEBUG_OUT(59 downto 52) <= rx_fsm_state & tx_fsm_state;
+
+ DEBUG_OUT(63 downto 60) <= "00" & tx_ready_i & tx_almost_ready_i;
+ DEBUG_OUT(99 downto 96) <= rx_almost_ready_i & rx_see_ready0_i & rx_saw_ready1_i & rx_valid_char_i;
process is
variable cnt, cntr : unsigned(15 downto 0);
-------------------------------------------------
-- Reset FSM & Link states
-------------------------------------------------
- THE_RX_FSM : rx_reset_fsm
+ THE_RX_FSM : cbmnet_phy_ecp3_rx_reset_fsm
port map(
RST_N => rst_n,
- RX_REFCLK => clk_125_i,
+ RX_REFCLK => clk_125_local,
TX_PLL_LOL_QD_S => tx_pll_lol,
- RX_SERDES_RST_CH_C => rx_fsm_serdes_rst,
RX_CDR_LOL_CH_S => rx_cdr_lol,
RX_LOS_LOW_CH_S => rx_los_low,
- RX_PCS_RST_CH_C => rx_fsm_pcs_rst,
- WA_POSITION => wa_position_buf,
+
+ RM_RESET_IN => '0', --rx_reset_from_rm_i,
+ PROPER_BYTE_ALIGN_IN=> proper_byte_align_i,
+ PROPER_WORD_ALIGN_IN=> proper_word_align_i,
+
+ RX_SERDES_RST_CH_C => rx_serdes_rst,
+ RX_PCS_RST_CH_C => rx_pcs_rst,
STATE_OUT => rx_fsm_state
);
THE_TX_FSM : tx_reset_fsm
port map(
RST_N => rst_n,
- TX_REFCLK => clk_125_internal,
+ TX_REFCLK => clk_125_local,
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
);
+
+ sd_los_i <= SD_LOS_IN when rising_edge(CLK);
- PROC_CLK_RESET: process is
- variable counter : unsigned(8 downto 0) := (others => '0');
- begin
- wait until rising_edge(clk_rx_half);
- CLK_RX_RESET_OUT <= '1';
+ gen_wa_fixation: if WA_FIXATION = c_YES generate
+ -- In slave mode, we need the barrel shifter to lock on the lowest position in
+ -- order to avoid a non-deterministic skew in the clock/data phase
+ -- If we're the master, we don't care about the proper barrel shifter alignment
+ proper_byte_align_i <=
+ '1' when IS_SYNC_SLAVE = c_NO else
+ proper_byte_align_i when not rising_edge(clk_125_i) else
+ '1' when wa_position(3 downto 0) = x"0" else '0';
+
+ -- detect misaligned gearing fifo
+ proper_word_align_i <=
+ '1' when rst_n = '0' or rx_serdes_rst = '1' else
+ proper_word_align_i when not rising_edge(clk_125_i) else
+ -- '0' when rx_serdes_rst ='1' or rst = '1' else
+ '0' when rx_data_i(17 downto 16) = "10" and
+ (rx_data_i(15 downto 8) = K284 or rx_data_i(15 downto 8) = K285 or rx_data_i(15 downto 8) = K287)
+ and rx_data_i(7 downto 0) = x"00" else '1';
+
+ serdes_rx_ready_i <= (not rx_cdr_lol) and proper_word_align_i and proper_byte_align_i when rx_fsm_state = x"6" else '0';
+ serdes_tx_ready_i <= (not tx_pll_lol) when tx_fsm_state = x"5" else '0';
+ serdes_ready_i <= serdes_rx_ready_i and serdes_tx_ready_i;
- if rx_cdr_lol = '1' then
- counter := (others => '0');
+ rx_data_buf_i <= rx_data_i;
+ end generate;
+
+ gen_wa_no_fixation: if WA_FIXATION = c_NO generate
+ proper_byte_align_i <= '1';
+ serdes_ready_i <= not (rx_cdr_lol or tx_pll_lol) when tx_fsm_state = x"5" and rx_fsm_state = x"6" else '0';
+
+ proc_wa: process is
+ variable locked : std_logic;
+ variable locked_with_delay : std_logic;
- elsif counter(counter'high) = '0' then
- counter := counter + 1;
+ variable delay : std_logic_vector(8 downto 0);
+ variable rx_pcs_rst_del : std_logic := '0';
+ begin
+ wait until rising_edge(clk_125_i);
+
+ if locked_with_delay = '1' then
+ rx_data_buf_i <= delay(8) & rx_data_i(17) & delay(7 downto 0) & rx_data_i(15 downto 8);
+ else
+ rx_data_buf_i <= rx_data_i;
+ end if;
- else
- CLK_RX_RESET_OUT <= '0';
+ delay := rx_data_i(16) & rx_data_i(7 downto 0);
- end if;
- end process;
-
- -- Master does not do bit-locking
- SYNC_WA_POSITION : process begin
- wait until rising_edge(clk_125_i);
- if IS_SYNC_SLAVE = 1 then
- wa_position_rx <= wa_position;
- else
- wa_position_rx <= x"0000";
- end if;
- end process;
+ if rx_pcs_rst = '1' and rx_pcs_rst_del = '0' then
+ locked := '0';
+
+ elsif locked = '0' then
+ if rx_data_i(17 downto 16) = "10" and (rx_data_i(15 downto 8) = K284 or rx_data_i(15 downto 8) = K285 or rx_data_i(15 downto 8) = K287) and rx_data_i(7 downto 0) = x"00" then
+ locked_with_delay := '1';
+ locked := '1';
+ elsif rx_data_i(17 downto 16) = "01" and (rx_data_i(7 downto 0) = K284 or rx_data_i(7 downto 0) = K285 or rx_data_i(7 downto 0) = K287) and rx_data_i(15 downto 8) = x"00" then
+ locked_with_delay := '0';
+ locked := '1';
+ end if;
+
+ end if;
- serdes_ready_i <= not (rx_cdr_lol or tx_pll_lol) when
- wa_position_rx = x"0000" and
- tx_fsm_state = x"5" and
- rx_fsm_state = x"6" else '0';
+ rx_pcs_rst_del := rx_pcs_rst;
+ proper_word_align_i <= locked;
+ end process;
+ end generate;
-------------------------------------------------
- -- CBMNet Link Init
+ -- CBMNet Ready Modules
-------------------------------------------------
THE_RX_READY: gtp_rx_ready_module
generic map (INCL_8B10B_DEC => c_No)
res_n => rx_rm_rst_n,
ready_MGT2RM => serdes_ready_i,
- rxdata_in(17 downto 0) => rx_data_i,
+ rxdata_in(17 downto 0) => rx_data_buf_i,
rxdata_in(19 downto 18) => "00",
tx_ready => tx_ready_i,
tx_almost_ready => tx_almost_ready_i,
ready_RM2LP => rx_ready_i,
- rxdata_out => PHY_RXDATA_OUT,
+ rxdata_out => PHY_RXDATA_OUT,
charisk_out => PHY_RXDATA_K_OUT,
almost_ready_OUT => rx_almost_ready_i,
saw_ready1 => rx_saw_ready1_i,
valid_char => rx_valid_char_i,
- reset_rx => rx_init_pcs_rst
+ reset_rx => rx_reset_from_rm_i
);
- rx_rm_rst_n <= not (rst or CTRL_OP(1)); -- or not serdes_ready_i);
+ rx_rm_rst_n <= not (rst or CTRL_OP(1) or not serdes_rx_ready_i); -- or not serdes_ready_i);
THE_TX_READY: gtp_tx_ready_module
port map (
clk => clk_125_i, -- : in std_logic;
- res_n => rx_rm_rst_n, -- : in std_logic;
- restart_link => CTRL_OP(14), -- : in std_logic;
- ready_MGT2RM => serdes_ready_i, -- : in std_logic;
+ res_n => rx_rm_rst_n, -- : in std_logic;
+ restart_link => CTRL_OP(14), -- : in std_logic;
+ ready_MGT2RM => serdes_tx_ready_i, -- : in std_logic;
txdata_in => PHY_TXDATA_IN , -- : in std_logic_vector((DATAWIDTH-1) downto 0);
txcharisk_in => PHY_TXDATA_K_IN, -- : in std_logic_vector((WORDS-1) downto 0);
gt11_reinit => open -- : out std_logic
);
+ tx_rm_rst_n <= not (rst or CTRL_OP(2) or not serdes_tx_ready_i);
+
rx_rm_ready_i <= rx_almost_ready_i or rx_ready_i;
SERDES_ready <= tx_ready_i and rx_ready_i when rising_edge(clk_125_i);
PROC_SCI_CTRL: process
variable cnt : integer range 0 to 4 := 0;
begin
- wait until rising_edge(CLK);
- 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;
-
+ wait until rising_edge(CLK);
+ 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_timer(sci_timer'left) = '1' then
+ sci_timer <= (others => '0');
+ sci_state <= GET_WA;
+ end if;
+
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;
-
+ 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;
-- RX/TX leds are on as soon as the correspondent pll is locked and data
-- other than the idle word is transmitted
- PROC_RX_TX_LEDS: process is
+ PROC_LEDS: process is
begin
wait until rising_edge(CLK);
led_rx <= not rx_cdr_lol;
led_tx <= not tx_pll_lol;
- if (timer(20) = '1') or (rx_data_i(17 downto 16) = "10" and rx_data_i(15 downto 0) = x"fcce") then
+ if (led_timer(20) = '1') or (rx_data_i(17 downto 16) = "10" and rx_data_i(15 downto 0) = x"fcce") then
led_rx <= '0';
end if;
- if (timer(20) = '1') or (tx_data_i(17 downto 16) = "10" and tx_data_i(15 downto 0) = x"fcce") then
+ if (led_timer(20) = '1') or (tx_data_i(17 downto 16) = "10" and tx_data_i(15 downto 0) = x"fcce") then
led_tx <= '0';
end if;
- end process;
-
- ROC_TIMER : process begin
- wait until rising_edge(CLK);
- timer <= timer + 1 ;
- if timer(20) = '1' then
- timer <= (others => '0');
- last_led_rx <= led_rx ;
- last_led_tx <= led_tx;
- end if;
- end process;
- -------------------------------------------------
- -- Debug Registers
- -------------------------------------------------
- debug_reg(2 downto 0) <= rx_fsm_state(2 downto 0);
- debug_reg(3) <= rx_serdes_rst;
-
- debug_reg(4) <= CLEAR;
- debug_reg(5) <= '1';
- debug_reg(6) <= rx_los_low;
- debug_reg(7) <= rx_cdr_lol;
-
- debug_reg(8) <= RESET;
- debug_reg(9) <= tx_pll_lol;
- debug_reg(10) <= '1';
- debug_reg(11) <= CTRL_OP(15);
+ led_timer <= led_timer + 1 ;
+ if led_timer(20) = '1' then
+ led_timer <= (others => '0');
+ last_led_rx <= led_rx ;
+ last_led_tx <= led_tx;
+ end if;
+ end process;
- debug_reg(12) <= '0';
- debug_reg(13) <= send_link_reset_i;
- debug_reg(14) <= sd_los_i;
- debug_reg(15) <= rx_pcs_rst;
- -- debug_reg(31 downto 24) <= tx_data;
-
- debug_reg(16) <= '0';
- debug_reg(17) <= '1';
- 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);
-
+ PROC_CLK_RESET: process is
+ variable counter : unsigned(8 downto 0) := (others => '0');
+ begin
+ wait until rising_edge(clk_rx_half);
+ CLK_RX_RESET_OUT <= '1';
+
+ if rx_cdr_lol = '1' then
+ counter := (others => '0');
- STAT_DEBUG <= debug_reg;
-
- sd_los_i <= SD_LOS_IN when rising_edge(CLK);
-
-
-
-
--- STAT_OP REGISTER
- STAT_OP(0) <= led_tx;
- STAT_OP(1) <= led_rx;
- STAT_OP(2) <= led_ok;
-
- STAT_OP(3) <= rx_valid_char_i;
- STAT_OP(4) <= rx_see_ready0_i;
- STAT_OP(5) <= rx_saw_ready1_i;
- STAT_OP(6) <= rx_almost_ready_i;
- STAT_OP(7) <= rx_ready_i;
- STAT_OP(8) <= rx_init_pcs_rst;
- STAT_OP(9) <= tx_almost_ready_i;
- STAT_OP(10) <= tx_ready_i;
- STAT_OP(11) <= rst_n;
- STAT_OP(12) <= serdes_ready_i;
- STAT_OP(13) <= lsm_status_i;
-
-
-
-
- -- STAT_OP(11 downto 8) <= rx_fsm_state;
-
- -- STAT_OP(15 downto 12) <= wa_position_rx( 3 downto 0);
+ elsif counter(counter'high) = '0' then
+ counter := counter + 1;
+
+ else
+ CLK_RX_RESET_OUT <= '0';
+
+ end if;
+ end process;
- --STAT_OP(12) <= rx_los_low;
- --STAT_OP(13) <= ;
- --STAT_OP(14) <= ;
- --STAT_OP(15) <= ;
+-- STAT_OP REGISTER
+STAT_OP(0) <= clk_125_local;
+STAT_OP(1) <= clk_125_i;
+STAT_OP(2) <= rst;
+STAT_OP(3) <= SD_LOS_IN;
+
+STAT_OP(4) <= rx_serdes_rst;
+STAT_OP(5) <= rx_pcs_rst;
+STAT_OP(6) <= tx_pcs_rst;
+STAT_OP(7) <= rst_qd;
+
+STAT_OP(8) <= rx_los_low;
+STAT_OP(9) <= rx_cdr_lol;
+STAT_OP(10) <= OR_ALL(rx_error);
+STAT_OP(11) <= rx_reset_from_rm_i;
+
+STAT_OP(12) <= tx_pll_lol;
+STAT_OP(13) <= proper_byte_align_i;
+STAT_OP(14) <= proper_word_align_i;
+STAT_OP(15) <= serdes_ready_i;
+
+
+-- STAT_OP(3) <= rx_valid_char_i;
+-- STAT_OP(4) <= rx_see_ready0_i;
+-- STAT_OP(5) <= rx_saw_ready1_i;
+-- STAT_OP(6) <= rx_almost_ready_i;
+-- STAT_OP(7) <= rx_ready_i;
+-- STAT_OP(8) <= rx_reset_from_rm_i;
+-- STAT_OP(9) <= tx_almost_ready_i;
+-- STAT_OP(10) <= tx_ready_i;
+-- STAT_OP(11) <= serdes_tx_ready_i;
+-- STAT_OP(12) <= proper_byte_align_i;
+-- STAT_OP(13) <= proper_word_align_i;
end architecture;
--- /dev/null
+--Media interface RX state machine
+-- initial version by lattice tempte
+-- adopted by Jan Michel for sync. TrbNet
+-- adopted by Manuel Penschuck for CbmNet phy
+
+
+LIBRARY IEEE;
+ USE IEEE.std_logic_1164.ALL;
+ USE IEEE.numeric_std.all;
+
+
+entity cbmnet_phy_ecp3_rx_reset_fsm is
+ port (
+ RST_N : in std_logic;
+ RX_REFCLK : in std_logic;
+ TX_PLL_LOL_QD_S : in std_logic;
+ RX_CDR_LOL_CH_S : in std_logic;
+ RX_LOS_LOW_CH_S : in std_logic;
+
+ RM_RESET_IN : in std_logic := '0';
+ PROPER_BYTE_ALIGN_IN : in std_logic := '1';
+ PROPER_WORD_ALIGN_IN : in std_logic := '1';
+
+ RX_SERDES_RST_CH_C: out std_logic;
+ RX_PCS_RST_CH_C : out std_logic;
+ STATE_OUT : out std_logic_vector(3 downto 0)
+ );
+end entity ;
+
+architecture rx_reset_fsm_arch of cbmnet_phy_ecp3_rx_reset_fsm is
+ constant count_index : integer := 19;
+ type statetype is (WAIT_FOR_PLOL, RX_SERDES_RESET, WAIT_FOR_timer1, CHECK_LOL_LOS, WAIT_FOR_timer2, NORMAL);
+
+ signal cs: statetype; -- current state of lsm
+ signal ns: statetype; -- next state of lsm
+
+ signal tx_pll_lol_qd_s_int: std_logic;
+ signal rx_los_low_int: std_logic;
+ signal plol_los_int: std_logic;
+ signal rx_lol_los : std_logic;
+ signal rx_lol_los_int: std_logic;
+ signal rx_lol_los_del: std_logic;
+ signal rx_pcs_rst_ch_c_int: std_logic;
+ signal rx_serdes_rst_ch_c_int: std_logic;
+
+ signal reset_timer1: std_logic;
+ signal reset_timer2: std_logic;
+
+ signal counter1: unsigned(1 downto 0);
+ signal timer1: std_logic;
+
+ signal counter2: unsigned(19 downto 0);
+ signal timer2 : std_logic;
+
+ signal rm_reset_i : std_logic;
+ signal proper_byte_align_i : std_logic;
+ signal proper_word_align_i : std_logic;
+begin
+
+ rx_lol_los <= rx_cdr_lol_ch_s or rx_los_low_ch_s ;
+
+ proc_fsm_sync: process(RX_REFCLK)
+ begin
+ if rising_edge(RX_REFCLK) then
+ if RST_N = '0' then
+ cs <= WAIT_FOR_PLOL;
+ rx_lol_los_int <= '1';
+ rx_lol_los_del <= '1';
+ tx_pll_lol_qd_s_int <= '1';
+ RX_PCS_RST_CH_C <= '1';
+ RX_SERDES_RST_CH_C <= '0';
+ rx_los_low_int <= '1';
+ else
+ cs <= ns;
+ rx_lol_los_del <= rx_lol_los;
+ rx_lol_los_int <= rx_lol_los_del;
+ tx_pll_lol_qd_s_int <= tx_pll_lol_qd_s;
+ RX_PCS_RST_CH_C <= rx_pcs_rst_ch_c_int;
+ RX_SERDES_RST_CH_C <= rx_serdes_rst_ch_c_int;
+ rx_los_low_int <= rx_los_low_ch_s;
+
+ rm_reset_i <= RM_RESET_IN;
+ proper_byte_align_i <= PROPER_BYTE_ALIGN_IN;
+ proper_word_align_i <= PROPER_WORD_ALIGN_IN;
+ end if;
+ end if;
+ end process;
+
+
+--timer2 = 400,000 Refclk cycles or 200,000 REFCLKDIV2 cycles
+--An 18 bit counter ([17:0]) counts 262144 cycles, so a 19 bit ([18:0]) counter will do if we set timer2 = bit[18]
+ proc_timer2: process begin
+ wait until rising_edge(RX_REFCLK);
+ if reset_timer2 = '1' then
+ counter2 <= "00000000000000000000";
+ timer2 <= '0';
+ else
+ if counter2(count_index) = '1' then
+ timer2 <='1';
+ else
+ timer2 <='0';
+ counter2 <= counter2 + 1 ;
+ end if;
+ end if;
+ end process;
+
+
+ proc_fsm_trans: process(cs, tx_pll_lol_qd_s_int, rx_los_low_int, timer1, rx_lol_los_int, timer2)
+ begin
+ -- reset_timer1 <= '0';
+ reset_timer2 <= '0';
+ STATE_OUT <= x"F";
+ case cs is
+ when WAIT_FOR_PLOL =>
+ rx_pcs_rst_ch_c_int <= '1';
+ rx_serdes_rst_ch_c_int <= '0';
+ if (tx_pll_lol_qd_s_int = '1' or rx_los_low_int = '1') then --Also make sure A Signal
+ ns <= WAIT_FOR_PLOL; --is Present prior to moving to the next
+ else
+ ns <= RX_SERDES_RESET;
+ end if;
+ STATE_OUT <= x"1";
+
+ when RX_SERDES_RESET =>
+ rx_pcs_rst_ch_c_int <= '1';
+ rx_serdes_rst_ch_c_int <= '1';
+ -- reset_timer1 <= '1';
+ ns <= WAIT_FOR_timer1;
+ STATE_OUT <= x"2";
+
+
+ when WAIT_FOR_timer1 =>
+ rx_pcs_rst_ch_c_int <= '1';
+ rx_serdes_rst_ch_c_int <= '1';
+ ns <= CHECK_LOL_LOS;
+ STATE_OUT <= x"3";
+
+ when CHECK_LOL_LOS =>
+ rx_pcs_rst_ch_c_int <= '1';
+ rx_serdes_rst_ch_c_int <= '0';
+ reset_timer2 <= '1';
+ ns <= WAIT_FOR_timer2;
+ STATE_OUT <= x"4";
+
+ when WAIT_FOR_timer2 =>
+ rx_pcs_rst_ch_c_int <= '1';
+ 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
+ ns <= WAIT_FOR_PLOL;
+ -- elsif proper_byte_align_i = '0' or proper_word_align_i = '0' then
+ -- ns <= CHECK_LOL_LOS;
+ else
+ ns <= NORMAL;
+ end if;
+ elsif rx_lol_los_int = '0' then
+ ns <= NORMAL;
+ else
+ ns <= WAIT_FOR_timer2;
+ end if;
+ else
+ ns <= CHECK_LOL_LOS; --RESET timer2
+ end if;
+ STATE_OUT <= x"5";
+
+
+ when NORMAL =>
+ rx_pcs_rst_ch_c_int <= '0';
+ rx_serdes_rst_ch_c_int <= '0';
+ if rx_lol_los_int = '1' or proper_byte_align_i = '0' or proper_word_align_i = '0' or rm_reset_i = '1' then
+ ns <= WAIT_FOR_PLOL;
+ else
+ ns <= NORMAL;
+ end if;
+ STATE_OUT <= x"6";
+
+ when others =>
+ ns <= WAIT_FOR_PLOL;
+
+ end case;
+ end process;
+
+end architecture;
\ No newline at end of file