1109
现在我们写它的验证,新建verilog,另存为mux2_dataflow_tb.v。
写它的时标。
然后我们把它置入testbench其中,把它的例化头复制过来。
1110
这个时候我们还没有进入行为,进入行为的时候,我们会来解释,为什么要声明成reg?
现在我们只能说,接到信号发生器的是reg,输出的是线。
本帖最后由 lcytms 于 2016-12-11 23:31 编辑
1111
写激励,八种情况。
写停机。
设置仿真。
1112
查看仿真波形。
看到设计已经得到了验证。
这是数据流的描述。
1113
然后,我们就要描述它的行为了。
行为就是用人类的语言来处理,如果,怎么样。
我们自然而然会想到,如果s为高电平,我们让f输出b,如果s为低电平,让f输出a。
那么就是写一个if的语句,if的语句,类似的就是人类行为的语句。
行为语句,EDA又该如何处理呢?
怎么样才能够描述这种行为的语句,能够被EDA接收,并且它又有哪些约定呢?
就诞生出reg这种定义来。
休息
1119
这个数据流的语句,描述的是what to do,还是how to do呢?
how to do也就是如何实现,如何实现是站在电路设计的角度上,用布尔表达式来实现。
所以说,现在数据流显然描述的只是what to do,在某种意义上,它有一定的how to do的描述,但是呢,是介于其中的。
现在呢,我们来看看行为,行为真正的只描述了what to do,而没有描述how to do,它这个电路结构跟我们的布尔表达式没有任何的关系。
我们只需要描述一个事实,如果怎么样,结果怎么样。
现在我们来做这种描述,我仍然选mux2的代码上,然后另存为mux2_behaviour.v,行为。
1120
交换顶层为mux2_behaviour.v。
我希望EDA能够支持它,因为马上要做仿真。
修改代码,现在我们来写行为。
行为嘛,就是if嘛,if语句,如果s为真值,我们让f输出b,相对的条件,让f输出a。
这个语句的描述,是真正意义上的what to do。
1121
我怎么描述呢?
就是根据事实来描述,根据电路处理的事实。
而电路究竟是如何实现,跟这个布尔表达式没有任何的关联。
它如何变成对应的电路实现,完全交给综合器去做,所以说这就体现出它的behaviour,它的行为。
Case也是行为,if也是行为。
可是这段行为语句呢,EDA却无法识别,因为EDA并不知道行为在什么时候出现。
EDA要是知道行为在什么时候出现,要理解这个行为语句,只有一种方法,就是必须把特定的行为语句置于一个特定的框架之中。
置于一个框架之中,EDA才能认为它是行为,才会执行对行为的处理。
1122
马上我们来看行为语句的三件事情。
行为语句,第一就是框架,置于一个框架之中,这个框架在verilog里面只有两个,一个是初始化的行为框架,就是initial,第二个就是称为循环行为框架,always。
Always的这个框架,当然它们都是行结构,多行要begin…end起来。
虽然if语句是一行,但是我现在还是用begin…end括起来,这是第一件事。
就是行为语句,if也好,case也好,必须置于特定的框架之中。
现在我们要把它置在循环行为框架,这个循环行为框架写成always,你从字面上理解,永远、一直、总在执行。
啥叫总在执行呢?
并不是执行的概念,在这个里面就是一种约定。
当你把行为语句,置于这个框架之中,EDA就会知道,这是一段行为,根据这段行为它就会得到对应的电路。
1123
但是仅仅这样还不够,第一件事要做的,就是框架。
第二件事,是什么呢?
如果我们这样写了以后,EDA还是无法识别。
它无法识别什么呢?
无法识别f这个值,这个时候f这个值是在循环行为体的框架里面,出现在赋值号的左侧的信号,是它的输出信号。
输出信号,这个时候,verilog有一种约定,行为语句的输出,置于循环行为体里面的肯定是循环行为语句。
行为语句的输出,这个行为语句赋值号的左侧,这个信号必须声明成reg。
至于它是否真的会变成寄存器呢?
不一定。
那完全由综合器决定,Moorby的团队,当时的编译器的团队,就是这么制定的,就是行为语句的输出就必须声明成reg。
1124
想到这一点,我们就可以理解了,为什么verilog在它的testbench里面,会把原本接入到信号发生器的部分声明成reg呢?
现在我们理解了,并不是由于它接信号发生器,要把它声明成reg。
而是这个信号会出现在行为语句的左侧。
什么是行为语句呢?
我们会放在初始化行为语句,initial语句里面,initial语句是一个初始化行为的框架。
这是第二件事。
就是行为语句的输出,要声明成reg。
然后还有第三件事。就是这样做了以后,EDA还是无法工作,早期就是这么做的。
为什么EDA还是无法工作呢?
由于这段行为语句,它是由输入关联到输出的,EDA怎么知道什么时候要做这件关联呢?
1125
因此上,它必须时时刻刻来做,每一个时间单位都来做。
每一个时间单位,我们在后仿的时候都涉及到,设置到ps的阶段,每一个ps都要处理时,EDA的开销异常的巨大,非常大。
这个呢,会引起用户管理器里面,我们就会看到CPU的占用率非常大了,而且会非常的卡。
为了解决这个问题,解决EDA的开销的问题,EDA的效率的问题,在米德体系下面,VHDL体系下面,就引入了信号敏感表。
什么是信号敏感表呢?
就是这个时候,有数据者通知EDA,@表明有哪些信号,发生变更的时候,EDA才处理这些行为,才处理对应的循环行为体,使得效率提升。
所以说这一段在VHDL里面,循环行为体的信号敏感表,是与综合无关的。
本帖最后由 lcytms 于 2016-12-18 22:26 编辑
1126
跟综合,不管什么电路,都没有关系,你做不做它,都得到完全相同的电路。
但是呢,非综合目的的时候,仿真验证的时候,在电脑里面运行的时候,由信号敏感表来通知EDA,什么时候做呢?
信号敏感表里面列出的信号发生变更的时候,行为语句才来处理,哪些信号会列到信号敏感表里面呢?
它发生了变更以后如何来处理呢?
显然输入的信号,s发生变化的时候,a发生变化的时候,b发生变化的时候,我们需要处理这段行为。
或者说,我们需要EDA处理这段行为。
所以说,信号敏感表,它的职能,就是哪些信号变化了以后,必须要EDA来处理,用于非综合目的。
但是在verilog里面,Moorby的团队下面呢,做了一个小小的修改,因为在他的团队的商业化运作里面,并没有精确地理解米德体系下信号敏感表的含义。
1127
在稍后我们会说到,信号敏感表里面出现的时钟沿,会影响到综合。
VHDL信号敏感表,不影响综合,和综合无关。
但verilog有关。
所以说,这三件事,我再重复一下。
第一件事,行为语句,要置于行为语句的框架之中。
verilog的框架有两个,第一是always循环行为框架,第二是initial,初始化行为框架,这是第一件事。
第二件事,行为语句的输出,必须声明成reg,这是第二件事。
第三件事,你需要EDA来处理行为的时候,通常用于非综合目的,verilog是跟综合有关,行为语句什么时候处理它的时候,你必须通知它,通知EDA.
有些信号变化的时候,你希望EDA来处理它,这是信号敏感表。
1128
第一,框架,行为体的框架。
第二,行为语句的输出声明成reg。
第三,你必须标注出信号敏感表。
当有些信号发生变化的时候,行为语句才来处理它。
这三件事,完成了以后,我们才正确的描述了what to do。
它要做什么,并没有描述它是如何实现的,如何实现我们交给EDA来去做。
现在,Ctrl+S、Ctrl+K。
现在我们顶层是行为,行为已经做成了,就是用这种方式来描述的。
现在呢,我们就来写验证。
新建verilog,另存为mux2_behaviour_tb.v文件,这是写行为的Testbench,我们不从头写了,将数据流复制过来,修改名字。
