• dff寄存器setup hold演示


    一、关于DFF的构成

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

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

    当D端为0,CLK为0时,此时第一级的D锁存器输出为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的理解

    相对容易理解,前一级寄存器的上一周期的q,也就是自己的din的最后变化时间,并不代表数据在LAT2一定可以稳定。在LAT1第一级NAND2上有变化所需时间,在LAT1第二级NAND2上还有稳定时间,所以 LAT1 构成setup time的主体。因此,setup time是能够让LAT2稳定获得正确状态的时间。

    关于hold time的理解

    另一种情况,在同一时钟周期的时钟上升沿,前一级寄存器q端特别快地到达了D端,后一级寄存器的LAT1的关闭和锁存,被影响到了,也会造成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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125

    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态。

  • 相关阅读:
    springboot2.0+springcloud 版本冲突解决方案
    NPM配置阿里云(淘宝)镜像仓库
    3.1虚拟化和安装Docker
    爱奇艺向抖音开启授权,打开内容价值的新大门
    关于 LLM 和知识图谱、图数据库,大家都关注哪些问题呢?
    JUC并发编程——读写锁(基于狂神说的学习笔记)
    java线程实现服务器与客户端互发消息
    VMware 配置记录
    面试百问:如何提高自动化测试脚本稳定性
    OpenFeign实现分析、源码解析
  • 原文地址:https://blog.csdn.net/zt5169/article/details/126490875