From 12a67493af78c0b351875355e4ab8e3a19458a68 Mon Sep 17 00:00:00 2001 From: rs <> Date: Tue, 11 Nov 2025 18:41:25 -0600 Subject: [PATCH] Use Gray counters in clock domain crossing FIFO --- libraries/utility/fifo_xclk.vhd | 48 ++++++++++---------- libraries/utility/gray_counter.vhd | 48 ++++++++++++++++++++ libraries/utility/tests/test_graycounter.vhd | 47 +++++++++++++++++++ 3 files changed, 120 insertions(+), 23 deletions(-) create mode 100644 libraries/utility/gray_counter.vhd create mode 100644 libraries/utility/tests/test_graycounter.vhd diff --git a/libraries/utility/fifo_xclk.vhd b/libraries/utility/fifo_xclk.vhd index a21ef0c..d2e55ce 100644 --- a/libraries/utility/fifo_xclk.vhd +++ b/libraries/utility/fifo_xclk.vhd @@ -26,15 +26,16 @@ end fifo_xclk; architecture behavioral of fifo_xclk is signal tail_adr_xclk: std_logic_vector(10 downto 0); - signal head_adr_reg: unsigned(10 downto 0) := (others => '0'); - signal head_adr_next: unsigned(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); signal head_rdy: std_logic; signal head_step: std_logic; signal is_full: std_logic; signal head_adr_xclk: std_logic_vector(10 downto 0); - signal tail_adr_reg: unsigned(10 downto 0) := (others => '0'); - signal tail_adr_next: unsigned(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); + signal tail_adr_next: std_logic_vector(10 downto 0); signal tail_stb: std_logic; signal tail_step: std_logic; signal is_empty: std_logic; @@ -56,16 +57,16 @@ begin head_rdy_o <= head_rdy; head_step <= head_stb_i and head_rdy; - head_adr_next <= head_adr_reg + 1; - process (head_clk_i) - begin - if rising_edge(head_clk_i) then - if head_step = '1' then - head_adr_reg <= head_adr_next; - end if; - end if; - end process; + e_head_adr: entity utility.gray_counter + generic map (N => 11) + port map ( + rst_i => '0', + clk_i => head_clk_i, + ena_i => head_step, + gray => head_adr_reg, + inc => head_adr_next + ); -- Tail logic @@ -83,16 +84,17 @@ begin tail_stb_o <= tail_stb; tail_step <= tail_stb and tail_ack_i; - tail_adr_next <= tail_adr_reg + 1 when tail_step = '1' else tail_adr_reg; - - process (tail_clk_i) - begin - if rising_edge(tail_clk_i) then - if tail_step = '1' then - tail_adr_reg <= tail_adr_next; - end if; - end if; - end process; + tail_adr_next <= tail_adr_inc when tail_step = '1' else tail_adr_reg; + + e_tail_adr: entity utility.gray_counter + generic map (N => 11) + port map ( + rst_i => '0', + clk_i => tail_clk_i, + ena_i => tail_step, + gray => tail_adr_reg, + inc => tail_adr_inc + ); -- FIFO memory diff --git a/libraries/utility/gray_counter.vhd b/libraries/utility/gray_counter.vhd new file mode 100644 index 0000000..c14020f --- /dev/null +++ b/libraries/utility/gray_counter.vhd @@ -0,0 +1,48 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + +entity gray_counter is + generic (N: positive := 8); + port ( + rst_i: in std_logic; + clk_i: in std_logic; + ena_i: in std_logic; + + gray: out std_logic_vector(N-1 downto 0); + inc: out std_logic_vector(N-1 downto 0) + ); +end gray_counter; + + +architecture behavioral of gray_counter is + + signal count_reg: unsigned(N-1 downto 0) := (others => '0'); + signal count_next: unsigned(N-1 downto 0); + + signal gray_reg: std_logic_vector(N-1 downto 0) := (others => '0'); + signal gray_next: std_logic_vector(N-1 downto 0); + +begin + + gray <= gray_reg; + inc <= gray_next; + + count_next <= count_reg + 1; + gray_next <= std_logic_vector(count_next xor ('0' & count_next(N-1 downto 1))); + + process (rst_i, clk_i) + begin + if rising_edge(clk_i) then + if rst_i = '1' then + gray_reg <= (others => '0'); + count_reg <= (others => '0'); + elsif ena_i = '1' then + gray_reg <= gray_next; + count_reg <= count_next; + end if; + end if; + end process; + +end behavioral; diff --git a/libraries/utility/tests/test_graycounter.vhd b/libraries/utility/tests/test_graycounter.vhd new file mode 100644 index 0000000..0b241b7 --- /dev/null +++ b/libraries/utility/tests/test_graycounter.vhd @@ -0,0 +1,47 @@ +library ieee; +use ieee.std_logic_1164.all; + +library work; + + +entity test_graycounter is +end test_graycounter; + + +architecture behavior of test_graycounter is + + signal rst: std_logic; + signal clk: std_logic; + signal ena: std_logic; + signal gray: std_logic_vector(7 downto 0); + +begin + + p_test: process + begin + ena <= '0'; + rst <= '1'; + wait until rising_edge(clk); + rst <= '0'; + ena <= '1'; + wait; + end process; + + e_gray: entity work.gray_counter + generic map (N => 8) + port map ( + rst_i => rst, + clk_i => clk, + ena_i => ena, + gray => gray + ); + + p_clk: process + begin + clk <= '0'; + wait for 10 ns; + clk <= '1'; + wait for 10 ns; + end process; + +end; -- 2.43.0