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