From 9325de6963349a03279856e31780d9d06d5fd801 Mon Sep 17 00:00:00 2001 From: Manuel Penschuck Date: Tue, 1 Oct 2013 09:16:38 +0200 Subject: [PATCH] Backup --- cbmnet/code/cbmnet_interface_pkg.vhd | 129 ++++++ cbmnet/code/cbmnet_phy_ecp3.vhd | 464 +++++++++---------- cbmnet/code/cbmnet_phy_ecp3_rx_reset_fsm.vhd | 184 ++++++++ cbmnet/code/cbmnet_phy_pkg.vhd | 20 +- cbmnet/compile_periph_frankfurt.pl | 16 + 5 files changed, 563 insertions(+), 250 deletions(-) create mode 100644 cbmnet/code/cbmnet_interface_pkg.vhd create mode 100644 cbmnet/code/cbmnet_phy_ecp3_rx_reset_fsm.vhd diff --git a/cbmnet/code/cbmnet_interface_pkg.vhd b/cbmnet/code/cbmnet_interface_pkg.vhd new file mode 100644 index 0000000..da8f286 --- /dev/null +++ b/cbmnet/code/cbmnet_interface_pkg.vhd @@ -0,0 +1,129 @@ +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 diff --git a/cbmnet/code/cbmnet_phy_ecp3.vhd b/cbmnet/code/cbmnet_phy_ecp3.vhd index 7eaf524..b3a3dae 100644 --- a/cbmnet/code/cbmnet_phy_ecp3.vhd +++ b/cbmnet/code/cbmnet_phy_ecp3.vhd @@ -71,14 +71,17 @@ architecture cbmnet_phy_ecp3_arch of cbmnet_phy_ecp3 is 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); @@ -91,21 +94,16 @@ architecture cbmnet_phy_ecp3_arch of cbmnet_phy_ecp3 is 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; @@ -119,37 +117,23 @@ architecture cbmnet_phy_ecp3_arch of cbmnet_phy_ecp3 is 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; @@ -160,29 +144,27 @@ architecture cbmnet_phy_ecp3_arch of cbmnet_phy_ecp3 is 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; ------------------------------------------------- @@ -206,7 +188,7 @@ begin 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, @@ -221,8 +203,8 @@ begin 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", @@ -244,7 +226,7 @@ begin 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, @@ -255,24 +237,19 @@ begin 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); @@ -289,64 +266,102 @@ begin ------------------------------------------------- -- 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) @@ -355,14 +370,14 @@ begin 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, @@ -370,17 +385,17 @@ begin 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); @@ -395,6 +410,8 @@ begin 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); @@ -407,177 +424,126 @@ begin 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; diff --git a/cbmnet/code/cbmnet_phy_ecp3_rx_reset_fsm.vhd b/cbmnet/code/cbmnet_phy_ecp3_rx_reset_fsm.vhd new file mode 100644 index 0000000..7d192e7 --- /dev/null +++ b/cbmnet/code/cbmnet_phy_ecp3_rx_reset_fsm.vhd @@ -0,0 +1,184 @@ +--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 diff --git a/cbmnet/code/cbmnet_phy_pkg.vhd b/cbmnet/code/cbmnet_phy_pkg.vhd index c8cb47a..3adddc2 100644 --- a/cbmnet/code/cbmnet_phy_pkg.vhd +++ b/cbmnet/code/cbmnet_phy_pkg.vhd @@ -114,7 +114,25 @@ package cbmnet_phy_pkg is -- refclk2fpga : out std_logic; serdes_rst_qd_c : in std_logic ); - end component; + end component; + + component 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 component ; end package cbmnet_phy_pkg; package body cbmnet_phy_pkg is diff --git a/cbmnet/compile_periph_frankfurt.pl b/cbmnet/compile_periph_frankfurt.pl index 939fd0d..fd58eed 100755 --- a/cbmnet/compile_periph_frankfurt.pl +++ b/cbmnet/compile_periph_frankfurt.pl @@ -31,6 +31,13 @@ if ($build_master and $build_slave) { system "xterm -e './compile_periph_frankfurt.pl s; read' &"; sleep 5; system "xterm -e './compile_periph_frankfurt.pl w; read' &"; + sleep 5; + local $| = 1; + while ( (-e '.lock_slave') or (-e '.lock_master')) { + sleep 3; + print '.'; + } + exit; } @@ -48,6 +55,7 @@ my $lm_license_file_for_par = "1702\@hadeb05.gsi.de"; my $workdir = "workdir_" . ($build_slave ? 'slave' : 'master'); +system "touch .lock_" . ($build_slave ? 'slave' : 'master'); symlink($CbmNetPath, 'cbmnet') unless (-e 'cbmnet'); unless(-e $workdir) { @@ -174,6 +182,14 @@ execute($c); chdir ".."; +unlink ".lock_" . ($build_slave ? 'slave' : 'master'); + +print "DONE\n"; + +unless (-e "$workdir/trb3_periph_cbmnet.bit") { + print "no bit file found. press enter to continue\n\a"; <>; +} + sub execute { my ($c, $op) = @_; -- 2.43.0