FPGA | 延迟模型

news2024/9/22 6:48:27

实际逻辑元器件和它们之间的传输路径都会存在延迟。因此,必须检查设计中的延迟是否满足实际电路的时序约束要求。可以用时序仿真的方法来检查时序(timing),即在仿真时向元件或路径中加入和实际相符的延迟信息,并进行相关计算来确定时序是否满足。

静态时序分析 (Static Timing Analysis, STA),也是一种时序验证的技术。它不关心逻辑功能的正确与否,只对设计中的时序进行计算分析,来确定电路中是否存在违反(violation) 时序约束的设计。STA 分析速度快,能够快速定位问题,但会忽略一些异步的问题。

所以 "STA + 时序仿真"是一种相对完善且安全的时序验证方法。

延迟模型

**延迟模型主要有 3 种:**分布延迟、集总延迟(lumped) 和路径延迟。

分布延迟

分布延迟需要给电路中每个独立的元件进行延迟定义,不同的路径有不同的延时,如下图所示。

分布延迟的 Verilog 模型和例化逻辑门单元并指定延迟值的方式基本一致。也可以使用连续赋值语句 assign 说明分布延迟。

集总延迟

集总延迟是将全部路径累计的延时集中到最后一个门单元上。

到最后一个门单元上的延迟会因路径的不同而不同,此时取最大延时作为最后一个门单元的延时。

将上述分布延迟图转化为集总延迟图,如下所示。

路径延迟

路径延迟是对每个输入引脚到每个输出引脚的所有路径指定延迟时间。

路径延迟示意图如下。

路径延迟模型需要用关键字 specify 来定义。

module and4(
   output       out,
   input        a, b, c, d);

   specify
      (a => out) = 2.5 ;
      (b => out) = 2.5 ;
      (c => out) = 3.5 ;
      (d => out) = 3.5 ;
   endspecify

   wire         an1, an2 ;
   and          (an1, a, b);
   and          (an2, c, d);
   and          (out, an1, an2);
endmodule

延迟模型比较

  • 分布延迟:分布延迟将延迟时间分散在了每一个门单元上,但仍然不能描述基本单元中不同引脚上延时的差异。当设计规模变大时,结构将变的复杂。
  • 集总延迟:该方式模型简单,适用于小规模的电路,但是不能描述输入端到输出端不同路径的延迟。
  • 路径延迟:指定了引脚到引脚的延迟,延迟信息比较齐全。虽然信息比较多,但对于大规模电路也更容易实现。因为设计者无需关心模块内部的实现逻辑,只需要了解输入到输出引脚的延迟即可。即便模块内部逻辑有所改变,路径延迟的说明也可以保持不变。

所以,大多数逻辑门单元库中的延迟信息,都是以路径延迟的方式给出的。很多集成模块,也可以从其数据手册中直接获取到路径延迟,十分方便。

specify 块语句

路径延迟用关键字 specify 和 endspecify 描述,关键字之间组成 specify 块语句。

specify 是模块中独立的一部分,不能出现在其他语句块(initial, always 等)中。

specify 块语句主要有以下功能:

  • 指定所有路径中引脚到引脚的延迟;
  • 定义 specparam 常量;
  • 在电路中设置时序检查。

并行连接

每条路径都有一个源引脚和目的引脚,将这些路径的延迟依次用 specify 语句描述出来,称为并行连接。

并行连接用法格式如下:

(<source_io> => <destination_io>) = <delay_value> ;
实例
module and4(
   output       out,
   input        a, b, c, d);

   specify
      specparam ab_2_out = 2.5 ;
      specparam cd_2_out = 3.5 ;
     
      (a => out) = ab_2_out ;
      (b => out) = ab_2_out ;
      (c => out) = cd_2_out ;
      (d => out) = cd_2_out ;
   endspecify
   wire         an1, an2 ;
   and          (an1, a, b);
   and          (an2, c, d);
   and          (out, an1, an2);
endmodule

可以用关键字 specparam 在 specify 块中定义延迟数值常量,然后赋值给路径延迟。

specparam 定义的常量只能在 specify 块内部使用

并行连接中,源引脚和目的引脚是一一对应的。并行连接也支持多位宽信号间的路径延迟描述,但是位宽必须保持一致。其中,specify 块语句也可以展开描述,两种表达方式是等效的。

全连接

在全连接中,源引脚中的每一位与目标引脚的每一位相连接。

源引脚和目的引脚的连接是组合遍历的,且不要求位宽对应。

全连接用法格式如下:

(<multiple_source_io> *> <multiple_destination_io>) = <delay_value> ;
module and4(
   output       out,
   input        a, b, c, d);

   specify
      (a,b *> out) = 2.5 ;
      (c,d *> out) = 3.5 ;
   endspecify

   wire         an1, an2 ;
   and          (an1, a, b);
   and          (an2, c, d);
   and          (out, an1, an2);
endmodule

边沿敏感路径

边沿敏感路径用于输入到输出延迟的时序建模,并使用边缘标识符指明触发条件。如果没有指明的话,任何变化都会触发源引脚到目的引脚的延迟值的变化。

用法举例如下:

    //在 clk 上升沿,从 clk 到 out 的路径上升延迟为 1,下降延迟为 2
    //从 in 到 out 的数据路径是同向的,即 out = in
    (posedge clk => (out +: in)) = (1,2);
   
    //在 clk 下降沿,从 clk 到 out 的路径上升延迟为 1,下降延迟为 2
    //从 in 到 out 的数据路径是反向的,即 out = ~in
    (negedge clk => (out -: in)) = (1,2);
   
    //clk 任意变化时,从 clk 到 out 的路径上升延迟为 1,下降延迟为 2
    //从 in 到 out 的数据路径是不可以预知的,同向、反向或不变
    (negedge clk => (out : in)) = (1,2);

条件路径

Verilog 也允许模型中根据信号值的不同,有条件的给路径延迟进行不同的赋值。

条件中的操作数可以是标量,也可以是向量,条件表达式也可以包含任意操作符。

需要注意的是,应当只使用 if 语句将条件路径中所有的输入状态都完整的声明。没有声明的路径会使用分布延迟,分布延迟也没有声明的话,将使用零延迟。如果路径延迟和分布延迟同时声明,将选择最大的延迟作为路径延迟。

但是 specify 中的 if 语句不能使用 else 结构,可以使用 ifnone 描述条件缺省时的路径延迟。

specify
      if (a)    (a => out) = 2.5 ;
      if (~a)   (a => out) = 1.5 ;

      if (b & c)        (b => out) = 2.5 ;
      if (!(b & c))     (b => out) = 1.5 ;

      if ({c, d} == 2'b01)
                (c,d *> out) = 3.5 ;
      ifnone    (c,d *> out) = 3 ;
   endspecify

门延迟路径

门延迟(上升延迟、下降延迟、关断延迟)的数值也可以通过路径延迟的方法来描述。

可以定义的延迟路径个数为 1 个,2 个,3 个,6 个, 12 个,其他数量的延迟值都是错误的。

下面举例说明门延迟模型中路径延迟的表示方法。

//1 个参数: 上升、下降、关断延迟只使用一个延迟参数
   specify
      specparam t_delay = 1.5 ;
      (clk => q) = t_delay ;
   endspecify

   //2 个参数: 上升延迟(0->1, z->1, 0->z)= 1.5
   //         下降延迟(1->0, z->0, 1->z)= 2
   specify
      specparam t_rise = 1.5, t_fall = 2 ;
      (clk => q) = (t_rise, t_fall) ;
   endspecify
 
   //3 个参数: 上升延迟(0->1, z->1)= 1.5
   //         下降延迟(1->0, z->0)= 2
   //         关断延迟(1->z, 0->z)= 1.8
   specify
      specparam t_rise = 1.5, t_fall = 2, t_turnoff = 1.8 ;
      (clk => q) = (t_rise, t_fall, t_turnoff);
   endspecify

   //6 个参数: 分别对应0->1, 1->0, 0->z, z->1, 1->z, z->0
   specify
      specparam t_01 = 1.5, t_10 = 2,   t_0z = 1.8 ;
      specparam t_z1 = 2,   t_1z = 2.2, t_z0 = 2.1 ;
      (clk => q) = (t_01, t_10, t_0z, t_z1, t_1z, t_z0) ;
   endspecify

   //12 个参数: 分别对应0->1, 1->0, 0->z, z->1, 1->z, z->0
   //                 0->x, x->1, 1->x, x->0, x->z, z->x
   specify
      specparam t_01 = 1.5, t_10 = 2,   t_0z = 1.8 ;
      specparam t_z1 = 2,   t_1z = 2.2, t_z0 = 2.1 ;
      specparam t_0x = 1.1, t_x1 = 1.2, t_1x = 2.1 ;
      specparam t_x0 = 2,   t_xz = 2  , t_zx = 2.1 ;

      (clk => q) = (t_01, t_10, t_0z, t_z1, t_1z, t_z0,
                    t_0x, t_x1, t_1x, t_x0, t_xz, t_zx) ;
   endspecify
//门路径延迟模型中,也可以指定最大值、最小值和典型值。
//上升、下降和关断延的延迟值:min: typical: max
   specify
      specparam t_rise    = 1:1.5:1.8;
      specparam t_fall    = 1:1.8:2 ;
      specparam t_turnoff = 1.1:1.2:1.3 ;
      (clk => q) = (t_rise, t_fall, t_turnoff);
   endspecify

X 传输延迟

如果没有指定 x 转换时间的延迟(门路径延迟中没有给出 12 个延迟参数),则规定:

  • 从 x 转换为已知状态的延迟时间为,可能需要的最大延迟时间;
  • 从已知状态转换为 x 的延迟时间为,可能需要的最小延迟时间。

例如,当门路径延迟中给出 6 个延迟参数时,则 x 传输延迟时间定义如下表所示:

x 转换延迟值
0->xmin(t_01, t_0z)
1->xmin(t_10, t_1z)
z->xmin(t_z1, t_z0)
x->0max(t_10, t_z0)
x->1max(t_01, t_z1)
x->zmax(t_1z, t_0z)

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

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

相关文章

4.34、组播(多播)

4.34、多播 1.组播(多播)的介绍①组播地址②如何设置组播&#xff08;组播的使用&#xff09; 2.代码编写①服务端②客户端 1.组播(多播)的介绍 单播地址标识单个 IP 接口&#xff0c;广播地址标识某个子网的所有 IP 接口&#xff0c;多播地址标识一组 IP 接口。单播和广播是寻…

ThreadPoolExecutor原理剖析

1.前言 1.1 为什么要使用线程池&#xff1f; 线程池主要为了解决两个问题 一是当执行大量异步任务时&#xff0c;线程池能够提供较好的性能&#xff0c;避免了重复创建和销毁线程带来的开销二是线程池提供了一种资源限制和管理的手段&#xff0c;比如限制线程个数&#xff0…

【蓝桥杯】最难算法没有之一· 动态规划真的这么好理解?(引入)

欢迎回到&#xff1a;遇见蓝桥遇见你&#xff0c;不负代码不负卿&#xff01; 目录 一、何为动态规划DP 二、记忆化搜索 典例1.斐波那契数列 方法一&#xff1a;暴力递归 方法二&#xff1a;记忆化搜索 变形题 典例2&#xff1a;爬楼梯&#xff08;青蛙跳台阶&#xf…

海睿思分享 | 低而不LOW的低代码开发

低代码&#xff08;Low-Code&#xff09; 是指输出最少的代码&#xff0c;快速完成软件系统开发&#xff0c;进而实现降低开发成本的成效。 Low-Code 中的“Low”与网络热词“LOW”同音同字&#xff0c;前者通常理解为低成本或少量的代码输出&#xff0c;后者是对低认知已见问…

【数据结构】数据结构小试牛刀之单链表

【数据结构】数据结构小试牛刀之单链表 一、目标二、实现1、初始化工作2、单链表的尾插2.1、图解原理2.2、代码实现解答一个疑问 3、单链表的尾删3.1、图解原理3.2、代码实现 4、打印单链表5、单链表的头插5.1、图解原理5.2、代码实现 6、单链表的头删6.1、图解原理6.2、代码实…

【Linux系统】理解Linux中进程间通信

Linux进程间通信 1 进程间通信的介绍1.1为什么要有进程间通信1.2 为什么能进程间通信 2 进程间通信的框架2.1 进程间通信机制的结构2.2 进程间通信机制的类型2.2.1 共享内存式2.2.2 消息传递式 2.3 进程间通信的接口设计 3 进程间通信机制简介4 详细讲解进程间通信部分机制&…

【OAuth2.0 Client 总结】对接github第三方登录以及其他第三方登录总结

之前搞 oauth 登录一直没有搞好&#xff0c;客户端、授权服务端、资源端一起搞对于我刚接触的小菜鸡来说&#xff0c;难度有点大。 然后就先搞了个 Client 端对接 Github 登录。 网上关于 Github 登录的资料有很多&#xff0c;而且框架对 Github 集成的也很好&#xff0c;配置起…

【深入解析K8S专栏介绍】

序言 时间永远是旁观者&#xff0c;所有的过程和结果&#xff0c;都需要我们自己去承担。 Kubernetes (k8s) 是一个容器编排平台&#xff0c;允许在容器中运行应用程序和服务。 专栏介绍 欢迎订阅&#xff1a;【深入解析k8s】专栏 简单介绍一下这个专栏要做的事&#xff1a; 主…

8年测试老兵竟被面试官10分钟pass,这也太难了吧...

前言 随着软件测试领域对于技术要求越来越清晰&#xff0c;到现在测试人员在市场上的岗位需求也变得越来越复杂。极大部分的企业都开始对自动化测试岗位有了更多的需要。自然而然&#xff0c;面试就相对于非常重要了。 笔试部分 1.阐述软件生命周期都有哪些阶段&#xff1f;…

stm32cubemx IAP升级(二)

stm32cubemx IAP升级- App的制作 板卡&#xff1a;Nucleo-L412 平台&#xff1a;macbook pro 工具&#xff1a;vscode stm32cubemx stm32cubeProgramer cmake toolchain 整体思路 将App设置为从0x08007000地址启动&#xff0c;然后初始化一路串口用作接收上位机的升级数据&a…

docker容器:docker镜像的三种创建方法及dockerfile案例

目录 一、基于现有镜像创建 1、创建启动镜像 2、生成新镜像 二、基于本地模板创建 1、OPENVZ 下载模板 2、导入容器生成镜像 三、基于dockerfile创建 1、dockerfile结构及分层 2、联合文件系统 3、docker镜像加载原理 4、dockerfile操作常用的指令 (1)FROM指令 (…

kotlin协程flow retry retryWhen(2)

kotlin协程flow retry retryWhen&#xff08;2&#xff09; 一、retry import kotlinx.coroutines.flow.* import kotlinx.coroutines.runBlockingfun main(args: Array<String>) {runBlocking {(1..5).asFlow().onEach {if (it 3) {println("-")throw Runti…

入行IC选择国企、私企还是外企?(内附各IC大厂薪资福利情况)

不少人想要转行IC&#xff0c;但不知道该如何选择公司&#xff1f;下面就来为大家盘点一下IC大厂的薪资和工作情况&#xff0c;欢迎大家在评论区补充。 一&#xff0e;老 牌 巨 头 在 IC 设计领域深耕许久&#xff0c;流程完善、技术扎实&#xff0c;公司各项制度都很完善、前…

关于改造维护工单BAPI_ALM_ORDER_MAINTAIN用于生产订单组件批量修改

1、研究背景 1.1、业务背景 由于销售、研发、工艺等需要频繁变更&#xff0c;导致工单中组件需要频繁的进行变更&#xff0c;修改组件的物料&#xff0c;数量&#xff0c;库存地点&#xff0c;工序等内容。 1.2、技术痛点 为了满足要求&#xff0c;使用了函数&#xff1a;CO…

FVM链的Themis Pro(0x,f4) 5日IDO超百万美元,或让Filecoin逆风翻盘

交易一直是DeFi乃至web3领域最经久不衰的话题&#xff0c;也因此催生了众多优秀的去中心化协议&#xff0c;如Uniswap和Curve。这些协议逐渐成为了整个系统的基石。 在永续合约方面&#xff0c;DYDX的出现将WEB2时代的订单簿带回了web3。其链下交易的设计&#xff0c;仿佛回到了…

为你的软件测试全职业生涯规划保驾护航

目录 前言 1. 软件测试行业现状和未来趋势 2. 从初级测试工程师到高级测试架构师的职业路径 3. 如何提升自身技能和素质 4. 如何管理好自己的职业生涯 总结 前言 作为一名软件测试人员&#xff0c;职业生涯规划是非常重要的。在这篇文章中&#xff0c;我将从以下几个方面…

Mac电脑安装apktool工具包

开发中少不了想看看别人怎么实现某个功能&#xff0c;于是会用到apktool反编译apk&#xff0c;apktool工具包是一个压缩包&#xff0c;下载后无需安装&#xff0c;简单配置下执行命令就能反编译apk了&#xff0c;下面我们看一下如何在Mac OS系统下如何安装apktool工具包&#x…

《Netty》从零开始学netty源码(四十)之SizeClasses

目录 SizeClasses SizeClasses 在netty中&#xff0c;内存会被切割成不同size的块&#xff0c;在分配的时候会根据所需的大小分配相应的内存大小&#xff0c;然而并不是所有的大小都会有相应大小的内存块&#xff0c;比如想要11kb的内存&#xff0c;它并不会确切的给你11kb&am…

Mybatis高级映射及延迟加载

准备数据库表&#xff1a;一个班级对应多个学生。班级表&#xff1a;t_clazz&#xff1b;学生表&#xff1a;t_student 创建pojo&#xff1a;Student、Clazz // Student public class Student {private Integer sid;private String sname;//...... }// Clazz public class Cla…

我开发了一个温柔的智能客服聊天机器人ChatBot,并回答为什么不是ChatGPT(附思路和代码)

前言 若问2023年科技领域什么最火&#xff0c;那当然是ChatGPT了&#xff0c;这么智能的对话机器人&#xff0c;给人带来无限的想象&#xff0c;围绕着ChatpGPT的各种热点和创意层出不穷。作为一个多年从事编程开发的程序员&#xff0c;我对于这么大的一个热点也很兴奋&#x…