dff寄存器setup hold演示

一、关于DFF的构成

我们将 DFF内部 分成 两个主要部分 LAT1(包括前4个nand2),LAT2(包括后4个nand2)。LAT1前两个NAND2我们成为LAT1的门,
LAT2前两个NAND2我们成为LAT2的门。

以上升沿触发为例,进一步分析D触发器在上升沿捕获数据,并维持锁存的过程。

当D端为0,CLK为0时,此时第一级的SR锁存器输出为0,第二级SR锁存器处于保持状态(图1)
在这里插入图片描述

若继续保持D端为0,CLK变为1时,第一级D锁存器处于保持状态,第二级的SR锁存器将上一次的D值传递到Q端输出(图2)
在这里插入图片描述

若在D端数值发生改变为1,且CLK仍然为1,第一级的D锁存器仍处于保持状态,不会由于D端的变化而改变,
更不会影响最后Q端的输出。(图3)
在这里插入图片描述

若D端继续保持为1,CLK转换为0,此时第一级D锁存器的输出为D端的数据,Q端输出仍为保持状态;(图4)
在这里插入图片描述

关于setup time的理解

当信号传递比较慢时,可能发生setup违例。
从LAT1的角度看,clk0时,LAT1一直可以接收上一个数据的变化,clk变1的瞬间,LAT1的门关闭,这段clk posedge附近的时间就是setup time。clk1时,不再接收数据的变化。这样,(1)LAT1关门之前,完成变化,这是我们期望的,(2)LAT1关门之后,一定不能进入LAT1,这也是我们期望的,(3)信号变化遇上LAT1正好关门,则属于不确定,也许进入了 LAT1,也许没有进入LAT1,这是我们希望避免的。
setup 问题,是前一级寄存器上一个周期的稳定值,经过组合逻辑,能否在当前周期稳定地进入LAT1。

关于hold time的理解

当信号传递特别快时,可能发生hold违例。
从LAT1的角度看,clk变1的瞬间,LAT1有可能接收前一级当拍数据的变化,LAT1的门关闭前,前一级的当拍数据已经进入到本级寄存器,这段clk posedge附近的时间也是hold time。这样,(1)LAT1关门之前,完成了不期望的变化,这是我们希望避免的,(2)LAT1关门之后,一定不能进入LAT1,这也是我们期望的,(3)当拍信号变化遇上LAT1正好关门,则属于不确定,也许进入了 LAT1,也许没有进入LAT1,这也是我们希望避免的。
hold,在同一时钟周期的时钟上升沿,前一级寄存器q端特别快地到达了D端,后一级寄存器的LAT1的关闭前,锁存了前一级当前周期的值,最终LAT2的状态不正确。

二、关于DFF setup hold的仿真

1)结构为 dff1–>dff2,

从 dff2检查相对于dff1的setup,hold。称为第一组。通过 rtl的延时写法,仿真可以报告vio,但是波形没有x态。
为了演示的清晰,增加一组 prim_dff1 --> prim_dff2,激励相同。称为第二组。通过原语的写法,仿真可以报告vio,波形也有x态。
第一组,是为了看清楚DFF结构,第二组是为了看清楚violation。

// nand_1 -- nand_2
// nand_3 -- nand_4

primitive violated_dff (q, v, clk, d, xxx);
	output q;
	reg q;
	input v, clk, d, xxx;

	table
		*  ?   ? ? : ? : x;
		? (x1) 0 0 : ? : 0;
		? (x1) 1 0 : ? : 1;
		? (x1) 0 1 : 0 : 0;
		? (x1) 1 1 : 1 : 1;
		? (x1) ? x : ? : -;
		? (bx) 0 ? : 0 : -;
		? (bx) 1 ? : 1 : -;
		? (x0) b ? : ? : -;
		? (x0) ? x : ? : -;
		? (01) 0 ? : ? : 0;
		? (01) 1 ? : ? : 1;
		? (10) ? ? : ? : -;
		?  b   * ? : ? : -;
		?  ?   ? * : ? : -;
	endtable
endprimitive


module d_lat(clk,s,r,q,qn);
    input clk, s, r;
    output q, qn;

    nand #2   u_nand_1(nand_1_o, s,clk);     
    nand #2   u_nand_2(nand_2_o,nand_1_o, nand_4_o);     
    nand #2   u_nand_3(nand_3_o,r, clk);     
    nand #2   u_nand_4(nand_4_o,nand_2_o, nand_3_o);

    buf #1 u_buf_q ( q,nand_2_o);
    buf #1 u_buf_qn(qn,nand_4_o);

endmodule

module mydff(clk,d,q,qn);
    input clk,d;
    reg notifier;
    output q,qn;

    not #1 u_clk_r(clk_r,clk);
    not #1 u_d_r(d_r,d);
    d_lat u_lat1(clk_r,d,d_r,q1,qn1);
    d_lat u_lat2(clk,q1,qn1,q,qn);

    specify
    specparam tsetup = 1.5, thold = 1.5;
    $setuphold(posedge clk, posedge d,tsetup,thold,notifier);
    $setuphold(posedge clk, negedge d,tsetup,thold,notifier);
    endspecify

endmodule

module prim_dff(clk,d,q,qn);

	output q,qn;
	input d, clk;
	reg notifier;
	wire delayed_D, delayed_CK;

	// Function
	wire int_q, unstable;

	violated_dff (int_q, notifier, delayed_CK, delayed_D, unstable);
	buf u_buf (q, int_q);
    not #1 u_not_qn (qn,q);

	specify
		(posedge clk => (q+:d)) = 3;
		$setuphold (posedge clk, posedge d, 1.5, 1.5, notifier,,, delayed_CK, delayed_D);
		$setuphold (posedge clk, negedge d, 1.5, 1.5, notifier,,, delayed_CK, delayed_D);
	endspecify

endmodule


module tb_top;
    bit clk;
    logic din;
    logic dq1_dly, dq1p_dly;
    logic dq1, dqn1, dq1p, dqn1p;
    
    integer dly1,dly2;

    initial begin
        clk = 1'b0;
        forever
           #(10) clk = ~clk; 
    end

    initial begin
        din = 1'b0;

        forever begin
           @(posedge clk); 
           dly1 = {$random}%20;
           dly2 = {$random}%20;
           //$display("dly1 is %0d", dly1);
           fork 
               begin #(dly1) din = ~din; end 
               begin #(dly2) dq1_dly = dq1; end
               begin #(dly2) dq1p_dly = dq1p; end
           join
        end
    end
    
    initial begin
      $fsdbDumpvars;
      $fsdbDumpon;
        #100us $finish;
    end

    mydff u_dff1(clk,din,dq1,dqn1);
    mydff u_dff2(clk,dq1_dly,dq2,dqn2);
 
    prim_dff u_p_dff1(clk,din,dq1p,dqn1p);
    prim_dff u_p_dff2(clk,dq1p_dly,dq2p,dqn2p);
endmodule

2)setup/hold的检查,是针对谁呢?

dff1/dff2都是clk/d之间检查,但是从clock cycle的角度看,则是:
setup 检查 前一个寄存器的前一个时钟,到本寄存器的本时钟周期。(前后周期)
hold检查前一个寄存器的本时钟周期,到本寄存器的本时钟周期。(同一周期)

先分析 dff setup time违例
假设 nand2 delay 2ns buf/ inverter delay 1ns(为了方便演示,假设很大,实际上很小)setup = 1.5ns, hold = 1.5ns
在这里插入图片描述每个竖线处,都是一个DFF1 setup违例。

在这里插入图片描述
上图出DFF2的setup 违例,d–>clk 1ns < 1.5ns,因为 clk->q 3ns,所以x出现在4ns之后。

其次,分析 dff hold time 违例
在这里插入图片描述由于输入相同,在双线处,dff1和prim_dff1都发生setuo violation(1ns < 1.5 hold time),只是dff1仅打印报告,没有x态。

  • 0
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值