Verilog HDL语言小知识

本文介绍了Verilog HDL的基础知识,包括模块的构成及其在设计中的作用,详细阐述了时延的概念以及如何通过连续赋值语句描述数据流行为。同时,探讨了行为描述方式,如initial和always语句在实现电路功能中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前面已经介绍了什么是HDL,现在我们来了解一下HDL的模块和数据流方式。

1、模块

模块是Verilog的基本描述单位,用于描述某个设计的功能或结构与其他模块通信的·外部端口。一个设计的结构可使用开关级原语、门级原语和用户定义的原语方式描述;设计数据流行行为使用连续赋值语句进行描述;时序行为使用过程结构描述。一个模块可以在另一个模块中使用。
一个模块基本语法如下:

module module_name(port_list);
	Declarations:
		reg,wire,parameter,
		input,output,inout,
		function,task,.......
	Statements:
		initial statement
		Always statement
		Module instantiation
		Gate instantiation
		Udp instantiation
		Continuous assignment
endmodule

说明部分和语句可以散布在模块的任何地方;但是变量、寄存器、线网和参数等的说明部分必须在使用前出现。为使得模块有好的可读性,最好把说明语句放在语句前面。
下面举一个半加器电路的模块例子。
1
程序如下:

module halfadder(A,B,Sum,Carry);
	input A,B;
	output Sum,Carry;
assign #2 Sum=A^B;
aseign #5 Carry = A & B;
endmodule

上面模块名字为halfadder。两个输入端口A和B,输出端口为Sum和Carry。因为没有定义端口的位数,所有端口大小为1位;因为没有说明各端口的数据类型说明,所以这四个端口都是线网数据类型。
模块包含两条描述半加器数据流行为的连续赋值语句。语句是并发的。
可以使用以下方式描述模块的设计:

  1. 数据流方式
  2. 行为方式
  3. 结构方式
  4. 上述描述方式的混合

2、时延

Verilog HDL模型中所有时延都根据时间单位定义。
带时延连续赋值语句实例:

assign #2 Sum=A^B; #2指的是2个时间单位

使用编译指令将时间单位与物理时间相关联。编译器指令需在模块描述前定义:

timescale lns/100ps
这个语句是讲时延单位为1ns,时间精度为100ps(时间精度指的是所有时延必须限定在0.1ns内)如果此编译器指令所在模块包含上面的连续赋值语句,#2代表2ns
如果没有这样的编译器指令,模拟器会指定一个缺省的时间单位

3、数据流描述方式

用数据流描述方式对一个设计建模的最基本的机制就是使用连续赋值语句。在连续赋值吾句中,某个值被指派给线网变量。连续赋值语句的语法为:

assign [delay] LHS_net=RHS_expression
右边表达式使用的操作数无论何时发生变化,右边都要重新计算,并且在指定的时延后变化值赋予左边表达式的线网变量。时延定义右边表达式操作数变化与赋值给左边的表达式之间的持续时间。如果没有定义时时延值,缺省时延为0.

下面举例一个使用数据流描述方式对解码器
2
3
以反引号“`”开始的第一条语句是编译器指令,编译器指令’timescale 将模块中所有时延的单位设置为1 ns,时间精度为1 ns。例如,在连续赋值语句中时延值#1和#2分别对应时延1 ns和2 ns。
模块Decoder2x4有3个输入端口和1个4位输出端口。线网类型说明了两个连线型变量Abar和Bbar(连线类型是线网类型的一种)。此外,模块包含6个连续赋值语句。
参见下图中的波形图。当EN在第5 ns变化时,语句3、4、5和6执行。这是因为EN是这些连续赋值语句中右边表达式的操作数。Z[0]在第7 ns时被赋予新值0。当A在第15 ns变化时,语句1、5和6执行。执行语句5和6不影响Z[0]和Z[1]的取值。执行语句5导致Z[2]值在第17 ns变为0。执行语句1导致Abar在第16 ns被重新赋值。由于Abar的改变,反过来又导致Z0]值在第18 ns变为1。
请注意连续赋值语句是如何对电路的数据流行为建模的;这种建模方式是隐式而非显式的建模方式。此外,连续赋值语句是并发执行的,也就是说各语句的执行顺序与其在描述中出现的顺序无关。
4

4、行为描述方式

设计的行为功能使用下述过程语句结构描述:1 ) initial语句:此语句只执行一次。
2) always语句:此语句总是循环执行,或者说此语句重复执行。
只有寄存器类型数据能够在这两种语句中被赋值。寄存器类型数据在被赋新值前保持原有值不变。所有的初始化语句和always语句在0时刻并发执行。
下例为always语句对1位全加器电路建模的示例,如图:。
5
模块F_Seq有三个输入和两个输出。由于Sum、Cout、T1、T2和T3在always语句中被赋值,它们被说明为reg 类型(reg是寄存器数据类型的一种)。always 语句中有一个与事件控制(紧跟在字符@后面的表达式)。相关联的顺序过程(begin-end对)。这意味着只要A、B或Cin 上发生事件,即A、B或Cin之一的值发生变化,顺序过程就执行。在顺序过程中的语句顺序执行,并且在顺序过程执行结束后被挂起。顺序过程执行完成后,always语句再次等待A、B或Cin上发生的事件。
6
在顺序过程中出现的语句是过程赋值模块化的实例。模块化过程赋值在下–条语句执行前完成执行。过程赋值可以有一个可选的时延。
时延可以细分为两种类型:
l)语句间时延:这是时延语句执行的时延。
2)语句内时延:这是右边表达式数值计算与左边表达式赋值间的时延。下面是语句间时延的示例:
sum = (A ^ B)^ cin;
#4 T1 = A & cin;
在第二条语句中的时延规定赋值延迟4个时间单位执行。就是说,在第一条语句执行后等待4个时间单位,然后执行第二条语句。下面是语句内时延的示例。
sum = #3 (A^B) ^ cin;
这个赋值中的时延意味着首先计算右边表达式的值,等待3个时间单位,然后赋值给Sum。
下面举例Initial语句的例子

'timescale 1ns / lns
module Test ( Pop, Pid) ;
output Pop,Pid;
reg Pop. Pid;
initial
begin
Pop =0 ; //语句1。
pid = 0 ;//语句 2。
Pop : #5 1;//语句 3。
Pid = # 3 1;//语句4。
Pop = #6 0 ;//语句5。
Pid = #20 ;//语句6。
end
endmodule

这一模块产生如下图所示的波形。initial语句包含一个顺序过程。这–顺序过程在0 ns时开始执行,并且在顺序过程中所有语句全部执行完毕后, initial语句永远挂起。这一顺序过程包含带有定义语句内时延的分组过程赋值的实例。语句1和2在0 ns时执行。第三条语句也在O时刻执行,导致Pop 在第5 ns时被赋值。语句4在第5 ns执行,并且Pid在第8 ns被赋值。同样,Pop在14 ns被赋值0,Pid在第16 ns被赋值0。第6条语句执行后,initial语句永远被挂起。
7

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值