一 前言
初始化操作只是针对Verilog代码,这个功能的目的在于减少门级仿真时初始化的时间,避免门级仿真时X的传播,导致逻辑行为异常。请参见VCS 用户手册 P197页:
对于编译选项+vcs+initreg+random 的,突发奇想的想测试一下,它到底是一个什么东西。
在vcs编译选项中,使用该功能,可以:
(1)该选项来将reg、bit、integer、int、logic变量的初值,设置成我们需要的值(0、1、random)
(2)initreg相关选项包括了编译选项和仿真选项
(3)请记住:只有这三种情况:0、1、0/1,没有x\z状态(但是config+config_file可以出现x、z态)
二 语法和组合
组合一:编译选项为(+vcs+initreg+0) + 仿真选项为(+vcs+initreg+0)
组合二:编译选项为(+vcs+initreg+1) + 仿真选项为(+vcs+initreg+1)
组合三:编译选项为(+vcs+initreg+random) + 仿真选项为(+vcs+initreg+0/1/random/seed)
组合四:编译选项为(+vcs+initreg+random) + 仿真选项为(+vcs+initreg+seed_value)
这样整个仿真的初值由仿真选项指定。random和seed_value表示初值为随机值,这是比较符合真实芯片特性的行为。seed_value主要是从可复现的角度来进行随机,种子相同时,随机出来值是一样的。以上初值设置对整个设计都是生效的。
更为具体的选项解释说明如下:
组合五:编译选项为(+vcs+initreg+config+config_file)+ 仿真选项为(+vcs+initreg+config+config_file)
通过该方式,仿真的初值也是由仿真选项指定。初值是什么,由config_file文件内容决定。和第一种方式的区别在于,这样可以比较灵活地指定设计的各个部分的初值是什么。比如harness中初值设定为0,DUT的初值设置为随机,config_file的文件语法格式可以参考vcs的user_guide。这里不展开介绍。
当多选项场合重叠使用的时候,选项优先级如下:
config_file 初始化数值的语法:
注1:depth :0 全部子单元均配置初始值;1 只是当前instance配置初始值;2 当前instance下2单元级被配置初始值,依次类推
注2:compile阶段的initfile可以与runtime不一致,以runtime的intfile为准
注3:需要打印设计中初始化的值,则需要使能VCS_PRINT_INITREG_INITIALIZATION值,方法为在makefile中,export VCS_PRINT_INITREG_INITIALIZATION = 1,会在仿真目录下产生vcs_initreg_random_value.txt。
注4:+nomem//不初始化memory及多维数组 ;+noreg//不初始化不包含多维数组的变量
+vcs+initreg+random+nomem +vcs+initreg+random+noreg
三 实战举例
看到一篇介绍博客,里面牵涉到该选项,但是博主介绍的并不彻底,今天,利用周末的时间,做个小实验,研究一下到底怎么运作和会有怎样的效果。
我们先给出一个最简单的例子:
`timescale 1ns/1ps
import uvm_pkg::*;
module tb_top();
reg clk,rst;
initial begin
clk = 0;
forever #5 clk = ~ clk;
end
initial begin
rst = 1;
#30 rst = 0;
end
always @ (posedge rst) begin:always_block1
$display("The always block1 was fired @Time %f", $time());
end
always @ (negedge rst) begin:always_block2
$display("The always block2 was fired @Time %f", $time());
end
always @ (rst) begin:always_block3
$display("The always block3 was fired @Time %f", $time());
end
initial begin
run_test("helloworld_test") ;
end
endmodule
上面的例子是一个很简单的基于UVM的test 顶层module。 里面定义了一个 reg: rst。
场景1:
rst 初始化数值为 1; 在30个 仿真时间单元之后,将其设置为0;同时,我们在vcs 编译选项中添加:+vcs+initreg+random
仿真结果(默认):,结果如下:
场景1.1:./simv +vcs+initreg+1 结果如下:
场景1.2:./simv +vcs+initreg+0 结果如下:
场景1.2:./simv +vcs+initreg+z 结果如下:
场景1.2:./simv +vcs+initreg+x 结果如下:
场景2:
rst 初始化数值为 0; 在30个 仿真时间单元之后,将其设置为0;同时,我们在vcs 编译选项中添加:+vcs+initreg+random
仿真结果(默认):
场景2.1:./simv +vcs+initreg+0
场景2.2:./simv +vcs+initreg+1
场景2.3:./simv +vcs+initreg+z
场景2.4:./simv +vcs+initreg+x
场景3:
rst 初始化数值为 ‘z; 在30个 仿真时间单元之后,将其设置为0;同时,我们在vcs 编译选项中添加:+vcs+initreg+random
场景3.1:./simv +vcs+initreg+z,结果如下:
场景3.2:./simv +vcs+initreg+0,结果如下:
场景3.3:./simv +vcs+initreg+1,结果如下:
场景3.4:./simv +vcs+initreg+x,结果如下:
场景4:
rst 初始化数值为 ‘x; 在30个 仿真时间单元之后,将其设置为0;同时,我们在vcs 编译选项中添加:+vcs+initreg+random
仿真结果: 和场景3 ,结果一模一样。
四 结论
该特性可以看成是一种特殊的0时刻赋值操作,即可以当成是一个独立的initial语句,且该语句的执行优先级最高,因此,如果使用+vcs+initreg+random特性,也会在0时刻触发对应的always块。