☰
Verilog基础:always结构和initial结构
2026/10/27 9:25:12 网站建设 项目流程

相关阅读

Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html?spm=1001.2014.3001.5482


always和initial是Verilog中非常核心的两种过程结构(construct),它们用于组织语句在仿真中的执行方式。虽然二者的语法形式很相似,但语义却并不相同:一个会反复执行,另一个只执行一次。下面分别对这两种结构进行说明。

always结构

图1是always结构的BNF范式语法(有关BNF范式,可以参考以往文章)。

图1 always结构的语法

从语法上看,always结构非常简单,本质上就是在always关键字后面跟一条语句(statement),它所表达的含义是:在仿真过程中,这条语句会不断重复执行。

这里自然会引出一个问题:什么是语句?Verilog中语句的定义如图2所示,同样是以BNF范式给出的。

图2 语句的定义

可以看出,语句可以是众多类语句中的一种,比如阻塞赋值语句(blocking_assignment) 、选择语句(case_statement),块语句(par_block、seq_clock)被视作一条语句,用于将多条语句以某种方式组织起来,它们在之前的文章中讨论过Verilog基础:块语句,这里不再展开。

由于always结构会持续执行后面的语句,因此该语句应有“过程语句前置时序控制”,这在之前的文章中也讨论过Verilog基础:延时模型。

由于always会持续不断地执行其后的语句,因此该语句通常必须带有某种过程语句前置时序控制,否则仿真器就可能陷入死锁,导致仿真时间无法推进。例如下面这段代码:

always clk = !clk //由于赋值语句一直执行,仿真时间停止在0,而无法推进

给always加上延时控制(delay control)后,就可以正确地描述周期性行为。下面是一个典型例子:

always #5 clk = !clk //赋值语句每5时间单位执行一次,因此该时钟周期为10个时间单位

这段代码的含义是:每过5个时间单位,clk的值就取反一次,因此clk每10个时间单位完成一个完整周期。这也是testbench中产生时钟信号最常见的写法之一。

在更常见的实际设计中,always后面通常会跟一个语句块,例如顺序块begin-end,而更常见的时序控制方式则是事件控制(event control)。例如:

always @(a, b) begin //语句前的@后使得该过程被挂起,直到a或b之一的值发生改变 c = a | b; d = a & b; end

这里的含义是:只有当a或b发生变化时,这个always过程才会被触发并执行一次;执行结束后,它又会再次挂起,等待下一次事件发生。

一个比较好的编码习惯是:当使用always结构时,不论后面实际上只有一条语句还是多条语句,都尽量使用begin-end顺序块将其包起来。

initial结构

图3是initial结构的BNF范式语法。

图3 initial结构的语法

它与always结构非常相似,唯一不同的就是initial结构使用的是initial关键词加一条语句。二者最本质的区别在于:initial结构代表着其后面的语句只会执行一次,一旦执行完毕后,initial结构就被销毁。从它这抽象的描述中,就可知它是不可综合的,它常用于仿真时使用的testbench中。

下面是一个initial结构,它在特定的时间将信号赋特定值,可以看做描述了一段波形。

initial begin a=1'b1; //在开始时,a是1 #5 a=1'b0; //在5时间单位,a变为0 #10 a=1'b1; //在15时间单位,a变为1 end

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询