Verilog 时延与过程结构

简介: 连续赋值延时语句中的延时,用于控制任意操作数发生变化到语句左端赋予新值之间的时间延时。时延一般是不可综合的。寄存器的时延也是可以控制的,这部分在时序控制里加以说明。连续赋值时延一般可分为普通赋值时延、隐式时延、声明时延。下面 3 个例子实现的功能是等效的,分别对应 3 种不同连续赋值时延的写法。

一、关键词:时延, 惯性时延

连续赋值延时语句中的延时,用于控制任意操作数发生变化到语句左端赋予新值之间的时间延时。

时延一般是不可综合的。

寄存器的时延也是可以控制的,这部分在时序控制里加以说明。

连续赋值时延一般可分为普通赋值时延、隐式时延、声明时延。

下面 3 个例子实现的功能是等效的,分别对应 3 种不同连续赋值时延的写法。

//普通时延,A&B计算结果延时10个时间单位赋值给Z
wire Z, A, B ;
assign #10    Z = A & B ;
//隐式时延,声明一个wire型变量时对其进行包含一定时延的连续赋值。
wire A, B;
wire #10        Z = A & B;
//声明时延,声明一个wire型变量是指定一个时延。因此对该变量所有的连续赋值都会被推迟到指定的时间。除非门级建模中,一般不推荐使用此类方法建模。
wire A, B;
wire #10 Z ;
assign           Z =A & B

1、惯性时延

在上述例子中,A 或 B 任意一个变量发生变化,那么在 Z 得到新的值之前,会有 10 个时间单位的时延。如果在这 10 个时间单位内,即在 Z 获取新的值之前,A 或 B 任意一个值又发生了变化,那么计算 Z 的新值时会取 A 或 B 当前的新值。所以称之为惯性时延,即信号脉冲宽度小于时延时,对输出没有影响。

因此仿真时,时延一定要合理设置,防止某些信号不能进行有效的延迟。

对一个有延迟的与门逻辑进行时延仿真。

module time_delay_module(
    input   ai, bi,
    output  so_lose, so_get, so_normal);
    assign #20      so_lose      = ai & bi ;
    assign  #5      so_get       = ai & bi ;
    assign          so_normal    = ai & bi ;
endmodule

testbench 参考如下:

`timescale 1ns/1ns
module test ;
    reg  ai, bi ;
    wire so_lose, so_get, so_normal ;
    initial begin
        ai        = 0 ;
        #25 ;      ai        = 1 ;
        #35 ;      ai        = 0 ;        //60ns
        #40 ;      ai        = 1 ;        //100ns
        #10 ;      ai        = 0 ;        //110ns
    end
    initial begin
        bi        = 1 ;
        #70 ;      bi        = 0 ;
        #20 ;      bi        = 1 ;
    end
    time_delay_module  u_wire_delay(
        .ai              (ai),
        .bi              (bi),
        .so_lose         (so_lose),
        .so_get          (so_get),
        .so_normal       (so_normal));
    initial begin
        forever begin
            #100;
            //$display("---gyc---%d", $time);
            if ($time >= 1000) begin
                $finish ;
            end
        end
    end
endmodule

仿真结果如下:

信号 so_normal 为正常的与逻辑。

由于所有的时延均大于 5ns,所以信号 so_get 的结果为与操作后再延迟 5ns 的结果。

信号 so_lose 前一段是与操作后再延迟 20ns 的结果。

由于信号 ai 第二个高电平持续时间小于 20ns,so_lose 信号会因惯性时延而漏掉对这个脉冲的延时检测,所以后半段 so_lose 信号仍然为 0。

2、源码下载

Download

二、关键词:initial, always

过程结构语句有 2 种,initial 与 always 语句。它们是行为级建模的 2 种基本语句。

一个模块中可以包含多个 initial 和 always 语句,但 2 种语句不能嵌套使用。

这些语句在模块间并行执行,与其在模块的前后顺序没有关系。

但是 initial 语句或 always 语句内部可以理解为是顺序执行的(非阻塞赋值除外)。

每个 initial 语句或 always 语句都会产生一个独立的控制流,执行时间都是从 0 时刻开始。

1、initial语句

initial 语句从 0 时刻开始执行,只执行一次,多个 initial 块之间是相互独立的。

如果 initial 块内包含多个语句,需要使用关键字 begin 和 end 组成一个块语句。

如果 initial 块内只要一条语句,关键字 begin 和 end 可使用也可不使用。

initial 理论上来讲是不可综合的,多用于初始化、信号检测等。

对上一节代码稍作修改,进行仿真,代码如下。

`timescale 1ns/1ns
module test ;
    reg  ai, bi ;
    initial begin
        ai         = 0 ;
        #25 ;      ai        = 1 ;
        #35 ;      ai        = 0 ;        //absolute 60ns
        #40 ;      ai        = 1 ;        //absolute 100ns
        #10 ;      ai        = 0 ;        //absolute 110ns
    end
    initial begin
        bi         = 1 ;
        #70 ;      bi        = 0 ;        //absolute 70ns
        #20 ;      bi        = 1 ;        //absolute 90ns
    end
    //at proper time stop the simulation
    initial begin
        forever begin
            #100;
            //$display("---gyc---%d", $time);
            if ($time >= 1000) begin
                $finish ;
            end
        end
   end
endmodule

仿真结果如下:

可以看出,2 个 initial 进程语句分别给信号 ai,bi 赋值时,相互间并没有影响。

信号 ai,bi 的值按照赋值顺序依次改变,所以 initial 内部语句也可以看做是顺序执行。

2、always 语句

与 initial 语句相反,always 语句是重复执行的。always 语句块从 0 时刻开始执行其中的行为语句;当执行完最后一条语句后,便再次执行语句块中的第一条语句,如此循环反复。

由于循环执行的特点,always 语句多用于仿真时钟的产生,信号行为的检测等。

下面用 always 产生一个 100MHz 时钟源,并在 1010ns 时停止仿真代码如下。

代码如下:

`timescale 1ns/1ns
module test ;
    parameter CLK_FREQ   = 100 ; //100MHz
    parameter CLK_CYCLE  = 1e9 / (CLK_FREQ * 1e6) ;   //switch to ns
    reg  clk ;
    initial      clk = 1'b0 ;      //clk is initialized to "0"
    always     # (CLK_CYCLE/2) clk = ~clk ;       //generating a real clock by reversing
    always begin
        #10;
        if ($time >= 1000) begin
            $finish ;
        end
    end
endmodule

仿真结果如下:

可见,时钟周期是我们想要得到的 100MHz。而且仿真在 1010ns 时停止。

3、源码下载

Download

相关文章
|
Unix Linux
`grep`命令进行文本搜索并忽略大小写
`grep`命令进行文本搜索并忽略大小写
677 2
|
Dubbo Java 应用服务中间件
微服务框架(十四)Spring Boot @ControllerAdvice异常处理
此系列文章将会描述Java框架Spring Boot、服务治理框架Dubbo、应用容器引擎Docker,及使用Spring Boot集成Dubbo、Mybatis等开源框架,其中穿插着Spring Boot中日志切面等技术的实现,然后通过gitlab-CI以持续集成为Docker镜像。   本文为Spring Boot使用@ControllerAdvice进行自定义异常捕捉
|
存储 编解码 数据库
基于人脸识别的智能门锁系统
基于人脸识别的智能门锁系统
396 0
|
缓存 移动开发 JavaScript
PCIe 参考时钟架构 (Refclk Architecture)
PCIe 参考时钟架构 (Refclk Architecture)
6317 0
PCIe 参考时钟架构 (Refclk Architecture)
|
监控 定位技术 安全
Qt编写安防视频监控系统10-视频轮询
一、前言 视频轮询在视频监控系统中是一个基础的核心功能,尤其是上了大屏以后,这个功能是必须的,根据预先设定的轮询间隔逐个加载视频到预先设定的通道画面数中,轮询间隔、轮询画面数、轮询采用的码流类型(主码流、子码流)都可以在系统设置中进行统一设置,轮询的视频源采用摄像机表中的所有摄像机,当画面数不够的时候,其余留空显示即可,轮询到最后一个视频,重新从第一个开始轮询。
1813 0
|
存储 负载均衡 NoSQL
|
8月前
|
存储 人工智能 算法
Magic 1-For-1:北大联合英伟达推出的高质量视频生成量化模型,支持在消费级GPU上快速生成
北京大学、Hedra Inc. 和 Nvidia 联合推出的 Magic 1-For-1 模型,优化内存消耗和推理延迟,快速生成高质量视频片段。
380 3
Magic 1-For-1:北大联合英伟达推出的高质量视频生成量化模型,支持在消费级GPU上快速生成
|
Linux 数据处理
探索Linux中的namei命令:文件路径解析的利器
`namei`是Linux工具,解析文件路径展示每个组件详情,包括类型、权限、属主等。它递归从根目录开始,帮助理解文件系统结构,尤其处理符号链接和挂载点。使用 `-l` 选项提供长格式输出, `-m` 以挂载点显示, `-x` 显示调试信息。示例用法如解析`/home/user/documents/report.txt`路径。注意权限、路径正确性及符号链接影响。可与其他命令结合使用。
|
Web App开发 数据采集 JavaScript
有JavaScript动态加载的内容如何抓取
有JavaScript动态加载的内容如何抓取
|
存储 缓存 Ubuntu
Docker详解:如何创建运行Memcached的Docker容器
Docker详解:如何创建运行Memcached的Docker容器
176 0