From caad0595a00d6f69aa59993a790c1aa3c8fd691f Mon Sep 17 00:00:00 2001 From: Dimitris Lampridis <dimitris.lampridis@cern.ch> Date: Wed, 13 Feb 2019 16:01:00 +0100 Subject: [PATCH] genrams: cleanup of inferred_async_fifos --- .../genrams/common/inferred_async_fifo.vhd | 60 +++++++++---------- .../common/inferred_async_fifo_dual_rst.vhd | 33 +++++++--- 2 files changed, 52 insertions(+), 41 deletions(-) diff --git a/modules/genrams/common/inferred_async_fifo.vhd b/modules/genrams/common/inferred_async_fifo.vhd index 6e746139..94966168 100644 --- a/modules/genrams/common/inferred_async_fifo.vhd +++ b/modules/genrams/common/inferred_async_fifo.vhd @@ -67,7 +67,7 @@ entity inferred_async_fifo is wr_empty_o : out std_logic; wr_full_o : out std_logic; - wr_almost_empty_o : out std_logic; -- TODO: assign + wr_almost_empty_o : out std_logic; wr_almost_full_o : out std_logic; wr_count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0); @@ -79,7 +79,7 @@ entity inferred_async_fifo is rd_empty_o : out std_logic; rd_full_o : out std_logic; rd_almost_empty_o : out std_logic; - rd_almost_full_o : out std_logic; -- TODO: assign + rd_almost_full_o : out std_logic; rd_count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0) ); @@ -88,30 +88,28 @@ end inferred_async_fifo; architecture syn of inferred_async_fifo is - function f_bin2gray(bin : std_logic_vector) return std_logic_vector is - begin - return bin(bin'LEFT) & (bin(bin'LEFT-1 downto 0) xor bin(bin'LEFT downto 1)); - end f_bin2gray; - - function f_gray2bin(gray : std_logic_vector) return std_logic_vector is - variable bin : std_logic_vector(gray'LEFT downto 0); - begin - -- gray to binary - for i in 0 to gray'LEFT loop - bin(i) := '0'; - for j in i to gray'LEFT loop - bin(i) := bin(i) xor gray(j); - end loop; -- j - end loop; -- i - return bin; - end f_gray2bin; - + -- We use one more bit to be able to differentiate between an empty FIFO + -- (where rcb = wcb) and a full FIFO (where rcb = wcb except from the most + -- significant extra bit). + -- This extra bit is not used of course for actual addressing of the memory. constant c_counter_bits : integer := f_log2_size(g_size) + 1; + subtype t_counter is std_logic_vector(c_counter_bits-1 downto 0); + -- bin: binary counter + -- bin_next: bin + 1 + -- bin_x: cross-clock domain version of bin + -- gray: gray code of bin + -- gray_next: gray code of bin_next + -- gray_x: gray code of bin_x + -- + -- We use gray codes for safe cross-clock domain crossing of counters. Thus, + -- a binary counter is converted to gray before crossing, and then it is + -- converted back to binary after crossing. type t_counter_block is record - bin, bin_next, gray, gray_next : t_counter; - bin_x, gray_x, gray_xm : t_counter; + bin, bin_next : t_counter; + gray, gray_next : t_counter; + bin_x, gray_x : t_counter; end record; type t_mem_type is array (0 to g_size-1) of std_logic_vector(g_data_width-1 downto 0); @@ -128,11 +126,11 @@ architecture syn of inferred_async_fifo is signal wr_count, rd_count : t_counter; signal rd_int, we_int : std_logic; - signal wr_empty_xm, wr_empty_x : std_logic; - signal rd_full_xm, rd_full_x : std_logic; + signal wr_empty_x : std_logic; + signal rd_full_x : std_logic; - signal almost_full_x, almost_full_xm : std_logic; - signal almost_empty_x, almost_empty_xm : std_logic; + signal almost_full_x : std_logic; + signal almost_empty_x : std_logic; signal q_int : std_logic_vector(g_data_width-1 downto 0) := (others => '0'); @@ -171,7 +169,7 @@ begin -- syn q_o <= q_int; wcb.bin_next <= std_logic_vector(unsigned(wcb.bin) + 1); - wcb.gray_next <= f_bin2gray(wcb.bin_next); + wcb.gray_next <= f_gray_encode(wcb.bin_next); p_write_ptr : process(clk_wr_i, rst_n_i) begin @@ -187,7 +185,7 @@ begin -- syn end process p_write_ptr; rcb.bin_next <= std_logic_vector(unsigned(rcb.bin) + 1); - rcb.gray_next <= f_bin2gray(rcb.bin_next); + rcb.gray_next <= f_gray_encode(rcb.bin_next); p_read_ptr : process(clk_rd_i, rst_n_i) begin @@ -220,8 +218,8 @@ begin -- syn d_i => wcb.gray, q_o => wcb.gray_x); - wcb.bin_x <= f_gray2bin(wcb.gray_x); - rcb.bin_x <= f_gray2bin(rcb.gray_x); + wcb.bin_x <= f_gray_decode(wcb.gray_x, 1); + rcb.bin_x <= f_gray_decode(rcb.gray_x, 1); p_gen_empty : process(clk_rd_i, rst_n_i) begin @@ -254,8 +252,6 @@ begin -- syn data_i => full_int, synced_o => rd_full_x); - - rd_empty_o <= empty_int; wr_empty_o <= wr_empty_x; diff --git a/modules/genrams/common/inferred_async_fifo_dual_rst.vhd b/modules/genrams/common/inferred_async_fifo_dual_rst.vhd index 45cddbcc..be6b94d4 100644 --- a/modules/genrams/common/inferred_async_fifo_dual_rst.vhd +++ b/modules/genrams/common/inferred_async_fifo_dual_rst.vhd @@ -77,14 +77,29 @@ entity inferred_async_fifo_dual_rst is end inferred_async_fifo_dual_rst; -architecture syn of inferred_async_fifo_dual_rst is +architecture arch of inferred_async_fifo_dual_rst is + -- We use one more bit to be able to differentiate between an empty FIFO + -- (where rcb = wcb) and a full FIFO (where rcb = wcb except from the most + -- significant extra bit). + -- This extra bit is not used of course for actual addressing of the memory. constant c_counter_bits : integer := f_log2_size(g_size) + 1; subtype t_counter is std_logic_vector(c_counter_bits-1 downto 0); + -- bin: binary counter + -- bin_next: bin + 1 + -- bin_x: cross-clock domain version of bin + -- gray: gray code of bin + -- gray_next: gray code of bin_next + -- gray_x: gray code of bin_x + -- + -- We use gray codes for safe cross-clock domain crossing of counters. Thus, + -- a binary counter is converted to gray before crossing, and then it is + -- converted back to binary after crossing. type t_counter_block is record - bin, bin_next, gray, gray_next : t_counter; - bin_x, gray_x, gray_xm : t_counter; + bin, bin_next : t_counter; + gray, gray_next : t_counter; + bin_x, gray_x : t_counter; end record; type t_mem_type is array (0 to g_size-1) of std_logic_vector(g_data_width-1 downto 0); @@ -101,15 +116,15 @@ architecture syn of inferred_async_fifo_dual_rst is signal wr_count, rd_count : t_counter; signal rd_int, we_int : std_logic; - signal wr_empty_xm, wr_empty_x : std_logic; - signal rd_full_xm, rd_full_x : std_logic; + signal wr_empty_x : std_logic; + signal rd_full_x : std_logic; - signal almost_full_x, almost_full_xm : std_logic; - signal almost_empty_x, almost_empty_xm : std_logic; + signal almost_full_x : std_logic; + signal almost_empty_x : std_logic; signal q_int : std_logic_vector(g_data_width-1 downto 0) := (others => '0'); -begin -- syn +begin -- arch rd_int <= rd_i and not empty_int; we_int <= we_i and not full_int; @@ -317,4 +332,4 @@ begin -- syn wr_count_o <= std_logic_vector(wr_count(f_log2_size(g_size)-1 downto 0)); rd_count_o <= std_logic_vector(rd_count(f_log2_size(g_size)-1 downto 0)); -end syn; +end arch; -- GitLab