📄 can_fifo.vhd
字号:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
use ieee.std_logic_arith.all;
entity can_fifo is
port (
clk : in std_logic ;
rst : in std_logic ;
wr : in std_logic ;
data_in : in std_logic_vector(7 downto 0) ;
addr : in std_logic_vector(7 downto 0) ;
reset_mode : in std_logic ;
release_buffer : in std_logic ;
extended_mode : in std_logic ;
data_out : out std_logic_vector(7 downto 0));
end can_fifo;
architecture RTL of can_fifo is
constant Tp : time := 1 ns;
type mem_1 is array(0 to 63) of std_logic_vector(7 downto 0);
type mem_2 is array(0 to 63) of std_logic_vector(3 downto 0);
type mem_3 is array(0 to 63) of std_logic;
signal fifo : mem_1;
signal rd_pointer : std_logic_vector(5 downto 0);
signal wr_pointer : std_logic_vector(5 downto 0);
signal read_address : std_logic_vector(5 downto 0);
signal length_info : mem_2;
signal wr_info_pointer : std_logic_vector(5 downto 0);
signal rd_info_pointer : std_logic_vector(5 downto 0);
signal overrun_info : mem_3;
signal wr_q : std_logic;
signal len_cnt : std_logic_vector(3 downto 0);
signal fifo_cnt : std_logic_vector(6 downto 0);
signal info_cnt : std_logic_vector(6 downto 0);
signal latch_overrun : std_logic;
signal write_length_info : std_logic;
signal fifo_empty : std_logic;
signal fifo_full : std_logic;
signal info_full : std_logic;
signal info_empty : std_logic;
begin
write_length_info <= (not wr) and wr_q;
-- Delayed write signal
process(clk,rst)
begin
if (clk = '1' and clk'event) then
if (rst = '1') then
wr_q <= '0';
elsif (reset_mode = '1') then
wr_q <= '0' after Tp;
else
wr_q <= wr after Tp;
end if;
end if;
end process;
-- length counter
process(clk,rst)
begin
if (clk = '1' and clk'event) then
if (rst = '1') then
len_cnt <= (others => '0');
elsif (reset_mode = '1' or write_length_info = '1') then
len_cnt <= (others => '0') after Tp;
elsif (wr = '1' and fifo_full = '0') then
len_cnt <= len_cnt + 1 after Tp;
end if;
end if;
end process;
-- wr_info_pointer
process(clk,rst)
begin
if (clk = '1' and clk'event) then
if (rst = '1') then
wr_info_pointer <= (others => '0');
elsif (reset_mode = '1') then
wr_info_pointer <= (others => '0') after Tp;
elsif (write_length_info = '1' and info_full = '0') then
wr_info_pointer <= wr_info_pointer + 1 after Tp;
end if;
end if;
end process;
-- length_info
process(clk)
begin
if (clk = '1' and clk'event) then
if (write_length_info = '1' and info_full = '0') then
length_info(conv_integer(wr_info_pointer)) <= len_cnt after Tp;
end if;
end if;
end process;
-- overrun_info
process(clk)
begin
if (clk = '1' and clk'event) then
if (write_length_info = '1' and info_full = '0') then
overrun_info(conv_integer(wr_info_pointer)) <= latch_overrun or (wr and fifo_full);
end if;
end if;
end process;
-- rd_info_pointer
process(clk,rst)
begin
if (clk = '1' and clk'event) then
if (rst = '1') then
rd_info_pointer <= (others => '0');
elsif (reset_mode = '1') then
rd_info_pointer <= (others => '0') after Tp;
elsif (release_buffer = '1' and fifo_empty = '0') then
rd_info_pointer <= rd_info_pointer + 1 after Tp;
end if;
end if;
end process;
-- rd_pointer
process(clk,rst)
begin
if (clk = '1' and clk'event) then
if (rst = '1') then
rd_pointer <= (others => '0');
elsif (release_buffer = '1' and fifo_empty = '0') then
rd_pointer <= rd_pointer + length_info(conv_integer(rd_info_pointer)) after Tp;
elsif (reset_mode = '1') then
rd_pointer <= (others => '0') after Tp;
end if;
end if;
end process;
-- wr_pointer
process(clk,rst)
begin
if (clk = '1' and clk'event) then
if (rst = '1') then
wr_pointer <= (others => '0');
elsif (wr = '1' and fifo_full = '0') then
wr_pointer <= wr_pointer + 1 after Tp;
elsif (reset_mode = '1') then
wr_pointer <= (others => '0') after Tp;
end if;
end if;
end process;
-- latch_overrun
process(clk,rst)
begin
if (clk = '1' and clk'event) then
if (rst = '1') then
latch_overrun <= '0';
elsif (reset_mode = '1' or write_length_info = '1') then
latch_overrun <= '0' after Tp;
elsif (wr = '1' and fifo_full = '1') then
latch_overrun <= '1' after Tp;
end if;
end if;
end process;
-- Counting data in fifo
process(clk,rst)
begin
if (clk = '1' and clk'event) then
if (rst = '1') then
fifo_cnt <= (others => '0');
elsif (wr = '1' and release_buffer = '0' and fifo_full = '0') then
fifo_cnt <= fifo_cnt + 1 after Tp;
elsif (wr = '0' and release_buffer = '1' and fifo_empty = '0') then
fifo_cnt <= fifo_cnt - length_info(conv_integer(rd_info_pointer)) after Tp;
elsif (wr = '1' and release_buffer = '1' and fifo_full = '0' and fifo_empty = '0') then
fifo_cnt <= fifo_cnt - length_info(conv_integer(rd_info_pointer)) + 1;
elsif (reset_mode = '1') then
fifo_cnt <= (others => '0');
end if;
end if;
end process;
fifo_full <= '1' when fifo_cnt = conv_std_logic_vector(64,7) else '0';
fifo_empty <= '1' when fifo_cnt = conv_std_logic_vector(0 ,7) else '0';
-- Counting data in length_info and overrun_info fifo
process(clk,rst)
begin
if (clk = '1' and clk'event) then
if (rst = '1') then
info_cnt <= (others => '0');
elsif (write_length_info = '1' xor release_buffer = '1') then
if (release_buffer = '1' and info_empty = '0') then
info_cnt <= info_cnt - 1 after Tp;
elsif (write_length_info = '1' and info_full = '0') then
info_cnt <= info_cnt + 1 after Tp;
end if;
end if;
end if;
end process;
info_full <= '1' when info_cnt = conv_std_logic_vector(64,7) else '0';
info_empty <= '1' when info_cnt = conv_std_logic_vector(0 ,7) else '0';
-- writing data to fifo
process(clk)
begin
if (clk = '1' and clk'event) then
if (wr = '1' and fifo_full ='0') then
fifo(conv_integer(wr_pointer)) <= data_in after Tp;
end if;
end if;
end process;
-- Selecting which address will be used for reading data from rx fifo
process(extended_mode,rd_pointer,addr)
begin
if (extended_mode = '1') then -- extended mode
read_address <= rd_pointer + conv_integer((addr - 16));
else -- normal mode
read_address <= rd_pointer + conv_integer((addr - 20));
end if;
end process;
data_out <= fifo(conv_integer(read_address));
end RTL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -