0

我正在制作定制硬件 ARINC 429 Core。现在我已经描述了传输中的模块(TX-FSM),根据 ARINC 429 标准和传输中的 FIFO,它从中获取数据并将它们发送到外部。FIFO 以 2MHz (clk2M) 的频率工作,而 TX-FSM 可以根据标准从 2MHz 生成 100kb/s 或 12.5kb/s (clk429) 的频率。

由于 FIFO 工作在较高频率(2 MHz),而 TX-FSM 工作在较低频率(100 kb/s),当 TX-FSM 通过提高“TX_FIFO_rd”信号(“ rd_en" on FIFO ),FIFO 提供其中包含的所有数据,因为在 FIFO 时钟域中,"rd_en" 信号在几个周期内保持高电平。

FIFO 一次只能提供一个数据。数据传输完毕后,TX-FSM 将请求下一个数据。

如何使用单个时钟使 FIFO 和 TX-FSM 同步工作?

FIFO VHDL代码:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity FIFO is
  generic (
    FIFO_WIDTH          : natural := 32;
    FIFO_DEPTH          : integer := 10;
    ALMOST_FULL_LEVEL   : integer := 8;
    ALMOST_EMPTY_LEVEL  : integer := 2
    );
  port (
    reset    : in std_logic;
    clk      : in std_logic;        
 
    -- FIFO Write Interface
    wr_en           : in  std_logic;
    wr_data         : in  std_logic_vector(FIFO_WIDTH-1 downto 0);
    ALMOST_FULL     : out std_logic;
    FULL            : out std_logic;
 
    -- FIFO Read Interface
    rd_en           : in  std_logic;
    rd_data         : out std_logic_vector(FIFO_WIDTH-1 downto 0);
    ALMOST_EMPTY    : out std_logic;
    EMPTY           : out std_logic
    );
    
end FIFO;

architecture rtl of FIFO is
 
  type t_FIFO_DATA is array (0 to FIFO_DEPTH) of std_logic_vector(FIFO_WIDTH-1 downto 0);
  signal r_FIFO_DATA : t_FIFO_DATA := (others => (others => '0'));
 
  signal r_WR_INDEX   : integer range 0 to FIFO_DEPTH -1 := 0;
  signal r_RD_INDEX   : integer range 0 to FIFO_DEPTH -1 := 0;
 
  -- # Words in FIFO, has extra range to allow for assert conditions
  signal r_FIFO_COUNT : integer range -1 to FIFO_DEPTH+1 := 0;
 
  signal w_FULL  : std_logic;
  signal w_EMPTY : std_logic;
  
   
begin

-- FIFO process
-------------------------------------------------------------------
-------------------------------------------------------------------

 WRITE_INDEX : process(clk)
  begin
    if rising_edge(clk) then
      if reset = '1' then
        r_WR_INDEX <= 1;
      else
        if (wr_en = '1' and w_FULL = '0') then
          if r_WR_INDEX = FIFO_DEPTH-1 then
            r_WR_INDEX <= 1;
          else
            r_WR_INDEX <= r_WR_INDEX + 1;
          end if;
        end if;
      end if;
    end if;
  end process;
 
 READ_INDEX : process(clk)
  begin
    if rising_edge(clk) then
      if reset = '1' then
        r_RD_INDEX <= 0;
      else      
         if (rd_en = '1' and w_EMPTY = '0') then
            if r_RD_INDEX = FIFO_DEPTH-1 then
                r_RD_INDEX <= 0;
            else
                r_RD_INDEX <= r_RD_INDEX + 1;
            end if;
         end if;
      end if;
    end if;
  end process;
  
 COUNT_INDEX : process(clk)
  begin
    if rising_edge(clk) then
      if reset = '1' then
        r_FIFO_COUNT <= 0;
      else
        if (wr_en = '1' and rd_en = '0') then
          r_FIFO_COUNT <= r_FIFO_COUNT + 1;
        elsif (wr_en = '0' and rd_en = '1') then
            if r_FIFO_COUNT > 0 then
                r_FIFO_COUNT <= r_FIFO_COUNT - 1;
            end if;
        end if;
      end if;
    end if;
  end process;

  Write_Data : process (clk) is
    begin
        if rising_edge(clk) then
            if wr_en = '1' then
                r_FIFO_DATA(r_WR_INDEX) <= wr_data;
            end if;
        end if;                          
  end process;
 
   
  rd_data <= r_FIFO_DATA(r_RD_INDEX);
 
  w_FULL  <= '1' when r_FIFO_COUNT = FIFO_DEPTH else '0';
  w_EMPTY <= '1' when r_FIFO_COUNT = 0       else '0';
 
  ALMOST_FULL <= '1' when r_FIFO_COUNT > ALMOST_FULL_LEVEL else '0';
  ALMOST_EMPTY <= '1' when r_FIFO_COUNT < ALMOST_EMPTY_LEVEL else '0';
   
  FULL  <= w_FULL;
  EMPTY <= w_EMPTY;
   
end rtl;

TX-FSM 代码

-- Arinc 429 trasmitter interface

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Tx is
    port 
        (
            --INPUT
            clk2M        : in std_logic;                        -- clock signal
            reset        : in std_logic;                        -- reset signal
            enable       : in std_logic;                        -- enable signal
            en_parity    : in std_logic;                        -- enable parity bit
            parity       : in std_logic;                        -- odd/even parity
            speed        : in std_logic;                        -- speed 100kbps or 12.5kbps    
            gap          : in std_logic;                        -- gap between two messages: 4 or 64 bit of gap
            TX_FIFO_ep   : in std_logic;                        -- TX FIFO EMPTY
            a429TX_in    : in std_logic_vector (31 downto 0);   -- data in
            
            --OUTPUT
            a429TX_outA  : out std_logic;                       -- positive out
            a429TX_outB  : out std_logic;                       -- negative out
            TX_FIFO_rd   : out std_logic                        -- TX FIFO READ
        );
        
end entity;

architecture RTL_A429TX of Tx is

-- FSM state name
type state_type is (IDLE,START, PAR,TRANSMITTING,WAITING);
signal state                : state_type;   
-- FSM register
signal shift_reg            : std_logic_vector (31 downto 0);   
signal shift_counter        : std_logic_vector (4 downto 0);
signal gap_counter          : std_logic_vector (6 downto 0);
-- speed clock register
signal clk429            : std_logic;
signal clk429_counter    : integer;
signal clk429_max_count  : integer;
signal clk429_half_count : integer;


begin
-- speed clock process
-------------------------------------------------------------------
-------------------------------------------------------------------
-- select speed process
process (speed)
    begin
        if (speed = '1') then
            clk429_max_count <= 19;         -- 100kbs/s
            clk429_half_count <= 10;
        else
            clk429_max_count <= 159;        -- 12.5kbs/s
            clk429_half_count <= 80;
        end if;
end process;

-- clock429 generate speed process          
process (clk2M, reset)
    begin
            if (reset = '1') then   
                clk429 <= '0';
            elsif rising_edge(clk2M) then
                    if (clk429_counter <= clk429_half_count ) then
                        clk429 <= '1';
                    else
                        clk429 <= '0';
                   end if;
            end if;
end process;

-- counter activity process
process (clk2M, reset)
    begin
        if (reset = '1') then   
            clk429_counter <= 0;
        elsif rising_edge(clk2M) then
                if (clk429_counter >= clk429_max_count) then
                    clk429_counter <= 0;
                else
                    clk429_counter <= clk429_counter + 1;
                end if;
        end if;
end process;
-------------------------------------------------------------------
-------------------------------------------------------------------

-- a429TX interface process
process (clk429, reset)
    variable p : std_logic;
    begin
        if reset = '1' then
            state           <= IDLE;
            shift_reg       <= (others => '0');
            shift_counter   <= (others => '0');
            gap_counter     <= (others => '0');
            a429TX_outA     <= '0';
            a429TX_outB     <= '0';
            TX_FIFO_rd      <= '0';
        elsif rising_edge(clk429) then
                case state is
                    when IDLE           =>  -- idle state
                                                if (enable = '1') then
                                                    if (gap = '1') then 
                                                        gap_counter <= "0000100"; -- 4 
                                                    else
                                                        gap_counter <= "1000000"; -- 64
                                                    end if;
                                                    if TX_FIFO_ep = '0' then
                                                        TX_FIFO_rd <= '1';
                                                        state <= START;
                                                    else
                                                        state <= IDLE;
                                                    end if;
                                                else
                                                    state <= IDLE;
                                                end if;     
                    when START          =>
                                                -- data formatting 
                                                TX_FIFO_rd <= '0';
                                                shift_reg <= a429TX_in(31 downto 8)& a429TX_in(0) & a429TX_in(1) & a429TX_in(2) & a429TX_in(3) & a429TX_in(4) & a429TX_in(5) & a429TX_in(6) & a429TX_in(7);
                                                shift_counter <= "11111";
                                                if ( en_parity = '1') then
                                                    state <= PAR;
                                                else
                                                    state <= TRANSMITTING;
                                                end if;
                                                    
                    when PAR            =>  -- parity state
                                                --TX_FIFO_rd <= '0';
                                                p := '0';
                                                for I in 31 downto 0 loop
                                                    p := p xor shift_reg(I);
                                                end loop;
                                                if (parity = '1') then
                                                    shift_reg(31) <= p;      -- odd
                                                else
                                                    shift_reg(31) <= not p;  -- even
                                                end if;
                                                state <= TRANSMITTING;
                                                
                    when TRANSMITTING   =>  -- transmission state
                                                --TX_FIFO_rd <= '0';
                                                a429TX_outA <= shift_reg(0);
                                                a429TX_outB <= not shift_reg(0);
                                                shift_reg <= shift_reg(0) & shift_reg(31 downto 1);
                                                if (shift_counter = "00000") then
                                                    state <= WAITING;
                                                else
                                                    shift_counter <= shift_counter -1;
                                                    state <= TRANSMITTING;
                                                end if;
                        
                    when WAITING        =>  -- wait state. generate gap
                                                a429TX_outA <= '0';
                                                a429TX_outB <= '0';
                                                if (gap_counter > 0) then
                                                    gap_counter <= gap_counter - 1;
                                                    state <= WAITING;
                                                else
                                                    state <= IDLE;
                                                end if;
                                                                                
                    when others         =>  -- default
                                                state <= IDLE;
                    end case;
        elsif falling_edge (clk429) then
            a429TX_outA <= '0';
            a429TX_outB <= '0';
        end if;
    end process;
    
    clk429 <= clk429;
end architecture; 

谢谢你的帮助。

4

1 回答 1

0

以 2 MHz 运行两个 FIFO clk2M,然后在需要 FIFO 读取数据传输时在 TX_FIFO_rd 上生成单周期启用指示。

因此,您可以从同步设计中获益,而无需处理多个时钟域。

clk429此外,生成像 而是制作一个在单个周期内置位的使能信号,在 上运行设计clk2M,并且仅在使能信号为高电平时更新相关状态。

于 2022-01-04T16:22:49.953 回答