vcs的仿真器中如何对指定的通用寄存器器设置不检查时序

豆丁微信公众号
君,已阅读到文档的结尾了呢~~
VCS学习总结_
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
VCS学习总结_
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='http://www.docin.com/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口specify block用来描述从源点(source:input/inout port)到终点(destination:output/inout port)的路径延时(path delay),由specify开始,到endspecify结束,并且只能在模块内部声明,具有精确性(accuracy)和模块性(modularity)的特点。specify block可以用来执行以下三个任务:一、描述横穿整个模块的各种路径及其延时。(module path delay)二、脉冲过滤限制。(pulse filtering limit)三、时序检查。(timing check)specify block有一个专用的关键字specparam用来进行参数声明,用法和parameter一样,不同点是两者的作用域不同:specparam只能在specify block内部声明及使用,而parameter只能在specify block外部声明及使用。////////////////////////////////////////////////////////////////////////////////第一个任务:模块路径延时(module path delay)一条模块路径可以是一条简单的路径(simple path),或者是一条边缘敏感的路径(edge sensitive path),或者是一条状态依赖的路径(state dependent path)。//------------------------------------------------------------------------------一、simple path,可以由以下两种格式中的任意一种来声明:1)、并行连接(patallel connection):source =& destination2)、全连接(full connection):&&&&& source *& destination例:&&& (a, b =& q, qn) = 1; 等价于:&&&&&&&&&&& (a =& q) = 1; (b =& qn) = 1;而(a, b *& q, qn) = 1; 等价于:&&&&&&&&&&& (a =& q) = 1; (b =& q) = 1; (a =& qn) = 1; (b =& qn) = 1;
//------------------------------------------------------------------------------二、edge sensitive path,是那些源点(source)使用边沿触发的路径,并使用边缘标示符指明触发条件(posedge/negedge),如果没有指明的话,那么就是任何变化都会触发终点(destination)的变化。例1:(posedge clk =& (out +: in)) = (1,2);在clk的上升沿,从clk到out的模块路径,其上升延时是1,下降延时是2,从in到out的数据路径是同向传输,即out = in。例2:(negedge clk =& (out -: in)) = (1,2);在clk的下降沿,从clk到out的模块路径,其上升延时是1,下降延时是2,从in到out的数据路径是反向传输,即out = ~in。例3:(clk =& (out : in)) = (1,2);clk的任何变化,从clk到out的模块路径,其上升延时是1,下降延时是2,从in到out的数据路径的传输是不可预知的,同向或者反向或者不变。Note:模块路径的极性(module path polarity):未知极性(unknown polarity,无),正极性(positive polarity,+),负极性(negative polarity,-)。//------------------------------------------------------------------------------三、state dependent path,是那些源点(source)以来指定条件状态的路径,使用if语句(不带else)。在条件=1 or X or Z的情况下,认为条件成立。如果有一条路经,存在多个条件同时成立的情况,那么使用延时最小值的那条限制。例1: specify&&&&&&& if(a)&&&& (b =& out) = (1,2);&&&&&&& if(~a)&&& (b =& out) = (2,3);&&&&&&& if(b)&&&& (a =& out) = (1,2);&&&&&&& if(~b)&&& (a =& out) = (2,3);&&&&& endspecify例2: specify&&&&&&& if(rst)&& (posedge clk =& (q +: data)) = (1,2);&&&&&&& if(~rst)& (posedge clk =& (q +: data)) = (2,3);&&&&& endspecify需要注意的是,所有输入状态都应该说明,否则没有说明的路径使用分布延时(distributed delay),如果也没有声明分布延时(distributed delay)的话,那么使用零延时(zero delay)。如果路径延时和分布延时同时声明的话,则选择最大的延时作为路径延时。另外,也可以使用ifnone语句,在其它所有条件都不满足的情况下,说明一个缺省的状态依赖路径延时。例3: specify&&&&&&& (posedge clk =& (q +: data)) = (1,2);&&&&&&& ifnone (clk =& q) = (2,3);&&&&& endspecify
////////////////////////////////////////////////////////////////////////////////第二个任务,脉冲过滤限制(pulse filtering limit)由于每条传播路径都具有一定的电容性和电阻性,电荷无法在一瞬间积累或消散,所以信号变化的物理特性是具有惯性的。为了更准确地描述这种能力,使用惯性延时(inertial delay),它可以抑制持续信号比传播延时短的输入信号的变化。例1:1ns宽度的窄脉宽通过一个传输延时为2ns的BUFFER
两个脉宽限制值:e-limit(error limit)和r-limit(rejection limit),并且要求e-limit &= r-limit,否则报错。当pulse width &= e-limit时,输出相应的逻辑值;当e-limit & pulse width &= r-limit时,输出X值;当r-limit & pulse width时,输出不发生变化。默认情况下,e-limit = r-limit = module transition delay,也可以使用以下3种控制方式中的任意一种改变路径脉冲限制值:1、使用verilog提供的PATHPULSE$参数,有些仿真器还要求同时使能相应的选项:比如VCS,添加+pathpulse选项。&&&&&&&&& PATHPULSE$ = (&reject-limit&, &error-limit&);&&&&&&&&& PATHPULSE$&path_source&$&path_destination& = (&reject-limit&, &error-limit&);例:&& specify&&&&&&&&&&& (en =& q) = 12;&&&&&&&&&&& (data =& q) = 10;&&&&&&&&&&& (clr, pre *& q) = 4;&&&&&&&&&&& specparam&&&&&&&&&&& PATHPULSE$ = 3, PATHPULSE$en$q = (2,9), PATHPULSE$clr$q = 1;&&&&&&& endspecify&&&&&&&&&&& en =& q的路径:reject-limit = 2, error-limit =9;&&&&&&&&&&& clr =& q和pre =& q的路径:reject-limit = error-limit = 1;&&&&&&&&&&& data =& q的路径:reject-limit = error-limit = 3;2、使用仿真器专用的编译指导。比如VCS,+pulse_r/20(取20%)和+pulse_e/80(取80%),需要注意的是,这个选项要求放在读入RTL网表文件之后,否则设置无效。3、使用SDF文件反标,并且SDF文件中的延时信息具有最高的优先级。SDF文件格式将在后面介绍。脉冲过滤限制的默认格式存在两个缺点:&&& 1、X状态的持续时间比较短。&&& 2、在上升延时和下降延时不相等的情况下,如果脉冲过窄,那么可能出现跟随边缘(trailing edge)先于或等于导引边缘(leading edge)的现象,这时就会淹没X状态。可以通过修改默认格式,加以改善,具体如下:on-event vs on-detect:
negative width pulse detection:
需要注意的是,showcancelled&&list_path_of_outputs,必须在模块路径之前使用,才可以约束到该模块路径。
////////////////////////////////////////////////////////////////////////////////
第三个任务,时序检查(timing check)描述设计要求的时序性能,所有的时序检查有一个参考事件(reference event)和一个数据事件(data event),它们通过一个布尔表达式相联接,还包括一个可选的notifier寄存器选项,这个寄存器用来打印错误信息或者传播X状态。这里把时序检查分成两组来说明:第一组,检查时序窗口的稳定性,包括:setup、hold、recovery和removal。setup:$setup (data_event, reference_event, limit, notifier);当reference_event time - limit & data_event time & reference_event time时,就会报告setup time violations。hold:& $hold&& (reference_event, data_event, limit, notifier);当reference_event time & data_event time & reference_event time + limit时,就会报告hold time violations。setup/hold:$setuphold (reference_event, data_event, setup_limit, hold_limit, notifier);&& $setuphold是$setup和$hold两者的联合。例如:&& $setuphold (posedge clk, negedge d, 2, 1, notifier); 等于&& $setup (negedge d, posedge clk, 2, notifier); 和 $hold (posedge clk, negedge d, 1, notifier);数据事件常常是数据信号,而参考事件常常是时钟信号,如下图:
recovery:$recovery (reference_event, data_event, limit, notifier);当data_event time - limit & reference_event time & data_event time时,就会报告recovery time violations。removal: $removal (reference_event, data_event, limit, notifier);当data_event time & reference_event time & data_event time + limit时,就会报告removal time violations。recovery/removal:$recrem (reference_event, data_event, recovery_limit, removal_limit, notifier);&& $recrem是$recovery和$removal两者的联合。&& $recrem (posedge clr, posedge clk, 2, 3, notifier); 等于&& $recovery (posedge clr, posedge clk, 2, notifier); 和 $removal (posedge clr, posedge clk, 3, notifier);数据事件常常是时钟信号,而参考事件常常是控制信号,比如清除信号或者置位信号,如下图:
$setuphold和$recrem可以接受负值,同时需要激活仿真器的负值时序检查选项(比如VCS:+neg_tchk),同时还有一个限制:&& setup_limit + hold_limit & 仿真精度(simulation unit of precision),&& recovery_limit + removal_limit & 仿真精度(simulation unit of precision),否则仿真器会把负值当成0处理。
第二组,检查时钟和控制信号在指定事件之间的时间间隔,包括:skew、width、period和nochange。skew:$skew (reference_event, data_event, limit, notifier);& 限制最大偏斜&&& $skew (posedge clk1, posedge clk2, 1, notifier);当data_event time - reference_event & limit,则会报告skew time violations。$skew是基于事件(event-based)的,如果监测到一个reference_event,那么就开始评估脉宽,只要监测到一个data_event,就会生成相应的报告,直到监测到下一个reference_event,才重新开始新的监测。如果在监测到一个data_event之前,又监测到一个reference_event,那么就放弃本次评估,重新开始新的评估。width:$width (controlled_reference_event, limit, threshold, notifier);& 限制最小脉宽&&&&&&&&&& $width (posedge in, 2, notifier);这里data_event是隐含的,它等于reference_event的相反边缘,当width & limit时,就会报告width time violations。period:$period (controlled_reference_event, limit, notifier);& 限制最小周期&&&&&&&&&& $period (negedge clk, 10, notifier);这里data_event是隐含的,它等于reference_event的相同边缘,当period & limit时,就会报告period time violations。nochange:$nochange (reference_event, data_event, start_edge_offset, end_edge_offset, notifier);当leading reference event time - start_edge_offset & data_event & trailing reference event time + end_edge_offset时,就会报告nochange time violations。例如:&&&&&&&&& $nochange (posedge clk, data, 0 , 0);当在clk高电平期间,data发生任何变化,就会报告nochange time violations。有时候,路径上的时序检查是在一定条件成立的前提下进行的,这就需要引入条件操作符:&&&。需要注意的是,当存在两个及以上的条件时,要求这些条件首先在specify块外部经过适当的组合逻辑产生一个新的控制信号,然后再引入到specify块内部使用。例如:&&& and u1 (clr_and_set, clr, set);&&& specify&&&&&& $setup (negedge data, posedge clk &&& clr_and_set, 3, notifier);&&& endspecify
////////////////////////////////////////////////////////////////////////////////
SDF文件简述:SDF文件包含指定路径延时(specify path delay),参数值(specparam values),时序检查约束(timing check constraints),互连线延时(interconnect delay),以及一些和仿真不相关的说明信息。反标SDF文件的过程,也算是更新specify block相对应信息的过程,如果SDF文件没有包含某些信息,则参考specify block中的相应信息。SDF时序信息在CELL内部描述,可以包含一个或多个DELAY、TIMINGCHECK和LABEL。DELAY部分包含指定路径的传播延时(specify path delay)和互连线延时(interconnect delay);TIMINGCHECK部分包含时序检查约束信息(timing check constraint);LABEL部分包含新的参数值(specparam)。
DELAY部分:
例1:SDF文件:(IOPATH& in& out& (1.1::1.3)& (1.5::1.7));verilog specify path:(in =& out) = (2, 3);例2:SDF文件:(COND& en==1'b1& (IOPATH& in& out& (1.2)& (1.6));verilog specify path:if (en) (in =& out) = (1, 2);例3:互连线延时:(INTERCONNECT& source_port& load_port& delay_values)SDF文件:(INTERCONNECT& u1/out& u2/in& (1.2::1.4)& (1.4::1.6));
&TIMINGCHECK部分:
例4: SDF文件: (SETUP (posedge data) (posedge clk) (3::4));&&&&&&&&&&&&&&& (HOLD& (posedge data) (posedge clk) (1::2));verilog timing checks: $setup (posedge data, posedge clk, 1);&&&&&&&&&&&&&&&&&&&&&&& $hold&& (posedge clk, posedge data, 2);例5: SDF文件: (SETUP (posedge data) (COND rb==1'b1 (posedge clk)) (3::4));&&&&&&&&&&&&&&& (HOLD& (posedge data) (COND rb==1'b1 (posedge clk)) (1::2));verilog timing checks: $setup (posedge data, posedge clk &&& rb, 1);&&&&&&&&&&&&&&&&&&&&&&& $hold&& (posedge clk &&& rb, posedge data, 2);LABEL部分:例6:SDF文件:(LABEL&&&&&&&&&&&&&&&&& (ABSOLUTE&&&&&&&&&&&&&&&&&&&&& (dh 60)&&&&&&&&&&&&&&&&&&&&& (dl& 40)))verilog文件:specparam dh = 60, dl=40;SDF文件反标是一个有序的过程,这就意味着对于同一对source/load,后续的信息可能修改(INCREMENT)或者覆盖(ABSOLUTE)前面已经声明过的信息,这在反标($sdf_annotate)多个SDF文件时,就很可能发生的。例7:覆盖前面的延时信息(DELAY&&& (ABSOLUTE&&& (IOPATH A Z (1) (2))&&& (IOPATH A Z (2) (3))))
阅读(...) 评论()1. 激励的产生
对于 testbench 而言,端口应当和被测试的 module 一一对应。
端口分为 input,output 和 inout 类型产生激励信号的时候,
input 对应的端口应当申明为 reg,
output 对应的端口申明为 wire,
inout 端口比较特殊,下面专门讲解。1)直接赋值
一般用 initial 块给信号赋初值,initial 块执行一次,always 或者 forever 表示由事件激发反复执行。
举例,一个 module
[plain] view plain copy
`timescale 1ns/1ps
module exam();
reg rst_n;
clk = 1'b0;
rst = 1'b1;
rst = 1'b0;
rst = 1'b1;
#10 clk = ~
大家应该注意到有个#符号,该符号的意思是指延迟相应的时间单位。该时间单位由 timscale 决定.
一般在 testbench 的开头定义时间单位和仿真精度,比如`timescale 1ns/1ps
前面一个是代表时间单位,后面一个代表仿真时间精度。
以上面的例子而言,一个时钟周期是 20 个单位,也就是 20ns。
而仿真时间精度的概念就是,你能看到 1.001ns 时对应的信号值,
而假如 timescale 1ns/1ns,1.001ns 时候的值就无法看到。
对于一个设计而言,时间刻度应该统一,如果设计文件和 testbench 里面的时间刻度不一致,
仿真器默认以 testbench 为准。
一个较好的办法是写一个 global.v 文件,然后用 include 的办法,可以防止这个问题。
对于反复执行的操作,可写成 task,然后调用,比如
task load_
input [3:0] load_
@(negedge clk_50);
$display($time, " && Loading the counter with %h &&", load_value);
load_l = 1’b0;
count_in = load_
@(negedge clk_50);
load_l = 1’b1;
endtask //of load_count
load_count(4’hA); // 调用 task
其他像 forever,for,function 等等语句用法类似,虽然不一定都能综合,但是用在 testbench 里面很方
便,大家可以自行查阅参考文档
2) 文件输入
有时候,需要大量的数据输入,直接赋值的话比较繁琐,可以先生成数据,再将数据读入到寄存器中,
需要时取出即可。
用 $readmemb 系统任务从文本文件中读取二进制向量(可以包含输入激励和输出期望值)。
$readmemh 用于读取十六进制文件。例如:
reg [7:0] mem[256:1] // a 8-bit, 256-word 定义存储器 mem
initial $readmemh ( "E:/readhex/mem.dat", mem ) // 将.dat 文件读入寄存器 mem 中
initial $readmemh ( "E:/readhex/mem.dat", mem, 128, 1 ) // 参数为寄存器加载数据的地址始终
文件调入和打印中,我们 $fread $fwrite 用的更多一些, 大家可以自行查阅参考文档2. 查看仿真结果
对于简单的 module 来说,要在 modelsim 的仿真窗口里面看波形,就用 add wave ..命令
比如, testbench 的顶层 module 名叫 tb,要看时钟信号,就用 add wave tb.clk
要查看所有信号的时候,就用 add wave /*
当然,也可以在 workspace 下的 sim 窗口里面右键单击 instance 来添加波形
对于复杂的仿真,免不了要记录波形和数据到文件里面去。
1)波形文件记录(这部分暂时我没用到呢!)
常见的波形文件一般有两种, vcd 和 fsdb, debussy 是个很好的工具,支持 fsdb,所以最好是 modelsim+debussy 的组
合默认情况下, modelsim 不认识 fsdb,所以需要先装 debussy,再生成 fsdb 文件。
$dumpfile 和$dumpvar 是 verilog 语言中的两个系统任务, 可以调用这两个系统任务来创建和将指定信息导入 VCD 文件.
对于 fsdb 文件来说,对应的命令是 fsdbDumpfile,dumpfsdbvars
(什么是 VCD 文件? 答: VCD 文件是在对设计进行的仿真过程中,记录各种信号取值变化情况的信息记录文件。 EDA
工具通过读取 VCD 格式的文件,显示图形化的仿真波形,所以,可以把 VCD 文件简单地视为波形记录文件.)下面分别
描述它们的用法并举例说明之。
$dumpfile 系统任务:为所要创建的 VCD 文件指定文件名。
举例( "//"符号后的内容为注释文字):
$dumpfile ("myfile.dump"); //指定 VCD 文件的名字为 myfile.dump,仿真信息将记录到此文件
$dumpvar 系统任务:指定需要记录到 VCD 文件中的信号,可以指定某一模块层次上的所有信号,也可以单独指定某一
典型语法为$dumpvar(level, module_name); 参数 level 为一个整数, 用于指定层次数, 参数 module 则指定要记录的模块。
整句的意思就是,对于指定的模块,包括其下各个层次(层次数由 level 指定)的信号,都需要记录到 VCD 文件中去。
$dumpvar (0, top); //指定层次数为 0,则 top 模块及其下面各层次的所有信号将被记录
$dumpvar (1, top); //记录模块实例 top 以下一层的信号
//层次数为 1,即记录 top 模块这一层次的信号
//对于 top 模块中调用的更深层次的模块实例,则不记录其信号变化
$dumpvar (2, top); //记录模块实例 top 以下两层的信号
//即 top 模块及其下一层的信号将被记录
假设模块 top 中包含有子模块 module1,而我们希望记录 top.module1 模块以下两层的信号,则语法举例如下:
$dumpvar (2, top.module1); //模块实例 top.module1 及其下一层的信号将被记录
假设模块 top 包含信号 signal1 和 signal2(注意是变量而不是子模块), 如我们希望只记录这两个信号,则语法举例如下:
$dumpvar (0, top.signal1, top.signal2); //虽然指定了层次数,但层次数是不影响单独指定的信号的
//即指定层次数和单独指定的信号无关
我们甚至可以在同一个$dumpvar 的调用中,同时指定某些层次上的所有信号和某个单独的信号,假设模块 top 包含信
号 signal1,同时包含有子模 块 module1,如果我们不但希望记录 signal1 这个独立的信号,而且还希望记录子模块 module1
以下三层的所有信号,则语法举例如下:
$dumpvar (3, top.signal1, top.module1); //指定层次数和单独指定的信号无关
//所以层次数 3 只作用于模块 top.module1, 而与信号
top.signal1 无关
上面这个例子和下面的语句是等效的:
$dumpvar (0, top.signal1);
$dumpvar (3, top.module1);
$dumpvar 的特别用法(不带任何参数):
$ //无参数,表示设计中的所有信号都将被记录
最后,我们将$dumpfile 和$dumpvar 这两个系统任务的使用方法在下面的例子中综合说明,假设我们有一个设计实例,
名为 i_design,此设计中包含模块 module1,模块 module1 下面还有很多层次,我们希望对这个设计进行仿真,并将仿
真过程中模块 module1 及其以下所有层次中所有信号的变化情况,记录存储到名为 mydesign.dump 的 VCD 文件中去,
则例示如下:
$dumpfile ("mydesign.dump"); //指定 VCD 文件名为 mydesign.dump
$dumpvar (0, i_design.module1); //记录 i_design.module1 模块及其下面层次中所有模块的所有信号
对于生成 fsdb 文件而言,也是类似的
[plain] view plain copy
$fsdbDumpfile("tb_xxx.fsdb");
$fsdbDumpvars(0,tb_xxx);
2)文件输出结果
integer out_ // out_file 是一个文件描述,需要定义为 integer 类型
out_file = $fopen ( " cpu.data " ); // cpu.data 是需要打开的文件,也就是最终的输出文本
设计中的信号值可以通过$fmonitor, $fdisplay,$fwrite
其中$fmonitor 只要有变化就一直记录, $fdisplay 和$fwrite 需要触发条件才记录
initial begin
$fmonitor(file_id, "%m: %t in1=%d o1=%h", $time, in1, o1);
always@(a or b)
$fwrite(file_id,"At time%t a=%b b=%b",$realtime,a,b);
3 参考“A Verilog HDL Test Bench Primier.pdf”
1) DUT(Design Under Test)部分
//-------------------------------------------------
// File: count16.v
// Purpose: Verilog Simulation Example
//-------------------------------------------------
`timescale 1 ns / 100 ps
module count16 (
input rst_n;
input load_l;
input enable_l;
input [3:0] cnt_
input oe_l;
output [3:0]
output [3:0] count_
// tri-state buffers
assign count_tri = (!oe_l) ? count : 4'bZZZZ;
// synchronous 4 bit counter
always @ (posedge clk or negedge rst_n)
if (!rst_n) begin
count &= 4'd0;
else begin
if (!load_l) begin
count &= cnt_
else if (!enable_l) begin
count &= count + 1;
endmodule //of count16
2) Test Bench
//-------------------------------------------------
// File: tb.v
// Purpose: Verilog Simulation Example
// Test Bench
//-----------------------------------------------------------
`timescale 1ns / 100ps
module tb ();
//---------------------------------------------------------
// inputs to the DUT are reg type
reg clk_50;
reg rst_n;
reg load_l;
reg enable_l;
reg [3:0] count_
//--------------------------------------------------------
// outputs from the DUT are wire type
wire [3:0] cnt_
wire [3:0] count_
//----------------------------------------------------------
// create a 50Mhz clock
always #10 clk_50 = ~clk_50; // every ten nanoseconds invert
//-----------------------------------------------------------
// initial blocks are sequential and start at time 0
$display($time, " && Starting the Simulation &&");
clk_50 = 1'd0;
// at time 0
rst_n = 0;
// reset is active
enable_l = 1'd1;
// disabled
load_l = 1'd1;
// disabled
count_in = 4'h0;
oe_l = 4'b0;
// enabled
#20 rst_n = 1'd1;
// at time 20 release reset
$display($time, " && Coming out of reset &&");
@(negedge clk_50); // wait till the negedge of
// clk_50 then continue
load_count(4'hA);
// call the load_count task
@(negedge clk_50);
$display($time, " && Turning ON the count enable &&");
enable_l = 1'b0;
// turn ON enable
// let the simulation run,
// the counter should roll
wait (cnt_out == 4'b0001); // wait until the count
// equals 1 then continue
$display($time, " && count = %d - Turning OFF the count enable &&",cnt_out);
enable_l = 1'b1;
// let the simulation run for 40ns
// the counter shouldn't count
$display($time, " && Turning OFF the OE &&");
oe_l = 1'b1;
// disable OE, the outputs of
// count_tri should go high Z.
$display($time, " && Simulation Complete &&");
// stop the simulation
//--------------------------------------------------------------
// This initial block runs concurrently with the other
// blocks in the design and starts at time 0
initial begin
// $monitor will print whenever a signal changes
// in the design
" clk_50=%b, rst_n=%b, enable_l=%b, load_l=%b, count_in=%h, cnt_out=%h, oe_l=%b, count_tri=%h",
clk_50, rst_n, enable_l, load_l, count_in, cnt_out, oe_l, count_tri
//--------------------------------------------------------------
// The load_count task loads the counter with the value passed
task load_
input [3:0] load_
@(negedge clk_50);
$display($time, " && Loading the counter with %h &&", load_value);
load_l = 1'b0;
count_in = load_
@(negedge clk_50);
load_l = 1'b1;
endtask //of load_count
//---------------------------------------------------------
// instantiate the Device Under Test (DUT)
// using named instantiation
count16 count16_m0 (
.clk (clk_50),
.rst_n (rst_n),
.load_l (load_l),
.cnt_in (count_in),
.enable_l (enable_l),
.oe_l (oe_l),
.count (cnt_out),
.count_tri (count_tri)
//---------------------------------------------------------
// read and write data
reg [7:0] mem[10:1];//read data from file
initial $readmemh ("F:/IC/prj/testbench/prj0/data/mem.dat", mem ); // 将.dat 文件读入寄存器 mem 中
//设计中的信号值可以通过$fmonitor, $fdisplay,$fwrite
//其中$fmonitor 只要有变化就一直记录, $fdisplay 和$fwrite 需要触发条件才记录
integer file_ // out_file 是一个文件描述,需要定义为 integer 类型
initial file_out = $fopen("F:/IC/prj/testbench/prj0/data/wr_mem.dat", "w");
// wr_mem.dat 是需要打开的文件,也就是最终的输出文本
always @(posedge clk_50)
if (/*tb.count16_m0.*/enable_l == 1'd0) begin
$fwrite (file_out, "%h\n", cnt_out[3:0]);
// $fdisplay(file_out, "%h", cnt_out[3:0]);
endmodule //of cnt16_tb
3) sim.do文件
#By : times_poem
cd F:/IC/prj/testbench/prj0
if [file exists work] {
vlog ./*.v
vlog ./src/*.v
vsim -t ps -novopt work.tb
do wave.do run -all
3 testbench 的技巧
1)如果激励中有一些重复的项目,可以考虑将这些语句编写成一个 task,这样会给书写和仿真带来很大方便。例如,
一个存储器的 testbench 的激励可以包含 write, read 等 task。
2)如果 DUT 中包含双向信号(inout),在编写 testbench 时要注意。需要一个 reg 变量来表示其输入,还需要一个 wire
变量表示其输出。
3)如果 initial 块语句过于复杂,可以考虑将其分为互补相干的几个部分,用数个 initial 块来描述。在仿真时,这些
initial 块会并发运行。这样方便阅读和修改。
4)每个 testbench 都最好包含$stop 语句,用以指明仿真何时结束。
5)加载测试向量时,避免在时钟的上下沿变化,比如数据最好在时钟上升沿之前变化,这也符合建立时间的要求。
4 一个简单的例子
测试对象DUT(Device Under Test),dut: device under test.这个只是表示你要调用单元的例化名而已,此名字可以改成任何verilog可识别的字符。
module counter (
output [3:0]
always @ (posedge clk)
if (reset == 1'b1) begin
count &= 0;
end else if ( enable == 1'b1) begin
count &= count + 1;
testbench:
module counter_
wire [3:0]
counter U0 (
.clk (clk),
.reset (reset),
.enable (enable),
.count (count)
initial begin
reset = 0;
enable = 0;
always #5 clk = !
initial begin
$dumpfile ("counter.vcd");
initial begin
$display("\t\ttime,\tclk,\treset,\tenable,\tcount");
$monitor("‰d,\t‰b,\t‰b,\t‰b,\t‰d",$time, clk,reset,enable,count);
initial #100 $
//Rest of testbench code after this line
4. 高级用法
比如 PLI 之类。有需要的,大家再讨论
总体感觉, testbench 是个很难的事情, 这里讨论的只是一些最基本的东西。 真正有技术含量的是 testcase 的设计,设计
阶段合理层次设计以及模块划分等等,我没有做过很大的项目,所以这方面也没有办法提供更多的帮助。经验丰富的
大牛不妨出来讲讲经验, ^_^
testbench 用的较多的东西是:
1、输入数据文件的产生,一般由 matlab 产生,这方面经常涉及浮点到定点的转换、进制的转换的问题;
2、输入数据文件的输出文件的设置;
3、 VCD、 fsdb 等和其他 eda 软件接口的文件的输出;
4、一定范围内的随机数的产生
5、双向端口的仿真
6、与上层 dsp 等 cpu 接口的时序仿真。
panwest: testbench 设计的掌握的技术可多可少,模块级的 HDL 就可以搞定了:
激励产生:高级语言实现( C, C++, Java 等)
DUT: HDL 实现
参考单元:高级语言实现( C, C++, Java 等)
初始化:脚本语言( perl, Tcl/TK)
波形输出:一般脚本自动对比了
数据通过 PLI 进行联系
日后 systemVerilog, e 等语言完善后会减轻一些建立平台的工作量。
synopsys vera support verification.
bench : vera produce
ref module: vera
monitor: vera
coverage analysis : VCS or vera
vera can load c, C++ file .
systemverilog 应该是以后的趋势
一些 random scenario 与 tlm base model 都可以用systemverilog 完成
而一个好的 framework 很重要现在有两各 framework 可以选择vmm, ovm
不过要用上述的 framework 需要很大的 oop 基础要花很长时间学习
关于 systemC 或者 system verilog,大家可以查找相关文档。
需求说明:Verilog设计基础
:testbench的设计 读取文件 写入文件
:时间的诗
十大基本功之 testbench
Verilog testbench的写法之输入输出文件
以下为代码和解释:
`timescale 1ns / 1ps
///////////////////////////////////////////////////////////////...
verilog读写文件测试
module file_test();
integer fp,ret,i;
reg [7:0]x[7:0];
reg [63:0]
Verilog 如何读取并写入文件
Verilog雖然為硬體描述語言,亦提供讀取/寫入文字檔的功能。
Introduction
為什麼需要用Verilog讀取/寫入文字檔呢?主要用在寫Testbench,並且...
verilog testbench编写笔记
1、initial模块赋值时注意在时钟上升沿打入数据
ax = 16'd0;
ay = 11'd0;
网上找来编写&em&testbench&/em&的一些总结,对初学者非常有用(基于&em&verilog&/em&)... 网上找来编写&em&testbench&/em&的一些总结,对初学者非常有用(基于&em&verilog&/em&) 综合评分:4 收藏评论(2)举报...
*版权证明: 只允许上传png/jpeg/jpg/gif格式的图片,且小于3M
*详细原因:
交 i2c_master &em&verilog&/em&代码&em&+testbench&/em& 5积分 立即下载 ...
并行块在测试中经常会用到
fork...join块。使用并行块能表示以同一个时间起点算起的多个时间的运行,并行的执行复杂的过程结构,如循环或任务。egmodule inilne_
verilog读写文件(整理)
以前我一般常用到的系统函数只有几个:$readmemb,$readmemh,$display,$fmonitor,$fwrite,$fopen,$fclose等。通常需要对文件作预处理,才...
verilog testbench中 文本读写的操作
对文件操作时注意文件数据格式和是否带符号
module nr_decoder_topv2_
没有更多推荐了,

我要回帖

更多关于 特殊功能寄存器 的文章

 

随机推荐