3. VCS仿真控制与波形生成
任务目标
本案例将使用VCS编译并运行一个最小Verilog测试平台,通过命令行参数控制仿真结束时间,并生成VPD格式波形文件,供DVE或Verdi查看。
环境依赖
需要安装Synopsys VCS(本案例使用2018.06版本验证)及配套的DVE波形查看工具。确保vcs命令已加入系统PATH。
设计文件:counter.v
module counter #(parameter WIDTH = 4) (
input wire clk,
input wire rst_n,
output reg [WIDTH-1:0] count
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
count <= 0;
else
count <= count + 1'b1;
end
endmodule
测试平台:tb_counter.v
module tb_counter;
parameter CYCLE = 10; // 时钟周期 10ns
reg clk;
reg rst_n;
wire [3:0] count;
// 时钟生成
initial clk = 0;
always #(CYCLE/2) clk = ~clk;
// 复位与激励
initial begin
rst_n = 0;
#(CYCLE*2);
rst_n = 1;
end
// 波形导出(VPD格式)
initial begin
$vcdpluson; // 开启VPD波形记录
$vcdplusmemon; // 记录存储器/寄存器变化
end
// 仿真结束控制(由命令行+plusarg指定时间)
initial begin
$timeformat(-9, 1, " ns", 8);
wait (rst_n == 1);
$display("Simulation started at time %0t", $time);
end
// 通过命令行参数控制仿真时长
initial begin
integer sim_end;
if (!$value$plusargs("END_TIME=%d", sim_end)) begin
sim_end = 200; // 默认仿真 200ns
$display("END_TIME not specified, using default %0d ns", sim_end);
end else begin
$display("END_TIME specified: %0d ns", sim_end);
end
#(sim_end);
$display("Simulation finished at time %0t", $time);
$finish;
end
// 被测模块实例化
counter #(.WIDTH(4)) u_counter (
.clk (clk),
.rst_n (rst_n),
.count (count)
);
// 监控输出
initial begin
$monitor("Time=%0t rst_n=%b count=%d", $time, rst_n, count);
end
endmodule
编译与运行
在终端执行以下命令(Linux环境):
# 1. 编译(生成可执行文件 simv)
vcs -sverilog +vcs+flush+all -o simv tb_counter.v counter.v -debug_access+all
# 2. 运行仿真,指定仿真结束时间为 500ns
./simv +END_TIME=500
# 3. 运行仿真,使用默认结束时间 200ns
./simv
验证方法
- 观察终端输出:仿真启动后,
$monitor会打印每个时钟沿的count值,从0递增至15后回卷;仿真结束时打印Simulation finished at time ...,时间应与+END_TIME参数一致。 - 检查波形文件:运行结束后,当前目录下应生成
vcdplus.vpd文件。执行ls -l vcdplus.vpd确认文件存在且大小非零。 - 查看波形:执行
dve -vpd vcdplus.vpd打开DVE,添加clk、rst_n、count信号,观察波形是否在复位释放后正常递增。
预期输出(部分)
END_TIME specified: 500 ns
Simulation started at time 10 ns
Time=10 rst_n=0 count=0
Time=15 rst_n=1 count=0
Time=20 rst_n=1 count=1
Time=25 rst_n=1 count=2
...
Simulation finished at time 510 ns
注意:$monitor在时钟上升沿触发,因此时间点均为CYCLE的整数倍加5ns(因#(CYCLE/2)延迟)。仿真结束时间比指定值多一个时钟沿,属正常现象。
常见问题
- VPD文件未生成:确认编译时使用了
-debug_access+all,且测试平台中$vcdpluson位于initial块内。 - 仿真时间不受控:检查
+END_TIME参数是否拼写正确(区分大小写),或改用+END_TIME=500格式(无空格)。 - 若需FSDB格式:替换
$vcdpluson为$fsdbDumpfile("wave.fsdb"); $fsdbDumpvars;,并使用Verdi查看。