首页 > 其他分享 >Verilog的时序控制

Verilog的时序控制

时间:2022-12-20 20:31:37浏览次数:33  
标签:控制 begin clk value 时序 Verilog 时延 test embed

关键词:时延控制,事件触发,边沿触发,电平触发

Verilog 提供了 2 大类时序控制方法:时延控制和事件控制。事件控制主要分为边沿触发事件控制与电平敏感事件控制。

时延控制

基于时延的时序控制出现在表达式中,它指定了语句从开始执行到执行完毕之间的时间间隔。

时延可以是数字、标识符或者表达式。

根据在表达式中的位置差异,时延控制又可以分为常规时延与内嵌时延。

常规时延

遇到常规延时时,该语句需要等待一定时间,然后将计算结果赋值给目标信号。

格式为:#delay procedural_statement,例如:

reg  value_test ;
reg value_general ;
#10 value_general = value_test ;

该时延方式的另一种写法是直接将井号 # 独立成一个时延执行语句,例如:

#10 ;
value_ single = value_test ;

内嵌时延

遇到内嵌延时时,该语句先将计算结果保存,然后等待一定的时间后赋值给目标信号。

内嵌时延控制加在赋值号之后。例如:

reg  value_test ;
reg value_embed ;
value_embed = #10 value_test ;

需要说明的是,这 2 种时延控制方式的效果是有所不同的。

当延时语句的赋值符号右端是常量时,2 种时延控制都能达到相同的延时赋值效果。

当延时语句的赋值符号右端是变量时,2 种时延控制可能会产生不同的延时赋值效果。

例如下面仿真代码:

`timescale 1ns/1ns

module test ;
reg value_test ;
reg value_general, value_embed, value_single ;

//signal source
initial begin
value_test = 0 ;
#25 ; value_test = 1 ;
#35 ; value_test = 0 ; //absolute 60ns
#40 ; value_test = 1 ; //absolute 100ns
#10 ; value_test = 0 ; //absolute 110ns
end

//(1)general delay control
initial begin
value_general = 1;
#10 value_general = value_test ; //10ns, value_test=0
#45 value_general = value_test ; //55ns, value_test=1
#30 value_general = value_test ; //85ns, value_test=0
#20 value_general = value_test ; //105ns, value_test=1
end

//(2)embedded delay control
initial begin
value_embed = 1;
value_embed = #10 value_test ; //0ns, value_test=0
value_embed = #45 value_test ; //10ns, value_test=0
value_embed = #30 value_test ; //55ns, value_test=1
value_embed = #20 value_test ; //85ns, value_test=0
end

//(3)single delay control
initial begin
value_single = 1;
#10 ;
value_single = value_test ; //10ns, value_test=0
#45 ;
value_single = value_test ; //55ns, value_test=1
#30 ;
value_single = value_test ; //85ns, value_test=0
#20 ;
value_single = value_test ; //105ns, value_test=1
end

always begin
#10;
if ($time >= 150) begin
$finish ;
end
end

endmodule

仿真结果如下,由图可知:

  • (1)一般延时的两种表达方式执行的结果都是一致的。
  • (2)一般时延赋值方式:遇到延迟语句后先延迟一定的时间,然后将当前操作数赋值给目标信号,并没有"惯性延迟"的特点,不会漏掉相对较窄的脉冲。
  • (3)内嵌时延赋值方式:遇到延迟语句后,先计算出表达式右端的结果,然后再延迟一定的时间,赋值给目标信号。

Verilog的时序控制_赋值

下面分析下内嵌延时的赋值过程:

value_embed  = #10 value_test ; //0ns, value_test=0

0ns 时,执行此延时语句。

先将 0 赋值给信号 value_embed, 延迟 10ns 输出为 0;

value_embed  = #45 value_test ; //10ns, value_test=0

10ns 时,执行此延时语句。

由于此时 value_test 仍然为 0,所以 value_embed 值不变。

即到 55ns 时,value_embed 值仍然保持为 0。

value_embed  = #30 value_test ; //55ns, value_test=1

同理,55ns 时,value_test 值为 1,将其赋值给 value_embed 并延迟 30ns 输出。

所以 85ns 时,value_embed 输出为 1。

value_embed  = #20 value_test ; //85ns, value_test=0

同理,105ns 时,value_embed 输出为 0。

边沿触发事件控制

在 Verilog 中,事件是指某一个 reg 或 wire 型变量发生了值的变化。

基于事件触发的时序控制又主要分为以下几种。

一般事件控制

事件控制用符号 @ 表示。

语句执行的条件是信号的值发生特定的变化。

关键字 posedge 指信号发生边沿正向跳变,negedge 指信号发生负向边沿跳变,未指明跳变方向时,则 2 种情况的边沿变化都会触发相关事件。例如:

//信号clk只要发生变化,就执行q<=d,双边沿D触发器模型
always @(clk) q <= d ;
//在信号clk上升沿时刻,执行q<=d,正边沿D触发器模型
always @(posedge clk) q <= d ;
//在信号clk下降沿时刻,执行q<=d,负边沿D触发器模型
always @(negedge clk) q <= d ;
//立刻计算d的值,并在clk上升沿时刻赋值给q,不推荐这种写法
q = @(posedge clk) d ;

命名事件控制

用户可以声明 event(事件)类型的变量,并触发该变量来识别该事件是否发生。命名事件用关键字 event 来声明,触发信号用 -> 表示。例如:

event     start_receiving ;
always @( posedge clk_samp) begin
-> start_receiving ; //采样时钟上升沿作为时间触发时刻
end

always @(start_receiving) begin
data_buf = {data_if[0], data_if[1]} ; //触发时刻,对多维数据整合
end

敏感列表

当多个信号或事件中任意一个发生变化都能够触发语句的执行时,Verilog 中使用"或"表达式来描述这种情况,用关键字 or 连接多个事件或信号。这些事件或信号组成的列表称为"敏感列表"。当然,or 也可以用逗号 , 来代替。例如:

//带有低有效复位端的D触发器模型
always @(posedge clk or negedge rstn) begin
//always @(posedge clk , negedge rstn) begin
//也可以使用逗号陈列多个事件触发
if(! rstn)begin
q <= 1'b ;
end
else begin
q <= d ;
end
end

当组合逻辑输入变量很多时,那么编写敏感列表会很繁琐。此时,更为简洁的写法是 @* 或 @(*),表示对语句块中的所有输入变量的变化都是敏感的。例如:

always @(*) begin
//always @(a, b, c, d, e, f, g, h, i, j, k, l, m) begin
//两种写法等价
assign s = a? b+c : d ? e+f : g ? h+i : j ? k+l : m ;
end

电平敏感事件控制

前面所讨论的事件控制都是需要等待信号值的变化或事件的触发,使用 @+敏感列表 的方式来表示的。

Verilog 中还支持使用电平作为敏感信号来控制时序,即后面语句的执行需要等待某个条件为真。Verilog 中使用关键字 wait 来表示这种电平敏感情况。例如:

initial begin
wait (start_enable) ; //等待 start 信号
forever begin
//start信号使能后,在clk_samp上升沿,对数据进行整合
@(posedge clk_samp) ;
data_buf = {data_if[0], data_if[1]} ;
end
end

标签:控制,begin,clk,value,时序,Verilog,时延,test,embed
From: https://blog.51cto.com/u_15641375/5956667

相关文章

  • 时序数据库 TDengine 3.0.2.0 版本正式发布
    近日,TDengine3.0.2.0正式发布了。这是自今年8月份TDengine3.0发布以来的第一个重要改进版本。:::hljs-center:::TDengine3.0带来了几大核心特性,包括云原生架......
  • 时序数据库 TDengine 3.0.2.0 版本正式发布
    近日,TDengine 3.0.2.0正式发布了。这是自今年8月份TDengine3.0发布以来的第一个重要改进版本。TDengine3.0带来了几大核心特性,包括云原生架构、流式计算,还增强......
  • Angular JS入门 (一)事件监听(二)多控制器思想与模块化编程(三)路由router
    AngularJS入门☀️将流式结构--->模块化一、事件监听1.事件监听前言NG框架中通过对元素标签添加[ng-事件名]指令,来对元素添加事件监听而事件监听的回调函数需要在con......
  • k8s原理之-Pod控制器--ReplicaSet、Deployment
    一、Pod控制器及其功用Pod控制器是用于实现管理pod的中间层,确保pod资源符合预期的状态,pod的资源出现故障时,会尝试进行重启,当根据重启策略无效,则会重新新建pod的资......
  • 打开cmd控制台方式和常用Dos命令
    打开CMD的方式开始+系统+命令提示符Win+R输入cmd打开控制台(常用)在任意文件夹按住Shift键+鼠标右击,点击在此处打开Powershell窗口资源管理器的地址前面加上cmd确......
  • Spring Security 动态url权限控制
    一、前言本篇文章将讲述SpringSecurity动态分配url权限,未登录权限控制,登录过后根据登录用户角色授予访问url权限基本环境 spring-boot2.1.8mybatis-plus2.2.0......
  • SAP Gateway 在开发系统和生产系统上的缓存控制
    SAPGateway元数据缓存可以启用和禁用,并且在非生产系统中默认停用。我们推荐以下缓存设置:开发系统应该禁用SAPGateway元数据缓存,以便始终获取最新的元数据(默认设置)......
  • 流程控制结构
    顺序结构分支结构循环结构#一、分支结构#1.if函数功能:实现简单的双分支语法:selectif(表达式1,表达式2,表达式3)执行顺序:表达式1成立,返回表达式2的值,否则返回表达......
  • Java笔记(5)——类的继承、访问控制、super关键字
      在类中,不写构造方法,相当于执行了默认的无参构造方法;写了有参构造方法,则只执行有参构造方法,默认的无参构造方法则会被屏蔽掉;若想拥有有参和无参构造方法,则同时显示地写出......
  • 细说集中式与分布式版本控制系统
    前言:分布式版本控制系统除了Git以及促使Git诞生的BitKeeper外,还有类似Git的Mercurial和Bazaar等。这些分布式版本控制系统各有特点,但最快、最简单也最流行的依然是Git!集中式......