赋值延迟
本课属于 Coddy Verilog 学习旅程的“基础知识”单元。第 69 课,共 90 课。
在之前的课中,我们学习了普通延迟(#10 a = b;)和门延迟(and #5 (out, a, b);)。现在,我们来学习赋值延迟,也就是在过程块(如 initial 或 always)内部,作为赋值语句一部分发生的延迟。
赋值延迟会等待指定的时间,然后执行赋值操作。延迟放在 # 符号之后,赋值之前。
语法:
variable = #delay expression;与常规延迟 #10 a = b;(先延迟,再赋值)不同,赋值延迟 a = #10 b; 会先获取此刻 b 的值,等待 10 个时间单位,然后将其赋给 a。
赋值延迟与一般延迟
| 一般延迟 | 赋值延迟 | |
|---|---|---|
| 语法 | #10 a = b; | a = #10 b; |
| 何时读取值? | 赋值时(延迟之后) | 立即(延迟之前) |
| 赋的是什么值? | 当时 b 的值 | 时间 0 时(或读取时)b 的值 |
| 何时赋值? | 延迟之后 | 延迟之后 |
示例:区别
initial begin
b = 1;
#5 b = 0;
// 普通延迟
#10 a1 = b; // 等待 10 后读取 b(b=0),得到 a1=0
// 赋值延迟
a2 = #10 b; // 现在读取 b(b=0),等待 10 后再赋值,得到 a2=0
end在这里,两者的结果相同。区别会在延迟期间 b 发生变化时显现出来。
关键差异示例
To show b changing during the delay, we need two separate initial blocks that run in parallel:
initial begin
b = 1;
a1 = #10 b; // 在时间 0 读取 b=1,在时间 10 将 a1 赋值为 1
end
initial begin
#5 b = 0; // 在时间 5 将 b 改为 0(延迟期间)
end- 在时间 0:
a1读取b = 1 - 在时间 5:
b变为0(此时a1仍在等待) - 在时间 10:
a1被赋值为1(在时间 0 读取的值),而不是0
如果在单独的代码块中使用普通延迟 #10 a2 = b;,则会在时间 10 读取 b(值为 0)。
重要规则
| 规则 | 说明 |
|---|---|
= 放在 # 前面 | 写作 a = #10 b;,而不是 a #10 = b; |
| 立即读取值 | 右侧会立即求值 |
| 延迟后进行赋值 | 左侧稍后获取该值 |
| 仅用于过程块 | 用于 initial 或 always |
挑战
要做什么:
添加缺失的赋值延迟,使 a 在 15 个时间单位后获得 b 的值,但立即读取 b。
亲手试试
module assignment_challenge;
reg a, b;
// 用单独的代码块在延迟期间修改 b
initial begin
b = 1;
// TODO: 添加赋值延迟
// 经过 15 个时间单位后,a 应获得 b 的值
// 现在读取 b,延迟后再赋值
end
initial begin
#5 b = 0; // 在延迟期间修改 b
#20 $display("Time %0t: a = %b", $time, a);
$finish;
end
endmodule这节课包含一个小测验。开始学习即可作答,并记录你的进度。
基础知识中的所有课
自己练习: Verilog 在线编译器