组合逻辑:输出只是当前输入逻辑电平的函数(有延时),与电路的原始状态无关。当前电路输入信号任何一个发生改变,输出都将发生改变。
时序逻辑:输出不仅是当前输入电平的函数,还与目前电路的状态有关。
同步时序:表示状态的寄存器组只能在唯一确定的触发条件发生时刻改变。
异步时序:表示触发条件由多个控制因素组成,如一个触发器的输出连接到另一个触发器的时钟就是异步时序逻辑。
阻塞赋值是按序执行,计算等号右边的值并同时赋给左边变量,当前语句完成才能执行下一句
所谓阻塞的概念是指在同一个always块中,其后面的赋值语句从概念上(即使不设定延迟)是在前一句赋值语句结束后再开始赋值的。
非阻塞赋值是并行执行,各语句同时执行,注意如果begin——end中存在非阻塞赋值,由于非阻塞是并发执行的,这时就不是一条一条执行的,有点类似fork——join块语句。
当执行“x=next_x;”时,x会立即的到next_x的值。而下一句“y=x;”必须等到“x=next_x;”执行完毕才能被执行。由于这两条语句都没有延迟(相当于导线),导致他们的等价语句为“y=next_x;”。时序逻辑用《=
① 在组合逻辑电路描述中采用阻塞赋值
② 时序逻辑描述,采用非阻塞赋值方式赋值
initial不可综合,一般是用在程序模块最开始初始化数据用,对寄存器、输出等变量进行清零等工作。特别是在testbench中应用非常普遍,
wire对应于连续赋值,如assign; reg对应于过程赋值,如always,initial;wire型变量综合出来一般情况下是一根导线。 reg变量在always中有两种情况: (1)always @(a or b or c)形式的,即不带时钟边沿的,综合出来还是组合逻辑,此时用阻塞赋值。; (2)always @(posedge clk)形式的,即带有边沿的,综合出来一般是时序逻辑,会包含触发器(Flip-Flop)
在组合电路always语句块里面,output信号必须定义为reg,不能用wire,如果只是assign语句,左侧必须为net类型(例如,wire),右侧wire和reg都可以。wire表示connection,reg表示variable,其实有两种意思,一种是时序电路的register,一种是组合电路的logic,verilog语法没有仔细地区分,造成一些误解,其实组合电路里面的应该定义成logic类型
设计中,输入信号一般来说不能判断出上一级是寄存器输出还是组合逻辑输出,对于本级来说,就当成一根导线,即wire型。而输出信号则由自己来决定是reg还是组合逻辑输出,wire和reg型都可以。但一般的,整个设计的外部输出(即最顶层模块的输出),要求是reg输出,这比较稳定、扇出能力好。
#1: 当为时序逻辑建模,使用“非阻塞赋值”。
#2: 当为锁存器(latch)建模,使用“非阻塞赋值”。
#3: 当用always块为组合逻辑建模,使用“阻塞赋值”
#4: 当在同一个always块里面既为组合逻辑又为时序逻辑建模,使用“非阻塞赋值”。
#5: 不要在同一个always块里面混合使用“阻塞赋值”和“非阻塞赋值”。
#6: 不要在两个或两个以上always块里面对同一个变量进行赋值。
#7: 使用$strobe以显示已被“非阻塞赋值”的值。
#8: 不要使用#0延迟的赋值。