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

📄 can_btl.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_btl is
port (

       clk: in std_logic;
       rst: in std_logic;
       rx : in std_logic;

--   Mode register 
       reset_mode: in std_logic;

-- Bus Timing 0 register 
       baud_r_presc    : in std_logic_vector(5 downto 0);
       sync_jump_width : in std_logic_vector(1 downto 0);

-- Bus Timing 1 register 
       time_segment1   : in std_logic_vector(3 downto 0);
       time_segment2   : in std_logic_vector(2 downto 0);
       triple_sampling : in std_logic;

-- Output from can_bsp module 
       rx_idle           : in std_logic;
       transmitting      : in std_logic;
       last_bit_of_inter : in std_logic;

-- Output signals from this module 
       clk_en        :  out std_logic ;
       sample_point  :  out std_logic ;
       sampled_bit   :  out std_logic ;
       sampled_bit_q :  out std_logic ;
       tx_point      :  out std_logic ;
       hard_sync     :  out std_logic ;
       resync        :  out std_logic);  
end can_btl;

architecture RTL of can_btl is

constant Tp              : time := 1 ns;

signal  clk_cnt          : std_logic_vector(8 downto 0);       
signal  clk_en_reg       : std_logic;        
signal  sync_blocked     : std_logic;  
signal  resync_blocked   : std_logic;
signal  sampled_bit_reg  : std_logic;   
signal  resync_reg       : std_logic;
signal  hard_sync_reg    : std_logic;
signal  quant_cnt        : std_logic_vector(7 downto 0);     
signal  delay            : std_logic_vector(3 downto 0);         
signal  sync             : std_logic;          
signal  seg1             : std_logic;          
signal  seg2             : std_logic;          
signal  resync_latched   : std_logic;
signal  sample           : std_logic_vector(1 downto 0);        
                     
signal  go_sync           : std_logic;       
signal  go_seg1           : std_logic;       
signal  go_seg2           : std_logic;       
signal  preset_cnt        : std_logic_vector(8 downto 0);    
signal  sync_window       : std_logic;   
                      
signal  baud_r_presc_plus_1: std_logic_vector(5 downto 0);

signal  delay_temp          : unsigned(3 downto 0);


 

begin

clk_en       <= clk_en_reg;
resync       <= resync_reg;
hard_sync    <= hard_sync_reg;
sampled_bit  <= sampled_bit_reg;

baud_r_presc_plus_1 <= baud_r_presc + 1;

preset_cnt <= "00"&baud_r_presc_plus_1(5 downto 0)&'0';        -- (BRP+1)*2
hard_sync_reg  <= '1' when (rx_idle = '1' or last_bit_of_inter = '1')  and rx = '0' and sampled_bit_reg = '1' and sync_blocked = '1' and transmitting = '0' else '0';  -- Hard synchronization
resync_reg     <= '1' when rx_idle = '0'                      and rx = '0' and sampled_bit_reg = '1' and  sync_blocked = '0' and resync_blocked = '0' and transmitting = '0' else '0';  -- Re-synchronization


-- Generating general enable signal that defines baud rate. 
process(clk,rst)
begin
if (clk = '1' and clk'event) then
  if (rst = '1') then
    clk_cnt <= (others => '0');
  elsif ((clk_cnt = (preset_cnt-1)) or reset_mode = '1') then
    clk_cnt <= (others => '0') after Tp;
  else
    clk_cnt <= clk_cnt + 1 after Tp;
  end if;
end if;
end process;


process(clk,rst)
begin
if (clk = '1' and clk'event) then
  if (rst = '1') then
    clk_en_reg  <= '0';
  elsif (clk_cnt = (preset_cnt-1)) then
    clk_en_reg  <= '1' after Tp;
  else
    clk_en_reg  <= '0' after Tp;
  end if;
end if;
end process;



-- Changing states 
go_sync <= '1' when clk_en_reg = '1' and (seg2 = '1' and hard_sync_reg = '0' and resync_reg = '0' and (quant_cnt = time_segment2)) else '0';
go_seg1 <= '1' when clk_en_reg = '1' and (sync = '1' or hard_sync_reg = '1' or (resync_reg = '1' and seg2 = '1' and sync_window = '1') or (resync_latched = '1' and sync_window = '1')) else '0';
go_seg2 <= '1' when clk_en_reg = '1' and (seg1 = '1' and hard_sync_reg = '0' and (quant_cnt = (time_segment1 + delay))) else '0';



-- When early edge is detected outside of the SJW field, synchronization request is latched and performed when
-- SJW is reached 
process(clk,rst)
begin
if (clk = '1' and clk'event) then
  if (rst = '1') then
    resync_latched <= '0';
  elsif (resync_reg = '1' and seg2 = '1' and sync_window = '0') then
    resync_latched <= '1' after Tp;
  elsif (go_seg1 = '1') then
    resync_latched <= '0';
  end if;
end if;
end process;



-- Synchronization stage/segment 
process(clk,rst)
begin
if (clk = '1' and clk'event) then
  if (rst = '1') then
    sync <= '0';
  elsif (go_sync = '1') then
    sync <= '1' after Tp;
  elsif (go_seg1 = '1') then
    sync <= '0' after Tp;
  end if;
end if;
end process;


tx_point <= go_sync;

-- Seg1 stage/segment (together with propagation segment which is 1 quant long) 
process(clk,rst)
begin
if (clk = '1' and clk'event) then
  if (rst = '1') then
    seg1 <= '1';
  elsif (go_seg1 = '1') then
    seg1 <= '1' after Tp;
  elsif (go_seg2 = '1') then
    seg1 <= '0' after Tp;
  end if;
end if;
end process;


-- Seg2 stage/segment 
process(clk,rst)
begin
if (clk = '1' and clk'event) then
  if (rst = '1') then
    seg2 <= '0';
  elsif (go_seg2 = '1') then
    seg2 <= '1' after Tp;
  elsif (go_sync = '1' or go_seg1 = '1') then
    seg2 <= '0' after Tp;
  end if;
end if;
end process;


-- Quant counter 
process(clk,rst)
begin
if (clk = '1' and clk'event) then
  if (rst = '1') then
    quant_cnt <= (others =>'0');
  elsif (go_sync = '1' or go_seg1 = '1' or go_seg2 = '1' or reset_mode = '1') then
    quant_cnt <= (others =>'0') after Tp;
  elsif (clk_en_reg = '1') then
    quant_cnt <= quant_cnt + 1 after Tp;
  end if;
end if;
end process;


-- When late edge is detected (in seg1 stage), stage seg1 is prolonged. 
process(clk,rst)
begin
if (clk = '1' and clk'event) then
  if (rst = '1') then
    delay_temp <= (others =>'0');
  elsif (clk_en_reg = '1' and resync_reg = '1' and seg1 = '1') then
    if (quant_cnt > sync_jump_width) then
     delay_temp <= to_unsigned(conv_integer(sync_jump_width),4) + 1 after
Tp;
    else
     delay_temp <= to_unsigned(conv_integer(quant_cnt),4) + 1 after Tp;
    end if;
  elsif (go_sync = '1' or go_seg1 = '1') then
    delay_temp <= (others =>'0');
  end if;
end if;
  delay <= std_logic_vector(delay_temp);
end process;




-- If early edge appears within this window (in seg2 stage), phase error is fully compensated
sync_window <= '1' when((time_segment2 - quant_cnt) < ( sync_jump_width + 1)) else '0';


-- Sampling data (memorizing two samples all the time).
process(clk,rst)
begin
if (clk = '1' and clk'event) then
  if (rst = '1') then
    sample <= "11";
  elsif (clk_en_reg = '1') then
    sample <= sample(0)&rx;
  end if;
end if;
end process;


-- When enabled, tripple sampling is done here.
process(clk,rst)
begin
if (clk = '1' and clk'event) then
  if (rst = '1') then
      sampled_bit_reg   <= '1';
      sampled_bit_q <= '1';
      sample_point  <= '0';
  elsif (clk_en_reg = '1' and hard_sync_reg = '0' ) then
      if (seg1 = '1' and (quant_cnt = (time_segment1 + delay))) then
          sample_point <= '1' after Tp;
          sampled_bit_q <= sampled_bit_reg after Tp;
          if (triple_sampling = '1') then
            sampled_bit_reg <= (sample(0) and sample(1)) or ( sample(0) and rx) or (sample(1) and rx);
          else
            sampled_bit_reg <= rx after Tp;
          end if;
      else
          sample_point <= '0' after Tp;
      end if;
  end if;
end if;
end process;



-- Blocking synchronization (can occur only once in a bit time) 
process(clk,rst)
begin
if (clk = '1' and clk'event) then
  if (rst = '1') then
    sync_blocked <= '0' after Tp;
  elsif (clk_en_reg = '1') then
      if (hard_sync_reg = '1' or resync_reg = '1') then
        sync_blocked <= '1' after Tp;
      elsif (seg2 = '1' and (quant_cnt = time_segment2)) then
        sync_blocked <= '0' after Tp;
      end if;
  end if;
end if;
end process;


-- Blocking resynchronization until reception starts (needed because after reset mode exits we are waiting for
-- end-of-frame and interframe. No resynchronization is needed meanwhile). */
process(clk,rst)
begin
if (clk = '1' and clk'event) then
  if (rst = '1') then
    resync_blocked <= '1' after Tp;
  elsif (reset_mode = '1') then
    resync_blocked <= '1' after Tp;
  elsif (hard_sync_reg = '1') then
    resync_blocked <= '0' after Tp;
  end if;
end if;
end process;

end RTL;





       





⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -