首先引入一个例子:

`timescale  1ns/100ps

module   TB;                                                                                       module  INV_DFF(Clock, Reset_n, DataIn, DataOut);

reg Ck, Rst_n, Din;                                                                                  input Clock;

wire Dout;                                                                                               input Reset_n;

//Clock  generation                                                                                  input DataIn;

initial   begin                                                                                           output reg Data_Out

Ck = 0;                                                                                   wire DataInv;

forever   #10 Ck = ~Ck;                                                           always @(posedge Clock or negedge Reset_n)

end                                                                                                           begin if(~Reset_n)

//Reset  generation                                                                                                            Data_Out <= 1'b0;

initial   begin                                                                                                                  else Data_Out <= Data_Inv;

Rst_n = 1;                                                                                             end

#5 Rst_n = 0;                                                                          assign #3 DataInv = ~ DataIn;

#55 Rst = 1;                                                                        endmodule

end

//Data input generation

initial   begin

Din = 0;

#80 Din = 1;

#40 Din = 0;

end

INV_DFF     u_INV_DFF(                 //DUV

.Clock(Ck),

.Reset_n(Rst_n),

.DataIn(Din),

.DataOut(Dout),

);

0仿真时刻:3个initial进程和1个DUV同时执行。同时执行的进程其顺序不是固定的,和所用的仿真器有关,假设此处的同时执行,按代码中的顺序来执行。

执行Clock Generation 中的语句Ck = 0; ~Ck。 执行forever #10 进程挂起。

执行Reset Generation 中的语句Rst_n = 1; #5 进程挂起。

执行Data Input Generation中的语句Din = 0; #80 进程挂起。

执行DUV中的语句~DataIn; #3进程挂起。always @进程挂起。 至此0仿真时刻的语句全部执行完毕,仿真时间轴向前推进。

3仿真时刻:只有一个计算事件 DataInv = #3 ~DataIn;更新DataInv的值。无触发更多计算事件,所以仿真时间轴向前推进。

5仿真时刻:执行Reset Generation 中的语句 Rst_n = 0; #55 进程挂起。

由于Rst_n的更新时间,DUV中的always @进程执行,DataOut值更新。无触发更多计算事件,仿真时间轴向前推进。

10仿真时刻: 执行Clock Gneration 中的计算事件CK。更新事件触发。#10进程挂起。

执行DUV中的always进程,计算事件Data_Out = 0。无触发更多事件,仿真时间轴向前推进。

60仿真时刻: 执行Clock Gneration 中的计算事件CK。更新事件触发。#10进程挂起。

执行Reset Generation 中的语句 Rst_n = 1; 进程结束。

执行DUV中的always进程,计算事件Data_Out = 1(Rst_n的值已经为1)。无触发更多事件,仿真时间轴向前推进。

80仿真时刻: 执行Clock Gneration 中的计算事件CK。更新事件触发。#10进程挂起。

执行Data Input Generation中的语句Din = 1; #40 进程挂起。

执行DUV中的always进程,计算事件Data_Out = Data_Inv。

执行DUV中的语句~DataIn; #3进程挂起。always @进程挂起。 至此0仿真时刻的语句全部执行完毕,仿真时间轴向前推进。

仿真时间:是仿真时间维护的时间值,用来对仿真电路的真实时间进行建模(仿真时间和软件的执行时间没有任何联系),当仿真时间推进到某一个时间点时,该时间点就被称为当前仿真时间,而以后的任何时间都被称为将来仿真时间。

事件:模型中数值的变化,功能仿真是一种事件驱动的仿真,整个仿真过程都是围绕事件来组织的。

更新事件:在被仿真的电路中,线网或寄存器的值在任何进程中的任何改变都被认为是一个更新事件。

计算事件:由于更新事件产生的,进程的计算,计算事件。

计算事件和更新事件之间循环往复的互相触发,推动仿真时间的前进。

进程是Verilog中的独立执行单元,包括:原语(Primitives), 模块(Moules), initial过程块, always过程块, 连续赋值语句(assign), 异步任务(task)。在仿真时,所有的进程都是仿真器按Verilog的语义来顺序执行的,效果是各个进程并行执行的效果,在未执行完当前所有的进程时,仿真时间不会向前推进。

initial   begin

Ck = 0;  forever Ck = ~Ck;

end

例子会hang在仿真时刻0,因为更新时间一直触发计算事件,计算事件一直触发更新时间。

Verilog中的时序控制:事件语句(@),延时语句(#),等待语句(wait)。

Verilog仿真时的不确定性:在同一个仿真时间内,几个同一调度模块中事件执行顺序的任意性,进程之间语句的任意交织。

verilog或者systemverilog相对于C,能用于硬件建模的最大区别:

1)connectivity  一个大的design可以由很多block,组成,通过例化或者interface来进行连接

2)time   time的变化可以使得design的state变化,与执行时间(execution time)完全不同,通过@/wait/#来实现

3)concurrency    event之间的同步发生关系, 通过initial/always/fork join来实现

对于验证还缺少:1)randomization;  2)constrainability;  3)functional coverage;

在simulator中的concurrency是基于time_share的来跑的,CPU轮询执行。

always模块,initial模块,连续赋值模块,fork/join,都是完全并行执行的,并没有先后顺序。

在基于time-sharing的处理中,simulator对于各个并行thread,保证访问机会时一样的,但是各个模块的先后顺序不能保证,

和代码块中的位置有关。simulator也不会自己关掉一个thread,除非自己执行结束。

Verilog的事件调度:

在systemverilog中有两种thread,module thread和program thread,module thread主要用来建模design,

program thread主要用来建模testbench。

program中的task的执行,主要看task的定义位置,如果是在module内定义的task,则尽管在program中调用,也算是一个

module thread。

对于program和module内的class的执行顺序,systemverilog标准中,并没有准确给出,根据simulator的实现而不同。

program中在SV2012中,才开始支持非阻塞赋值。

其中的执行顺序:

1)sample阶段,进行clock,property这样的采样。

2)excute阶段,执行阻塞赋值等。

3)reactive阶段,执行非阻塞赋值等。以及阻塞赋值的迭代。

4)evaluate阶段,执行assertion的判断。

5)program thread阶段,执行program中的阻塞赋值,非阻塞赋值

simulation的前进,依靠两条线,一条simulation time,另一个是module thread中的非阻塞赋值和阻塞赋值之间的迭代。

其中第二种也称为delta cycle,一个设计中可能会有很多delta cycle,因为信号的依赖关系可以一直迭代。

几种存在race condition的情况:

1)concurrent中的冲突:

2)delta cycle对clock的影响:

如果两个时钟有信号之间的采样关系,而且一个clock比另一个clock多一个非阻塞赋值。

此时,两个clock之间会差一个delta cycle,在RTL仿真时,两个clock之间的信号采样会出错。

快一点的clock的值,可以再被慢一点的采到,但是在波形中不会体现出来。

这时的解决方法:

1)手工增加delay

2)将另一个clock 也经过一个非阻塞赋值。

Verilog篇(三)仿真原理的更多相关文章

  1. VCS使用学习笔记(1)——Verilog相关的仿真知识

    本文主要学习Verilog的仿真特性,以及仿真器对Verilog的处理,算是对Verilog知识的增量学习.本文内容与我的另一篇博文(http://www.cnblogs.com/IClearner/ ...

  2. 敌情篇 ——DDoS攻击原理

    敌情篇 ——DDoS攻击原理 DDoS攻击基础 DDoS(Distributed Denial of Service,分布式拒绝服务)攻击的主要目的是让指定目标无法提供正常服务,甚至从互联网上消失,是 ...

  3. 阻塞赋值与非阻塞赋值(verilog篇)

    阻塞赋值与非阻塞赋值(verilog篇) 2017-09-30 竹海 相约电子ee 相信刚刚接触verilog的读者,多少对阻塞赋值和非阻塞赋值仍有一些困惑.笔者在这篇文章,带领大家深入的理解这两者的 ...

  4. 【基于WinForm+Access局域网共享数据库的项目总结】之篇三:Access远程连接数据库和窗体打包部署

    篇一:WinForm开发总体概述与技术实现 篇二:WinForm开发扇形图统计和Excel数据导出 篇三:Access远程连接数据库和窗体打包部署 [小记]:最近基于WinForm+Access数据库 ...

  5. 【基于WPF+OneNote+Oracle的中文图片识别系统阶段总结】之篇三:批量处理后的txt文件入库处理

    篇一:WPF常用知识以及本项目设计总结:http://www.cnblogs.com/baiboy/p/wpf.html 篇二:基于OneNote难点突破和批量识别:http://www.cnblog ...

  6. 【SSRS】入门篇(三) -- 为报表定义数据集

    原文:[SSRS]入门篇(三) -- 为报表定义数据集 通过前两篇文件 [SSRS]入门篇(一) -- 创建SSRS项目 和 [SSRS]入门篇(二) -- 建立数据源 后, 我们建立了一个SSRS项 ...

  7. 机器学习之决策树三-CART原理与代码实现

    决策树系列三—CART原理与代码实现 本文系作者原创,转载请注明出处:https://www.cnblogs.com/further-further-further/p/9482885.html ID ...

  8. 爬虫前篇 /https协议原理剖析

    爬虫前篇 /https协议原理剖析 目录 爬虫前篇 /https协议原理剖析 1. http协议是不安全的 2. 使用对称秘钥进行数据加密 3. 动态对称秘钥和非对称秘钥 4. CA证书的应用 5. ...

  9. Verilog学习笔记设计和验证篇(三)...............同步有限状态机的指导原则

    因为大多数的FPGA内部的触发器数目相当多,又加上独热码状态机(one hot code machine)的译码逻辑最为简单,所以在FPGA实现状态机时,往往采用独热码状态机(即每个状态只有一个寄存器 ...

随机推荐

  1. spring boot 单元测试,如何使用profile

    一.问题概述 spring boot项目.单元测试的时候,我发现,总是会使用application.properties的内容,而该文件里,一般是我的开发时候的配置. 比如上图中,dev是开发配置,p ...

  2. 4G厂商版《出师表》

    转载:http://mp.weixin.qq.com/s?__biz=MzAwNDAyODM0NA==&mid=408013599&idx=1&sn=70cd33d037604 ...

  3. POJ 3258 River Hopscotch(二分答案)

    River Hopscotch Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 21939 Accepted: 9081 Desc ...

  4. 从Java代码到字节码(1)

    理解Java代码是如何被编译为字节码并在Java虚拟机(JVM)上执行是非常重要的,这将帮助理解你的程序是如何执行的.这样的理解不仅仅能够让你在逻辑上更好的掌握语言特性,而且能够有机会理解在做出重要决 ...

  5. 【CF720D】Slalom 扫描线+线段树

    [CF720D]Slalom 题意:一个n*m的网格,其中有k个矩形障碍,保证这些障碍不重叠.问你从(1,1)走到(n,m),每步只能往右或往上走,不经过任何障碍的方案数.两种方案被视为不同,当且仅当 ...

  6. Spark2 Dataset之视图与SQL

    // 创建视图 data.createOrReplaceTempView("Affairs") val df1 = spark.sql("SELECT * FROM Af ...

  7. ubuntu下中文乱码解决方案(全)

    转自 http://www.cnblogs.com/end/archive/2011/04/19/2021507.html   1.ibus输入法 Ubuntu 系统安装后已经自带了ibus输入法,在 ...

  8. stress test - volume test

    D:\wamp64\bin\mysql\mysql5.7.11\bin>mysqlslap --delimiter=";" --query=" INSERT I N ...

  9. JIRA licence and vulnarability,jenkins,devops

    http://blog.itpub.net/13651903/viewspace-1079918/ http://www.freebuf.com/articles/web/34051.html JIR ...

  10. Java中子类是否可以继承父类的static变量和方法而呈现多态特性

    静态方法 通常,在一个类中定义一个方法为static,那就是说,无需本类的对象即可调用此方法,关于static方法,声明为static的方法有以下几条限制: 它们仅能调用其他的static 方法. 它 ...