Verilog重要语法和关键字梳理

1 语法

Verilog HDL建模方法
——时序逻辑建模(时钟驱动,上升沿,下降沿always@(posedge ** or negedge **),有限状态机FSM)
——组合逻辑建模(always@(*))

技巧
上述建模方法提示我们

  1. 善于用always@(posedge clk)来检测状态;
  2. 善于用assign生成触发信号、标志信号或者驱动后级电路的信号;
  3. 所有的时序电路都可以用状态机来实现,线程的并行是必须的,正因为线程的特性导致c语言是简单的。

Verilog HDL描述方法
–结构描述:(例化)
–数据流描述:(assign,并行赋值语句)
–行为描述: 过程结构语句(always initial task initial)
case条件语句
语句块(begin_end fork_join)
时序控制 时延控制 事件控制 边沿事件 电平敏感
过程性赋值 连续赋值 阻塞赋值 非阻塞赋值 过程性连续赋值 条件赋值
–混合描述:(各种建模方法结合起来)

RTL
RTL概念:(可综合)
RTL描述:以规定设计中的各类寄存器为特征,在寄存器之间插入组合逻辑。特色是由一系列组合电路模块和寄存器模块相互级联而成的。即组合电路和时序电路各自独立且级联,
而信号的通过由一种逐级传输的特征,所以这种电路被称为寄存器传输级电路。

一切用于各种独立的组合电路模块和独立的组合电路和独立的寄存器模块以数字电路的形式都称为RTl描述,而且即使不包含时序模块,或只有寄存器模块的同类描述形式也被称为RTL描述。

RTL仿真:即功能仿真,不涉及电路的细节(如门级细节)的RTL模块级构成的系统的仿真。而设计电路细节和时序仿真的叫做门级仿真。

RTl描述:把一个完整的,可综合的HDL代码对电路的表述称之为RTL描述。

RTL级,RTL电路:可用电路模块表述的电路层次,对应的电路就称之为RTL电路。
物理级——晶体管级——门级——RTL级——行为级——系统级

锁存器与触发器
不完整的if语句会产生锁存器:1、时序电路,生成触发器,触发器是有使能端的,使能端无效时数据不变,这是触发器的特性。 2、组合逻辑,由于数据要保持不变,只能通过锁存器来保存
锁存器与触发器最大的区别在于,锁存器是电平触发,而触发器是边沿触发。锁存器在不锁存数据时,输出随输入变化;但一旦数据锁存时,输入对输出不产生任何影响。

语句不完整即有某些情况的输入对输出无任何影响,根据锁存器的特征,反映到硬件电路即会产生锁存器。

2 关键字

2.1 “=”和“<=”的区别

一般情况下使用<=,组合逻辑使用=赋值,时序逻辑使用<=赋值。

举个例子:初始化m=1,n=2,p=3;分别执行以下语句

1、begin 
   m=n;n=p;p=m;
   end
2、begin
   m<=n; n<=p; p<=m;
   end

结果分别是:
1、m=2,n=3,p=2;(在给p赋值时m=2已经生效)
2、m=2,n=3,p=1;(在begin-end过程中,m=2一直无效而是在整体执行完后才生效)

这两种赋值“=”用于阻塞式赋值;“<=”用于非阻塞式赋值中。

阻塞赋值:阻塞赋值语句是在这句之后所有语句执行之前执行的,即后边的语句必须在这句执行完毕才能执行,所以称为阻塞,实际上就是顺序执行,相当于串行执行。

非阻塞赋值:非阻塞赋值就是与后边相关语句同时执行,即就是并行执行。

所以一般时序电路使用非阻塞赋值,assign语句一般使用=阻塞赋值;组合逻辑电路使用阻塞赋值;

2.2 reg-always和wire-assign

2.2.1 wire和reg

wire型变量综合出来一般情况下是一根导线。 reg变量在always中有两种情况(1)always @(a or b or c)形式的,即不带时钟边沿的,综合出来还是组合逻辑
(2)always @(posedge clk)形式的,即带有边沿的,综合出来一般是时序逻辑,会包含触发器(Flip-Flop)

设计中,输入信号一般来说不能判断出上一级是寄存器输出还是组合逻辑输出,对于本级来说,就当成一根导线,即wire型。而输出信号则由自己来决定是reg还是组合逻辑输出,wire和reg型都可以。但一般的,整个设计的外部输出(即最顶层模块的输出),要求是reg输出,这比较稳定、扇出能力好。

大体来说,reg和wire类似于C、C++的变量,但若此变量要放在begin…end之内,则该变量只能是reg型;在begin…end之外,则用wire型;使用wire型时,必须搭配assign;reg型可以不用;input、output、inout预设值都是wire型。

reg和wire的区别

  1. reg型数据保持最后一次的赋值,而wire型数据需要持续的驱动。wire用在连续赋值语句assign中;reg用于always过程赋值语句中。

  2. 在连续赋值语句assign中,表达式右侧的计算结果可以立即更新到表达式的左侧,可以理解为逻辑之后直接连接了一条线,这个逻辑对应于表达式的右侧,这条线对应于wire;

  3. 在过程赋值语句中,表达式右侧的计算结果在某种条件的触发下放到一个变量当中,这个变量可以声明成reg型,根据触发条件的不同,过程语句可以建模不同的硬件结构:

    (1)如果这个条件是时钟上升沿或下降沿,那硬件模型就是一个触发器,只有是指定了always@(posedge or negedge)才是触发器。

    (2)如果这个条件是某一信号的高低电平,那这个硬件模型就是一个锁存器。

    (3)如果这个条件是赋值语句右侧任意操作数的变化,那这个硬件模型就是一个组合逻辑。

2.2.2 always和assign

过程赋值语句always@和连续赋值语句assign的区别:

(1)wire型用于assign的赋值,always@块下的信号用reg型。这里的reg并不是真正的触发器,只有敏感列表内的为上升沿或下降沿触发时才综合为触发器。

(2)另一个区别,举例:

wire a;
reg b;
assign  a = 1'b0;
always@(*)
       b = 1'b0;

上面例子仿真时a将会是0,但是b的状态是不确定的。因为Verilog规定,always@()中的指的是该always块内的所有输入信号的变化为敏感列表,就是说只有当always@(*)块内输入信号发生变化,该块内描述的信号才会发生变化。

像always@(*) b= 1’b0; 中由于1‘b0是个常数,一直没有变化,由于b的足组合逻辑输出,所有复位时没有明确的值–即不确定状态,又因为always@(*)块内没有敏感信号变化,此时b信号一直保持不变,即不确定是啥,取决于b的初始状态。

猜你喜欢

转载自blog.csdn.net/zhanshen112/article/details/107523553