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

📄 fifo.vhd

📁 一个用VHDL源码编写的先进先出(FIFO)缓冲器模块.可以进行FIFO的仿真验证
💻 VHD
字号:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity FIFO is
  generic(
    fifowidth   : integer := 32;
    packS       : integer := 4;
    packDepth   : integer := 512;
    status_bit  : integer := 4;
    bram_size   : integer := 16384;
    eop_add     : boolean := true;
    info_loc    : integer := 4;
    wrclkeqrdclk: boolean := false;
    wrclkgtrdclk: boolean := true
  );
  port(
    reset       : in  std_logic;
    wrclk       : in  std_logic;
    rdclk       : in  std_logic;
    wrsop       : in  std_logic;
    wrsopt      : in  std_logic;
    wren        : in  std_logic;
    wreop       : in  std_logic;
    wrd         : in  std_logic_vector(fifowidth + status_bit - 1 downto 0);
    rdsop       : in  std_logic;
    rden        : in  std_logic;
    rdeop       : in  std_logic;
    rdd         : out std_logic_vector(fifowidth + status_bit - 1 downto 0);
    rbe         : out std_logic;
    wbf         : out std_logic
  );
end FIFO;

architecture syn of FIFO is
  constant  BLOCK_RAM_SIZE    : integer := bram_size;
  constant  MAX_BUF_ADDRESS   : integer := 16;
  constant  ZERO              : std_logic_vector(fifowidth + status_bit - 1 downto 0) := (others=>'0');
  function Get_Address(packDepth : in integer) return integer is
    variable temp : integer;
  begin
    temp := 0;
    for i in 0 to MAX_BUF_ADDRESS - 1 loop
      if 2**i >= packDepth then
        temp   := i;
        exit;
      end if;
    end loop;
    return(temp);
  end;
  component block_ram is
	port (
	  addra   : in  std_logic_vector(Get_Address(BLOCK_RAM_SIZE/fifowidth) - 1 downto 0);
	  addrb   : in  std_logic_vector(Get_Address(BLOCK_RAM_SIZE/fifowidth) - 1 downto 0);
	  clka    : in  std_logic;
	  clkb    : in  std_logic;
	  dina    : in  std_logic_vector(fifowidth + status_bit - 1 downto 0);
	  douta	  : out std_logic_vector(fifowidth + status_bit - 1 downto 0);
	  doutb   : out std_logic_vector(fifowidth + status_bit - 1 downto 0);
	  wea     : in  std_logic;
	  web     : in  std_logic;
	  dinb    : in  std_logic_vector(fifowidth + status_bit - 1 downto 0)
	);
  end component;

  constant RAM_BLK  : integer := (packDepth*fifowidth*packS)/BLOCK_RAM_SIZE;
  signal wraddr     : std_logic_vector(Get_Address(BLOCK_RAM_SIZE/fifowidth) - 1 downto 0);
  signal rdaddr     : std_logic_vector(Get_Address(BLOCK_RAM_SIZE/fifowidth) - 1 downto 0);
  signal wra,rda    : std_logic_vector(Get_Address(packDepth) - 1 downto 0);
  signal wrcnt      : std_logic_vector(Get_Address(packS) - 1 downto 0);
  signal rdcnt      : std_logic_vector(Get_Address(packS) - 1 downto 0);
  signal cnt        : integer range 0 to packS := 0;
  type fifodatatype is array (RAM_BLK - 1 downto 0) of std_logic_vector(fifowidth + status_bit - 1 downto 0);
  signal dataout    : fifodatatype;
  signal wr_en      : std_logic_vector(RAM_BLK - 1 downto 0);
  signal sysclk     : std_logic;
  signal weop       : std_logic;
  signal reop       : std_logic;
  signal eop_syn    : std_logic;
  signal error      : std_logic;

begin

  label1 : if wrclkeqrdclk = true generate
  begin
    sysclk      <= wrclk;
    weop        <= wren and wreop and not wrsop;
    reop        <= rden and rdeop;
  end generate;

  label2 : if (wrclkeqrdclk /= true ) and (wrclkgtrdclk = true) generate
  begin
    sysclk      <= wrclk;
    weop        <= wren and wreop and not wrsop;
    rdeop_syn_proc : process(rdclk,reop)
    begin
      if (reop or reset) = '1' then
        eop_syn     <= '0';
      elsif rdclk'event and rdclk = '1' then
        if (rden and rdeop) = '1' then
          eop_syn   <= '1';
        end if;
      end if;
    end process;
    rdeop_proc : process(sysclk)
    begin
      if sysclk'event and sysclk = '1' then
        reop      <= eop_syn;
      end if;
    end process;
  end generate;

  label3 : if (wrclkeqrdclk /= true ) and (wrclkgtrdclk /= true) generate
  begin
    sysclk      <= rdclk;
    reop        <= rden and rdeop;
    wreop_syn_proc : process(wrclk,weop)
    begin
      if (weop or reset) = '1' then
        eop_syn     <= '0';
      elsif wrclk'event and wrclk = '1' then
        if (wren and wreop and not wrsop) = '1' then
          eop_syn   <= '1';
        end if;
      end if;
    end process;
    wreop_proc : process(sysclk)
    begin
      if sysclk'event and sysclk = '1' then
        weop        <= eop_syn;
      end if;
    end process;
  end generate;

  fifo_proc : process(sysclk)
  begin
    if sysclk'event and sysclk = '1' then
      if reset = '1' then
        rbe      <= '1';
        wbf      <= '0';
        error   <= '0';
      else
        if cnt = 0 then
          rbe    <= '1';
          if wrcnt /= rdcnt then
            error   <= '1';
          else
            error   <= '0';
          end if;
        else
          rbe    <= '0';
        end if;
        if cnt = packS then
          wbf  <= '1';
        else
          wbf  <= '0';
        end if;
      end if;
    end if;
  end process;

  wraProc : process(wrclk)
  begin
    if wrclk 'event and wrclk = '1' then
      if reset = '1' then
        wra    <= (others=>'0');
      else
        if wren = '1' then
          if wreop = '1' then
            wra  <= (others => '0');
          elsif wrsop = '1' then
            wra  <= (others => '0');
          elsif wrsopt = '1' then
            wra  <= conv_std_logic_vector(info_loc,Get_Address(PackDepth));
          else
            wra  <= wra + 1;
          end if;
        end if;
      end if;
    end if;
  end process;

  rdaProc : process(rdclk)
  begin
    if rdclk'event and rdclk = '1' then
      if reset = '1' then
        rda  <= (others => '0');
      else
        if rden = '1' then
          if rdeop = '1' then
            rda  <= (others => '0');
          elsif rdsop = '1' then
            rda  <= (others => '0');
          else
            rda  <= rda + 1;
          end if;
        end if;
      end if;
    end if;
  end process;

  label5: if RAM_BLK = 1 generate
  begin
    wraddr    <= wrcnt & wra;
    rdaddr    <= rdcnt & rda;
  end generate;

  label6: if RAM_BLK /= 1 generate
  begin
    wraddr    <= wra;
    rdaddr    <= rda;
  end generate;

  cnt_proc : process(sysclk)
  begin
    if sysclk'event and sysclk = '1' then
      if reset = '1' then
        cnt     <= 0;
        wrcnt   <= (others=>'0');
        rdcnt   <= (others=>'0');
      else
        if weop = '1' then
          if cnt < packS then
            if conv_integer(wrcnt) = packS - 1 then
              wrcnt <= (others=>'0');
            else
              wrcnt <= wrcnt + 1;
            end if;
          end if;
        else
          if error = '1' then
            wrcnt   <= (others=>'0');
          end if;
        end if;
        if reop = '1' then
          if cnt > 0 then
            if conv_integer(rdcnt) = packS - 1 then
              rdcnt <= (others=>'0');
            else
              rdcnt <= rdcnt + 1;
            end if;
          end if;
        else
          if error = '1' then
            rdcnt   <= (others=>'0');
          end if;
        end if;
        if (weop = '1') and (reop = '0') then
          if cnt < packS then
            cnt  <= cnt + 1;
          end if;
        elsif (weop = '0') and (reop = '1') then
          if cnt > 0 then
            cnt  <= cnt - 1;
          end if;
        end if;
      end if;
    end if;
  end process;

  synProc : process(rdclk)
  begin
    if rdclk'event and rdclk = '1' then
      if RAM_BLK = 1 then
        rdd <= dataout(0);
      else
        rdd <= dataout(conv_integer(rdcnt));
      end if;
    end if;
  end process;

  wren_proc : process(wrcnt,wren,wrsopt,wrsop,wreop)
  begin
    if RAM_BLK = 1 then
      if cnt < packS then
        if eop_add = true then
          wr_en(0) <= wren and (not wrsopt) and (not wrsop);
        else
          wr_en(0) <= wren and (not wrsopt) and (not wrsop) and (not wreop);
        end if;
      else
        wr_en(0) <= '0';
      end if;
    else
      for i in 0 to RAM_BLK - 1 loop
        if cnt < packS then
          if conv_integer(wrcnt) = i then
            if eop_add = true then
              wr_en(i) <= wren and (not wrsopt) and (not wrsop);
            else
              wr_en(i) <= wren and (not wrsopt) and (not wrsop) and (not wreop);
            end if;
          else
            wr_en(i) <= '0';
          end if;
        else
          wr_en(i) <= '0';
        end if;
      end loop;
    end if;
  end process;

  LABEL4 : for i in 0 to RAM_BLK - 1 generate
  begin
  U : block_ram
  port map(
	  addra   => wraddr,
	  addrb   => rdaddr,
	  clka    => wrclk,
	  clkb    => rdclk,
	  dina    => wrd,
	  douta   => open,
	  doutb   => dataout(i),
	  wea     => wr_en(i),
	  web     => '0',
	  dinb    => ZERO
	);
  end generate;

end syn;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -