📄 freefifo.vhd
字号:
----------------------------------------------------------------------------
----------------------------------------------------------------------------
-- The Free IP Project
-- VHDL Free-FIFO Core
-- (c) 2000, The Free IP Project and David Kessner
--
--
-- FREE IP GENERAL PUBLIC LICENSE
-- TERMS AND CONDITIONS FOR USE, COPYING, DISTRIBUTION, AND MODIFICATION
--
-- 1. You may copy and distribute verbatim copies of this core, as long
-- as this file, and the other associated files, remain intact and
-- unmodified. Modifications are outlined below.
-- 2. You may use this core in any way, be it academic, commercial, or
-- military. Modified or not.
-- 3. Distribution of this core must be free of charge. Charging is
-- allowed only for value added services. Value added services
-- would include copying fees, modifications, customizations, and
-- inclusion in other products.
-- 4. If a modified source code is distributed, the original unmodified
-- source code must also be included (or a link to the Free IP web
-- site). In the modified source code there must be clear
-- identification of the modified version.
-- 5. Visit the Free IP web site for additional information.
-- http://www.free-ip.com
--
----------------------------------------------------------------------------
----------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
package free_fifo is
component fifo_sync
generic (data_bits :integer;
addr_bits :integer;
block_type :integer := 0);
port (reset :in std_logic;
clk :in std_logic;
wr_en :in std_logic;
wr_data :in std_logic_vector (data_bits-1 downto 0);
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 component;
component fifo_async
generic (data_bits :integer;
addr_bits :integer;
block_type :integer := 0;
fifo_arch :integer := 0); -- 0=Generic architecture, 1=Xilinx, 2=Xilinx w/carry
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);
full :out std_logic;
empty :out std_logic
);
end component;
component fifo_wrcount
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 component;
component fifo_wrcount_orig
generic (data_bits :integer;
addr_bits :integer;
block_type :integer := 0;
fifo_arch :integer := 0); -- 0=Generic architecture, 1=Xilinx, 2=Xilinx w/carry
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 component;
component fifo_rdcount
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 component;
component fifo_rdcount_orig
generic (data_bits :integer;
addr_bits :integer;
block_type :integer := 0;
fifo_arch :integer := 0); -- 0=Generic architecture, 1=Xilinx, 2=Xilinx w/carry
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 component;
component fifo_async_xilinx
generic (data_bits :integer;
addr_bits :integer;
block_type :integer := 0;
fpga_type :integer := 0); -- 0=generic VHDL, 1=Xilinx Spartan2/Virtex
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);
full_out :out std_logic;
empty_out :out std_logic
);
end component;
component fifo_async_generic
generic (data_bits :integer;
addr_bits :integer;
block_type :integer := 0);
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);
full :out std_logic;
empty :out std_logic
);
end component;
function bin_to_gray(din :std_logic_vector)
return std_logic_vector;
end package;
----------------------------------------------------------------------------
----------------------------------------------------------------------------
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;
package body free_fifo is
function bin_to_gray(din :std_logic_vector)
return std_logic_vector is
variable dout :std_logic_vector(din'range);
begin
dout := din xor ("0" & din(din'high downto 1));
return dout;
end bin_to_gray;
end free_fifo;
----------------------------------------------------------------------------
----------------------------------------------------------------------------
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_async_xilinx is
generic (data_bits :integer;
addr_bits :integer;
block_type :integer := 0;
fpga_type :integer := 0);
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);
full_out :out std_logic;
empty_out :out std_logic
);
end fifo_async_xilinx;
architecture arch_fifo_async_xilinx of fifo_async_xilinx is
signal full :std_logic;
signal empty :std_logic;
signal rd_allow :std_logic;
signal wr_allow :std_logic;
signal rd_addr :std_logic_vector (addr_bits-1 downto 0);
signal rd_addr_gray1 :std_logic_vector (addr_bits-1 downto 0);
signal rd_addr_gray2 :std_logic_vector (addr_bits-1 downto 0);
signal rd_addr_gray3 :std_logic_vector (addr_bits-1 downto 0);
signal wr_addr :std_logic_vector (addr_bits-1 downto 0);
signal wr_addr_gray1 :std_logic_vector (addr_bits-1 downto 0);
signal wr_addr_gray2 :std_logic_vector (addr_bits-1 downto 0);
signal emptyg :std_logic;
signal almostemptyg :std_logic;
signal fullg :std_logic;
signal almostfullg :std_logic;
signal always_one :std_logic;
signal always_zero :std_logic;
-- MUXCY_L -- 2-to-1 Multiplexer for Carry Logic with Local Output
-- Applies only to the Xilinx Virtex and Spartan-II FPGA's
-- http://toolbox.xilinx.com/docsan/2_1i/data/common/lib/lib7_35.htm
-- VHDL Equivalent: LO <= DI when S='0' else CI;
component MUXCY_L
port (
DI: IN std_logic;
CI: IN std_logic;
S: IN std_logic;
LO: OUT std_logic);
END component;
-- Note: These signals are only used for the Xilinx version (fpga_type=1)
signal ecomp :std_logic_vector (addr_bits-1 downto 0);
signal aecomp :std_logic_vector (addr_bits-1 downto 0);
signal fcomp :std_logic_vector (addr_bits-1 downto 0);
signal afcomp :std_logic_vector (addr_bits-1 downto 0);
signal emuxcyo :std_logic_vector (addr_bits-1 downto 0);
signal aemuxcyo :std_logic_vector (addr_bits-1 downto 0);
signal fmuxcyo :std_logic_vector (addr_bits-1 downto 0);
signal afmuxcyo :std_logic_vector (addr_bits-1 downto 0);
signal ecin :std_logic;
signal aecin :std_logic;
signal fcin :std_logic;
signal afcin :std_logic;
begin
always_one <= '1';
always_zero <= '0';
---------------------------------------------------------------
-- Generate the read/write allow signals
---------------------------------------------------------------
rd_allow <= '1' when rd_en='1' and empty='0' else '0';
wr_allow <= '1' when wr_en='1' and full='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, wr_addr_gray2, wr_data,
rd_clk, rd_addr_gray2, rd_data);
---------------------------------------------------------------
-- Generate the read addresses & pipelined gray-code versions
-- If you're reading along in the Xilinx XAPP174, here's the conversion chart:
-- rd_addr_gray1 == read_nextgray
-- rd_addr_gray2 == read_addrgray
-- rd_addr_gray3 == read_lastgray
--
-- The addr and gray-code reset procedure has been designed
-- to be more "dumb-proof" when parameterized. The initial
-- values are different than the Xilinx version.
---------------------------------------------------------------
process (rd_clk, reset)
variable addr :std_logic_vector (rd_addr'range);
begin
if reset='1' then
addr := (others=>'0');
rd_addr_gray3 <= bin_to_gray (addr);
addr := addr + 1;
rd_addr_gray2 <= bin_to_gray (addr);
addr := addr + 1;
rd_addr_gray1 <= bin_to_gray (addr);
addr := addr + 1;
rd_addr <= addr;
elsif rd_clk'event and rd_clk='1' then
if rd_allow='1' then
rd_addr_gray3 <= rd_addr_gray2;
rd_addr_gray2 <= rd_addr_gray1;
rd_addr_gray1 <= bin_to_gray(rd_addr);
rd_addr <= rd_addr + 1;
end if;
end if;
end process;
---------------------------------------------------------------
-- Generate the write addresses & pipelined gray-code versions
-- wr_addr_gray1 == write_nextgray
-- wr_addr_gray2 == write_addrgray
---------------------------------------------------------------
process (wr_clk, reset)
variable addr :std_logic_vector (rd_addr'range);
begin
if reset='1' then
addr := (others=>'0');
--wr_addr_gray3 <= bin_to_gray (addr); -- There isn't a wr_addr_gray3
addr := addr + 1;
wr_addr_gray2 <= bin_to_gray (addr);
addr := addr + 1;
wr_addr_gray1 <= bin_to_gray (addr);
addr := addr + 1;
wr_addr <= addr;
elsif wr_clk'event and wr_clk='1' then
if wr_allow='1' then
wr_addr_gray2 <= wr_addr_gray1;
wr_addr_gray1 <= bin_to_gray(wr_addr);
wr_addr <= wr_addr + 1;
end if;
end if;
end process;
---------------------------------------------------------------
-- Generate Empty
---------------------------------------------------------------
process (rd_clk, reset)
begin
if reset='1' then
empty <= '1';
elsif rd_clk'event and rd_clk='1' then
if emptyg='1' or (almostemptyg='1' and rd_allow='1') then
empty <= '1';
else
empty <= '0';
end if;
end if;
end process;
empty_out <= empty;
---------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -