diff --git a/common/hdl/delay_filter.vhd b/common/hdl/delay_filter.vhd index 0d31ce182..931c6b173 100644 --- a/common/hdl/delay_filter.vhd +++ b/common/hdl/delay_filter.vhd @@ -38,9 +38,6 @@ signal pulse_buf : std_logic_vector(2 downto 0) := "000"; signal filt : std_logic := '0'; signal jk : std_logic_vector(1 downto 0); -attribute async_reg : string; -attribute async_reg of pulse_buf : signal is "TRUE"; - begin -------------------------------------------------------------------------- diff --git a/common/hdl/iobuf_registered.vhd b/common/hdl/iobuf_registered.vhd index fd911d85d..fc28b9538 100644 --- a/common/hdl/iobuf_registered.vhd +++ b/common/hdl/iobuf_registered.vhd @@ -32,6 +32,14 @@ architecture rtl of iobuf_registered is signal ipad : std_logic; signal opad : std_logic; +attribute IOB : string; +attribute IOB of ipad : signal is "TRUE"; +attribute ASYNC_REG : string; +attribute ASYNC_REG of opad : signal is "TRUE"; + +signal tied_to_ground : std_logic := '0'; +signal tied_to_vcc : std_logic := '1'; + begin -------------------------------------------------------------------------- @@ -39,11 +47,23 @@ begin -------------------------------------------------------------------------- process(clock) begin if rising_edge(clock) then - O <= opad; ipad <= I; end if; end process; +IDDR_inst : IDDR + generic map ( + DDR_CLK_EDGE => "SAME_EDGE_PIPELINED") + port map ( + Q1 => O, + Q2 => open, + C => clock, + CE => tied_to_vcc, + D => opad, + R => tied_to_ground, + S => tied_to_ground +); + -- Physical IOBUF instantiations controlled with PROTOCOL IOBUF_inst : IOBUF port map ( diff --git a/common/templates/top_defines.vhd.jinja2 b/common/templates/top_defines.vhd.jinja2 index e101fdd5b..d2cbdd577 100644 --- a/common/templates/top_defines.vhd.jinja2 +++ b/common/templates/top_defines.vhd.jinja2 @@ -44,6 +44,7 @@ constant EBUSW : natural := 12; -------------------------------------------------------------------------- constant DCARD_MONITOR : std_logic_vector(2 downto 0) := "011"; +constant DCARD_MON_CTRL : std_logic_vector(2 downto 0) := "010"; type t_mode_group is array (5 downto 0) of std_logic_vector(31 downto 0); type t_mode is array (PBUSW-1 downto 0) of t_mode_group; diff --git a/targets/PandABox/SlowFPGA/src/hdl/dcard_ctrl.vhd b/targets/PandABox/SlowFPGA/src/hdl/dcard_ctrl.vhd index 37c7d81cd..3f17ef426 100644 --- a/targets/PandABox/SlowFPGA/src/hdl/dcard_ctrl.vhd +++ b/targets/PandABox/SlowFPGA/src/hdl/dcard_ctrl.vhd @@ -52,6 +52,8 @@ begin return X"0C"; when "011" => -- EnDat return X"14"; + when "110" => -- SSI-splitter + return X"03"; -- same as Incremental when others => return X"00"; end case; @@ -72,22 +74,25 @@ begin return X"07"; when "101" => -- Data passthrough (same as SSI) return X"28"; + when "110" => -- SSI-splitter + return X"07"; -- same as Incremental when others => - return X"00"; + return X"04"; end case; end OUTENC_CONV; -function CONV_PADS(INENC, OUTENC : std_logic_vector) return std_logic_vector is +function CONV_PADS(INENC, OUTENC, DCARD_MODE : std_logic_vector) return std_logic_vector is variable enc_ctrl_pad : std_logic_vector(11 downto 0); begin enc_ctrl_pad(1 downto 0) := INENC(1 downto 0); enc_ctrl_pad(3 downto 2) := OUTENC(1 downto 0); - enc_ctrl_pad(4) := INENC(2); + enc_ctrl_pad(4) := not INENC(2) when DCARD_MODE(3 downto 1) = DCARD_MON_CTRL else INENC(2); enc_ctrl_pad(5) := OUTENC(2); enc_ctrl_pad(7 downto 6) := INENC(4 downto 3); enc_ctrl_pad(9 downto 8) := OUTENC(4 downto 3); - enc_ctrl_pad(10) := INENC(5); + enc_ctrl_pad(10) := '1' when (DCARD_MODE(3 downto 1) = DCARD_MONITOR + or DCARD_MODE(3 downto 1) = DCARD_MON_CTRL) else INENC(5); enc_ctrl_pad(11) := OUTENC(5); return enc_ctrl_pad; @@ -133,10 +138,10 @@ begin end process; -- Interleave Input and Output Controls to the Daughter Card Pins. -dcard_ctrl1_io(11 downto 0) <= CONV_PADS(inenc_ctrl(0), outenc_ctrl(0)); -dcard_ctrl2_io(11 downto 0) <= CONV_PADS(inenc_ctrl(1), outenc_ctrl(1)); -dcard_ctrl3_io(11 downto 0) <= CONV_PADS(inenc_ctrl(2), outenc_ctrl(2)); -dcard_ctrl4_io(11 downto 0) <= CONV_PADS(inenc_ctrl(3), outenc_ctrl(3)); +dcard_ctrl1_io(11 downto 0) <= CONV_PADS(inenc_ctrl(0), outenc_ctrl(0), DCARD_MODE_i(0)); +dcard_ctrl2_io(11 downto 0) <= CONV_PADS(inenc_ctrl(1), outenc_ctrl(1), DCARD_MODE_i(1)); +dcard_ctrl3_io(11 downto 0) <= CONV_PADS(inenc_ctrl(2), outenc_ctrl(2), DCARD_MODE_i(2)); +dcard_ctrl4_io(11 downto 0) <= CONV_PADS(inenc_ctrl(3), outenc_ctrl(3), DCARD_MODE_i(3)); DCARD_MODE <= DCARD_MODE_i; diff --git a/targets/PandABox/blocks/inenc/inenc.block.ini b/targets/PandABox/blocks/inenc/inenc.block.ini index 74c1a42d4..f51f5101c 100644 --- a/targets/PandABox/blocks/inenc/inenc.block.ini +++ b/targets/PandABox/blocks/inenc/inenc.block.ini @@ -1,6 +1,7 @@ [.] description: Input encoder entity: inenc +ip: ila_32x8K [CLK] type: bit_mux @@ -13,6 +14,7 @@ description: Type of absolute/incremental protocol 1: SSI 2: BISS 3: enDat +6: SSI-Splitter [CLK_SRC] type: param enum @@ -48,6 +50,14 @@ description: Set point type: param bit description: Zero position on Z rising edge +[DEBOUNCE_EN] +type: param bit +description: Enable optional debouncing for clock input lines + +[DEBOUNCE_TIME] +type: param uint 127 +description: Time constant in clock ticks for debounce timeout + [A] type: bit_out description: Quadrature A if in incremental mode @@ -91,7 +101,7 @@ type: read enum description: Daughter card jumper mode 0: DCARD id 0 1: Encoder Control -2: DCARD id 2 +2: Encoder Mon+Ctrl 3: Encoder Monitor 4: DCARD id 3 5: DCARD id 4 diff --git a/targets/PandABox/blocks/outenc/outenc.block.ini b/targets/PandABox/blocks/outenc/outenc.block.ini index fd99a5005..5959d9685 100644 --- a/targets/PandABox/blocks/outenc/outenc.block.ini +++ b/targets/PandABox/blocks/outenc/outenc.block.ini @@ -37,6 +37,7 @@ description: Type of absolute/incremental protocol 3: enDat 4: ABZ Passthrough 5: DATA Passthrough +6: SSI-Splitter [BITS] type: param uint 32 @@ -66,7 +67,7 @@ type: read enum description: Daughter card jumper mode 0: DCARD id 0 1: Encoder Control -2: DCARD id 2 +2: Encoder Mon+Ctrl 3: Encoder Monitor 4: DCARD id 3 5: DCARD id 4 diff --git a/targets/PandABox/hdl/encoders.vhd b/targets/PandABox/hdl/encoders.vhd index 496a50e7f..3ade9c9f3 100644 --- a/targets/PandABox/hdl/encoders.vhd +++ b/targets/PandABox/hdl/encoders.vhd @@ -58,6 +58,8 @@ port ( SETP_i : in std_logic_vector(31 downto 0); SETP_WSTB_i : in std_logic; RST_ON_Z_i : in std_logic_vector(31 downto 0); + DEBOUNCE_EN_i : in std_logic; + DEBOUNCE_TIME_i : in std_logic_vector(6 downto 0); STATUS_o : out std_logic_vector(31 downto 0); INENC_HEALTH_o : out std_logic_vector(31 downto 0); HOMED_o : out std_logic_vector(31 downto 0); @@ -69,14 +71,27 @@ end entity; architecture rtl of encoders is +COMPONENT ila_32x8K + +PORT ( + clk : IN STD_LOGIC; + probe0 : IN STD_LOGIC_VECTOR(31 DOWNTO 0); + probe1 : IN STD_LOGIC_VECTOR(31 DOWNTO 0) +); +END COMPONENT ; + constant c_ABZ_PASSTHROUGH : std_logic_vector(2 downto 0) := std_logic_vector(to_unsigned(4,3)); constant c_DATA_PASSTHROUGH : std_logic_vector(2 downto 0) := std_logic_vector(to_unsigned(5,3)); constant c_BISS : std_logic_vector(2 downto 0) := std_logic_vector(to_unsigned(2,3)); constant c_enDat : std_logic_vector(2 downto 0) := std_logic_vector(to_unsigned(3,3)); +constant c_SSI_SPLITTER : std_logic_vector(2 downto 0) := std_logic_vector(to_unsigned(6,3)); signal quad_a : std_logic; signal quad_b : std_logic; -signal sdat : std_logic; +signal ssi_slave1_dat : std_logic; +signal ssi_slave2_dat : std_logic; +signal ssi_slave1_clk : std_logic; +signal ssi_slave2_clk : std_logic; signal bdat : std_logic; signal health_biss_slave : std_logic_vector(31 downto 0); @@ -127,15 +142,25 @@ signal CLK_OUT : std_logic; signal CLK_IN : std_logic; -signal Bs0_t : std_logic; +signal Bs0_T : std_logic; +signal Bm0_T : std_logic; + +signal SnffrClk : std_logic; + +signal data_out_biss_master : std_logic; + +signal outenc_data_in : std_logic; + +signal inenc_dir_biss : std_logic; +signal outenc_dir_biss : std_logic; begin --- Unused Nets. -inenc_dir <= '0'; -outenc_dir <= '0'; -Am0_opad <= '0'; -Zm0_opad <= '0'; +-- Temporary assignments for bi-directional signal - also needs to be implemented for endat +inenc_dir_biss <= '0'; +data_out_biss_master <= '0'; +outenc_dir_biss <= '0'; + -----------------------------OUTENC--------------------------------------------- -------------------------------------------------------------------------------- @@ -143,12 +168,16 @@ Zm0_opad <= '0'; -- used to generate the Clock inputted to the Inenc. -- Assign outputs -A_OUT <= a_ext_i when (OUTENC_PROTOCOL_i = c_ABZ_PASSTHROUGH) else quad_a; -B_OUT <= b_ext_i when (OUTENC_PROTOCOL_i = c_ABZ_PASSTHROUGH) else quad_b; -Z_OUT <= z_ext_i when (OUTENC_PROTOCOL_i = c_ABZ_PASSTHROUGH) else '0'; +A_OUT <= a_ext_i when (OUTENC_PROTOCOL_i = c_ABZ_PASSTHROUGH) + else clk_out_encoder_ssi when (OUTENC_PROTOCOL_i = c_SSI_SPLITTER) + else quad_a; +B_OUT <= b_ext_i when (OUTENC_PROTOCOL_i = c_ABZ_PASSTHROUGH) else + ssi_slave2_dat when (OUTENC_PROTOCOL_i = c_SSI_SPLITTER) else quad_b; +Z_OUT <= z_ext_i when (OUTENC_PROTOCOL_i = c_ABZ_PASSTHROUGH) else + ssi_slave1_dat when (OUTENC_PROTOCOL_i = c_SSI_SPLITTER) else '0'; DATA_OUT <= data_ext_i when (OUTENC_PROTOCOL_i = c_DATA_PASSTHROUGH) else - bdat when (OUTENC_PROTOCOL_i = c_BISS) else sdat; - + bdat when (OUTENC_PROTOCOL_i = c_BISS) else ssi_slave1_dat; +outenc_dir <= outenc_dir_biss when (OUTENC_PROTOCOL_i = c_BISS) else '0'; -- -- INCREMENTAL OUT -- @@ -168,14 +197,29 @@ port map ( -- -- SSI SLAVE -- -ssi_slave_inst : entity work.ssi_slave + +ssi_slave1_clk <= Z_IN when (INENC_PROTOCOL_i = c_SSI_SPLITTER) else CLK_IN; +ssi_slave2_clk <= B_IN; + +ssi_slave1_inst : entity work.ssi_slave -- regular SSI slave instance, \ + -- or PMAC in SSI-Splitter mode +port map ( + clk_i => clk_i, + reset_i => reset_i, + BITS => OUTENC_BITS_i, + posn_i => posn_i, + ssi_sck_i => ssi_slave1_clk, + ssi_dat_o => ssi_slave1_dat +); + +ssi_slave2_inst : entity work.ssi_slave -- for PLC in SSI-Splitter mode port map ( clk_i => clk_i, reset_i => reset_i, BITS => OUTENC_BITS_i, posn_i => posn_i, - ssi_sck_i => CLK_IN, - ssi_dat_o => sdat + ssi_sck_i => ssi_slave2_clk, + ssi_dat_o => ssi_slave2_dat ); -- @@ -300,9 +344,11 @@ port map ( clk_i => clk_i, reset_i => reset_i, BITS => INENC_BITS_i, + DEBOUNCE_EN_i => DEBOUNCE_EN_i, + DEBOUNCE_TIME_i => DEBOUNCE_TIME_i, link_up_o => linkup_ssi, error_o => open, - ssi_sck_i => CLK_IN, + ssi_sck_i => SnffrClk, ssi_dat_i => DATA_IN, posn_o => posn_ssi_sniffer ); @@ -335,7 +381,7 @@ port map ( link_up_o => linkup_biss_sniffer, health_o => health_biss_sniffer, error_o => open, - ssi_sck_i => CLK_IN, + ssi_sck_i => SnffrClk, ssi_dat_i => DATA_IN, posn_o => posn_biss_sniffer ); @@ -355,9 +401,10 @@ begin INENC_HEALTH_o(0) <= not(linkup_incr); INENC_HEALTH_o(31 downto 1)<= (others=>'0'); HOMED_o <= homed_qdec; - + Am0_opad <= '0'; when "001" => -- SSI & Loopback - if (DCARD_MODE_i(3 downto 1) = DCARD_MONITOR) then + if (DCARD_MODE_i(3 downto 1) = DCARD_MONITOR) + OR (DCARD_MODE_i(3 downto 1) = DCARD_MON_CTRL) then posn <= posn_ssi_sniffer; STATUS_o(0) <= linkup_ssi; if (linkup_ssi = '0') then @@ -371,16 +418,22 @@ begin INENC_HEALTH_o <= (others=>'0'); end if; HOMED_o <= TO_SVECTOR(1,32); + Am0_opad <= '0'; when "010" => -- BISS & Loopback - if (DCARD_MODE_i(3 downto 1) = DCARD_MONITOR) then + if (DCARD_MODE_i(3 downto 1) = DCARD_MONITOR) + OR (DCARD_MODE_i(3 downto 1) = DCARD_MON_CTRL) then posn <= posn_biss_sniffer; STATUS_o(0) <= linkup_biss_sniffer; INENC_HEALTH_o <= health_biss_sniffer; + inenc_dir <= '0'; + Am0_opad <= '0'; else -- DCARD_CONTROL posn <= posn_biss; STATUS_o(0) <= linkup_biss_master; INENC_HEALTH_o<=health_biss_master; + inenc_dir <= inenc_dir_biss; + Am0_opad <= data_out_biss_master; end if; HOMED_o <= TO_SVECTOR(1,32); @@ -389,6 +442,8 @@ begin posn <= (others => '0'); STATUS_o <= (others => '0'); HOMED_o <= TO_SVECTOR(1,32); + inenc_dir <= '0'; -- temporary signal awaiting enDat definitions + Am0_opad <= '0'; end case; end if; end process; @@ -409,7 +464,7 @@ begin when "010" => -- BiSS-C inenc_ctrl <= "101"; when "011" => -- EnDat - inenc_ctrl <= inenc_dir & "00"; + inenc_ctrl <= NOT(inenc_dir) & "00"; when others => inenc_ctrl <= "111"; end case; @@ -426,11 +481,13 @@ IOBUF_Am0 : entity work.iobuf_registered port map ( IO => Am0_pad_io ); +Bm0_T <= '1' when (DCARD_MODE_i(3 downto 1) = DCARD_MON_CTRL) else inenc_ctrl(1); + IOBUF_Bm0 : entity work.iobuf_registered port map ( clock => clk_i, I => Bm0_opad, O => Bm0_ipad, - T => inenc_ctrl(1), + T => Bm0_T, IO => Bm0_pad_io ); @@ -443,6 +500,7 @@ IOBUF_Zm0 : entity work.iobuf_registered port map ( ); Bm0_opad <= CLK_OUT; +Zm0_opad <= inenc_dir; a_filt : entity work.delay_filter port map( clk_i => clk_i, @@ -465,12 +523,7 @@ z_filt : entity work.delay_filter port map( filt_o => Z_IN ); -datain_filt : entity work.delay_filter port map( - clk_i => clk_i, - reset_i => reset_i, - pulse_i => Am0_ipad, - filt_o => DATA_IN -); +DATA_IN <= A_IN; -------------------------------------------------------------------------- -- On-chip IOBUF controls based on protocol for OUTENC Blocks @@ -487,9 +540,9 @@ begin when "001" => -- SSI outenc_ctrl <= "011"; when "010" => -- BiSS - outenc_ctrl <= outenc_dir & "10"; + outenc_ctrl <= NOT(outenc_dir) & "10"; when "011" => -- EnDat - outenc_ctrl <= outenc_dir & "10"; + outenc_ctrl <= NOT(outenc_dir) & "10"; -- when "100" => -- Pass-Through -- outenc_ctrl <= "000"; when "101" => @@ -530,16 +583,20 @@ IOBUF_Zs0 : entity work.iobuf_registered port map ( ); -- A output is shared between incremental and absolute data lines. -As0_opad <= A_OUT when (OUTENC_PROTOCOL_i(1 downto 0) = "00") else DATA_OUT; +As0_opad <= A_OUT when + (OUTENC_PROTOCOL_i(1 downto 0) = "00" OR OUTENC_PROTOCOL_i = c_SSI_SPLITTER) + else DATA_OUT; Bs0_opad <= B_OUT; -Zs0_opad <= Z_OUT; +Zs0_opad <= Z_OUT when + (OUTENC_PROTOCOL_i(1 downto 0) = "00" OR OUTENC_PROTOCOL_i = c_SSI_SPLITTER) + else outenc_dir; INENC_A_o <= A_IN; INENC_B_o <= B_IN; INENC_Z_o <= Z_IN; INENC_DATA_o <= DATA_IN; -clk_int_o <= CLK_IN; +clk_int_o <= Z_IN when OUTENC_PROTOCOL_i = c_SSI_SPLITTER else SnffrClk; clkin_filt : entity work.delay_filter port map ( clk_i => clk_i, @@ -547,5 +604,28 @@ clkin_filt : entity work.delay_filter port map ( pulse_i => Bs0_ipad, filt_o => CLK_IN ); + +outenc_din_filt : entity work.delay_filter port map ( + clk_i => clk_i, + reset_i => reset_i, + pulse_i => As0_ipad, + filt_o => outenc_data_in +); + +SnffrClk <= B_IN when DCARD_MODE_i(3 downto 1) = DCARD_MON_CTRL else CLK_IN; + +ssi_ila : ila_32x8K +PORT MAP ( + clk => clk_i, + probe0 => posn_ssi_sniffer, + probe1(2 downto 0) => INENC_PROTOCOL_i, + probe1(10 downto 3) => INENC_BITS_i, + probe1(11) => linkup_ssi, + probe1(12) => SnffrClk, + probe1(13) => DATA_IN, + probe1(31 downto 14) => (others => '0') +); + + end rtl; diff --git a/targets/PandABox/hdl/encoders_block.vhd b/targets/PandABox/hdl/encoders_block.vhd index f019eb8f8..6b86068a8 100644 --- a/targets/PandABox/hdl/encoders_block.vhd +++ b/targets/PandABox/hdl/encoders_block.vhd @@ -92,6 +92,8 @@ signal SETP : std_logic_vector(31 downto 0); signal SETP_WSTB : std_logic; signal RST_ON_Z : std_logic_vector(31 downto 0); signal STATUS : std_logic_vector(31 downto 0); +signal DEBOUNCE_EN : std_logic_vector(31 downto 0); +signal DEBOUNCE_TIME : std_logic_vector(31 downto 0); signal read_ack : std_logic; signal LSB_DISCARD : std_logic_vector(31 downto 0); signal MSB_DISCARD : std_logic_vector(31 downto 0); @@ -191,6 +193,8 @@ port map ( SETP_WSTB => SETP_WSTB, RST_ON_Z => RST_ON_Z, RST_ON_Z_WSTB => open, + DEBOUNCE_EN => DEBOUNCE_EN, + DEBOUNCE_TIME => DEBOUNCE_TIME, HEALTH => INENC_HEALTH, HOMED => HOMED, DCARD_TYPE => DCARD_TYPE @@ -249,6 +253,8 @@ port map( SETP_i => SETP, SETP_WSTB_i => SETP_WSTB, RST_ON_Z_i => RST_ON_Z, + DEBOUNCE_EN_i => DEBOUNCE_EN(0), + DEBOUNCE_TIME_i => DEBOUNCE_TIME(6 downto 0), STATUS_o => STATUS, INENC_HEALTH_o => INENC_HEALTH, HOMED_o => HOMED, diff --git a/targets/PandABox/hdl/encoders_top.vhd b/targets/PandABox/hdl/encoders_top.vhd index cdee5b644..d60eb106c 100644 --- a/targets/PandABox/hdl/encoders_top.vhd +++ b/targets/PandABox/hdl/encoders_top.vhd @@ -126,12 +126,7 @@ begin if (OUTENC_write_address = OUTENC_PROTOCOL_addr) then slow_tlp_o.strobe <= '1'; slow_tlp_o.address <= OUTPROT_ADDR_LIST(OUTENC_blk_addr); - -- When using a monitor card, the protocol needs to make sure the CLK is enabled. - if (DCARD_MODE_i(OUTENC_blk_addr)(3 downto 1) = DCARD_MONITOR) then - slow_tlp_o.data <= x"0000000" & '0' & write_data_i(2) & '1' & write_data_i(0); - else - slow_tlp_o.data <= write_data_i; - end if; + slow_tlp_o.data <= write_data_i; end if; elsif (INENC_write_strobe_i = '1') then if (INENC_write_address = INENC_PROTOCOL_addr) then diff --git a/targets/PandABox/hdl/ssi_sniffer.vhd b/targets/PandABox/hdl/ssi_sniffer.vhd index dd0d635c7..b7eb0b4b2 100644 --- a/targets/PandABox/hdl/ssi_sniffer.vhd +++ b/targets/PandABox/hdl/ssi_sniffer.vhd @@ -23,8 +23,11 @@ port ( reset_i : in std_logic; -- Configuration interface BITS : in std_logic_vector(7 downto 0); + DEBOUNCE_EN_i : in std_logic; + DEBOUNCE_TIME_i : in std_logic_vector(6 downto 0); link_up_o : out std_logic; error_o : out std_logic; + -- Physical SSI interface ssi_sck_i : in std_logic; ssi_dat_i : in std_logic; @@ -35,6 +38,15 @@ end ssi_sniffer; architecture rtl of ssi_sniffer is +COMPONENT ila_32x8K + +PORT ( + clk : IN STD_LOGIC; + probe0 : IN STD_LOGIC_VECTOR(31 DOWNTO 0); + probe1 : IN STD_LOGIC_VECTOR(31 DOWNTO 0) +); +END COMPONENT ; + -- Ticks in terms of internal serial clock period. constant SYNCPERIOD : natural := 125 * 5; -- 5usec @@ -56,6 +68,9 @@ signal serial_clock_fall : std_logic; signal serial_clock_rise : std_logic; signal shift_counter : unsigned(7 downto 0); signal shift_enabled : std_logic; +signal debounce_en : std_logic; +signal db_timeout : std_logic; +signal DEBOUNCE_TIME : unsigned(6 downto 0); begin @@ -68,6 +83,9 @@ uBITS <= unsigned(BITS); -- Internal reset when link is down reset <= reset_i or not link_up; +debounce_en <= DEBOUNCE_EN_i; +DEBOUNCE_TIME <= unsigned(DEBOUNCE_TIME_i); + serial_clock <= ssi_sck_i; serial_data <= ssi_dat_i; @@ -80,10 +98,32 @@ begin end process; -- Shift source synchronous data on the Falling egde of clock -serial_clock_fall <= not serial_clock and serial_clock_prev; -serial_clock_rise <= serial_clock and not serial_clock_prev; +serial_clock_fall <= '0' when (db_timeout='1' and debounce_en='1') else (not serial_clock and serial_clock_prev); +serial_clock_rise <= '0' when (db_timeout='1' and debounce_en='1') else (serial_clock and not serial_clock_prev); serial_data_rise <= serial_data and not serial_data_prev; +-- Optional debounce circuit for incoming serial clock, to ensure logic does not respond to reflections +-- on the incoming clock lines. + +debouncer : process(clk_i) + variable db_ctr : unsigned(6 downto 0); -- Allow just over 1 us timeout +begin + if rising_edge(clk_i) then + if (db_timeout = '0') then + if (serial_clock_rise='1' or serial_clock_fall='1') then + db_timeout <= '1'; + end if; + else + if (db_ctr = DEBOUNCE_TIME) then + db_timeout <= '0'; + db_ctr := (others => '0'); + else + db_ctr := db_ctr + 1; + end if; + end if; + end if; +end process; + -------------------------------------------------------------------------- -- Detect link if clock is asserted for > 5us. -------------------------------------------------------------------------- @@ -184,4 +224,25 @@ end process; link_up_o <= link_up; error_o <= '0'; -- n/a +ssi_ila : ila_32x8K +PORT MAP ( + clk => clk_i, + probe0 => data, + probe1(0) => data_valid, + probe1(1) => serial_data, + probe1(2) => serial_clock_fall, + probe1(10 downto 3) => BITS, + probe1(11) => link_up, + probe1(12) => serial_clock, + probe1(13) => reset, + probe1(14) => serial_data_prev, + probe1(15) => serial_clock_prev, + probe1(16) => ssi_frame, + probe1(17) => serial_data_rise, + probe1(18) => serial_clock_rise, + probe1(19) => shift_enabled, + probe1(27 downto 20) => std_logic_vector(shift_counter), + probe1(31 downto 28) => (others => '0') +); + end rtl; diff --git a/targets/PandABox/scripts/build_ips.tcl b/targets/PandABox/scripts/build_ips.tcl index 6ebcea2ba..5314d54cc 100644 --- a/targets/PandABox/scripts/build_ips.tcl +++ b/targets/PandABox/scripts/build_ips.tcl @@ -240,6 +240,8 @@ create_ip -vlnv [get_ipdefs -filter {NAME == ila}] \ set_property -dict [list \ CONFIG.C_PROBE0_WIDTH {32} \ + CONFIG.C_NUM_OF_PROBES {2} \ + CONFIG.C_PROBE1_WIDTH {32} \ CONFIG.C_DATA_DEPTH {8192} \ ] [get_ips ila_32x8K]