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

📄 mini_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 mini_fifo is  -- slave mode
  generic(
    fifo_width  : integer := 32;
    fifo_ports  : integer := 1;
    fifo_depth  : integer := 8;
    ram_depth   : integer := 16384;
    status_bit  : integer := 4
  );
  Port (
    sysclk      : in  std_logic;
    reset       : in  std_logic;
    wren        : in  std_logic;
    wrsop       : in  std_logic;
    wreop       : in  std_logic;
    wrport      : in  std_logic_vector(7 downto 0);
    wrd         : in  std_logic_vector(fifo_width + status_bit - 1 downto 0);
    rden        : in  std_logic;
    rdeop       : in  std_logic;
    rdsop       : in  std_logic;
    rdport      : in  std_logic_vector(7 downto 0);
    rdd         : out std_logic_vector(fifo_width + status_bit - 1 downto 0);
    fifoempty   : out std_logic_vector(fifo_ports - 1 downto 0);
    fifofull    : out std_logic_vector(fifo_ports - 1 downto 0);
    fifohalffull: out std_logic_vector(fifo_ports - 1 downto 0)
  );
end mini_fifo;

architecture syn of mini_fifo is
  constant  BLOCK_RAM_SIZE   : integer := 16384;
  constant  MAX_BUF_ADDRESS  : integer := 16;
  function Get_Address(DEPTH : in integer) return integer is
    variable temp : integer;
  begin
    temp := 0;
    for i in 0 to MAX_BUF_ADDRESS - 1 loop
      if 2**i >= DEPTH 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/fifo_width) - 1 downto 0);
	  addrb   : in  std_logic_vector(Get_Address(BLOCK_RAM_SIZE/fifo_width) - 1 downto 0);
	  clka    : in  std_logic;
	  clkb    : in  std_logic;
	  dina    : in  std_logic_vector(fifo_width + status_bit - 1 downto 0);
	  douta	  : out std_logic_vector(fifo_width + status_bit - 1 downto 0);
	  doutb   : out std_logic_vector(fifo_width + status_bit - 1 downto 0);
	  wea     : in  std_logic;
	  web     : in  std_logic;
	  dinb    : in  std_logic_vector(fifo_width + status_bit - 1 downto 0)
	);
  end component;

  constant IPPacks  : integer := ram_depth / (fifo_width * (2**Get_Address(fifo_depth)) * (2**Get_Address(fifo_ports)));
  constant BLOCKS   : integer := ram_depth / 16384;
  constant zero     : std_logic_vector(fifo_width + status_bit - 1 downto 0) := (others=>'0');
  signal wraddr     : std_logic_vector(Get_Address(ram_depth/fifo_width) - 1 downto 0);
  signal rdaddr     : std_logic_vector(Get_Address(ram_depth/fifo_width) - 1 downto 0);
  type   in_blkaddr_type is array(fifo_ports - 1 downto 0) of std_logic_vector(Get_Address(fifo_depth) - 1 downto 0);
  type   blk_addr_type is array(fifo_ports - 1 downto 0) of std_logic_vector(Get_Address(IPPacks) - 1 downto 0);
  signal wr_in_fifo_addr: in_blkaddr_type;
  signal wr_fifo_addr   : blk_addr_type;
  signal rd_in_fifo_addr: in_blkaddr_type;
  signal rd_fifo_addr   : blk_addr_type;
  type   IPcnttype is array(fifo_ports - 1 downto 0) of integer range 0 to IPPacks;
  signal IPcnt      : IPcnttype;
  type   datatype is array(BLOCKS - 1 downto 0) of std_logic_vector(fifo_width + status_bit - 1 downto 0);
  signal dataout    : datatype;
  signal wr_port    : integer range 0 to fifo_ports - 1 := 0;
  signal rd_port    : integer range 0 to fifo_ports - 1 := 0;
  signal blk_din    : std_logic_vector(fifo_width + status_bit - 1 downto 0);
  signal blk_wren   : std_logic_vector(BLOCKS - 1 downto 0);
  signal wp_eq_rp   : std_logic;
  signal en_ipwr    : std_logic_vector(fifo_ports - 1 downto 0);
  signal en_iprd    : std_logic_vector(fifo_ports - 1 downto 0);
  signal error      : std_logic_vector(fifo_ports - 1 downto 0);
begin

  label1 : if fifo_ports = 1 generate
    wr_port   <= 0;
    rd_port   <= 0;
  end generate;

  label2 : if fifo_ports /= 1 generate
    wr_rd_port_proc : process(sysclk)
    begin
      if sysclk'event and sysclk = '1' then
        --wr_port   <= conv_integer(wrport(Get_Address(fifo_ports) - 1 downto 0));
        --rd_port   <= conv_integer(rdport(Get_Address(fifo_ports) - 1 downto 0));
        if conv_integer(wrport(Get_Address(fifo_ports) - 1 downto 0)) < fifo_ports then
          wr_port   <= conv_integer(wrport(Get_Address(fifo_ports) - 1 downto 0));
        else
          wr_port   <= 0;
        end if;
        if conv_integer(rdport(Get_Address(fifo_ports) - 1 downto 0)) < fifo_ports then
          rd_port   <= conv_integer(rdport(Get_Address(fifo_ports) - 1 downto 0));
        else
          rd_port   <= 0;
        end if;
      end if;
    end process;
  end generate;

  clk_proc : process(sysclk)
  begin
    if sysclk'event and sysclk = '1' then
      for i in 0 to fifo_ports - 1 loop
        if IPcnt(i) < IPPacks then
          en_ipwr(i)   <= '1';
        else
          en_ipwr(i)   <= '0';
        end if;
        if IPcnt(i) > 0 then
          en_iprd(i)   <= '1';
        else
          en_iprd(i)   <= '0';
        end if;
      end loop;
      if wrport /= rdport then
        wp_eq_rp <= '0';
      else
        wp_eq_rp <= '1';
      end if;
    end if;
  end process;

  fifo_proc : process(sysclk)
  begin
    if sysclk'event and sysclk = '1' then
      if reset = '1' then
        for i in 0 to fifo_ports - 1 loop
          IPcnt(i)       <= 0;
          fifoempty(i)   <= '1';
          fifofull(i)    <= '0';
          fifohalffull(i)<= '0';
          error(i)       <= '0';
        end loop;
      else
        for i in 0 to fifo_ports - 1 loop
          if IPcnt(i) = 0 then
            fifoempty(i) <= '1';
            if wr_fifo_addr(i) /= rd_fifo_addr(i) then
              error(i) <= '1';
            else
              error(i) <= '0';
            end if;
          else
            fifoempty(i) <= '0';
          end if;
          if IPcnt(i) = IPpackS then
            fifofull(i)  <= '1';
          else
            fifofull(i)  <= '0';
          end if;
          if IPcnt(i) >= 4 then
            fifohalffull(i) <= '1';
          else
            fifohalffull(i) <= '0';
          end if;
        end loop;
        if wp_eq_rp = '0' then
          if wren = '1' then
            if (wreop = '1') then
              for i in 0 to fifo_ports - 1 loop
                if i = wr_port then
                  if en_ipwr(i) = '1' then
                    IPcnt(i)  <= IPcnt(i) + 1;
                  end if;
                end if;
              end loop;
            end if;
          end if;
          if rden = '1' then
            if (rdeop = '1') then
              for i in 0 to fifo_ports - 1 loop
                if i = rd_port then
                  if en_iprd(i) = '1' then
                    IPcnt(i) <= IPcnt(i) - 1;
                  end if;
                end if;
              end loop;
            end if;
          end if;
        else
          if ((wren and wreop) = '1') and ((rden and rdeop) = '0') then
            for i in 0 to fifo_ports - 1 loop
              if i = wr_port then
                if en_ipwr(i) = '1' then
                  IPcnt(i)  <= IPcnt(i) + 1;
                end if;
              end if;
            end loop;
          elsif ((rden and rdeop)= '1') and ((wren and wreop) = '0') then
            for i in 0 to fifo_ports - 1 loop
              if i = rd_port then
                if en_iprd(i) = '1' then
                  IPcnt(i) <= IPcnt(i) - 1;
                end if;
              end if;
            end loop;
          end if;
        end if;
      end if;
    end if;
  end process;

  wraddrProc : process(sysclk)
  begin
    if sysclk 'event and sysclk = '1' then
      if reset = '1' then
        for i in 0 to fifo_ports - 1 loop
          wr_in_fifo_addr(i)         <= (others=>'0');
          wr_fifo_addr(i)            <= (others=>'0');
        end loop;
      else
        if wren = '1' then
          if wreop = '1' then
            for i in 0 to fifo_ports - 1 loop
              if i = wr_port then
                wr_in_fifo_addr(i)   <= (others=>'0');
                if en_ipwr(i) = '1' then
                  wr_fifo_addr(i)    <= wr_fifo_addr(i) + 1;
                end if;
              end if;
            end loop;
          elsif wrsop = '1' then
            for i in 0 to fifo_ports - 1 loop
              if i = wr_port then
                wr_in_fifo_addr(i)   <= (others=>'0');
              end if;
            end loop;
          else 
            for i in 0 to fifo_ports - 1 loop
              if i = wr_port then
                wr_in_fifo_addr(i)   <= wr_in_fifo_addr(i) + 1;
              end if;
            end loop;
          end if;
        else
          for i in 0 to fifo_ports - 1 loop
            if i = wr_port then
              if error(i) = '1' then
                wr_fifo_addr(i)  <= (others=>'0');
              end if;
            end if;
          end loop;
        end if;
      end if;
    end if;
  end process;

  rdaddrProc : process(sysclk)
  begin
    if sysclk 'event and sysclk = '1' then
      if reset = '1' then
        for i in 0 to fifo_ports - 1 loop
          rd_in_fifo_addr(i)  <= (others=>'0');
          rd_fifo_addr(i)     <= (others=>'0');
        end loop;
      else
        if rden = '1' then
          if (rdeop = '1') then
            for i in 0 to fifo_ports - 1 loop
              if i = rd_port then
                rd_in_fifo_addr(i)  <= (others=>'0');
                if en_iprd(i) = '1' then
                  rd_fifo_addr(i)   <= rd_fifo_addr(i) + 1;
                end if;
              end if;
            end loop;
          elsif rdsop = '1' then
            for i in 0 to fifo_ports - 1 loop
              if i = rd_port then
                rd_in_fifo_addr(i)<= (others=>'0');
              end if;
            end loop;
          else
            for i in 0 to fifo_ports - 1 loop
              if i = rd_port then
                rd_in_fifo_addr(i)<= rd_in_fifo_addr(i) + 1;
              end if;
            end loop;
          end if;
        else
          for i in 0 to fifo_ports - 1 loop
            if i = rd_port then
              if error(i) = '1' then
                rd_fifo_addr(i)  <= (others=>'0');
              end if;
            end if;
          end loop;
        end if;
      end if;
    end if;
  end process;

  label3 : if fifo_ports = 1 generate
    clk_syn1 : process(sysclk)
    begin
      if sysclk'event and sysclk = '1' then
        wraddr  <= wr_fifo_addr(wr_port) & wr_in_fifo_addr(wr_port);
        rdaddr  <= rd_fifo_addr(rd_port) & rd_in_fifo_addr(rd_port);
      end if;
    end process;
  end generate;

  label4 : if fifo_ports /= 1 generate
    clk_syn2 : process(sysclk)
    begin
      if sysclk'event and sysclk = '1' then
        wraddr  <= wrport(Get_Address(fifo_ports) - 1 downto 0) & wr_fifo_addr(wr_port) & wr_in_fifo_addr(wr_port);
        rdaddr  <= rdport(Get_Address(fifo_ports) - 1 downto 0) & rd_fifo_addr(rd_port) & rd_in_fifo_addr(rd_port);
      end if;
    end process;
  end generate;

  label5 : if BLOCKS = 1 generate
    clk_syn3 : process(sysclk)
    begin
      if sysclk'event and sysclk = '1' then
        blk_wren(0)   <= wren;
        blk_din       <= wrd;
        rdd           <= dataout(0);
      end if;
    end process;
  end generate;

  label6 : if BLOCKS /= 1 generate
    data_out_proc : process(sysclk)
    begin
      if sysclk'event and sysclk = '1' then
        rdd <= dataout(conv_integer(rdaddr(Get_Address(ram_depth/fifo_width) - 1 downto 9)));
        blk_din         <= wrd;
        for i in 0 to BLOCKS - 1 loop
          if i = conv_integer(wraddr(Get_Address(ram_depth/fifo_width) - 1 downto 9)) then
            blk_wren(i) <= wren;
          else
            blk_wren(i) <= '0';
          end if;
        end loop;
      end if;
    end process;
  end generate;

  label7 : for i in 0 to BLOCKS - 1 generate
  begin
  U : block_ram
  port map(
    addra   => wraddr(8 downto 0),
    addrb   => rdaddr(8 downto 0),
    clka    => sysclk,
    clkb    => sysclk,
    dina    => blk_din,
    douta   => open ,
    doutb   => dataout(i),
    wea     => blk_wren(i),
    web     => '0',
    dinb    => blk_din
  );
  end generate;
end syn;

⌨️ 快捷键说明

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