From 2f3a0e2d96a54351b7642825e7e3fa528a0157da Mon Sep 17 00:00:00 2001 From: rs <> Date: Tue, 11 Nov 2025 20:08:23 -0600 Subject: [PATCH] Add reset logic and update clock syncs --- libraries/nexys2/tests/nexys2_usb.vhd | 4 +- libraries/nexys2/usb.vhd | 53 ++++++++++++++++++++--- libraries/utility/fifo_xclk.vhd | 27 +++++++++++- libraries/utility/sync_rst.vhd | 32 ++++++++++++++ libraries/utility/tests/test_sync_rst.vhd | 47 ++++++++++++++++++++ libraries/utility/xclk_sig.vhd | 11 +++-- libraries/utility/xclk_vec.vhd | 16 ++++--- 7 files changed, 167 insertions(+), 23 deletions(-) create mode 100644 libraries/utility/sync_rst.vhd create mode 100644 libraries/utility/tests/test_sync_rst.vhd diff --git a/libraries/nexys2/tests/nexys2_usb.vhd b/libraries/nexys2/tests/nexys2_usb.vhd index 2d1c22c..c8e4816 100644 --- a/libraries/nexys2/tests/nexys2_usb.vhd +++ b/libraries/nexys2/tests/nexys2_usb.vhd @@ -58,6 +58,8 @@ begin e_usb: entity work.usb_cypress port map ( + rst_i => rst, + EppDB_DstmDB => EppDB_DstmDB, EppWRITE => EppWRITE, EppASTB_DstmFLAGA => EppASTB_DstmFLAGA, @@ -72,7 +74,6 @@ begin UsbMode => UsbMode, UsbRdy => UsbRdy, - epp_rst_i => rst, epp_clk_i => clk_50, epp_cyc_o => wb_cyc, epp_stb_o => wb_stb, @@ -82,7 +83,6 @@ begin epp_dat_i => wb_miso, epp_dat_o => wb_mosi, - stm_rst_i => rst, stm_clk_i => clk_50, stm_dl_stb_o => stm_stb, stm_dl_ack_i => stm_ack, diff --git a/libraries/nexys2/usb.vhd b/libraries/nexys2/usb.vhd index 878dbd0..6f0a002 100644 --- a/libraries/nexys2/usb.vhd +++ b/libraries/nexys2/usb.vhd @@ -7,7 +7,10 @@ library work; entity usb_cypress is + generic (SYNC_STAGES: positive := 2); port ( + rst_i: in std_logic; + -- Nexys2 pins EppDB_DstmDB: inout std_logic_vector(7 downto 0); EppWRITE: in std_logic; @@ -24,7 +27,6 @@ entity usb_cypress is UsbRdy: in std_logic; -- EPP-Wishbone interface - epp_rst_i: in std_logic; epp_clk_i: in std_logic; epp_cyc_o: out std_logic; @@ -36,7 +38,6 @@ entity usb_cypress is epp_dat_o: out std_logic_vector(7 downto 0); -- STM-Pipeline interfaces - stm_rst_i: in std_logic; stm_clk_i: in std_logic; stm_dl_stb_o: out std_logic; @@ -52,6 +53,10 @@ end usb_cypress; architecture behavioral of usb_cypress is + signal ifclk_rst: std_logic; + signal epp_rst: std_logic; + signal stm_rst: std_logic; + -- Between USB mux and EPP interface, in DstmIFCLK domain signal epp_en: std_logic; signal epp_astb: std_logic; @@ -98,6 +103,34 @@ architecture behavioral of usb_cypress is begin + ------------------------------------------------------------------------ + -- Synchronize reset signal to all clock domains + + e_sync_rst_ifclk: entity utility.sync_rst + generic map (SYNC_STAGES => SYNC_STAGES+1) + port map ( + rst_i => rst_i, + clk_i => DstmIFCLK, + rst_o => ifclk_rst + ); + + e_sync_rst_epp: entity utility.sync_rst + generic map (SYNC_STAGES => SYNC_STAGES+1) + port map ( + rst_i => rst_i, + clk_i => epp_clk_i, + rst_o => epp_rst + ); + + e_sync_rst_stm: entity utility.sync_rst + generic map (SYNC_STAGES => SYNC_STAGES+1) + port map ( + rst_i => rst_i, + clk_i => stm_clk_i, + rst_o => stm_rst + ); + + ------------------------------------------------------------------------ -- Sharing single USB controller interface between EPP and STM @@ -144,19 +177,19 @@ begin -- EPP clock domain crossing e_xclk_eppen: entity utility.xclk_sig - generic map (INIT => '0') + generic map (SYNC_STAGES => SYNC_STAGES, INIT => '0') port map (a_sig_i => epp_en, b_clk_i => epp_clk_i, b_sig_o => xclk_eppen); e_xclk_astb: entity utility.xclk_sig - generic map (INIT => '1') + generic map (SYNC_STAGES => SYNC_STAGES, INIT => '1') port map (a_sig_i => epp_astb, b_clk_i => epp_clk_i, b_sig_o => xclk_astb); e_xclk_dstb: entity utility.xclk_sig - generic map (INIT => '1') + generic map (SYNC_STAGES => SYNC_STAGES, INIT => '1') port map (a_sig_i => epp_dstb, b_clk_i => epp_clk_i, b_sig_o => xclk_dstb); e_xclk_wait: entity utility.xclk_sig - generic map (INIT => '0') -- FIXME: is this the best initial value for WAIT? + generic map (SYNC_STAGES => SYNC_STAGES, INIT => '0') -- FIXME: is this the best initial value for WAIT? port map (a_sig_i => xclk_wait, b_clk_i => DstmIFCLK, b_sig_o => epp_wait); -- These signals are stable during the time that they're validated by the @@ -178,7 +211,7 @@ begin EppDB_w => xclk_db_w, EppWait => xclk_wait, - rst_i => epp_rst_i, + rst_i => epp_rst, clk_i => epp_clk_i, cyc_o => epp_cyc_o, stb_o => epp_stb_o, @@ -220,7 +253,10 @@ begin -- STM clock domain crossing, download side e_dl_fifo: entity utility.fifo_xclk + generic map (SYNC_STAGES => SYNC_STAGES) port map ( + rst_i => rst_i, + head_clk_i => dstm_ifclk, head_stb_i => dl_stb, head_rdy_o => dl_rdy, @@ -234,7 +270,10 @@ begin -- STM clock domain crossing, upload side e_ul_fifo: entity utility.fifo_xclk + generic map (SYNC_STAGES => SYNC_STAGES) port map ( + rst_i => rst_i, + head_clk_i => stm_clk_i, head_stb_i => stm_ul_stb_i, head_rdy_o => stm_ul_ack_o, diff --git a/libraries/utility/fifo_xclk.vhd b/libraries/utility/fifo_xclk.vhd index d2e55ce..4709d93 100644 --- a/libraries/utility/fifo_xclk.vhd +++ b/libraries/utility/fifo_xclk.vhd @@ -9,7 +9,10 @@ library utility; entity fifo_xclk is + generic (SYNC_STAGES: positive := 2); port ( + rst_i: in std_logic; + head_clk_i: in std_logic; head_stb_i: in std_logic; head_rdy_o: out std_logic; @@ -25,6 +28,7 @@ end fifo_xclk; architecture behavioral of fifo_xclk is + signal head_rst: std_logic; signal tail_adr_xclk: std_logic_vector(10 downto 0); signal head_adr_reg: std_logic_vector(10 downto 0) := (others => '0'); signal head_adr_next: std_logic_vector(10 downto 0); @@ -32,6 +36,7 @@ architecture behavioral of fifo_xclk is signal head_step: std_logic; signal is_full: std_logic; + signal tail_rst: std_logic; signal head_adr_xclk: std_logic_vector(10 downto 0); signal tail_adr_reg: std_logic_vector(10 downto 0) := (others => '0'); signal tail_adr_inc: std_logic_vector(10 downto 0); @@ -44,7 +49,16 @@ begin -- Head logic + e_head_reset: entity utility.sync_rst + generic map (SYNC_STAGES => SYNC_STAGES+1) + port map ( + rst_i => rst_i, + clk_i => head_clk_i, + rst_o => head_rst + ); + e_xclk_tail: entity utility.xclk_vec + generic map (SYNC_STAGES => SYNC_STAGES) port map ( a_sig_i => std_logic_vector(tail_adr_reg), b_clk_i => head_clk_i, @@ -61,7 +75,7 @@ begin e_head_adr: entity utility.gray_counter generic map (N => 11) port map ( - rst_i => '0', + rst_i => head_rst, clk_i => head_clk_i, ena_i => head_step, gray => head_adr_reg, @@ -71,7 +85,16 @@ begin -- Tail logic + e_tail_reset: entity utility.sync_rst + generic map (SYNC_STAGES => SYNC_STAGES+1) + port map ( + rst_i => rst_i, + clk_i => tail_clk_i, + rst_o => tail_rst + ); + e_xclk_head: entity utility.xclk_vec + generic map (SYNC_STAGES => SYNC_STAGES) port map ( a_sig_i => std_logic_vector(head_adr_reg), b_clk_i => tail_clk_i, @@ -89,7 +112,7 @@ begin e_tail_adr: entity utility.gray_counter generic map (N => 11) port map ( - rst_i => '0', + rst_i => tail_rst, clk_i => tail_clk_i, ena_i => tail_step, gray => tail_adr_reg, diff --git a/libraries/utility/sync_rst.vhd b/libraries/utility/sync_rst.vhd new file mode 100644 index 0000000..42b6731 --- /dev/null +++ b/libraries/utility/sync_rst.vhd @@ -0,0 +1,32 @@ +library ieee; +use ieee.std_logic_1164.all; + + +entity sync_rst is + generic (SYNC_STAGES: positive := 2); + port ( + rst_i: in std_logic; + clk_i: in std_logic; + rst_o: out std_logic + ); +end sync_rst; + + +architecture behavioral of sync_rst is + + signal shift_reg: std_logic_vector(SYNC_STAGES-1 downto 0) := (others => '1'); + +begin + + rst_o <= shift_reg(0); + + process (rst_i, clk_i) + begin + if rst_i = '1' then + shift_reg <= (others => '1'); + elsif rising_edge(clk_i) then + shift_reg <= '0' & shift_reg(SYNC_STAGES-1 downto 1); + end if; + end process; + +end behavioral; diff --git a/libraries/utility/tests/test_sync_rst.vhd b/libraries/utility/tests/test_sync_rst.vhd new file mode 100644 index 0000000..8529d93 --- /dev/null +++ b/libraries/utility/tests/test_sync_rst.vhd @@ -0,0 +1,47 @@ +library ieee; +use ieee.std_logic_1164.all; + +library work; + + +entity test_sync_rst is +end test_sync_rst; + + +architecture behavior of test_sync_rst is + + signal rst_i: std_logic; + signal clk_i: std_logic; + signal rst_o: std_logic; + +begin + + p_test: process + begin + rst_i <= '0'; + wait until rst_o = '0'; + wait for 40 ns; + rst_i <= '1'; + wait for 2 ns; + rst_i <= '0'; + + wait; + end process; + + e_uut: entity work.sync_rst + generic map (SYNC_STAGES => 5) + port map ( + rst_i => rst_i, + clk_i => clk_i, + rst_o => rst_o + ); + + p_clk: process + begin + clk_i <= '0'; + wait for 10 ns; + clk_i <= '1'; + wait for 10 ns; + end process; + +end; diff --git a/libraries/utility/xclk_sig.vhd b/libraries/utility/xclk_sig.vhd index aec6e8c..f253156 100644 --- a/libraries/utility/xclk_sig.vhd +++ b/libraries/utility/xclk_sig.vhd @@ -4,6 +4,7 @@ use ieee.std_logic_1164.all; entity xclk_sig is generic ( + SYNC_STAGES: positive := 2; INIT: std_logic := '0' ); port ( @@ -17,18 +18,16 @@ end xclk_sig; architecture behavioral of xclk_sig is - signal b_0_reg: std_logic := INIT; - signal b_1_reg: std_logic := INIT; + signal sync_regs: std_logic_vector(SYNC_STAGES-1 downto 0) := (others => INIT); begin - process (b_clk_i, a_sig_i, b_0_reg) + process (b_clk_i, a_sig_i, sync_regs) begin if rising_edge(b_clk_i) then - b_0_reg <= a_sig_i; - b_1_reg <= b_0_reg; + sync_regs <= a_sig_i & sync_regs(SYNC_STAGES-1 downto 1); end if; end process; - b_sig_o <= b_1_reg; + b_sig_o <= sync_regs(0); end behavioral; diff --git a/libraries/utility/xclk_vec.vhd b/libraries/utility/xclk_vec.vhd index cd50daa..a1662da 100644 --- a/libraries/utility/xclk_vec.vhd +++ b/libraries/utility/xclk_vec.vhd @@ -3,6 +3,7 @@ use ieee.std_logic_1164.all; entity xclk_vec is + generic (SYNC_STAGES: positive := 2); port ( a_sig_i: in std_logic_vector; @@ -14,18 +15,21 @@ end xclk_vec; architecture behavioral of xclk_vec is - signal b_0_reg: std_logic_vector(b_sig_o'high downto 0) := (others => '0'); - signal b_1_reg: std_logic_vector(b_sig_o'high downto 0) := (others => '0'); + type value_array is array(natural range <>) of std_logic_vector(a_sig_i'high downto 0); + + signal sync_regs: value_array(SYNC_STAGES-1 downto 0); begin - process (b_clk_i, a_sig_i, b_0_reg) + process (b_clk_i, a_sig_i, sync_regs) begin if rising_edge(b_clk_i) then - b_0_reg <= a_sig_i; - b_1_reg <= b_0_reg; + sync_regs(SYNC_STAGES-1) <= a_sig_i; + for i in SYNC_STAGES-2 downto 0 loop + sync_regs(i) <= sync_regs(i+1); + end loop; end if; end process; - b_sig_o <= b_1_reg; + b_sig_o <= sync_regs(0); end behavioral; -- 2.43.0