verilog系统函数解读Word下载.docx
- 文档编号:21733421
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:19
- 大小:27.10KB
verilog系统函数解读Word下载.docx
《verilog系统函数解读Word下载.docx》由会员分享,可在线阅读,更多相关《verilog系统函数解读Word下载.docx(19页珍藏版)》请在冰豆网上搜索。
用于从文件中读取数据到寄存器中,任何时候都可以被执行(数据方向:
文件>
>
寄存器);
有以下用法:
1)$readmemb("
<
数据文件名>
"
存贮器名>
2)$readmemb("
起始地址>
3)$readmemb("
结束地址>
4)$readmemh("
5)$readmemh("
6)$readmemh("
其中文件中的地址表示方式@hhhh--hh,但是寄存器中的地址可直接用数表示。
这里说的地址均是寄存器的地址。
9.显示层次任务:
$display("
Dispalyingin%m"
//可以显示正在仿真的位置
10.选通显示:
$strobe(<
输出格式>
//可以保证当所有的赋值语句完成之后才进行显示,同步机制。
11.值变转储任务:
将调试过程中感兴趣的信号转存到VCD文件中的任务。
$dumpfile();
//选择转储的VCD文件
$dumpvars();
//选择需要存储的VCD变量范围
$dumpall;
//建立一个监测点,转储当前所有VCD变量的现行值
$dumpon;
和$dumpoff;
//控制转储的开始和结束,可用时间延时控制转储过程。
1.激励的设置
相应于被测试模块的输入激励设置为reg型,输出相应设置为wire类型,双向端口inout在测试中需要进行处理。
方法1:
为双向端口设置中间变量inout_reg作为该inout的输出寄存,inout口在testbench中要定义为wire型变量,然后用输出使能控制传输方向。
eg:
inout[0:
0]bi_dir_port;
wire[0:
reg[0:
0]bi_dir_port_reg;
regbi_dir_port_oe;
assignbi_dir_port=bi_dir_port_oe?
bi_dir_port_reg:
1'
bz;
用bi_dir_port_oe控制端口数据方向,并利用中间变量寄存器改变其值。
等于两个模块之间用inout双向口互连。
往端口写(就是往模块里面输入)
方法2:
使用force和release语句,这种方法不能准确反映双向端口的信号变化,但这种方法可以反映块内信号的变化。
具体如示:
moduletest();
wiredata_inout;
regdata_reg;
reglink;
#xx;
//延时
forcedata_inout=1'
bx;
//强制作为输入端口
...............
releasedata_inout;
//释放输入端口
endmodule
从文本文件中读取和写入向量
1)读取文本文件:
用$readmemb系统任务从文本文件中读取二进制向量(可以包含输入激励和输出期望值)。
$readmemh用于读取十六进制文件。
例如:
reg[7:
0]mem[1:
256]//a8-bit,256-word定义存储器mem
initial$readmemh("
mem.data"
mem)//将.dat文件读入寄存器mem中
mem,128,1)//参数为寄存器加载数据的地址始终
2)输出文本文件:
打开输出文件用?
$fopen例如:
integerout_file;
//out_file是一个文件描述,需要定义为integer类型
out_file=$fopen("
cpu.data"
);
//cpu.data是需要打开的文件,也就是最终的输出文本
设计中的信号值可以通过$fmonitor,$fdisplay,
2.Verilog和Ncverilog命令使用库文件或库目录
ex).ncverilog-frun.f-vlib/lib.v-ylib2+libext+.v//一般编译文件在run.f中,库文件在lib.v中,lib2目录中的.v文件系统自动搜索
使用库文件或库目录,只编译需要的模块而不必全部编译
3.VerilogTestbench信号记录的系统任务:
1).SHM数据库可以记录在设计仿真过程中信号的变化.它只在probes有效的时间内记录你setprobeon的信号的变化.
ex).$shm_open("
waves.shm"
//打开波形数据库
$shm_probe(top,"
AS"
//setprobeon"
top"
第二个参数:
A--signalsofthespecificscrope
S--Portsofthespecifiedscopeandbelow,excludinglibrarycells
C--Portsofthespecifiedscopeandbelow,includinglibrarycells
AS--Signalsofthespecifiedscopeandbelow,excludinglibrarycells
AC--Signalsofthespecifiedscopeandbelow,includinglibrarycells
还有一个M,表示当前scope的memories,可以跟上面的结合使用,"
AM"
"
AMS"
AMC"
什么都不加表示当前scope的ports;
$shm_close//关闭数据库
2).VCD数据库也可以记录在设计仿真过程中信号的变化.它只记录你选择的信号的变化.
ex).$dumpfile("
filename"
//打开数据库
$dumpvars(1,top.u1);
//scope=top.u1,depth=1
第一个参数表示深度,为0时记录所有深度;
第二个参数表示scope,省略时表当前的scope.
$dumpvars;
//depth=allscope=all
$dumpvars(0);
//depth=allscope=current
//depth=1scope=top.u1
$dumpoff//暂停记录数据改变,信号变化不写入库文件中
$dumpon//重新恢复记录
3).Debussyfsdb数据库也可以记录信号的变化,它的优势是可以跟debussy结合,方便调试.
如果要在ncverilog仿真时,记录信号,首先要设置debussy:
a.setenvLD_LIBRARY_PATH:
$LD_LIBRARY_PATH
(pathfordebpli.sofile(/share/PLI/nc_xl//nc_loadpli1))
b.whileinvokingncverilogusethe+ncloadpli1option.
ncverilog-frun.f+debug+ncloadpli1=debpli:
deb_PLIPtr
fsdb数据库文件的记录方法,是使用$fsdbDumpfile和$fsdbDumpvars系统函数,使用方法参见VCD
注意:
在用ncverilog的时候,为了正确地记录波形,要使用参数:
+access+rw"
否则没有读写权限
在记录信号或者波形时需要指出被记录信号的路径,如:
tb.module.u1.clk.
………………………………………………………………………………………………………
关于信号记录的系统任务的说明:
在testbench中使用信号记录的系统任务,就可以将自己需要的部分的结果以及波形文件记录下来(可采用sigalscan工具查看),适用于对较大的系统进行仿真,速度快,优于全局仿真。
使用简单,在testbench中添加:
initialbegin
$shm_open("
$shm_probe("
要记录信号的路径“,”AS“);
#10000
$shm_close;
即可。
4.ncverilog编译的顺序:
ncverilogfile1file2....
有时候这些文件存在依存关系,如在file2中要用到在file1中定义的变量,这时候就要注意其编译的顺序是
从后到前,就先编译file2然后才是file2.
5.信号的强制赋值force
首先,force语句只能在过程语句中出现,即要在initial或者always中间.去除force用release语句.
initialbeginforcesig1=1'
b1;
...;
releasesig1;
end
force可以对wire赋值,这时整个net都被赋值;
也可以对reg赋值.
6.加载测试向量时,避免在时钟的上下沿变化
为了模拟真实器件的行为,加载测试向量时,避免在时钟的上下沿变化,而是在时钟的上升沿延时一个时间单位后,加载的测试向量发生变化。
assign#5c=a^b
……
@(posedgeclk)#(0.1*`cycle)A=1;
******************************************************************************
//testbench的波形输出
moduletop;
...
initial
begin
$dumpfile("
./top.vcd"
//存储波形的文件名和路径,一般是.vcd格式.
$dumpvars(1,top);
//存储top这一层的所有信号数据
$dumpvars(2,top.u1);
//存储top.u1之下两层的所有数据信号(包含top.u1这一层)
$dumpvars(3,top.u2);
//存储top.u2之下三层的所有数据信号(包含top.u2这一层)
$dumpvars(0,top.u3);
//存储top.u3之下所有层的所有数据信号
end
//产生随机数,seed是种子
$random(seed);
ex:
din<
=$random(20);
//仿真时间,为unsigned型的64位数据
$time
timecondition_happen_time;
condition_happen_time=$time;
$monitor($time,"
datautput=%d"
dout);
//参数
parameterpara1=10,
para2=20,
para3=30;
//显示任务
$display();
//监视任务
$monitor();
//延迟模型
specify
//describpin-to-pindelay
endspecify
modulenand_or(Y,A,B,C);
inputA,B,C;
outputY;
AND2#0.2(N,A,B);
OR2#0.1(Y,C,N);
(A*->
Y)=0.2;
(B*->
Y)=0.3;
(C*->
Y)=0.1;
//时间刻度
`timescale单位时间/时间精确度
//文件I/O
1.打开文件
integerfile_id;
file_id=fopen("
file_path/file_name"
2.写入文件
//$fmonitor只要有变化就一直记录
$fmonitor(file_id,"
%format_char"
parameter);
eg:
%m:
%tin1=%do1=%h"
$time,in1,o1);
//$fwrite需要触发条件才记录
$fwrite(file_id,"
//$fdisplay需要触发条件才记录
$fdisplay(file_id,"
$fstrobe();
3.读取文件
file_id=$fread("
"
r"
4.关闭文件
$fclose(fjile_id);
5.由文件设定存储器初值
$readmemh("
file_name"
memory_name"
//初始化数据为十六进制
$readmemb("
//初始化数据为二进制
//仿真控制
$finish(parameter);
//parameter=0,1,2
$stop(parameter);
//读入SDF文件
$sdf_annotate("
sdf_file_name"
module_instance,"
scale_factors"
//module_instance:
sdf文件所对应的instance名.
//scale_factors:
针对timmingdelay中的最小延时min,典型延迟typ,最大延时max调整延迟参数
//generate语句,在Verilog-2001中定义.用于表达重复性动作
//必须事先声明genvar类型变量作为generate循环的指标
genvari;
generatefor(i=0;
i<
4;
i=i+1)
assign=din[i]=i%2;
endgenerate
//资源共享
always@(AorBorCorD)
sum=sel?
(A+B):
(C+D);
//上面例子使用两个加法器和一个MUX,面积大
//下面例子使用一个加法器和两个MUX,面积小
tmp1=sel?
A:
C;
tmp2=sel?
B:
D;
always@(tmp1ortmp2)
sum=tmp1+tmp2;
模板:
moduletestbench;
//定义一个没有输入输出的module
reg……//将DUT的输入定义为reg类型
wire……//将DUT的输出定义为wire类型
//在这里例化DUT
……//在这里添加激励(可以有多个这样的结构)
always……//通常在这里定义时钟信号
//在这里添加比较语句(可选)
//在这里添加输出语句(在屏幕上显示仿真结果)
一下介绍一些书写Testbench的技巧:
1.如果激励中有一些重复的项目,可以考虑将这些语句编写成一个task,这样会给书写和仿真带来很大方便。
例如,一个存储器的testbench的激励可以包含write,read等task。
2.如果DUT中包含双向信号(inout),在编写testbench时要注意。
需要一个reg变量来表示其输入,还需要一个wire变量表示其输出。
3.如果initial块语句过于复杂,可以考虑将其分为互补相干的几个部分,用数个initial块来描述。
在仿真时,这些initial块会并发运行。
这样方便阅读和修改。
4.每个testbench都最好包含$stop语句,用以指明仿真何时结束。
最后提供一个简单的示例(转自Xilinx文档):
DUT:
moduleshift_reg(clock,reset,load,sel,data,shiftreg);
inputclock;
inputreset;
inputload;
input[1:
0]sel;
input[4:
0]data;
output[4:
0]shiftreg;
reg[4:
always@(posedgeclock)
if(reset)
shiftreg=0;
elseif(load)
shiftreg=data;
else
case(sel)
2’b00:
shiftreg=shiftreg;
2’b01:
shiftreg=shiftreg<
1;
2’b10:
shiftreg=shiftreg>
default:
endcase
Testbench:
//declaretestbenchname
regclock;
regload;
regreset;
//declarationofsignals
wire[4:
reg[1:
//instantiationoftheshift_regdesignbelow
shift_regdut(.clock(clock),
.load(load),
.reset(reset),
.shiftreg(shiftreg),
.data(data),
.sel(sel));
//thisprocessblocksetsupthefreerunningclock
clock=0;
forever#50clock=~clock;
initialbegin//thisprocessblockspecifiesthestimulus.
reset=1;
data=5’b00000;
load=0;
sel=2’b00;
#200
reset=0;
load=1;
data=5’b00001;
#100
sel=2’b01;
sel=2’b10;
#1000$stop;
initialbegin//thisprocessblockpipestheASCIIresultstothe
//terminalortexteditor
$timeformat(-9,1,"
ns"
12);
TimeClkRstLdSftRgDataSel"
$monitor("
%t%b%b%b%b%b%b"
$realtime,
clock,reset,load,shiftreg,data,sel);
posted@2009-10-2811:
24神一样驴子阅读(508)评论
(1)编辑
(转)verilog中文件输入/输出任务
全文地址:
系统函数$fopen用于打开一个文件,并还回一个整数指针.然后,$fdisplay就可以使用这个文件指针在文件中写入信息,写完后,则可以使用$fclose系统关闭这个文件
integerwrite_out_file;
//定义一个文件指针
integerwrite_out_file=$fopen("
write_out_file.txt"
$fdisplay(write_out_file,"
@%h\n%h"
,addr,data);
$fclose("
write_out_file"
以上语法是将addr,data分别显示在"@%h\n%h"中的2个%h的位置,并写入write_out_file文件指针所指向的write_out_file.txt中.
从文件中读取数据,可以用$readmemb
$readmemh
从文件中读入数据,该文件格式是一定的.
reg[7:
0] data[47:
0];
file_name.txt"
data);
就是将file_name.txt中的数据读入到data数组中,然后就可以使用这些数据了.
还有一种方式可以把指定的数据放入指定的存储器地址单元内,就是在存放数据的文本文件内,给相应的数据规定其内存地址,形式如下:
@address_in_hexadecimal data
@2f 20
两个系统任务可以在仿真的任何时刻被执行使用,其使用格式共有以下六种:
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- verilog 系统 函数 解读