Skip to content
Snippets Groups Projects
Commit 6d33dca2 authored by Dimitris Lampridis's avatar Dimitris Lampridis
Browse files

hdl: introduce generic dual rst async fifo

parent 7faa55fe
No related branches found
No related tags found
No related merge requests found
files = ["inferred_sync_fifo.vhd",
"inferred_async_fifo.vhd",
"generic_shiftreg_fifo.vhd"]
files = [
"inferred_sync_fifo.vhd",
"inferred_async_fifo_dual_rst.vhd",
"inferred_async_fifo.vhd",
"generic_shiftreg_fifo.vhd",
]
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: inferred_async_fifo_dual_rst
--
-- description: Parametrizable asynchronous FIFO (Generic version).
-- Dual-clock asynchronous FIFO.
-- - configurable data width and size
-- - configurable full/empty/almost full/almost empty/word count signals
-- - dual sunchronous reset
--
--------------------------------------------------------------------------------
-- Copyright CERN 2011-2018
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.genram_pkg.all;
use work.gencores_pkg.all;
entity inferred_async_fifo_dual_rst is
generic (
g_data_width : natural;
g_size : natural;
g_show_ahead : boolean := FALSE;
g_with_rd_empty : boolean := TRUE;
g_with_rd_full : boolean := FALSE;
g_with_rd_almost_empty : boolean := FALSE;
g_with_rd_almost_full : boolean := FALSE;
g_with_rd_count : boolean := FALSE;
g_with_wr_empty : boolean := FALSE;
g_with_wr_full : boolean := TRUE;
g_with_wr_almost_empty : boolean := FALSE;
g_with_wr_almost_full : boolean := FALSE;
g_with_wr_count : boolean := FALSE;
g_almost_empty_threshold : integer;
g_almost_full_threshold : integer);
port (
-- write port
rst_wr_n_i : in std_logic := '1';
clk_wr_i : in std_logic;
d_i : in std_logic_vector(g_data_width-1 downto 0);
we_i : in std_logic;
wr_empty_o : out std_logic;
wr_full_o : out std_logic;
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);
-- read port
rst_rd_n_i : in std_logic := '1';
clk_rd_i : in std_logic;
q_o : out std_logic_vector(g_data_width-1 downto 0);
rd_i : in std_logic;
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;
rd_count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0)
);
end inferred_async_fifo_dual_rst;
architecture syn of inferred_async_fifo_dual_rst is
constant c_counter_bits : integer := f_log2_size(g_size) + 1;
subtype t_counter is std_logic_vector(c_counter_bits-1 downto 0);
type t_counter_block is record
bin, bin_next, gray, gray_next : t_counter;
bin_x, gray_x, gray_xm : 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);
signal mem : t_mem_type;
signal rcb, wcb : t_counter_block;
signal full_int, empty_int : std_logic;
signal almost_full_int, almost_empty_int : std_logic;
signal going_full : std_logic;
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 almost_full_x, almost_full_xm : std_logic;
signal almost_empty_x, almost_empty_xm : std_logic;
signal q_int : std_logic_vector(g_data_width-1 downto 0) := (others => '0');
begin -- syn
rd_int <= rd_i and not empty_int;
we_int <= we_i and not full_int;
p_mem_write : process(clk_wr_i)
begin
if rising_edge(clk_wr_i) then
if we_int = '1' then
mem(to_integer(unsigned(wcb.bin(wcb.bin'LEFT-1 downto 0)))) <= d_i;
end if;
end if;
end process p_mem_write;
p_mem_read : process(clk_rd_i)
begin
if rising_edge(clk_rd_i) then
if rd_int = '1' then
q_int <= mem(to_integer(unsigned(rcb.bin(rcb.bin'LEFT-1 downto 0))));
end if;
end if;
end process p_mem_read;
q_o <= q_int;
wcb.bin_next <= std_logic_vector(unsigned(wcb.bin) + 1);
wcb.gray_next <= f_gray_encode(wcb.bin_next);
p_write_ptr : process(clk_wr_i)
begin
if rising_edge(clk_wr_i) then
if rst_wr_n_i = '0' then
wcb.bin <= (others => '0');
wcb.gray <= (others => '0');
elsif we_int = '1' then
wcb.bin <= wcb.bin_next;
wcb.gray <= wcb.gray_next;
end if;
end if;
end process p_write_ptr;
rcb.bin_next <= std_logic_vector(unsigned(rcb.bin) + 1);
rcb.gray_next <= f_gray_encode(rcb.bin_next);
p_read_ptr : process(clk_rd_i)
begin
if rising_edge(clk_rd_i) then
if rst_rd_n_i = '0' then
rcb.bin <= (others => '0');
rcb.gray <= (others => '0');
elsif rd_int = '1' then
rcb.bin <= rcb.bin_next;
rcb.gray <= rcb.gray_next;
end if;
end if;
end process p_read_ptr;
U_Sync1 : gc_sync_register
generic map (
g_width => c_counter_bits)
port map (
clk_i => clk_wr_i,
rst_n_a_i => '1',
d_i => rcb.gray,
q_o => rcb.gray_x);
U_Sync2 : gc_sync_register
generic map (
g_width => c_counter_bits)
port map (
clk_i => clk_rd_i,
rst_n_a_i => '1',
d_i => wcb.gray,
q_o => wcb.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)
begin
if rising_edge (clk_rd_i) then
if rst_rd_n_i = '0' then
empty_int <= '1';
elsif rcb.gray = wcb.gray_x or (rd_int = '1' and (wcb.gray_x = rcb.gray_next)) then
empty_int <= '1';
else
empty_int <= '0';
end if;
end if;
end process p_gen_empty;
U_Sync_Empty : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_wr_i,
rst_n_i => '1',
data_i => empty_int,
synced_o => wr_empty_x);
U_Sync_Full : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_rd_i,
rst_n_i => '1',
data_i => full_int,
synced_o => rd_full_x);
rd_empty_o <= empty_int;
wr_empty_o <= wr_empty_x;
p_gen_going_full : process(rcb, wcb, we_int)
begin
if ((wcb.bin (wcb.bin'LEFT-1 downto 0) = rcb.bin_x(rcb.bin_x'LEFT-1 downto 0))
and (wcb.bin(wcb.bin'LEFT) /= rcb.bin_x(wcb.bin_x'LEFT))) then
going_full <= '1';
elsif (we_int = '1'
and (wcb.bin_next(wcb.bin'LEFT-1 downto 0) = rcb.bin_x(rcb.bin_x'LEFT-1 downto 0))
and (wcb.bin_next(wcb.bin'LEFT) /= rcb.bin_x(rcb.bin_x'LEFT))) then
going_full <= '1';
else
going_full <= '0';
end if;
end process p_gen_going_full;
p_register_full : process(clk_wr_i)
begin
if rising_edge (clk_wr_i) then
if rst_wr_n_i = '0' then
full_int <= '0';
else
full_int <= going_full;
end if;
end if;
end process p_register_full;
wr_full_o <= full_int;
rd_full_o <= rd_full_x;
p_reg_almost_full : process(clk_wr_i)
begin
if rising_edge(clk_wr_i) then
if rst_wr_n_i = '0' then
almost_full_int <= '0';
else
wr_count <= std_logic_vector(unsigned(wcb.bin) - unsigned(rcb.bin_x));
if (unsigned(wr_count) < g_almost_full_threshold) then
almost_full_int <= '0';
else
almost_full_int <= '1';
end if;
end if;
end if;
end process p_reg_almost_full;
U_Sync_AlmostFull : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_rd_i,
rst_n_i => '1',
data_i => almost_full_int,
synced_o => almost_full_x);
wr_almost_full_o <= almost_full_int;
rd_almost_full_o <= almost_full_x;
p_reg_almost_empty : process(clk_rd_i)
begin
if rising_edge(clk_rd_i) then
if rst_rd_n_i = '0' then
almost_empty_int <= '1';
else
rd_count <= std_logic_vector(unsigned(wcb.bin_x) - unsigned(rcb.bin));
if (unsigned(rd_count) > g_almost_empty_threshold) then
almost_empty_int <= '0';
else
almost_empty_int <= '1';
end if;
end if;
end if;
end process p_reg_almost_empty;
U_Sync_AlmostEmpty : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_wr_i,
rst_n_i => '1',
data_i => almost_empty_int,
synced_o => almost_empty_x);
rd_almost_empty_o <= almost_empty_int;
wr_almost_empty_o <= almost_empty_x;
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;
files = ["generic_async_fifo.vhd",
"generic_sync_fifo.vhd"]
files = [
"generic_async_fifo_dual_rst.vhd",
"generic_async_fifo.vhd",
"generic_sync_fifo.vhd",
]
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: generic_async_fifo_dual_rst
--
-- description: Parametrizable asynchronous FIFO (Generic version).
-- Dual-clock asynchronous FIFO.
-- - configurable data width and size
-- - configurable full/empty/almost full/almost empty/word count signals
-- - dual sunchronous reset
--
--------------------------------------------------------------------------------
-- Copyright CERN 2011-2018
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.genram_pkg.all;
entity generic_async_fifo_dual_rst is
generic (
g_data_width : natural;
g_size : natural;
g_show_ahead : boolean := FALSE;
g_with_rd_empty : boolean := TRUE;
g_with_rd_full : boolean := FALSE;
g_with_rd_almost_empty : boolean := FALSE;
g_with_rd_almost_full : boolean := FALSE;
g_with_rd_count : boolean := FALSE;
g_with_wr_empty : boolean := FALSE;
g_with_wr_full : boolean := TRUE;
g_with_wr_almost_empty : boolean := FALSE;
g_with_wr_almost_full : boolean := FALSE;
g_with_wr_count : boolean := FALSE;
g_almost_empty_threshold : integer := 0;
g_almost_full_threshold : integer := 0);
port (
-- write port
rst_wr_n_i : in std_logic := '1';
clk_wr_i : in std_logic;
d_i : in std_logic_vector(g_data_width-1 downto 0);
we_i : in std_logic;
wr_empty_o : out std_logic;
wr_full_o : out std_logic;
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);
-- read port
rst_rd_n_i : in std_logic := '1';
clk_rd_i : in std_logic;
q_o : out std_logic_vector(g_data_width-1 downto 0);
rd_i : in std_logic;
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;
rd_count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0));
end generic_async_fifo_dual_rst;
architecture arch of generic_async_fifo_dual_rst is
begin -- arch
U_Inferred_FIFO : entity work.inferred_async_fifo_dual_rst
generic map (
g_data_width => g_data_width,
g_size => g_size,
g_show_ahead => g_show_ahead,
g_with_rd_empty => g_with_rd_empty,
g_with_rd_full => g_with_rd_full,
g_with_rd_almost_empty => g_with_rd_almost_empty,
g_with_rd_almost_full => g_with_rd_almost_full,
g_with_rd_count => g_with_rd_count,
g_with_wr_empty => g_with_wr_empty,
g_with_wr_full => g_with_wr_full,
g_with_wr_almost_empty => g_with_wr_almost_empty,
g_with_wr_almost_full => g_with_wr_almost_full,
g_with_wr_count => g_with_wr_count,
g_almost_empty_threshold => g_almost_empty_threshold,
g_almost_full_threshold => g_almost_full_threshold)
port map (
rst_wr_n_i => rst_wr_n_i,
clk_wr_i => clk_wr_i,
d_i => d_i,
we_i => we_i,
wr_empty_o => wr_empty_o,
wr_full_o => wr_full_o,
wr_almost_empty_o => wr_almost_empty_o,
wr_almost_full_o => wr_almost_full_o,
wr_count_o => wr_count_o,
rst_rd_n_i => rst_rd_n_i,
clk_rd_i => clk_rd_i,
q_o => q_o,
rd_i => rd_i,
rd_empty_o => rd_empty_o,
rd_full_o => rd_full_o,
rd_almost_empty_o => rd_almost_empty_o,
rd_almost_full_o => rd_almost_full_o,
rd_count_o => rd_count_o);
end arch;
......@@ -124,6 +124,44 @@ package genram_pkg is
qb_o : out std_logic_vector(g_data_b_width-1 downto 0));
end component;
component generic_async_fifo_dual_rst is
generic (
g_data_width : natural;
g_size : natural;
g_show_ahead : boolean := false;
g_with_rd_empty : boolean := true;
g_with_rd_full : boolean := false;
g_with_rd_almost_empty : boolean := false;
g_with_rd_almost_full : boolean := false;
g_with_rd_count : boolean := false;
g_with_wr_empty : boolean := false;
g_with_wr_full : boolean := true;
g_with_wr_almost_empty : boolean := false;
g_with_wr_almost_full : boolean := false;
g_with_wr_count : boolean := false;
g_almost_empty_threshold : integer := 0;
g_almost_full_threshold : integer := 0);
port (
rst_wr_n_i : in std_logic := '1';
clk_wr_i : in std_logic;
d_i : in std_logic_vector(g_data_width-1 downto 0);
we_i : in std_logic;
wr_empty_o : out std_logic;
wr_full_o : out std_logic;
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);
rst_rd_n_i : in std_logic := '1';
clk_rd_i : in std_logic;
q_o : out std_logic_vector(g_data_width-1 downto 0);
rd_i : in std_logic;
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;
rd_count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0));
end component generic_async_fifo_dual_rst;
component generic_async_fifo
generic (
g_data_width : natural;
......
--------------------------------------------------------------------------------
-- Modifications:
-- 2016-08-24: by Jan Pospisil (j.pospisil@cern.ch)
-- * added assignments to (new) unspecified WB signals
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: xwb_clock_crossing
--
-- description: Cross clock-domain wishbone adapter
--
--------------------------------------------------------------------------------
-- Copyright CERN 2012-2018
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library ieee;
......@@ -97,12 +115,12 @@ begin
end if;
end process;
mfifo : generic_async_fifo
mfifo : generic_async_fifo_dual_rst
generic map(
g_data_width => mlen,
g_size => g_size)
port map(
rst_n_i => slave_rst_n_i,
rst_wr_n_i => slave_rst_n_i,
clk_wr_i => slave_clk_i,
d_i => msend_vect,
we_i => mw_en,
......@@ -111,6 +129,7 @@ begin
wr_almost_empty_o => open,
wr_almost_full_o => open,
wr_count_o => open,
rst_rd_n_i => master_rst_n_i,
clk_rd_i => master_clk_i,
q_o => mrecv_vect,
rd_i => mr_en,
......@@ -132,12 +151,12 @@ begin
mrecv.DAT <= mrecv_vect(mDAT_end downto mDAT_start);
mrecv.SEL <= mrecv_vect(mSEL_end downto mSEL_start);
sfifo : generic_async_fifo
sfifo : generic_async_fifo_dual_rst
generic map(
g_data_width => slen,
g_size => g_size)
port map(
rst_n_i => master_rst_n_i,
rst_wr_n_i => master_rst_n_i,
clk_wr_i => master_clk_i,
d_i => ssend_vect,
we_i => sw_en,
......@@ -146,6 +165,7 @@ begin
wr_almost_empty_o => open,
wr_almost_full_o => open,
wr_count_o => open,
rst_rd_n_i => slave_rst_n_i,
clk_rd_i => slave_clk_i,
q_o => srecv_vect,
rd_i => sr_en,
......@@ -184,14 +204,16 @@ begin
master_o.SEL <= mrecv.SEL;
master_o.DAT <= mrecv.DAT;
drive_master_port : process(master_clk_i, master_rst_n_i)
drive_master_port : process(master_clk_i)
begin
if rising_edge(master_clk_i) then
if master_rst_n_i = '0' then
master_o_STB <= '0';
elsif rising_edge(master_clk_i) then
master_o_STB <= mr_en or (mrecv.CYC and master_o_STB and master_i.STALL);
master_o_STB <= '0';
else
master_o_STB <= mr_en or (mrecv.CYC and master_o_STB and master_i.STALL);
end if;
end process;
end if;
end process drive_master_port;
-- Master clock domain: master -> sFIFO
sw_en <= master_i.ACK or master_i.ERR or master_i.RTY;
......@@ -208,15 +230,17 @@ begin
slave_o.RTY <= srecv.RTY and slave_o_PUSH;
slave_o.ERR <= srecv.ERR and slave_o_PUSH;
drive_slave_port : process(slave_clk_i, slave_rst_n_i)
drive_slave_port : process(slave_clk_i)
begin
if slave_rst_n_i = '0' then
if rising_edge(slave_clk_i) then
if slave_rst_n_i = '0' then
slave_o_PUSH <= '0';
slave_CYC <= '0';
elsif rising_edge(slave_clk_i) then
slave_CYC <= '0';
else
slave_o_PUSH <= sr_en;
slave_CYC <= slave_i.CYC;
end if;
end process;
slave_CYC <= slave_i.CYC;
end if;
end if;
end process drive_slave_port;
end rtl;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment