草庐IT

3.5 Verilog 延迟反标注

runoob 2023-03-28 原文

关键词: 延迟反标注, SDF

延迟反标注是设计者根据单元库工艺、门级网表、版图中的电容电阻等信息,借助数字设计工具将延迟信息标注到门级网表中的过程。利用延迟反标注后的网表,就可以进行精确的时序仿真,使仿真更接近实际工作的数字电路。

延迟反标注过程

前面教程中的仿真基本都是功能性的仿真。无论是进行 IC 设计还是 FPGA 开发,时序仿真都是必不可少的。《Verilog 教程》的《1.4 Verilog 设计方法》章节中也描述了完整的数字设计开发流程。

下面,说明延迟反标注在该流程中是怎么使用的,权当复习与巩固。

  • (1) 利用硬件描述语言完成 RTL 层级的描述,进行功能仿真。
  • (2) 对时钟、复位、输出端口等信号进行一定的时序约束,包括时钟频率、时序检查、延迟等信息的设置,并用于逻辑综合。
  • (3) 综合出的门级网表包含各种粗略估计的延迟信息。此时可以进行去除掉 hold、recovery、 removal、interconnect(互联线)等延迟信息,进行初步的时序仿真和静态时序分析 (STA),初步验证 setup 等时序是否满足时序要求。很多公司或个人也会将此步的仿真略过。
  • (4) 对门级网表进行布局布线,转换为版图级网表。根据元器件几何形状和制造工艺等信息可以提取版图电路中的电容和电阻信息,再根据此信息就可以计算出版图中的延迟值。
  • (5)将布局布线后版图中的延迟信息反标到版图级网表中,便可以精确的修改网表中的延迟值。此时再进行时序仿真和 STA,以验证时序是否满足。
  • (6) 如果所有验证均通过,则可以进行下载或实现、生产。如果时序有 violation,首先需要检查时序约束设置,比如延迟参数、时钟频率、信号关系等设置是否有问题,再重新布局布线验证是否能消除 violation。如果上述措施均不能消除 violation,则需要回到设计初始,优化 RTL 的描述。

此过程示意图如下,标黄部分表示数字设计流程中可以增加的操作说明。


SDF 文件

SDF (Standard Delay Format),标准延时格式文件,常用延迟反标注。该文件包含了仿真用到的所有 IOPATH,INTERCONNECT、TIMING CHECK 等延迟时间和时序约束的参数。下面就简单的介绍下 SDF 文件。

文件格式

SDF 文件用关键字 DELAYFILE 声明,并包含 DESIGN、DATE 等关键字信息。

延迟时间和时序约束参数均在 CELL 内说明。

SDF 文件就是由文件声明信息和很多个不同的 CELL 组成的,格式如下。


(DELAYFILE
(DESIGN "top")
(DATE "Love Sep 7 11:11:11 2017")
......
(TIMESCALE 1ns)
(CELL
  ......
)
(CELL
  ......
)
......
)

延迟类型

SDF 文件中的延迟类型包括 cell delay 和 wire delay。cell delay 指逻辑门单元器件内部的延迟,wire delay 是指器件之间通过 wire 互联的延迟。

cell delay 描述如下,定义了 module "and_gate" 中输入端口(A/B)与输出端口(Z)的上升延迟和下降延迟,并指定了最小值和最大值。


(CELL
  (CELLTYPE "and_gate")  //module 名字
  (INSTANCE u_and)       //例化名字,如果多层次访问需要指定访问层次
  (DELAY
    (ABSOLUTE
    (IOPATH A Z (1.5::1.8) (1.3::1.7))  //上升延迟最小值1.5,最大值1.8
    (IOPATH B Z (1.5::1.8) (1.3::1.7))  //下降延迟最小值1.3,最大值1.7
    )
  )
)

wire delay 描述如下,定义了在 module "top" 中,从 u_and 输出端到 u_dt 输入端的上升延迟和下降延迟,并指定了最小值和最大值。

一般 RTL 级仿真或综合出的门级网表是可以忽略 wire delay的,因为后端还需要重新布局布线。布局布线后的网表就接近真实的电路,此时就需要考虑 wire delay。


(CELL
  (CELLTYPE "top") //module 名字
  (INSTANCE)       //如果是顶层设计模块,可忽略例化名字
  (DELAY
    (ABSOLUTE
    (INTERCONNECT u_and.Z u_dt.D (0.500::0.751) (0.400::0.551))
    //(INTERCONNECT u_and/Z u_dt/D (0.500::0.751) (0.400::0.551))
    //层次访问符号,有的编译器支持".",有的编译器支持"/",这里需要注意
    )
  )
)

条件延迟及时序检查

CELL 中还可以用关键字 COND 指定条件延迟。

同时,也可以在 CELL 内做时序检查。

一个 D 触发器的延迟说明及时序检查举例如下。


(CELL
  (CELLTYPE "d_gate")
  (INSTANCE u_dt)
  (DELAY
    (ABSOLUTE
    // D=1时 上升延迟为1.3-2.3, 下降延迟为1.5-2.2
    (COND D==1'b1 (IOPATH CP Q (1.3::2.3) (1.5::2.2)))
    // D=0时 上升延迟为1.2-2.1, 下降延迟为1.4-2.0
    //此处只是为了说明 COND 的用法,D=1时下降延迟参数不可能用到
    //                          D=0时上升延迟参数也不可能用到
    (COND D==1'b0 (IOPATH CP Q (1.2::2.1) (1.4::2.0)))
    )
  )
  (TIMINGCHECK
  (SETUP D (posedge CP) (0.8::1))
  //setup check, D-CP 时间小于0.8或1时,便打印 violation
  )
)

使用方法

Verilog 提供了系统函数 $sdf_annotate 去调用 SDF 文件完成延迟反标注的过程。

使用格式如下:

$sdf_annotate ('sdf_file'[, module_instance] [,'sdf_configfile'][,'sdf_logfile'][,'mtm_spec'] [,'scale_factors'][,'scale_type']);

这里,sdf_file 必须指定,其余参数可选。

这里只对前几个常用的参数进行说明。

  • sdf_file: SDF 文件名字,包含路径信息。
  • module_instance: 例化的设计模块名字,一般为 testbench 中所例化的数字设计模块名称,注意和 SDF 文件内容中的声明保持层次的一致。
  • log_file: 编译时关于 SDF 的日志,方便查阅。
  • mtm_spec: 指定使用的延迟类型,选项包括 MAXIMUM、MINIMUM、TYPICAL,分别表示使用 SDF 文件中标注的最大值、最小值或典型值。当然上述 SDF 文件例子中没有给出典型值。

使用 specify 仿真

下面使用 specify 进行简单的时序仿真,以便与使用 SDF 文件进行时序仿真做对比。

一个用 specify 指定延迟的与门逻辑描述如下:


module and_gate(
   output  Z,
   input   A, B);

   assign Z = A & B ;

   specify
      specparam t_rise = 1.3:1.5:1.7 ;
      specparam t_fall = 1.1:1.3:1.6 ;
      (A, B  *> Z) = (t_rise, t_fall) ;
   endspecify

 endmodule

一个用 specify 指定延迟的 D 触发器描述如下:

实例


module d_gate(
            output      Q ,
            input       D, CP);

   reg                  Q_r ;
   always @(posedge CP)
     Q_r <= D ;
   assign       Q = Q_r ;

   specify
      if (D == 1'b1)
        (posedge CP => (Q +: D)) = (1.3:1.5:1.7, 1.1:1.4:1.9) ;
      if (D == 1'b0)
        (posedge CP => (Q +: D)) = (1.2:1.4:1.6, 1.0:1.3:1.8) ;
      $setup(D, posedge CP, 1);
   endspecify

endmodule

顶层模块描述如下,主要功能是将与逻辑的输出结果输入到 D 触发器进行缓存。

实例


module top(
   output  and_out,
   input   in1, in2, clk);

   wire    res_tmp ;
   and_gate u_and(res_tmp, in1, in2);
   d_gate   u_dt(and_out, res_tmp, clk);

endmodule

testbench 描述如下,仿真时设置 "+maxdelays",使用最大延迟值。

实例


`timescale 1ns/1ps
module test ;
   wire         and_out ;
   reg          in1, in2 ;
   reg          clk ;

   initial begin
      clk = 0 ;
      forever begin
          #(10/2) clk = ~clk ;
      end
   end

   initial begin
      in1 = 0 ; in2 = 0 ;
      # 32 ;
      in1 = 1 ; in2 = 1 ;
      # 13 ;
      in1 = 1 ; in2 = 0 ;
   end

   top   u_top(
               .and_out (and_out),
               .in1     (in1),
               .in2     (in2),
               .clk     (clk));

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

endmodule // test

仿真时序如下所示,由图可知:

  • (1) 与门输入端 A/B 到输出端 Z 的上升延迟为 33.7-32=1.7ns;
  • (2) 与门输出端 Z 到触发器输入端 D 的互联延迟为 0;
  • (3) 触发器 D 端到 CP 端时间差为 35-33.7=1.3ns,大于 setup check 时设置的 1ns,因此时序满足要求,不存在 violation 。
  • (4) 触发器 CP 端到输出端 Q 的上升延迟为 36.7-35=1.7ns;

综上所述,仿真结果符合设计参数。

使用 SDF 仿真

保持关于 SDF 文件的例子中涉及的参数不变,将多个 CELL 说明整合成完整的 SDF 文件,命名为"simple_test.sdf"。

在 testbench 中加入以下语句,将 SDF 文件中的延迟信息反标注到设计的模块 top 中,重新进行时序上的仿真。


   initial begin
      $sdf_annotate("../rtl/simple_test.sdf", u_top, , "sdf.log", "MAXIMUM", ,);
   end

仿真时序及 log 打印信息如下,由图可知:

  • (1) 与门输入端 A/B 到输出端 Z 的上升延迟为 33.8-32=1.8ns;
  • (2) 与门输出端 Z 到触发器输入端 D 的互联延迟为 34.551-33.8= 0.751ns,不再为 0;
  • (3) 触发器 D 端到 CP 端时间差为 35-34.551=0.449ns,小于 setup check 时设置的 1ns,因此时序不满足要求,会打印存在 violation 的信息。
  • (4) 触发器 CP 端到输出端 Q 的上升延迟为 37.3-35=2.3ns;

综上所述,仿真结果符合设计参数,但是时序存在 violation。主要原因是因为与门输入端的数据和触发器时钟是异步不相关的。为解决此类异步问题,请参考下一章节《4 章:同步与异步》。

需要说明的是:

与 specify 块语句相比,SDF 文件还可以指定模块间 wire delay。

一般来说,使用 SDF 文件指定版图级的网表 timing 信息最接近实际数字电路,相比 rtl 或综合出的门级网表,此版本的 timing 是最差的。

SDF 文件指定模块内路径延迟时,原模块的 specify 块必须保留,且 specify 块与 SDF 文件中指定的延迟的条件、类型等均需一致,延迟值可以不同。例如在 specify 块中无条件指定延迟:

(A => Z) = (1.3, 1.7) ;

在 SDF 文件中指定条件延迟:

(COND A==1'b1&&B==1'b1 (IOPATH A Z (1.5::1.8) (1.3::1.7)))

则在编译阶段就会报告"IOPATH from A to Z is not found."的 SDF Warning。SDF 文件设置的延迟是无效的。此处 SDF 文件也应该使用无条件的方法指定路径延迟。

本次只是为了介绍 SDF 文件及其用法而手动编写的 SDF 文件。实际上 SDF 文件都是由设计人员借助 IC 设计工具(例如 PrimeTime)生成的,上一条注意事项也无需太过担心,调试时注意就好。一般数字设计的门级网表数量巨大,人为写 SDF 文件也不切实际。

本章节源码下载

Download

有关3.5 Verilog 延迟反标注的更多相关文章

  1. ruby-on-rails - 在所有延迟的作业之前 Hook - 2

    是否可以在所有delayed_job任务之前运行一个方法?基本上,我们试图确保每个运行delayed_job的服务器都有我们代码的最新实例,所以我们想运行一个方法来在每个作业运行之前检查它。(我们已经有了“check”方法并在别处使用它。问题只是关于如何从delayed_job中调用它。) 最佳答案 现在有一种官方方法可以通过插件来做到这一点。这篇博文通过示例清楚地描述了如何执行此操作http://www.salsify.com/blog/delayed-jobs-callbacks-and-hooks-in-rails(本文中描述

  2. Verilog使用inout信号的方法 - 2

    目录一、inout在设计文件中的使用方法1.1、inout的第一种使用方法1.2、inout实现的第二种使用方法1.3、inout使用总结 二、inout在仿真测试中的使用方法一、inout在设计文件中的使用方法在FPGA的设计过程中,有时候会遇到双向信号(既能作为输出,也能作为输入的信号叫双向信号)。比如,IIC总线中的SDA信号就是一个双向信号,QSPIFlash的四线操作的时候四根信号线均为双向信号。在Verilog中用关键字inout定义双向信号,这里总结一下双向信号的处理方法。1.1、inout的第一种使用方法  实际上,双向信号的本质是由一个三态门组成的,三态门可以输出高电平,低电

  3. ruby - Heroku - 如何开始工作人员(延迟工作)? - 2

    我有一些使用delayed_job的小程序。在我的本地主机上一切正常,但是当我将我的应用程序部署到Heroku并单击应该由delayed_job执行的链接时,没有任何反应,“任务”只是保存到表delayed_job中。Inthisarticleonherokublog写入时,执行delayed_job表中的任务,当运行此命令时rakejobs:work。但是我怎样才能运行这个命令呢?命令应该放在哪里?在代码中,还是从终端控制台? 最佳答案 如果您正在运行Cedar堆栈,请从终端控制台运行以下命令:herokurunrakejobs:

  4. ruby-on-rails - 成功发送延迟作业电子邮件后更新用户表 - 2

    我是一个尝试使用delayed_job的NOOB。我想在使用延迟作业成功发送邮件后更新用户模型。发送邮件:UserMailer.delay.welcome_email(user)如果邮件发送成功,请执行以下操作:User.update_attributes(:emailed=>true)邮件发送成功后如何回调或触发? 最佳答案 您需要创建一个Job对象而不是调用#delay帮助程序。您可以使用successHook来执行回调。classWelcomeEmailJob 关于ruby-on-

  5. ruby-on-rails - 启动同一作业的多个延迟作业进程 - 2

    我在运行多个工作器的设置中使用延迟作业。就我的问题而言,这并不重要,但假设我有10个worker(目前在开发模式下这样做)。我遇到的问题是两个不同的工作人员有时会开始处理同一个工作,调用我的工作对象的perform方法。据我所知,DelayedJob正在使用悲观锁定来防止这种情况发生,但有时它似乎仍然有足够的时间在第一个worker有时间实际锁定它之前锁定它。我只是想看看有没有其他人遇到过这个问题,或者是我的设置有问题。我正在使用Postrgres,这发生在我的开发机器和我托管它的Heroku上。我会尝试在我的工作中解决这个问题,但发生这种情况仍然有点问题。理想情况下,延迟作业永远不会

  6. ruby - 延迟作业每次引发错误时都会创建空气制动器 - 2

    defperformrefund_log={success:refund_retry.success?,amount:refund_amount,action:"refund"}ifrefund_retry.success?refund_log[:reference]=refund_retry.transaction.idrefund_log[:message]=refund_retry.transaction.statuselserefund_log[:message]=refund_retry.messagerefund_log[:params]={}refund_retry.er

  7. ruby-on-rails - 定期延迟工作 - 2

    我正在使用DelayedJob来管理后台工作。但是我有一些任务需要定期执行。例如每小时、每天或每周。现在,当我执行任务时,我会创建一个新任务,在一天/一周/一个月内执行。不过我不是很喜欢。如果由于任何原因,任务没有完全执行,我们不会创建下一个任务,我们可能会失去任务的执行。您如何在Rails应用程序中管理此类事情(延迟作业)以确保您的常规任务列表保持正确? 最佳答案 如果你可以访问Cron,我强烈推荐Wheneverhttp://github.com/javan/whenever您指定要运行什么以及在简单的ruby​​中以什么频率运

  8. iphone - 扩展 restful_authentication/AuthLogic 以支持匿名 iPhone 的延迟登录的最佳方法是什么? - 2

    我正在构建一个与RubyonRails后端对话的iPhone应用程序。RubyonRails应用程序还将为Web用户提供服务。restful_authentication插件是提供快速和可定制的用户身份验证的绝佳方式。但是,我希望iPhone应用程序的用户在新列中存储一个由手机的唯一标识符([[UIDevicedevice]uniqueIdentifier])自动创建的帐户。稍后,当用户准备好创建用户名/密码时,帐户将更新为包含用户名和密码,iPhone唯一标识符保持不变。用户在设置用户名/密码之前不能访问该网站。然而,他们可以使用iPhone应用程序,因为该应用程序可以使用它的标识符

  9. ruby-on-rails - 我如何找到特定的延迟工作(不是通过 id)? - 2

    Delayed::Job将您的类、方法和参数序列化到处理程序字段中。我们目前求助于将这种序列化方法硬编码到我们的代码中。这太恶心了。我们应该如何构建处理程序以便我们可以查找现有的排队作业? 最佳答案 这是我做的:1)添加两个新列到delayed_jobs表db/migrations/20110906004963_add_owner_to_delayed_jobs.rbclassAddOwnerToDelayedJobs2)添加多态关联到Delayed::Job模型config/initializers/delayed_job.rbc

  10. ruby - 如何在 ruby 中产生延迟 - 2

    如何在ruby中产生延迟?我使用了sleep语句,但它没有给我想要的东西。puts"amit"sleep(10)puts"scj"我希望它先打印amit,然后延迟10秒,然后打印scj。但在上述情况下,它会暂停10秒,然后同时打印amit和scj。我不想这样。我希望你明白我想说的。 最佳答案 我无法重现这个。在控制台中,这完全符合您的预期:puts"amit"sleep10puts"scj"(Linux上的Ruby1.8.6)您能否提供一个类似的简短但完整的示例,该示例没有做您想要的-或者更多地解释您的上下文?如果您正在编写Web应

随机推荐