IC验证零基础学习-Verilog-PartA

IC验证零基础学习-Verilog-PartA
第一部分 HDL设计方法简介
一、
使用HDL(Hardware Description Language)语言,可以从算法、系统级(System Level)、功能模块级(Functional Model Level)、行为级(Behavioral Level)、寄存器传输级(RTL,Register Transfer Level)、门级(Gate Level)到开关级(Switch Level)等不同层次描述数字系统电路系统,然后通过EDA工具综合,仿真并实现该系统。
1)从高层次的电路描述通过EDA工具解析到门级等低层次的电路描述的过程叫“综合”(Synthesize)。
2)Verilog HDL与VHDL应用最为广泛,共同特点是:利于自顶向下的设计,利于模块的划分与复用,可移植性好,通用性好,设计不因芯片的工艺与结构的变化而变化,更利于向ASIC的移植。
3)辅助设计输入方法
(1)波形输入:只要绘制出激励波形和输出波形,EDA软件就能够自动地根据响应关系进行设计或仿真。
(2)状态机输入:设计者只须画出状态转移图,EDA软件就能生成相应的HDL代码或原理图。
4)Verilog与C 语言的最大区别:
(1)互连:硬件系统中,互连是非常重要的部分,而在C语言中并没有直接可以用来表示模块间互连的变量;而Verilog的wire型变量配合一些驱动结构能够有效地描述网线的互连。
(2)并发:C语言天生是串行的,不能描述硬件之间的并发特性,C语言编译后,其机器指令在CPU的高速缓冲队列中基本是顺序执行;而Verilog可以有效地描述并行的硬件系统,硬件系统比软件系统速度快,实时性高的一个重要原因就是硬件系统中各个单元的运算是独立的,信号流是并行的。
(3)时间:C程序运行的时候。没有一个严格的时间概念,程序运行的时间长短取决于处理器本身的性能;而Verilog语言本身定义了绝对和相对的时间度量,在仿真时可以通过时间度量与周期关系描述信号直接的时间关系。
5)Verilog作为硬件描述语言,它的本质作用在于描述硬件,虽然采用了C语言的形式,但是它的最终描述结果是芯片内部的实际电路。HDL代码优劣的最终标准是其描述并实现的硬件电路的性能(速度与面积)。
6)编程语言接口-PLI,PLI可以在仿真器中将C语言的程序和Verilog的程序互相通信,或者在Verilog中调用C语言的函数库,拓展了Verilog语言的灵活性和高层次抽象的能力。验证工程师可以使用C来编写测试向量。
7)HDL设计与验证流程的关键步骤
(1)系统与功能模块的定义
对系统级的仿真侧重于对整个系统的功能和性能指标的考量,功能模块级设计时将系统整体功能划分为可实现的具体功能模块,大致确定模块间的接口,如时钟,读写信息,数据流,控制信号。
(2)行为级描述测试激励(Behavioral leve)
行为级模块描述的最大特点是必须明确每个模块间的所有接口和边界。常用行为级描述方式编写测试激励。
(3)寄存器传输级(RTL)
寄存器传输级指不关注寄存器和组合逻辑的细节(使用了多少逻辑门,逻辑门之间的连接拓扑结构等),通过描述寄存器到寄存器之间的逻辑功能描述电路的HDL层次。寄存器传输级描述的最大特点是可以直接用综合工具综合为门级网表。RTL设计直接决定设计的功能和效率。
(4)对RTL级描述进行功能仿真
一般来说需要对RTL级设计进行功能仿真,仿真的目的为了验证RTL级描述是否与设计意图一致,为了提高效率,一般功能仿真的测试激励使用行为级的HDL语言描述。
(5)逻辑综合(使用RTL级EDA工具)
RTL级综合指将RTL级HDL语言翻译成由与、或、非门等基本逻辑单元组成的门级连接(网表),并根据设计目标与要求(约束条件)优化所生成的逻辑连接,输出门级网表文件。
(6)门级
(7)综合后门级仿真
综合完成后,如果需要检查综合结果是否与原设计一致,就需要做综合后仿真。
(8)布局规划和布局布线
(9)布局布线后时序仿真与验证
将最终布局布线的时延信息反标注到设计网表中,所进行的仿真就叫时序仿真,简称后仿真。时序仿真的目的在于发现时序违规(Timing Violation),即不满足时序约束条件或器件固有时序规则(建立时间、保持时间)的情况。
第二部分 Verilog 语言基础
本部分主要内容:基本语法,模块和端口,编译指令,逻辑值与常量,变量类型,参数,Verilog中的并发与顺序,操作数与操作符、表达式,系统任务和系统函数。
一、
硬件电路最大的特点是由一个个模块组成,模块之间使用互连线,各个模块独立并行工作,同时,它们通过输入和输出端口与相邻的模块互相沟通,每个硬件单元都有相应的延时特性,硬件的延时也是设计的目标之一。
1)Verilog HDL区分大小写,VHDL不分区大小写。
在Verilog中所有关键字都是小写,标识符可以是字母、数字、$、_(下划线)任意组合,只要第一个字符是字母或下划线即可。
2)“//”单行注释,
包含范围内全为注释

/*······*/

通常使用空格符,跳格符和换行符作为间隔。在书写代码的时候,适当运用间隔符可以提高代码的可读性。
3)在Verilog中,模块是基本的组成单位。

module (...);	//模块名称(端口列表)
//声明
	reg,wire,parameter;
	input,output,inout;
	function,task;
//语句
	initial;
	always;
	module n1 ...;
	//门实例化
	assign ;	//连续赋值
endmodule

在同一个module内的语句,其相互之间是没有任何顺序关系的。
4)Verilog中使用反引号“ ’ ”来标识编译指令。编译器一旦遇到某个编译指令,则其整个编译过程中有效,可以包含多个文件,直到编译器遇到另一个相同的编译指令。'define用于定义宏。是一种全局定义。
5)逻辑值与常量
(1)除了0和1的逻辑值,还增加了X与Z的逻辑值。
X表示未知值,或者不关心,用在条件判断时(casex或casez中)表示不关心。
Z表示高阻态,也就是没有任何驱动,通常用来对三态总线进行建模。
其中通常net型变量如果没有初始化,其值为Z,register型变量如果没有初始化,其值为X。X与Z不区分大小写。
(2)常量包括三种:整数型,实数型,字符串型。
整数型,其格式:[长度]'数值符号 数字
其长度可有可无,数值符号中,h表示十六进制,o表示8进制,b表示二进制,d表示十进制。如果长度比后面数字的实际位数多,则自动在数字左边补0,如果位数少,则自动截断数字左边超出的位数。
6)变量类型
具有两大变量类型,线网型:表示电路间的物理连线;寄存器型:Verilog中的一个抽象的存储数据单元。
对于初学者而言,①凡是在always或initial语句中赋值的变量,一定是寄存器变量;②在assign中赋值的一定是线网变量。
(1)线网类型,最长用的就是wire型,其未初始化时为Z,tri用于多驱动源建模,其未初始化为X。
(2)寄存器类型
reg:是最常用的寄存器类型数据,可以是一位或者多位,二维数组(存储器)。
integer:整形数据,存储一个至少32位的整数。
time:时间类型,存储一个至少64位的时间值。
real,realtime:实数与实数时间寄存器。

reg AB;			//定义一个名为AB的一位寄存器
reg [3:0] AB;	//定义一个名为ABC的4位寄存器

ABC [3] = 1;	//将ABC的第3位赋值为1
ABC [2:1] = 2'b01;	//将ABC的第1、2位赋值为1和0

在Verilog中,不存在一条语句可以对整个存储器赋值,必须对每个单元独立赋值。
(3)变量的物理含义
线网变量可以理解为电路模块中的连线,但是寄存器并不是严格对应于电路上的存储单元,包括触发器(fiip-flop)或者锁存器(latch)。从语义上讲,寄存器类型的变量是占用仿真环境的物理内存的,线网类型是不占仿真内存的。
(4)驱动(Driving)与赋值(Assigning)
线网是被驱动的,该值不被保持,在任意一个仿真步进上都需要重新计算;
寄存器是被赋值的,且该值在仿真过程中被保持,直到下一个赋值的出现。

assign #1 A_xor = eq0^eq1;		//这里A_xor被声明为wire

always @ (eq0 or eq1)
	A_xor = eq0^eq1;			//这里A_xor被声明为reg

两者的描述的目的都是一样的,都是一个异或门。但是从语义上来说,存在着差别。
第一种方式使用assign语句,Verilog中称其为连续赋值语句,实际上是连续驱动的过程,也就是说,在任意一个仿真时刻,当前时刻eq0和eq1相异或的结果决定了1ns以后的线网变量A_xor的值,不管eq0和eq1变化与否,这个驱动过程一直存在。
第二种方式使用always语句,后面紧跟着一个敏感列表:@(eq0 or eq1)。因此,这个语句只有在eq0或eq1发生变化时才会执行。
不管采用哪种方式,所描述的是一样的组合电路,尤其是第二种描述,虽然其语法上被定义为reg,但并不是对应硬件上的触发器,而是Verilog语言仿真上的寄存器概念。
7)参数
参数是一种常量,常被用来定义状态机的状态,数据位宽,延时大小等。
参数值可以在被编译时被改变,前面提到的’define是一种全局的定义,而parameter是一种模块内部的定义,可以被灵活改变。
8)并发与顺序
Verilog语言的描述语句之间都是并行发生的。
begin…end是顺序语句组;fork…join是并行语句组。
9)操作数。操作符和表达式
算术,按位,归约,逻辑,相等,全等,关系,移位,条件,连接复制。注意操作符之间的优先级。
(1)二进制数值
在一个6位二进制整型变量中:
①无符号数能表示的范围是0~63;
②有符号采用二进制补码方式,能表示的范围是-32~31。其中二进制的最高位表示符号,最高位为1表示该数为负数,0表示该数为正数。
只要存在一个无符号数参与运算,都要先转成无符合数,再进行运算。
10)系统函数与系统任务
$display 是显示任务,通常用来显示变量值,字符串以及仿真信息。
$finish 表示使仿真器退出
$stop 表示使仿真挂起
$setup 系统任务用来检测建立时间
$hold 系统任务用来检查保持时间
$time 系统函数用来返回一个64位的模拟时间
$random 系统函数用来返回一个32位的有符号整形随机数
实际上,系统函数/任务只有在仿真器中运行,仅仅对代码仿真有意义,综合和布线工具将忽略所有的系统任务与函数。

第三部分 描述方式与设计层次
Verilog语言中有三种最为基本的描述方式:①数据流描述,采用assgin连续赋值语句;②行为描述,使用always语句或者initial语句块中的过程赋值语句;③结构化描述,实例化已有的功能模块或原语。
一、
1)数据流描述,数字电路中,信号经过组合逻辑时有点类似数据流动,信号从输入流向输出,而信号不会在其中存储。
2)连续赋值语句其特点:①连续驱动;②只有线网类型能在assign中赋值;③使用assign对组合逻辑建模;④并行性。
3)行为描述语句,使用always和initial语句,可以是非阻塞、阻塞过程赋值语句,连续过程赋值或高级编程语句。
(1)initial语句在0仿真时间执行,而且只执行一次;always语句同样在0仿真时间开始执行,但是它将一直循环执行。
(2)时序控制,①事件语句(@);②延时语句(#);③等待语句。
4)过程赋值语句
(1)阻塞赋值,寄存器变量=表达式;①右边表达式的计算和对左边寄存器变量的赋值是一个统一的原子操作中的两个动作。这两个动作和自己不能插入任何其他的动作。②如果多个赋值语句顺序出现在begin…end语句中,前面的语句在执行时,将完全阻塞后面的语句,直到前面语句的赋值完成以后,才会执行下一句的右边表达式计算。
begin m = n; n = m; end 这样执行的结果是n的初始值不变,而且m与n相等。
(2)非阻塞赋值,寄存器变量 <= 表达式;其特点是,①首先计算右边的表达式,然后并不立刻对左边的变量赋值。由于这个赋值操作在当前仿真时间事件队列中的优先级比较低,因此将赋值推迟到当前仿真时刻的后期运行。②如果多个非阻塞赋值语句顺序出现在begin…end语句中,前面语句的执行,并不会阻塞后面语句的执行。前面语句的计算完成,还没有赋值时,就会执行下一句的右边表达式计算。
begin m <= n; n <= m; end 这样执行最后的结果是n与m值互换。
(3)过程连续赋值
①assign与deassign:过程语句块中对寄存器变量强制赋值和放开。
②force与release:过程语句块中对寄存器和线网进行强制赋值和放开。
5)语句组,顺序语句组begin…end;并行语句组fork…join。语句组可以具有标识符,也可以没有,其中always以外的i变量和always内定义的变量属于不同的两个变量,并不冲突。
6)高级编程语句,
(1)if…else;后面跟着begin_end,fork_join语句块,该语句实际上存在优先级。
(2)case;注意所有可能出现的情况,避免生产锁存器,default是一条描述所有没有明确说明的其他可能情况。
①casez,将分支条件中所有的z看作不关心的值,而不看成任何逻辑值,条件中的z可以改写成?。
②casex,将分支条件中所有的x与z都看作不关心的值。
(3)循环语句forever,repeat,while,for
①forever循环,永远执行。

initial begin
	clk = 0;
	forever #25 clk = ~clk;
end

以上语句产生一个50个时间单位的时钟
②repeat循环:执行固定次数。

if (rotate == 1)
	repeat(8) begin
		tmp = data[15];
		data = {data << 1,tmp};
	end

以上语句,当rotate为1时,重复对data数据做8次循环左移。
③while循环,当表达式为真时执行。

intitle begin 
	count = 0;
	while(count < 101) begin
		$display ("count = %d",coount);
	end
end

在while语句中,只要后面的条件满足,就可以持续执行该语句,直到条件不满足,跳出循环。这里是将count从0增到101,逐步打印出来。
④for循环,从初始值开始,如果表达式为真就执行。

integer i;		//为for循环声明索引
always @ (inp or cnt) begin 
	result[7:4] = 0;
	result[3:0] = inp;
	if (cnt == 1) begin
		for (i = 4;i <= 7;i = i+1) begin 
			result[i] = result[i-4];
		end
	result[3:0] = 0;
	end
end

for语句开始执行直到i大于7,跳出循环。如上代码实现了一个4位的左移器。
5)结构化描述
实例模块化方法,实例模块端口对应方式:名称对应及位置对应。
参数的定制有两种:①通过defparam关键字对模块中的参数重新定义;②参数直接在实例化模块时代入。
6)设计层次
(1)系统级和行为级
(2)RTL级,最常用的设计层次就是RTL级,在RTL描述时,设计者需要关注寄存器的行为,其中保存着数据,同时需要关注寄存器和寄存器之间的组合逻辑功能,是否满足功能需求和时序需求。RTL级模型是严格精确到时钟周期的模型。
行为级关心的是代码的行为,RTL级关心的是电路的实现方式和性能。

参考书籍《Verilog数字系统设计教程》《轻松成为设计高手-Verilog HDL实用讲解》

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值