首先引入一个例子:

`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. 部署OpenStack问题汇总(七)--解决apache启动错误"httpd:Could not reliably determine..."

    今天在调试openstack的时候,重启apache,出现以下报错: [root@hctrl log]# service httpd restart 停止 httpd:[确定] 正在启动 httpd: ...

  2. 编译源码 JAVA out of memory

  3. 搭建IPv4专有网络

    搭建IPv4专有网络 版权归属:阿里云网站   本教程将指引您搭建一个具有IPv4地址块的专有网络,并为专有网络中的ECS实例绑定一个弹性公网IP(EIP)进行公网访问. 步骤一:创建专有网络和交换机 ...

  4. 配置java环境变量后没有生效的解决办法

    参考文章:https://blog.csdn.net/tooky_poom/article/details/60768458 系统安装了jdk1.7,环境变量正常,但是安装jdk1.8后,修改环境变量 ...

  5. 生存分析(survival analysis)

    一.生存分析(survival analysis)的定义 生存分析:对一个或多个非负随机变量进行统计推断,研究生存现象和响应时间数据及其统计规律的一门学科. 生存分析:既考虑结果又考虑生存时间的一种统 ...

  6. vue之指令系统

    所谓指令系统,大家可以联想咱们的cmd命令行工具,只要我输入一条正确的指令,系统就开始干活了. 在vue中,指令系统,设置一些命令之后,来操作我们的数据属性,并展示到我们的DOM上. OK,接下来我们 ...

  7. OpenCV Create Circular Mask 圆形遮罩

    在OpenCV中,比较常见的是矩形遮罩CvRect,没有专门提供圆形的mask,那么我们只能自己写一个来模拟圆形mask的函数,需要提供的参数为原图的大小,以及圆形mask的圆心位置和半径即可,返回一 ...

  8. react实现全选、取消全选和个别选择

    react里面实现全选和取消全选,个别选择等操作,效果如下 代码: import React, {Component} from 'react' export default class Demo e ...

  9. CentOS 6U7分区大于2TB的磁盘以及挂载大于16TB分区磁盘的解决方案

    一.内容介绍1.问题描述1).问题一 CentOS 6.x 在格式化大于16TB的ext4分区时,会提示如下错误: mke2fs 1.41.12 (17-May-2010)mkfs.ext4: Siz ...

  10. 线程池和进程池的通用写法 ProcessPoolExecutor 和 ThreadPoolExecutor

    import time from comcurrent.futures import ThreadPoolExecutor,ProcessPoolExccoutor#这个方法可以用进程池或者线程池 d ...