📄 fifo_status.vhd
字号:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity fifo_status is
port (
rd_clk, wr_clk, reset, rd, wr, pn_lock, wr_addr_srst : in std_logic;
rd_addr, wr_addr : out std_logic_vector (10 downto 0);
full, empty, almost_full, half_full, almost_empty : out std_logic;
pn_lock_rd_clk : out std_logic);
end fifo_status;
architecture rtl of fifo_status is
signal wr_dtct : std_logic_vector (3 downto 0);
signal flag_wr_addr, flag_cnt : std_logic_vector (10 downto 0);
signal pn_lock_rd_clk_p0, pn_lock_rd_clk_i : std_logic;
signal rd_addr_i, wr_addr_i : std_logic_vector (10 downto 0);
begin -- rtl
--_____________________________________________________________________________________
-- Cross clock domains for pn_lock from wr_clk to rd_clk
--_____________________________________________________________________________________
pn_lock_rd_clk <= pn_lock_rd_clk_i;
process (rd_clk, reset)
begin -- process
if reset = '1' then -- asynchronous reset (active high)
pn_lock_rd_clk_p0 <= '0';
pn_lock_rd_clk_i <= '0';
elsif rising_edge(rd_clk) then -- rising clock edge
pn_lock_rd_clk_p0 <= pn_lock; -- gaurds agains metastability
pn_lock_rd_clk_i <= pn_lock_rd_clk_p0;
end if;
end process;
--_____________________________________________________________________________________
-- Create read address (counter)
--_____________________________________________________________________________________
rd_addr <= rd_addr_i;
create_read_addr: process (rd_clk, reset)
begin -- process create_read_addr
if reset = '1' then -- asynchronous reset (active high)
rd_addr_i <= (others => '0');
elsif rising_edge(rd_clk) then -- rising clock edge
if rd = '1' and pn_lock_rd_clk_i = '1' then
rd_addr_i <= rd_addr_i + 1;
elsif pn_lock_rd_clk_i = '0' then
rd_addr_i <= (others => '0');
end if;
end if;
end process create_read_addr;
--_____________________________________________________________________________________
-- Create write address (counter)
--_____________________________________________________________________________________
wr_addr <= wr_addr_i;
create_wr_addr: process (wr_clk, reset)
begin -- process create_wr_addr
if reset = '1' then -- asynchronous reset (active high)
wr_addr_i <= (others => '0');
elsif rising_edge(wr_clk) then -- rising clock edge
if wr_addr_srst = '1' then -- synchronous reset for wr_addr when pn_lock is lost
wr_addr_i <= (others => '0');
elsif wr = '1' then
wr_addr_i <= wr_addr_i + 1;
end if;
end if;
end process create_wr_addr;
-- write detection circuit synchronized to faster rd_clk
write_detect: process (rd_clk, reset)
begin -- process write_detect
if reset = '1' then -- asynchronous reset (active high)
wr_dtct <= (others => '0');
flag_wr_addr <= (others => '0');
elsif rising_edge(rd_clk) then -- rising clock edge
if wr_dtct(0) = '1' then -- synchronous reset. This will work for rd_clk upto 4x faster than wr_clk
wr_dtct <= (others => '0');
flag_wr_addr <= wr_addr_i; -- cross domains with stable wr_addr
else
wr_dtct <= wr & wr_dtct(3 downto 1);
end if;
end if;
end process write_detect;
-- Create counter used to create full/empty signals
create_flag_count: process (rd_clk, reset)
begin -- process create_flag_count
if reset = '1' then -- asynchronous reset (active high)
flag_cnt <= (others => '0');
elsif rising_edge(rd_clk) then -- rising clock edge
--default
flag_cnt <= (others => '0');
if pn_lock_rd_clk_i = '1' then -- create the flag_cnt if this channel has a lock, otherwise assume data is empty
flag_cnt <= flag_wr_addr - rd_addr_i;
end if;
end if;
end process create_flag_count;
-- Create full/empty flag signals
create_full_empty_flags: process (rd_clk, reset)
begin -- process create_full_empty_flags
if reset = '1' then -- asynchronous reset (active high)
full <= '0';
almost_full <= '0';
half_full <= '0';
empty <= '0';
almost_empty <= '0';
elsif rising_edge(rd_clk) then -- rising clock edge
-- defaults (infers gates rather than latches or clk enables)
full <= '0';
almost_full <= '0';
half_full <= '0';
empty <= '0';
almost_empty <= '0';
if flag_cnt = conv_std_logic_vector(0, 11) then
empty <= '1';
end if;
if flag_cnt <= conv_std_logic_vector(8, 11) then
almost_empty <= '1';
end if;
if flag_cnt >= conv_std_logic_vector(1024, 11) then
half_full <= '1';
end if;
if flag_cnt >= conv_std_logic_vector(2040, 11) then
almost_full <= '1';
end if;
if flag_cnt = conv_std_logic_vector(2047, 11) then
full <= '1';
end if;
end if;
end process create_full_empty_flags;
end rtl;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -