过程结构

下述两种语句是为一个设计行为建模的主要机制:

  1. initial 语句
  2. always 语句

一个模块可以包含任意多个 initialalways 语句。这些语句相互并行执行,即这些语句的执行顺序与其在模块中的顺序无关。一个 initialalways 语句的执行产生一个单独的控制流,所有的 initialalways 语句在 0 时刻开始并行执行

initial 语句

initial 语句只执行一次initial 语句在模拟开始时执行,即在 0 时刻开始执行。语法如下

initial
[timing control] procedural_statement

procedural_statement 是下列语句之一:

顺序过程begin...end)最常使用进程语句中。这里时序控制可以时延控制,即等待一个确定的时间;或事件控制,即等待确定的事件发生或某一特定的条件为真。

always 语句

initial 语句相反,always 语句重复执行。与 initial 语句类似,always 语句语法如下:

always
  [timing control] procedural_statement

例如,产生时钟周期为 10 的波形

always
  #5 clk = ~ clk;

下例是由事件控制顺序过程always 语句:

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过程语句基于事件执行。有两种类型的事件控制方式

  1. 边沿触发事件控制
  2. 电平敏感事件控制

边沿触发事件控制如下:

@ event procedural_statement

如下例所示

@(posedge clock)
curr_state = next_state

带有事件控制的进程过程语句的执行,须等到指定事件发生。上例中,如果 clock 信号低电平变为高电平(正沿),就执行赋值语句;否则进程被挂起,直到 clock 信号产生下一个正跳边沿。

电平敏感事件控制中,进程语句或进程中的过程语句一直延迟条件变为真后才执行。电平敏感事件控制以如下形式给出:

wait(Condition)
  procedural_statement

过程语句只有在条件为真时才执行,否则过程语句一直等待到条件为真。如果执行到该语句时条件已经为真,那么过程语句立即执行。在上面的表示形式中,过程语句是可选的。

语句块

语句块提供将两条或更多条语句组合语法结构上相当于一条语句的机制。在 Verilog 中有两类语句块,即:

  1. 顺序语句块(begin...end):语句块中的语句按给定次序顺序执行。
  2. 并行语句块(fork...join):语句块中的语句并行执行。

顺序语句块

顺序语句块中的语句按顺序方式执行。每条语句中的时延值与其前面的语句执行的模拟时间相关。一旦顺序语句块执行结束,跟随顺序语句块过程的下一条语句继续执行。顺序语句块的语法如下:

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 个赋值,以此类推。

过程性赋值

过程性赋值是在 initialalways 语句内的赋值,它只能对寄存器数据类型变量赋值

过程性赋值分两类:

  1. 阻塞性过程赋值
  2. 阻塞性过程赋值

阻塞性过程赋值

赋值操作符= 的过程赋值是阻塞性过程赋值。阻塞性过程赋值在其后所有语句执行前执行,即在下一语句执行前该赋值语句完成执行。

非阻塞性过程赋值

在非阻塞性过程赋值中,使用赋值符号 <=

在非阻塞性过程赋值中,对目标的赋值是非阻塞的(因为时延),但可预定在将来某个时间步发生(根据时延;如果是 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进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注