Verilog 中的 initial
语句块,这是行为级建模与 testbench 构建中非常关键的结构之一。
initial
语句块?initial
是 Verilog 中用于在仿真开始时只执行一次的过程性语句块。
它在 时间0(仿真启动) 执行,并按照代码顺序执行,适用于仿真环境中的激励产生、初始化赋值、时序控制等任务。
initial begin
a = 0;
b = 1;
#10 a = 1; // 10ns 后 a 变为 1
#5 b = 0; // 再过 5ns b 变为 0
end
特性 | 说明 |
---|---|
只执行一次 | 和 always 不同,它在仿真开始时只触发一次 |
执行顺序明确 | 顺序执行代码,类似 C 语言过程 |
不能综合 | initial 语句是仿真结构,不能被综合工具用于逻辑综合 |
可用于 delay | 使用 #10 等时间控制进行行为模拟 |
reg [7:0] mem [0:15];
initial begin
mem[0] = 8'h12;
mem[1] = 8'h34;
mem[2] = 8'h56;
...
end
forever
)reg clk;
initial begin
clk = 0;
forever #5 clk = ~clk; // 每 5ns 翻转一次
end
reg rst_n;
initial begin
rst_n = 0;
#20 rst_n = 1; // 仿真 20ns 后释放复位
end
initial begin
#1000 $finish; // 仿真 1000ns 后自动结束
end
initial
块行为Verilog 支持多个 initial
块,它们在仿真时同时开始执行,顺序不确定,但每个都只执行一次。
initial begin
a = 0;
end
initial begin
#5 a = 1;
end
建议:testbench 中复杂初始化使用一个
initial
,配合任务(task
)进行组织更清晰。
错误 | 说明 |
---|---|
将 initial 用于设计模块 |
不可综合,不能用在综合级 RTL 代码中 |
不加时间延迟控制顺序 | 会在同一仿真时刻执行,行为可能不符合预期 |
initial 中使用阻塞赋值影响 testbench 时序 |
推荐明确控制时间间隔,避免 race condition |
task reset_sequence;
begin
rst_n = 0;
#20 rst_n = 1;
end
endtask
initial begin
reset_sequence();
end
这样便于代码复用、逻辑清晰。
always
块的对比总结特性 | initial |
always |
---|---|---|
执行次数 | 仿真开始时执行一次 | 持续触发,事件驱动 |
用途 | testbench、初始化 | 设计逻辑建模 |
可综合性 | ❌ 不可综合 | ✅ 可综合(结构符合要求) |
时间控制支持 | ✅ # 延迟可用 |
❌ 不能直接在综合代码中使用 # |
常见使用场合 | 时钟生成、复位、激励、仿真结束控制 | 时序逻辑、组合逻辑建模 |
initial
module dff_tb;
reg clk, rst_n, d;
wire q;
dff dut (
.clk(clk),
.rst_n(rst_n),
.d(d),
.q(q)
);
// clock generation
initial begin
clk = 0;
forever #5 clk = ~clk;
end
// stimulus
initial begin
rst_n = 0;
d = 0;
#12 rst_n = 1;
#10 d = 1;
#10 d = 0;
#30 $finish;
end
endmodule
initial
编写 testbench 时,避免 race 条件,尽量使用 #delay
控制顺序;$readmemh
或 $readmemb
导入文件;fork...join
和 task
组织多个并行初始化行为。