过程结构
一个模块中可以包含任意多个 initial
或 always
语句。这些语句相互并行执行,即这些语句的执行顺序与其在模块中的顺序无关。一个 initial
或 always
语句的执行产生一个单独的控制流,所有的 initial
和 always
语句在 0 时刻开始并行执行。
initial
语句
initial
语句只执行一次。initial
语句在模拟开始时执行,即在 0 时刻开始执行。语法如下:
initial
[timing control] procedural_statement
- procedural_assignment (blocking or non–blocking)
- procedural_continuous_assignment
- conditional_statement
- case_statement
- loop_statament
- wait_statement
- disable_statement
- event_trigger
- sequential_block
- parallel_block
- task_enable
顺序过程(begin...end
)最常使用在进程语句中。这里的时序控制可以是时延控制,即等待一个确定的时间;或事件控制,即等待确定的事件发生或某一特定的条件为真。
always
语句
与 initial
语句相反,always
语句重复执行。与 initial
语句类似,always
语句语法如下:
always
[timing control] procedural_statement
always
#5 clk = ~ clk;
reg[0:5] InstrReg;
reg[3:0] Accum;
wire ExecuteCycle;
always@(ExecuteCycle)
begin
case(InstrReg[0:1])
2'b00: Store(Accum, InstrReg[2:5]);
2'b11: Load(Accum, InstrReg[2:5]);
2'b01: Jump(InstrReg[2:5]);
2'b10:;
endcase
end
// Store、Load 和 Jump 是在别处定义的用户自定义的任务
事件控制
在事件控制中,always
的过程语句基于事件执行。有两种类型的事件控制方式:
边沿触发事件控制如下:
@ event procedural_statement
如下例所示:
@(posedge clock)
curr_state = next_state
带有事件控制的进程或过程语句的执行,须等到指定事件发生。上例中,如果 clock
信号从低电平变为高电平(正沿),就执行赋值语句;否则进程被挂起,直到 clock
信号产生下一个正跳边沿。
在电平敏感事件控制中,进程语句或进程中的过程语句一直延迟到条件变为真后才执行。电平敏感事件控制以如下形式给出:
wait(Condition)
procedural_statement
过程语句只有在条件为真时才执行,否则过程语句一直等待到条件为真。如果执行到该语句时条件已经为真,那么过程语句立即执行。在上面的表示形式中,过程语句是可选的。
语句块
语句块提供将两条或更多条语句组合成语法结构上相当于一条语句的机制。在 Verilog 中有两类语句块,即:
顺序语句块
顺序语句块中的语句按顺序方式执行。每条语句中的时延值与其前面的语句执行的模拟时间相关。一旦顺序语句块执行结束,跟随顺序语句块过程的下一条语句继续执行。顺序语句块的语法如下:
begin
[:block_id{declarations}]
procedural_statement(s)
end
begin
#2 Stream = 1;
#5 Stream = 0;
#3 Stream = 1;
#4 Stream = 0;
#2 Stream = 1;
#5 Stream = 0;
end
假定顺序语句块在第 10 个时间单位开始执行。两个时间单位后第 1 条语句执行,即第 12 个时间单位。此执行完成后,下 1 条语句在第 17 个时间单位执行(延迟 5 个时间单位)。然后下 1 条语句在第 20 个时间单位执行,以此类推。
并行语句块
并行语句块中的各语句并行执行。并行语句块内的各条语句指定的时延值都与语句块开始执行的时间相关。当并行语句块中最后的动作执行完成时(最后的动作并不一定是最后的语句),顺序语句块的语句继续执行。换一种说法就是并行语句块内的所有语句必须在控制转出语句块前完成执行。例如
fork
#2 Stream = 1;
#7 Stream = 0;
#10 Stream = 1;
#14 Stream = 0;
#16 Stream = 1;
#21 Stream = 0;
join
如果并行语句块在第 10 个时间单位开始执行,所有的语句并行执行并且所有的时延都是相对于时刻 10 的。例如,第 3 个赋值在第 20 个时间单位执行,并在第 26 个时间单位执行第 5 个赋值,以此类推。
过程性赋值
过程性赋值是在 initial
或 always
语句内的赋值,它只能对寄存器数据类型的变量赋值。
过程性赋值分两类:
阻塞性过程赋值
赋值操作符是 =
的过程赋值是阻塞性过程赋值。阻塞性过程赋值在其后所有语句执行前执行,即在下一语句执行前该赋值语句完成执行。
非阻塞性过程赋值
在非阻塞性过程赋值中,对目标的赋值是非阻塞的(因为时延),但可预定在将来某个时间步发生(根据时延;如果是 0 时延,那么在当前时间步结束)。
begin
Load <= 32;
RegA <= Load;
RegB <= Store;
end
当非阻塞性过程赋值被执行时,计算右端表达式,右端值被赋于左端目标,并继续执行下一条语句。在上面的例子中,我们假设顺序语句块在时刻 10 执行。第一条语句促使 Load
在第 10 个时间单位结束时被赋值为 32;然后执行第 2 条语句, Load
的值不变(注意时间还没有前进,并且第 1 个赋值还没有被赋新值),RegA
的赋值被预定为在第 10 个时间步结束时。在所有的事件在第 10 个时间单位发生后,完成对左端目标的所有预定赋值。
下面是同时使用阻塞性和非阻塞性过程赋值的实例,注意它们的区别。
reg[0:2] Q_State;
initial begin
Q_state = 3'b011;
Q_state <= 3'b100;
$display("Current value of Q_State is %b", Q_State);
#5;
$display("The delayed value of Q_State is %b", Q_State);
end
执行 initial
语句产生如下结果:
Current value of Q_State is 011
The delayed value of Q_State is 100
原文地址:https://blog.csdn.net/myDarling_/article/details/134734958
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_22414.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!