【Xilinx FPGA】异步 FIFO 的复位

FIFO(First-In-First_Out,先入先出)是一种的存储器类型,在 FPGA 开发中通常用于数据缓存、位宽转换或者跨时钟域(多 bit 数据流)。在使用异步 FIFO 时,应注意复位信号是否遵循相关要求和规范,避免数据丢失或损坏。本文主要介绍 Xilinx FPGA 对异步 FIFO 复位的时序要求,并参考 IP 核示例工程设计异步 FIFO 的复位逻辑。

目录

[1 复位类型](#1 复位类型)

[2 异步 FIFO 的复位](#2 异步 FIFO 的复位)


1 复位类型

Xilinx FIFO Generator 提供了复位端口,用于复位计数器与输出寄存器。有两种复位的类型:同步复位(Synchronous Reset)和异步复位(Asynchronous Reset)。

对于同步复位方式,由于复位信号已经是同步的,因此无需设计额外的同步逻辑。

The asynchronous reset (rst) input asynchronously resets all counters, output registers, and memories when asserted. When reset is implemented, it is synchronized internally to the core with each respective clock domain for setting the internal logic of the FIFO to a known state. This synchronization logic allows for proper timing of the reset logic within the core to avoid glitches and metastable behavior.

对于异步复位方式,复位信号会分别被同步到读/写时钟域,同步逻辑确保 FIFO 正确复位,避免"毛刺"或者亚稳态。

异步复位应遵循以下 2 个设计规则:

(1)复位必须在所有时钟有效时进行,否则 FIFO 的状态无法预测;

(2)复位信号的脉宽至少为 3 个慢时钟周期。

在复位期间,应避免对 fifo 进行读写操作,以防止数据丢失或损坏。在复位完成后,需要等待一段时间才能对 fifo 进行读写操作。

开启 Safety Circuit 的 FIFO,复位释放之后需至少等待 60 个慢时钟周期。

未开启 Safety Circuit 的 FIFO,复位释放之后需至少等待 30 个慢时钟周期。

2 异步 FIFO 的复位

打开 IP 核自带的 Example Design,参考激励文件异步 FIFO 的复位逻辑。

在 reset 释放之后 50 个写周期,释放 reset_ext 信号。reset 连接到 FIFO 的异步复位端口,reset_ext 则用于读/写控制逻辑的复位。

在 Example Design 的顶层文件中,将 reset_ext 信号分别同步到读/写时钟域。这里不知道是不是参考工程的错误,rst_async_rd1 ~ rst_async_rd3 使用了同步复位,异步释放的方式。

以下是根据参考工程,自己设计的异步 FIFO 的复位控制逻辑。

复制代码
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity eth_rx_adjust is
   port(
      -- System level
      nRst                : in std_logic;
      sysclk              : in std_logic;

      -- GMII IN data port
      --gmii_rxd_rxctl    : in std_logic_vector(9 downto 0);
      --gmii_rxc          : in std_logic;
      eth_phy_rxd         : in std_logic_vector(7 downto 0);
      eth_phy_rxdv        : in std_logic;
      eth_phy_rxc         : in std_logic;

      -- eth_rx data
      eth_rxd_sys         : out std_logic_vector(7 downto 0);
      eth_rxdv_sys        : out std_logic
   );
end entity;
architecture behav of eth_rx_adjust is
-- internal component and signal declarations
component fifo_8bit_2048 is
   port(
      din                 : in std_logic_vector(7 downto 0);
      wr_en               : in std_logic;
      wr_clk              : in std_logic;
      full                : out std_logic;
      dout                : out std_logic_vector(7 downto 0);
      rd_en               : in std_logic;
      rd_clk              : in std_logic;
      empty               : out std_logic;
      rst                 : in std_logic;
      wr_data_count       : out std_logic_vector(10 downto 0);
      rd_data_count       : out std_logic_vector(10 downto 0)
   );
end component;

signal reset              : std_logic := '1';
signal reset_cnt          : std_logic_vector(5 downto 0) := (others => '0');
signal reset_ext_cnt      : std_logic_vector(5 downto 0) := (others => '0');
signal RESET_EXT          : std_logic := '1';
signal rst_async_wr1      : std_logic := '1';
signal rst_async_wr2      : std_logic := '1';
signal rst_async_wr3      : std_logic := '1';
signal rst_async_rd1      : std_logic := '1';
signal rst_async_rd2      : std_logic := '1';
signal rst_async_rd3      : std_logic := '1';
signal rst_int_wr         : std_logic := '1';
signal rst_int_rd         : std_logic := '1';

signal eth_fifo_wdata     : std_logic_vector(7 downto 0);
signal eth_fifo_wrreq     : std_logic;
signal eth_fifo_empty     : std_logic;
signal eth_fifo_rcnt      : std_logic_vector(10 downto 0);
signal eth_fifo_rdreq     : std_logic;
signal eth_fifo_rdata     : std_logic_vector(7 downto 0);
signal eth_fifo_rdvld     : std_logic;

attribute ASYNC_REG: string;
attribute ASYNC_REG of rst_async_wr1: signal is "true";
attribute ASYNC_REG of rst_async_wr2: signal is "true";
attribute ASYNC_REG of rst_async_wr3: signal is "true";

attribute ASYNC_REG of rst_async_rd1: signal is "true";
attribute ASYNC_REG of rst_async_rd2: signal is "true";
attribute ASYNC_REG of rst_async_rd3: signal is "true";

---------------------------------------------------------
begin
---------------------------------------------------------

process(nRst,eth_phy_rxc) 
begin
   if nRst = '0' then
      reset_cnt <= "000000";
   elsif rising_edge(eth_phy_rxc) then
      if reset_cnt < "001000" then
         reset_cnt <= reset_cnt + '1';
      else
         reset_cnt <= reset_cnt;
      end if;
   end if;
end process;

process(nRst,eth_phy_rxc) 
begin
   if nRst = '0' then
      reset <= '1';
   elsif rising_edge(eth_phy_rxc) then
      if reset_cnt < "001000" then
         reset <= '1';
      else
         reset <= '0';
      end if;
   end if;
end process;

process(reset,eth_phy_rxc) 
begin
   if reset = '1' then
      reset_ext_cnt <= "000000";
   elsif rising_edge(eth_phy_rxc) then
      if reset_ext_cnt < "110010" then
         reset_ext_cnt <= reset_ext_cnt + '1';
      else
         reset_ext_cnt <= reset_ext_cnt;
      end if;
   end if;
end process;

process(reset,eth_phy_rxc) 
begin
   if reset = '1' then
      RESET_EXT <= '1';
   elsif rising_edge(eth_phy_rxc) then
      if reset_ext_cnt < "110010" then
         RESET_EXT <= '1';
      else
         RESET_EXT <= '0';
      end if;
   end if;
end process;

-- Asynchronous reset, synchronous release for rst_async_wr1, rst_async_wr2, rst_async_wr3
process(RESET_EXT,eth_phy_rxc) 
begin
   if RESET_EXT = '1' then
      rst_async_wr1 <= '1';
      rst_async_wr2 <= '1';
      rst_async_wr3 <= '1';
   elsif rising_edge(eth_phy_rxc) then
      rst_async_wr1 <= RESET_EXT;
      rst_async_wr2 <= rst_async_wr1;
      rst_async_wr3 <= rst_async_wr2;
   end if;
end process;

-- Asynchronous reset, synchronous release for rst_async_rd1, rst_async_rd2, rst_async_rd3
process(RESET_EXT,sysclk) 
begin
   if RESET_EXT = '1' then
      rst_async_rd1 <= '1';
      rst_async_rd2 <= '1';
      rst_async_rd3 <= '1';
   elsif rising_edge(sysclk) then
      rst_async_rd1 <= RESET_EXT;
      rst_async_rd2 <= rst_async_rd1;
      rst_async_rd3 <= rst_async_rd2;
   end if;
end process;

rst_int_wr <= rst_async_wr3;
rst_int_rd <= rst_async_rd3;

--===============================================================
-- eth_fifo_inst
eth_fifo_instx: component fifo_8bit_2048
port map(
   din             => eth_fifo_wdata     , -- in std_logic_vector(7 downto 0)
   wr_en           => eth_fifo_wrreq     , -- in std_logic
   wr_clk          => eth_phy_rxc        , -- in std_logic
   full            => open               , -- out std_logic
   dout            => eth_fifo_rdata     , -- out std_logic_vector(7 downto 0)
   rd_en           => eth_fifo_rdreq     , -- in std_logic
   rd_clk          => sysclk             , -- in std_logic
   empty           => eth_fifo_empty     , -- out std_logic
   rst             => reset              , -- in std_logic
   wr_data_count   => open               , -- out std_logic_vector(10 downto 0)
   rd_data_count   => eth_fifo_rcnt        -- out std_logic_vector(10 downto 0)
);

process(rst_int_wr,eth_phy_rxc) 
begin
   if rst_int_wr = '1' then
      eth_fifo_wdata <= (others => '0');
      eth_fifo_wrreq <= '0';
   elsif rising_edge(eth_phy_rxc) then
      eth_fifo_wdata <= eth_phy_rxd;
      eth_fifo_wrreq <= eth_phy_rxdv;
   end if;
end process;

process(rst_int_rd,sysclk) 
begin
   if rst_int_rd = '1' then
      eth_fifo_rdreq <= '0';
      eth_fifo_rdvld <= '0';
   elsif rising_edge(sysclk) then
      if eth_fifo_rcnt > 6 then
         eth_fifo_rdreq <= '1';
      elsif eth_fifo_rcnt = 1 then
         eth_fifo_rdreq <= '0';
      end if;
      eth_fifo_rdvld <= eth_fifo_rdreq;
   end if;
end process;

process(rst_int_rd,sysclk) 
begin
   if rst_int_rd = '1' then
      eth_rxd_sys <= (others => '0');
      eth_rxdv_sys <= '0';
   elsif rising_edge(sysclk) then
      eth_rxd_sys <= eth_fifo_rdata;
      eth_rxdv_sys <= eth_fifo_rdvld;
   end if;
end process;
end architecture;
相关推荐
LabVIEW开发1 天前
LabVIEW FPGA 编程:少编译几次的办法(系列 04/05)
fpga开发·labview
cmc10281 天前
318.关于在ip内部封装PLL,MMCM的注意事项
fpga开发
LabVIEW开发2 天前
LabVIEW CompactRIO 编程模式怎么选(系列 02/05)
fpga开发·labview
FPGA工程笔记2 天前
Xilinx Divider Generator IP 实战:64位有符号除法、Fractional 输出解析与定点数转换
verilog·fpga·vivado·xilinx·定点数·divider gen·fractional
FPGA小迷弟2 天前
FPGA 与千兆以太网校验和:从原理到 Verilog 实现
嵌入式硬件·fpga开发·无人机·ai编程·fpga
码农小韩3 天前
FPGA学习(二)——LED闪烁
fpga开发·verilog·fpga·led·组合逻辑·分频设计
9527华安4 天前
FPGA纯verilog实现DP视频接口,支持2K60帧分辨率,提供3套工程源码和技术支持
fpga开发·音视频·dp
ChaseVLSI4 天前
FPGA与ASIC的区别详解:内部结构、开发成本与适用场景,项目选型到底该选哪个
嵌入式硬件·fpga开发·硬件架构·硬件工程
9527华安5 天前
FPGA实现ARINC818总线协议,基于GT Transceivers Wizard高速收发器,提供7套工程源码和技术支持
fpga开发·transceivers·arinc818
小蘇的FPGA5 天前
fpga-wide-data-crc32
fpga开发