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

📄 freefifo.vhd

📁 常见的输入输出及存储器件(ram及fifo)vhdl实现
💻 VHD
📖 第 1 页 / 共 4 页
字号:
      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 + -