FPGA 异步复位同步释放 详解

上次芯动面试官问到了这个问题,回答的比较草率,这次把这个问题总结一下

首先分析一下什么是异步复位,同步复位

同步复位:只有在时钟沿到来时复位信号才起作用。

缺点是复位信号持续的时间应该超过一个时钟周期才能保证系统复位

异步复位:复位信号与时钟沿是否到来无关。

缺点是复位信号容易受到毛刺的影响。并且如果复位结束时刻恰在亚稳态窗口内时,就无法正常复位

所以为了避免同步复位和异步复位的缺点,就产生了一种“异步复位同步释放”的复位方式

异步复位同步释放:

当异步复位有效时,复位信号立刻复位

信号释放时,会在时钟上升沿来临时,才可以恢复

用一个例题来看看代码实现:使用异步复位同步释放来将输入数据a存储到寄存器中

 FPGA 异步复位同步释放 详解_第1张图片

clk为时钟,rst_n为低电平复位,d信号输入,dout信号输出

步骤是:

(1)缓存复位信号,打2拍

(2)数据输出时复位信号选择打两拍之后的复位信号

代码如下:

`timescale 1ns/1ns
module example(
input clk,
input rst_n,
input d,
output reg dout
 );
  reg [1:0] rst_reg;
  //缓存rst并打2拍
  always@(posedge clk or negedge rst_n) begin
    if(!rst_n)
      rst_reg <= 2'b0;
    else
      rst_reg <= {rst_reg[0],1'b1};
  end
  
  always@(posedge clk or negedge rst_reg[1]) begin
    if(!rst_reg[1])//这里用打两拍之后的复位信号
      dout <= 1'b0;
    else
      dout <= d;
  end
  
endmodule

 TB:

module tb;
reg  clk,rst_n,d;
wire dout;
 	 re dut(.clk(clk),
         .rst_n(rst_n),
            .d(d),
            .dout(dout));
   
     initial begin
      clk = 0;
      forever begin
        #5
        clk = ~clk;
      end
    end
  
    initial begin
      rst_n = 0;
      #8
      rst_n = 1;
      #200
      $stop();
    end
  
    initial begin
      d = 0;
      #10 d = 1;
      #10 d = 0;
      #15 d = 1;
    end
  endmodule : tb

可以看出,dout在rst_reg[1]为低时没有输出数据,在rst_reg[1]为高时输出数据

FPGA 异步复位同步释放 详解_第2张图片

你可能感兴趣的:(fpga开发)