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

📄 can_fifo.vhd

📁 一个基于can_bus的虚拟程序
💻 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 + -