📄 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 + -