4.2 initial 结构和 always 结构
引言部分
1.行为级建模的四种结构:
- (1)initial 结构
- (2)always 结构
- (3)task 结构
- (4)function 结构
2.initial 结构和 always 结构特点
- 一个程序模块可以有多个 initial 和 always 过程块。
- 一个 module 里的所有 initial结构 和 always结构,在仿真的一开始同时执行。
- initial 模块只执行一次,always 模块的触发条件只要满足,就运行一次,直到仿真结束。
- initial 结构和 always 结构都不支持嵌套使用,即 initial 结构中不能再出现 initial 结构。
一、 initial 结构
1. 语句格式
initial a=1; //仅包含一条语句
initial //包含多条语句时
begin
语句 1;
语句 2;
end
2. initial 结构用途和用法
(1)initial 结构的主要功能就是 进行初始化,进行信号和变量初始化的常用形式。
(2)由其用途可推断其用法,initial 结构仅在仿真开始的时候被激活一次,然后该结构中所有语句执行一次,执行结束后不再执行。
3. 举例说明
(1)对存储器变量赋初值
initial begin
areg=0; //初始化寄存器areg
for( index = 0; index < size; index++ )
memory[index] = 0; //初始化一个memory
end
注意:在仿真一开始就对各变量进行初始化,这个初始化过程不需要任何仿真时间,即在 0 ns 时间内,便可完成存储器的初始化工作。
(2)用于测试文件,生成激励波形。
//产生激励
initial begin
a=0; b=0;
#15 a=0; b=1;
#15 a=1; b=0;
#15 a=1; b=1;
#15 a=0; b=0;
end
//产生时钟信号
initial clk = 1'b1;
always#(`clock_period/2) Clk = ~Clk;
//产生 Cin激励信号 和 Rst_n复位信号
initial begin
Rst_n = 0; //首先系统处于复位状态
Cin = 1'b0;
#(`clock_period*200); //延时200个系统时钟周期
Rst_n = 1'b1; //系统开始运行
#(`clock_period*20);
repeat(30) begin //重复执行30次。1个周期高电平,5个周期低电平。
Cin = 1'b1;
#`clock_period;
Cin = 1'b0;
#(`clock_period*5);
end
#(`clock_period*20);
$stop;
end
二、 always 结构
1.语句结构
always <时序控制方式> 执行语句
2.特点
可以执行多次,在仿真的过程中是时刻活动的。
3. 三种控制方式
- a. 基于延迟的控制
- b. 基于事件的控制
- c. 基于电平敏感的控制
需要控制方式的原因:
always 结构时刻活动,如果没有控制方式的参与,此结构中的语句可能会一直执行并发生死锁,或者编程数据流级的语句。举个栗子:
always a=~a; //因为没有控制,a会时刻把自己取反信号赋值给自己,生成死循环。
always sum=a+b; // 不如替换成:assign sum=a+b;
(1) 基于延迟的控制
always #5 a=~a; //每隔五个时间单位,把a取反信号赋给自己。
时钟信号的生成:
// 时钟信号的生成
initial clk=1; //赋初值!!不能忘
always #10 clk=~clk; //周期为20个时间单位的时钟。
- 也可以添加多条语句,但一般少用。
//这样的信号也是一个时钟,但占空比不是50%,而是25%。
initial clk=0;
always
begin
#15 clk=1;
#5 clk=0;
end
- 注意:语句前的延迟,是指延迟一定时间之后执行该语句,而不是该语句执行了多长时间。
(2)基于事件的控制
always @ (敏感事件表)
-
always 结构时刻观察敏感事件列表中的信号,等待敏感事件的出现,所有事件当中只要满足一个,就会执行本结构中的语句。
-
always@(a or b or c) // 只有a,b, c中有一个发生变化,就会执行always结构中的语句。
或always@(a,b,c)
或always@(*) // * 代表always结构中所有的输入信号
(3)基于电平敏感的控制
- 电平敏感:组合电路
- 边沿敏感:时序电路
eg.电平触发的 D 触发器
always@(clk or rst or d) begin
if(rst) q <= 0; // rst 为高电平时清零
else if(clk) // 否则当clk为高电平时,q输出d的值
q <= d;
end
eg. 上升沿触发的同步清零 D 触发器
always@(posedge clk)begin //仅在 clk 上升沿来临时,才会执行always
if(!rst) q <= 0;
else q <= d;
end
eg. 上升沿触发的异步清零 D 触发器
always@(posedge clk or negedge rst) begin //敏感列表包含了rst,rst每次从 1 变为 0 ,always 都会被执行,所以是异步清零。
if(!rst) q <= 0;
else q <= d;
end
注意:
1. 边沿触发的敏感列表不能使用 “*” 来省略,可以用“,”或者 or 。posedge 上升沿,negedge 下降沿。
2. 电平敏感和边沿敏感不要同时出现在敏感列表中。

浙公网安备 33010602011771号