Verilog 时序检查

news2025/2/26 5:50:00

setup    hold     recovery     removal     width     period

指定路径延迟,目的是让仿真的时序更加接近实际数字电路的时序。利用时序约束对数字设计进行时序仿真,检查设计是否存在违反(violation)时序约束的地方,并加以修改,也是数字设计中不可或缺的过程。

Verilog 提供了一些系统任务,用于时序检查。这些系统任务只能在 specify 块中调用。下面就介绍 6 种常用的用于时序检查的系统任务:$setup, $hold, $recovery, $removal, $width 与 $period

$setup, $hold

系统任务 $setup 用来检查设计中元件的建立时间约束条件,$hold 用来检查保持时间约束条件。其用法格式如下:

$setup(data_event, ref_event, setup_limit);
  • data_event: 被检查的信号,判断它是否违反约束
  • ref_event: 用于检查的参考信号,一般为时钟信号的跳变沿
  • setup_limit: 设置的最小建立时间

如果 T( ref_event - data_event) < setup_limit, 则会打印存在 violation 的报告。

$hold(ref_event, data_event, hold_limit);
  • data_event: 被检查的信号,判断它是否违反约束
  • ref_event: 用于检查的参考信号,一般为时钟信号的跳变沿
  • hold_limit: 设置的最小保持时间

如果 T( data_event - ref_event ) < hold_limit, 则会打印存在 violation 的报告。

注意: $setup 和 $hold 输入端口的位置是不同的。

Verilog 提供了同时检查建立时间和保持时间的系统任务

$setuphold (ref_event, data_event, setup_limit, hold_limit);

下面完成一个数乘以 15 的操作,来说明 $setup 和 $hold 的用法。

Verilog 中,一个变量乘以常数一般用移位相加的方法来完成,例如对变量 num 乘以 15 的操作可以表示为:

num x 15 = (num << 3) + (num << 2) + (num << 1) + num

此操作需要 3 个加法器。下面对加法器进行建模,并指定路径延迟。

实例

//单 bit 全加器,指定路径延迟
module full_adder1(
   input   Ai, Bi, Ci,
   output  So, Co);

   assign So = Ai ^ Bi ^ Ci ;
   assign Co = (Ai & Bi) | (Ci & (Ai | Bi));

   specify
      (Ai, Bi, Ci *> So) = 1.1 ;
      (Ai, Bi     *> Co) = 1.3 ;
      (Ci         => Co) = 1.2 ;
   endspecify
endmodule

//8bit 位宽加法器例化
module full_adder8(
     input [7:0]   a ,   //adder1
     input [7:0]   b ,   //adder2
     input         c ,   //input carry bit
     output [7:0]  so ,  //adding result
     output        co    //output carry bit
     );

   wire [7:0]      co_temp ;
   full_adder1  u_adder0(
                         .Ai     (a[0]),
                         .Bi     (b[0]),
                         .Ci     (c==1'b1 ? 1'b1 : 1'b0),
                         .So     (so[0]),
                         .Co     (co_temp[0]));

   genvar          i ;
   generate
      for(i=1; i<=7; i=i+1) begin: adder_gen
         full_adder1  u_adder(
                              .Ai     (a[i]),
                              .Bi     (b[i]),
                              .Ci     (co_temp[i-1]),
                              .So     (so[i]),
                              .Co     (co_temp[i]));
      end
   endgenerate
   assign co    = co_temp[7] ;
endmodule

8bit 位宽的触发器描述如下。触发器中指定路径延迟,并加入建立时间和保持时间的时序检查。

建立时间设置为 2ns,保持时间设置为 3ns。

实例

module D8(
    input       [7:0]   d ,
    input               clk ,
    output reg [7:0]    q);

   always @(posedge clk)
     q <= d ;
   specify
      $setup(d, posedge clk, 2);
      $hold(posedge clk, d, 3);
      (d,clk *> q) = 0.3 ;
   endspecify
endmodule

在 testbench 里完成乘以 15 的操作,并在一个周期内输出给下一级寄存器。

实例

`timescale 1ns/1ns
module test ;
   reg  [3:0]   a ;
   reg  [3:0]   b ;
   wire [3:0]   so ;
   wire         co ;

   parameter    CYCLE_10NS = 10ns;
   reg          clk ;
   initial begin
      clk = 0 ;
      # 111 ;
      forever begin
          #(CYCLE_10NS/2) clk = ~clk ;
      end
   end

   //需要乘以 15 的数
   reg [7:0]    num = 0 ;
   always @(posedge clk) begin
      num[3:0] <= num[3:0] + 1 ;
   end

   // num * 8 + num * 4
   wire [7:0]    adder1 ;
   full_adder8  u1_adder8(
               .a      (num<<2),
               .b      (num<<3),
               .c      (1'b0),
               .so     (adder1),
               .co     ());
   //num * 2 + num
   wire [7:0]    adder2 ;
   full_adder8  u2_adder8(
               .a      (num<<1),
               .b      (num),
               .c      (1'b0),
               .so     (adder2),
               .co     ());
   //num x 15
   wire [7:0]    adder3 ;
   full_adder8  u3_adder8(
               .a      (adder1),
               .b      (adder2),
               .c      (1'b0),
               .so     (adder3),
               .co     ());
   
   //store the result
   wire [7:0]    res_mul15 ;
   D8   data_store(
               .d       (adder3),
               .clk     (clk),
               .q       (res_mul15));

   initial begin
      forever begin
         #100;
         if ($time >= 1000)  $finish ;
      end
   end
endmodule // test

仿真报告中则出现了带有 setup/hold violation 的打印信息,部分截图如下。

截取出现 violation 时间的波形图,如下所示。

分析如下:

  • (1) 建立时间和保持时间均出现了 violation,虽然仿真中变量 num 乘以 15 以后延迟一个时钟周期的输出结果是正确的,但实际电路是很危险的。
  • (2) 波形中信号的建立时间 166-164.4 = 1.6 ns,小于设置的 2ns,所以会报告 violation。
  • (3) 波形中信号的保持时间 168.2-166 = 2.2 ns,小于设置的 3ns,所以会报告 violation。
  • (4) 图中红色部分是信号 d 变化的中间过程,因为信号各 bit 延迟不同,所以中间可能会出现多个不同的结果。

时序优化

保持时间的时序优化,在 RTL 层级描述上一般不好控制,这属于后端设计工程师的工作范畴,这里不做讨论。本次主要简单探讨建立时间不满足约束条件时的优化问题。由上一节《3.3 建立时间和保持时间》中可知建立时间约束表达式为:

Tcq + Tcomb + Tsu <= Tclk + Tskew (1)
  • Tcq: 寄存器 clock 端到 Q 端的延迟;
  • Tcomb: data path 中的组合逻辑延迟;
  • Tsu: 建立时间;
  • Tclk: 时钟周期;
  • Tskew: 时钟偏移。

优化此不等式可从以下几个方面考虑:

  • (1) 选取时序较好的工艺原件,其 Tcq 和 Tsu 值越小越好;
  • (2) 优化组合逻辑,使组合逻辑延迟 Tcomb 越小越好;
  • (3) 降低工作时钟频率,增大工作时钟周期 Tclk;
  • (4) 增加时钟偏移 Tskew,但时钟偏移过大又会造成其他问题,例如保持时间可能不满足,功能逻辑错误等。

从 RTL 层次进行时序优化时,只能考虑方法(2)(3)。

例如,将上述仿真中的工作时钟周期由 10ns 改为 20ns,则不会出现 setup violation。

或者,调整逻辑,一个周期内完成 3 次加法运算,改为分散到两个周期内完成,中间增加一级寄存器进行缓冲,来减少时序上的压力。同时,变量 num 的变化周期也应该变为原来的 2 倍时长。

testbench 修改如下:

实例

`timescale 1ns/1ns
`define LOGIC_BUF
module test ;
   parameter    CYCLE_10NS = 10ns;
   reg          clk ;
   initial begin
      clk = 0 ;
      # 111 ;
      forever begin
          #(CYCLE_10NS/2) clk = ~clk ;
      end
   end

   reg          slow_flag = 0 ;
   always @(posedge clk) begin
`ifdef LOGIC_BUF
      slow_flag <= ~slow_flag ;
`else
      slow_flag <= 1'b1 ;
`endif
   end

   reg  [7:0]    num = 0 ;
   always @(posedge clk) begin
      if(slow_flag)
        num[3:0] <= num[3:0] + 1 ;
   end

   wire [7:0]    adder1 ;
   full_adder8  u1_adder8(
               .a      (num<<2),
               .b      (num<<3),
               .c      (1'b0),
               .so     (adder1),
               .co     ());

   wire [7:0]    adder2 ;
   full_adder8  u2_adder8(
               .a      (num<<1),
               .b      (num),
               .c      (1'b0),
               .so     (adder2),
               .co     ());

   //====== for better time=========
   //adding buffer
   wire [7:0]    adder1_r, adder2_r ;
   D8   adder1_buf(
               .d       (adder1),
               .clk     (clk),
               .q       (adder1_r));
   D8   adder2_buf(
               .d       (adder2),
               .clk     (clk),
               .q       (adder2_r));

`ifdef LOGIC_BUF
   wire [7:0]         adder1_t       = adder1_r ;
   wire [7:0]         adder2_t       = adder2_r ;
`else
   wire [7:0]         adder1_t       = adder1 ;
   wire [7:0]         adder2_t       = adder2 ;
`endif

   wire [7:0]    adder3 ;
   full_adder8  u3_adder8(
               .a      (adder1_t),
               .b      (adder2_t),
               .c      (1'b0),
               .so     (adder3),
               .co     ());

   wire [7:0]    res_mul15 ;
   D8   data_store(
               .d       (adder3),
               .clk     (clk),
               .q       (res_mul15));

   initial begin
      forever begin
         #100;
         if ($time >= 1000)  $finish ;
      end
   end

endmodule // test

此时仿真报告中不再有 violation,仿真截图如下。

由图可知,信号提前到达并保持不变的时间可达 8.6 ns,完全满足建立时间的时序要求。

此种方法的根本原理,是将信号多次变化的时序,分散在多个周期内,来满足时序约束的要求。此外,流水线设计,并行设计等都可以优化时序。

$recovery, $removal

建立时间和保持时间的概念都是出现在同步电路的设计中。对于异步复位的触发器来说,异步复位信号也需要满足 recovery time(恢复时间)和 removal time(去除时间),才能有效的复位和释放复位,防止出现亚稳态。释放复位时,复位信号在时钟有效沿来临之前就需要提前一段时间恢复到非复位状态,这段时间为 recovery time。类似于同步时钟下触发器的 setup time。复位时,复位信号在时钟有效沿来临之后,还需要在一段时间内保持不变,这段时间为 removal time。类似于同步时钟下触发器的 hold time。recovery 与 removal time 示意图如下所示。

系统任务 $recovery 与 $removal 分别用于 recovery 和 removal time 的检查,用法如下:

$recovery (ref_event, data_event, recovery_limit) ;
  • ref_event: 用于检查的参考信号,一般为清零或复位信号跳变沿;
  • data_event: 被检查的信号,一般为时钟信号跳变沿。
  • recovery_limit:设置的最小 recovery time。

当 ref_event (reset) < data_event (clock) 且 T(data_event - ref_event) < recovery_limit 时,即复位信号在时钟信号到来之前如果不满足 recovery time,则报告中会打印 violation。

$removal (ref_event, data_event, removal_limit) ;
  • ref_event: 用于检查的参考信号,一般为清零或复位信号跳变沿;
  • data_event: 被检查的信号,一般为时钟信号跳变沿。
  • removal_limit:设置的最小 removal time。

当 ref_event (reset) > data_event (clock) 且 T(ref_event - data_event) > removal_limit 时,即复位信号在时钟信号到来之后如果不满足 removal time,则报告中会打印 violation。

Verilog 提供了同时检查 revomal 和 recovery 的系统任务:

$recrem (ref_event, data_event, recovery_limit, removal_limit);

$width, $period

有些数字设计,例如 flash 存储器,还需要对脉冲宽度或周期进行检查,为此 Verilog 分别提供了系统任务 $width 和 $period。用法如下:

$width(ref_event, time_limit) ;
  • ref_event: 边沿触发事件
  • time_limit: 脉冲的最小宽度

$width 用于检查边沿触发事件 ref_event 到下一个反向跳变沿之间的时间,常用于脉冲宽度的检查。如果两次相反跳边沿之间的时间小于 time_limit,则会报告 violation。

$period(ref_event, time_limit) ;

$period 用于检查边沿触发事件 ref_event 到下一个同向跳变沿之间的时间,常用于时钟周期的检查。如果两次同向跳边沿之间的时间小于 time_limit,则报告中会打印 violation。

检查信号 CLK 宽度和周期的 specify 块描述如下:

实例

   specify
      $width(posedge CLK, 10);  
      $period(posedge CLK, 20);
   endspecify

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/39472.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

鲲鹏devkit开发套件——编译调试工具介绍

鲲鹏devkit编译调试工具介绍 编译调试插件是其中的一个子工具。编译调试插件即插即用&#xff0c;支持一键安装服务器鲲鹏编译器&#xff0c;支持单机下Nvidia GPU应用调试能力&#xff0c;通过统一调试界面调试GPU应用&#xff0c;实现cuda-gdb调试能力&#xff0c;以及鲲鹏平…

Spring Security 使用JSON格式参数登录的两种方式

前言 在 Spring Security 中&#xff0c;默认的登陆方式是以表单形式进行提交参数的。可以参考前面的几篇文章&#xff0c;但是在前后端分离的项目&#xff0c;前后端都是以 JSON 形式交互的。一般不会使用表单形式提交参数。所以&#xff0c;在 Spring Security 中如果要使用…

python3-turtle(1)

turtle 是海龟绘图模块&#xff0c;海龟绘图很适合用来引导孩子学习编程&#xff0c;最初构想来自于 Wally Feurzeig, Seymour Papert 和 Cynthia Solomon 于 1967 年所创造的 Logo 编程语言&#xff0c;它是基于tkinter 模块打造&#xff0c;提供简单的绘图方法。 turtle模块假…

集合框架----源码解读ArrayList篇

1.ArrayList<E> ArrayList是继承AbstractList<E> List 接口的可调整数组实现。实现所有可选的列表操作&#xff0c;并允许所有元素&#xff0c;包括null。除了实现List接口之外&#xff0c;该类还提供了一些方法来操作内部用于存储列表的数组的大小。(这个类大致相…

准备蓝桥杯的宝贝们看过来,二分法一网打尽(基础篇)

今天给大家介绍一下简单的二分法&#xff08;刷题第一步&#xff01;&#xff09; 二分基础题链接 二分查找有个很明显的特点就是有序&#xff0c;这个特点同学如果在题中看到就要格外注意 一定要看完&#xff0c;基本的三种解法&#xff0c;后面还有真题链接哦&#xff01;…

异步请求-AJAX

什么是同步交互 首先用户向HTTP服务器提交一个处理请求。接着服务器端接收到请求后&#xff0c;按照预先编写好的程序中的业务逻辑进行处理&#xff0c;比如和数据库服务器进行数据信息交换。最后&#xff0c;服务器对请求进行响应&#xff0c;将结果返回给客户端&#xff0c;返…

TCP三次握手与四次挥手

TCP三次握手的建立与四次挥手的过程 TCP协议 TCP 用于处理实时通信TCP是基于端口&#xff0c;面向连接的传输层协议TCP的握手和挥手本质上都是四次&#xff0c;只不过握手合并成三次。因为主机之间要想通信需要先建立双向数据通道TCP的主要特点是传输稳定性高&#xff0c;但是…

[自建题库]c认证初级

UTF-8的编码实现方式有几种? UTF8-1 / UTF8-2 / UTF8-3 / UTF8-4 二进制数1111.1111转换成十进制数是多少&#xff1f; 如果二进制数字“1000111______”采取偶校验&#xff0c;那么下划线的校验位处应该填什么&#xff1f; 0 在MPEG-4中&#xff0c;第九部分定义了IP网络传…

JS高级-语言特性(持续更新一)

JS高级-语言特性 JS高级-语言特性 一、JS面向对象编程 1.1面向对象介绍 1.2面向对象编程 1.3创建对象 二、构造函数 2.1构造函数 2.2构造函数存在的问题 三、原型 3.1构造函数的prototype属性 3.2构造函数、实例、原型三者之间的关系 3.3原型对象的获取及修改 3.4原…

[附源码]Python计算机毕业设计高校电子作业提交与批改系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;我…

CTFHub | Refer注入

0x00 前言 CTFHub 专注网络安全、信息安全、白帽子技术的在线学习&#xff0c;实训平台。提供优质的赛事及学习服务&#xff0c;拥有完善的题目环境及配套 writeup &#xff0c;降低 CTF 学习入门门槛&#xff0c;快速帮助选手成长&#xff0c;跟随主流比赛潮流。 0x01 题目描述…

[C#] GDI+ 之鼠标交互:原理、示例、一步步深入、性能优化

一、前言 “GDI”与“鼠标交互”&#xff0c;乍一听好像不可能&#xff0c;也无从下手&#xff0c;但是实现原理比想象中要简单很多。 基于“GDI”的“交互”&#xff0c;应用场景也很多&#xff0c;比如&#xff1a;流程图、数据图表、思维导图等等。 本篇文章就通过多个示例…

美新科技IPO过会:9个月营收6亿 林东融三兄弟为实控人

雷递网 雷建平 11月26日美新科技股份有限公司&#xff08;简称&#xff1a;“美新科技”&#xff09;日前IPO过会&#xff0c;准备在深交所创业板上市。美新科技计划募资9.58亿元&#xff0c;其中&#xff0c;5.1亿元用于美新科技新型环保塑木型材产业化项目&#xff08;一期&a…

基于HTML+CSS+JavaScript制作学生网页——外卖服务平台10页带js 带购物车

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | HTML期末大学生网页设计作业 HTML&#xff1a;结构 CSS&#xff1a;样式 在操作方面上运用了html5和css3&#xff0c; 采用了divcss结构、表单、超链…

[附源码]SSM计算机毕业设计拾穗在线培训考试系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

JS逆向 Frida - 夜神模拟器安装配置 基本使用

JS逆向 Frida - 夜神模拟器安装配置 基本使用 文章目录JS逆向 Frida - 夜神模拟器安装配置 基本使用前言一、Frida简单介绍&#xff1f;1.Frida是什么2.Frida原理(建议了解一下&#xff0c;否则后续的安装会有些懵懂)二、Frida下载1.pip安装frida模块2.查看本地的frida版本&…

大数据项目之电商数仓DataX、DataX简介、DataX支持的数据源、DataX架构原理、DataX部署

文章目录1. DataX简介1.1 DataX概述1.2 DataX支持的数据源2. DataX架构原理2.1 DataX设计理念2.2 DataX框架设计2.3 DataX运行流程2.4 DataX调度决策思路2.5 DataX与Sqoop对比3. DataX部署3.1 下载DataX安装包并上传到hadoop102的/opt/software3.2 解压datax.tar.gz到/opt/modu…

一、微服务入门

文章目录一、微服务大概认识二、单体架构架构和分布式架构三、微服务架构特征四、微服务技术对比五、SpringCloud 与 SpringBoot版本兼容关系如下&#xff1a;一、微服务大概认识 二、单体架构架构和分布式架构 单体架构&#xff1a;将业务的所有功能集中在一个项目中开发&…

一文弄懂 Diffusion Model

什么是 Diffusion Model 一、前向 Diffusion 过程 Diffusion Model 首先定义了一个前向扩散过程&#xff0c;总共包含T个时间步&#xff0c;如下图所示&#xff1a; 最左边的蓝色圆圈 x0 表示真实自然图像&#xff0c;对应下方的狗子图片。 最右边的蓝色圆圈 xT 则表示纯高斯…

Tomcat安装及配置和常见的问题(2022最新详解、图文教程)

Tomcat的配置安装1. 关于WEB服务器软件2. 配置Tomcat的服务器第一步&#xff1a;配置Java的运行环境第二步&#xff1a;Tomcat的安装第三步&#xff1a;启动Tomcat3. 问题一&#xff1a;解决Tomcat服务器在DOS命令窗口中的乱码问题&#xff08;控制台乱码&#xff09;4. 测试To…