⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fifo_status.vhd

📁 it describe how to develop the field programmable gate array
💻 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 + -