📄 freefifo.vhd
字号:
addr := addr + 1;
wrptr_bin <= addr;
elsif wr_clk'event and wr_clk='1' then
if wr_allow='1' then
wrptr <= wrptr1;
wrptr1 <= bin_to_gray (wrptr_bin);
wrptr_bin <= wrptr_bin + 1;
end if;
end if;
end process;
---------------------------------------------------------------
-- Generate the read addresses
---------------------------------------------------------------
process (rd_clk, reset)
variable addr :std_logic_vector (wrptr_bin'range);
begin
if reset='1' then
addr := (others=>'0');
rdptr <= bin_to_gray (addr);
addr := addr + 1;
rdptr_bin <= addr;
addr := addr + async_size;
rdptr_max_bin <= addr;
addr := addr - 1;
rdptr_max <= bin_to_gray(addr);
elsif rd_clk'event and rd_clk='1' then
if rd_allow='1' then
rdptr <= bin_to_gray (rdptr_bin);
rdptr_bin <= rdptr_bin + 1;
rdptr_max <= bin_to_gray (rdptr_max_bin);
rdptr_max_bin <= rdptr_max_bin + 1;
end if;
end if;
end process;
---------------------------------------------------------------
-- Generate the mid addresses
---------------------------------------------------------------
process (wr_clk, reset)
variable addr :std_logic_vector (wrptr_bin'range);
begin
if reset='1' then
addr := (others=>'0');
midptr <= bin_to_gray (addr);
addr := addr + 1;
midptr1 <= bin_to_gray (addr);
addr := addr + 1;
midptr_bin <= addr;
elsif wr_clk'event and wr_clk='1' then
if mid_allow='1' then
midptr <= midptr1;
midptr1 <= bin_to_gray (midptr_bin);
midptr_bin <= midptr_bin + 1;
end if;
end if;
end process;
---------------------------------------------------------------
-- Calculate all the combinatorial match signals
---------------------------------------------------------------
wf_full_match <= '1' when wrptr1 = rdptr else '0';
wf_empty_match <= '1' when wrptr = midptr else '0'; -- synced to wr_clk!
wf_aempty_match <= '1' when wrptr = midptr1 else '0'; -- synced to wr_clk!
rf_full_match <= '1' when midptr1 = rdptr_max else '0';
rf_empty_match <= '1' when rdptr = midptr else '0';
---------------------------------------------------------------
-- Generate the full/empty flags
---------------------------------------------------------------
--wf_empty_int <= wf_empty_match; -- The small but slow way
process (wr_clk, reset) -- The large but fast way
begin
if reset='1' then
wf_empty_int <= '1';
elsif wr_clk'event and wr_clk='1' then
if wf_aempty_match='1' and wr_allow='0' and mid_allow='1' then
wf_empty_int <= '1';
elsif wf_empty_match='1' and wr_allow='0' then
wf_empty_int <= '1';
else
wf_empty_int <= '0';
end if;
end if;
end process;
process (rd_clk, rf_empty_match)
begin
if rf_empty_match='1' then
rf_empty_int <= '1';
elsif rd_clk'event and rd_clk='1' then
rf_empty_int <= rf_empty_match;
end if;
end process;
-- This version matches the count output, but can result in a
-- couple of unused memory locations.
process (wr_clk, reset)
variable tmp1 :std_logic_vector (count'range);
variable tmp2 :std_logic_vector (count'range);
begin
if reset='1' then
wf_full_int <= '0';
elsif wr_clk'event and wr_clk='1' then
tmp1 := (others=>'0');
tmp2 := tmp1 + 1;
if wf_full_int='1' and mid_allow='1' then
wf_full_int <= '0';
elsif wf_count=tmp2 and wr_allow='1' and mid_allow='0' then
wf_full_int <= '1';
elsif wf_count=tmp1 then
wf_full_int <= '1';
else
wf_full_int <= '0';
end if;
end if;
end process;
process (wr_clk, rf_full_match)
begin
if rf_full_match='1' then
rf_full_int <= '1';
elsif wr_clk'event and wr_clk='1' then
rf_full_int <= rf_full_match;
end if;
end process;
---------------------------------------------------------------
-- Keep a count of the number of empty entries in the write FIFO
---------------------------------------------------------------
process (wr_clk, reset)
variable addr :std_logic_vector (wrptr'range);
begin
if reset='1' then
addr := (others=>'1');
addr := addr - async_size;
addr := addr + 1;
wf_count <= addr;
elsif wr_clk='1' and wr_clk'event then
if wr_allow='1' and mid_allow='0' then
wf_count <= wf_count - 1;
elsif wr_allow='0' and mid_allow='1' then
wf_count <= wf_count + 1;
end if;
end if;
end process;
end arch_fifo_wrcount;
----------------------------------------------------------------------------
----------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
library work;
use work.free_fifo.all;
use work.ram_lib.all;
entity fifo_rdcount is
generic (data_bits :integer;
addr_bits :integer;
block_type :integer := 0;
async_size :integer := 16);
port (reset :in std_logic;
wr_clk :in std_logic;
wr_en :in std_logic;
wr_data :in std_logic_vector (data_bits-1 downto 0);
rd_clk :in std_logic;
rd_en :in std_logic;
rd_data :out std_logic_vector (data_bits-1 downto 0);
count :out std_logic_vector (addr_bits-1 downto 0);
full :out std_logic;
empty :out std_logic
);
end fifo_rdcount;
architecture arch_fifo_rdcount of fifo_rdcount is
signal wrptr_bin :std_logic_vector (addr_bits-1 downto 0);
signal wrptr :std_logic_vector (addr_bits-1 downto 0);
signal wrptr1 :std_logic_vector (addr_bits-1 downto 0);
signal rdptr_bin :std_logic_vector (addr_bits-1 downto 0);
signal rdptr1 :std_logic_vector (addr_bits-1 downto 0);
signal rdptr :std_logic_vector (addr_bits-1 downto 0);
signal midptr_bin :std_logic_vector (addr_bits-1 downto 0);
signal midptr :std_logic_vector (addr_bits-1 downto 0);
signal midptr1 :std_logic_vector (addr_bits-1 downto 0);
signal rf_count :std_logic_vector (addr_bits-1 downto 0);
signal wf_full_match :std_logic;
signal wf_empty_match :std_logic;
signal rf_empty_match :std_logic;
signal rf_aempty_match:std_logic;
signal wf_full_int :std_logic;
signal wf_empty_int :std_logic;
signal rf_empty_int :std_logic;
signal rd_allow :std_logic;
signal wr_allow :std_logic;
signal mid_allow :std_logic;
begin
empty <= rf_empty_int;
full <= wf_full_int;
count <= rf_count;
---------------------------------------------------------------
-- Generate the read/write allow signals
---------------------------------------------------------------
rd_allow <= '1' when rd_en='1' and rf_empty_int='0' else '0';
wr_allow <= '1' when wr_en='1' and wf_full_int='0' else '0';
mid_allow <= '1' when wf_empty_int='0' else '0';
---------------------------------------------------------------
-- Instantiate the RAM
---------------------------------------------------------------
fifo_ram: ram_dp
generic map (addr_bits => addr_bits,
data_bits => data_bits,
register_out_flag => 1,
block_type => block_type)
port map (reset,
wr_clk, wr_allow, wrptr, wr_data,
rd_clk, rdptr, rd_data);
---------------------------------------------------------------
-- Generate the write addresses
---------------------------------------------------------------
process (wr_clk, reset)
variable addr :std_logic_vector (wrptr_bin'range);
begin
if reset='1' then
addr := (others=>'0');
wrptr <= bin_to_gray (addr);
addr := addr + 1;
wrptr1 <= bin_to_gray (addr);
addr := addr + 1;
wrptr_bin <= addr;
elsif wr_clk'event and wr_clk='1' then
if wr_allow='1' then
wrptr <= wrptr1;
wrptr1 <= bin_to_gray (wrptr_bin);
wrptr_bin <= wrptr_bin + 1;
end if;
end if;
end process;
---------------------------------------------------------------
-- Generate the read addresses
---------------------------------------------------------------
process (rd_clk, reset)
variable addr :std_logic_vector (wrptr_bin'range);
begin
if reset='1' then
addr := (others=>'0');
rdptr <= bin_to_gray (addr);
addr := addr + 1;
rdptr1 <= bin_to_gray (addr);
addr := addr + 1;
rdptr_bin <= addr;
elsif rd_clk'event and rd_clk='1' then
if rd_allow='1' then
rdptr <= rdptr1;
rdptr1 <= bin_to_gray (rdptr_bin);
rdptr_bin <= rdptr_bin + 1;
end if;
end if;
end process;
---------------------------------------------------------------
-- Generate the mid addresses
---------------------------------------------------------------
process (rd_clk, reset)
variable addr :std_logic_vector (wrptr_bin'range);
begin
if reset='1' then
addr := (others=>'0');
midptr <= bin_to_gray (addr);
addr := addr + 1;
midptr_bin <= addr;
elsif rd_clk'event and rd_clk='1' then
if mid_allow='1' then
midptr <= bin_to_gray (midptr_bin);
midptr_bin <= midptr_bin + 1;
end if;
end if;
end process;
---------------------------------------------------------------
-- Calculate all the match signals and full/empty flags
---------------------------------------------------------------
wf_full_match <= '1' when wrptr1 = rdptr else '0';
wf_empty_match <= '1' when wrptr = midptr else '0';
rf_empty_match <= '1' when rdptr = midptr else '0'; -- synced to rd_clk!
rf_aempty_match <= '1' when rdptr1 = midptr else '0'; -- synced to rd_clk!
---------------------------------------------------------------
-- Generate the full/empty flags
---------------------------------------------------------------
--rf_empty_int <= rf_empty_match; -- The slow, but small approach
process (rd_clk, reset) -- The large, but fast approach
begin
if reset='1' then
rf_empty_int <= '1';
elsif rd_clk'event and rd_clk='1' then
if rf_aempty_match='1' and rd_allow='1' and mid_allow='0' then
rf_empty_int <= '1';
elsif rf_empty_match='1' and mid_allow='0' then
rf_empty_int <= '1';
else
rf_empty_int <= '0';
end if;
end if;
end process;
process (wr_clk, wf_full_match)
begin
if wf_full_match='1' then
wf_full_int <= '1';
elsif wr_clk'event and wr_clk='1' then
wf_full_int <= wf_full_match;
end if;
end process;
process (rd_clk, wf_empty_match)
begin
if wf_empty_match='1' then
wf_empty_int <= '1';
elsif rd_clk'event and rd_clk='1' then
wf_empty_int <= wf_empty_match;
end if;
end process;
---------------------------------------------------------------
-- Keep a count of the number of empty entries in the read FIFO
---------------------------------------------------------------
process (rd_clk, reset)
begin
if reset='1' then
rf_count <= (others=>'0');
elsif rd_clk='1' and rd_clk'event then
if rd_allow='1' and mid_allow='0' then
rf_count <= rf_count - 1;
elsif rd_allow='0' and mid_allow='1' then
rf_count <= rf_count + 1;
end if;
end if;
end process;
end arch_fifo_rdcount;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -