编辑推荐: |
本文主要介绍3个部分:从Verilog
HDL的类型和常量到硬件的映射;从Verilog语句到硬件逻辑门的映射,解释了运算符、表达式和赋值语句是如何映射成硬件的;以综合为目标对硬件元件进行建模,并且采用Verilog
HDL进行实现(建模的示例)。
本文来自于CSDN,由火龙果软件Alice编辑、推荐。 |
|
1. 介绍
1.1 什么是综合?
Verilog HDL或VHDL都只是一种硬件的描述语言,并且允许在不同的抽象层次上对电路进行建模。VerilogHDL侧重于电路级,可以在门级和寄存器传输级(RTL)描述硬件,也可以在算法级对硬件加以描述。而VHDL侧重于系统级。
综合就是将Verilog描述的RTL级的电路模型构造出门级网表的过程。综合只是个中间步骤,综合后生成的网表文件,就是由导线相互连接的寄存器传输级功能块
(像是触发器、算术逻辑单元和多路选择器等)组成的。这里就需要一个叫做RTL模块构造器的程序,用来针对用户指定的目标工艺从预定义元件库中构造或获取每一个必须的RTL功能模块。
图1 :综合过程
综合产生网表文件后,逻辑优化器 会读入网表,并且会按照用户提供的面积(即资源要求)和定时(时序要求)约束为目标来优化网表。并且,这些面积和定时约束也能够指导
模块构造器 恰当地选取或生成寄存器传输级功能块。
1.2 不可综合
上文介绍了HDL的描述有不同的抽象层次,从门级、RTL级、行为级以及算法级进行建模。但是,并不是所有层次上的描述方式都可以被综合成想要的硬件元件,即不可综合。比如Verilog中存在一些用于仿真验证的子集,属于仿真验证语言,只在仿真时候使用,不能被综合成电路,因为没有相应的硬件元件与其对应。如系统任务$dsiplay(),
initial语句等。
还需要说明的是,不同的综合器所支持的Verilog可综合的子集一般是不同的,而Verilog中不存在单个的对象来表示锁存器或触发器因此每一种综合器都会有自己的综合机制来实现锁存器或触发器的建模。下图说明了Verilog中采用不同的描述方式去描述同一个电路。但某综合系统仅仅支持方式A和B,却不支持方式C,这也说明同一个电路模块,在不同的综合器之间一般是不可移植的。二方式D属于压根就不可综合的一种。
图2 :同样的行为,有不同的建模方式
1.3 在设计流程中的位置?
不同综合器支持的综合子集不同,这就为开发人员带来的困扰。在学习和使用的过程中,不仅要理解Verilog HDL而且还得理解特定综合器的建模方式,这样才可写入完全可综合的模型。下面是FPGA开发时的典型流程,但并非固定。
图3:典型的设计流程
2. 映射机制
既然综合器能够将HDL语言转换成门级网表,那么综合器必定有一种映射的机制,能够实现Verliog代码中的某些变量、组件映射成对应的硬件元件。
图4:综合过程涉及到的两个领域
Part1 -从Verilog HDL的类型和常量到硬件的映射
主要介绍 Verilog HDL的类型和常量到硬件的映射。
1. 逻辑值体系
硬件建模常用的值:逻辑0、逻辑1、高阻抗、无关值、不定之。在Verilog中对无关值之外的其他值都做了明确的定义,当值
x 被赋值给某一个变量时,综合器会将该值视为 无关值 。对应关系:
图5:Verilog HDL数值与硬件建模之间对应关系
1.1 位宽
1) 变量数据类型
数据类型(Data Type )是用来分别表示数字电路中的物理连线、数据存储和传输单元等物理量的。
Verilog中的变量数据类型有两种 : a) 寄存器数据类型 和
b) 网线数据类型 (net型)。
在Verilog1995中寄存器类型,但在Verilog2001标准中将register一次改为了variable,以避免初学者将register和硬件中的寄存器概念混淆。
a) 网线数据类型
在声明时 可以明确的指定变量的位宽。未明确指明,默认1位。能够综合的网线数据类型有:
wire [5:0] data_bus
; //6位的wire网线
wor Ax ; //1位wor网线 |
wire网线是最最常用的类型,当多个驱动源驱动同一根wire网线时,这些驱动源的输出端就会被短接在一起(线与):
module wire_example(BpW
,Error , Wait, Vaild , Clear);
input Error, Wait, Valid, Clear;
output BpW;
wire Bpw;
assign BpW = Error & Wait ;
assign BpW = Error | Clear;
endmodule |
如图6所示
图6:多驱动源驱动同一wire网线
当采用“或逻辑和“与逻辑”实现多个驱动源驱动同一根网线的驱动效果
,则分别需要用wor和wand网线类型。综合的时候,同一根wor网线的多个驱动源都连接到一或门上,而驱动同一根wang网线的驱动源都连接到与门上。示例如下:
module UseGates(BpW,
Bpr,Valid,Error,Wait,Clear);
input Error,Wait,Clear;
output BpW,BpR;
wor BpW;
wand BpR;
assign BpW = Error & Wait ;
assign BPW = Valid | Clear;
assign BpR = Error ^Valid;
assign BpR = !clear;
endmodule |
综合后的网表如下图7所示:
图7:多个驱动源驱动wor网线和wand网线
tri网线型与wire网线型采用相同的方式综合。而supply0网线综合的连线会固定连接在0电平(逻辑0)上,而由supply1网线综合出的连线固定连接在1电平(逻辑1)上。
b) 寄存器数据类型(Variable型)
可综合的寄存器类型有:reg 型 和 integer型 。
reg型声明语句同样可以明确地指定位宽,即该变量在硬件上相应的位数,未指定默认1bit。而整数类型最大位宽32bit,并且假定用二进制补码形式表示,即是有符号数形式。
Integer型
多用于循环变量 ;
不能作为位向量访问;
综合时,integer型变量的初始值位x。
在声明整数型变量时,可以让综合器自己对数据流分析来确定各整型变量所需的最大位宽。例如:
wire [4:0] A,B;
integer Sum;
...
sum = A + B ; |
可以确定这里的Sum位宽应该为6位,故一个6位的加法器就够了,并且Sum的最高位为进位位。
time和real型也属于寄存器类型,但是不能综合。
2)常量
Verilog中有3种常量:
整型(integer) ;
实型(real) ;
字符串型(strings)。
其中,实型和字符串型的常量并不能够被综合,而整型是可以综合的。
整型
整型常量的表示: a) 简单的十进制 b)基数格式 。
需要注意:
实数型(Real)
实数有两种表示方法: a)十进制表示法 b) 科学计数法
字符串(Strings)
字符串是双引号内的字符序列;
字符序列不能分成多行书写,例如: "INTERNAL ERROR"
字符串的作用主要用于 仿真 ,显示一些相关的信息或者指定显示的格式。
(3)参数
Verilog中,用参数(关键字parameter)来定义符号常量,即用parameter来定义一个标志符代表一个常量。定义参数常用于定义时延和变量的宽度。
由于不允许指定参数的位宽,因此其位宽与所对应的常量的位宽相同。下面的参数red和green是两个32位的符号常量。READY、
BUSY 和EXIT是三个位宽为2的参数。
parameter red
= -1,
green = 2 ;
parameter READY = 2'b0 ;
patameter BUSY = 2'b11 ;
parameter EXIT = 2'b10 ; |
1.2. 值保持器建模
硬件种有3种基本的值保持器:
a) 连线 ;
b) 触发器 (边沿触发的存储器件);
c) 锁存器(电平敏感的存储器件)
下面将介绍关于对这三种器件的推导。
在前面位宽中介绍了,Verilog中的变量数据类型既可以是网线型,也可以是寄存器类型。综合的时候就会把网线类型映射成硬件中的连线,而寄存器变量则还需要根据被赋值的上下文环境来确定这个寄存器变量到底是映射成连线还是映射成存储期间(触发器或锁存器)。在Verilog
HDL的整个仿真运行过程中,寄存器变量一致保持自己的值,因而把它推导成存储器。但是综合的时候不是绝对。
【注】:reg型变量并不一定都是会综合成触发器或锁存器,也可能是硬件连线。
下面例子中的变量仅用作一个临时变量,因而 没有必要将其映射成存储元件。
wire Acr,Bar
,Fra; //网线型
reg Trq ,Sqb; //寄存器型
...
always@(Bar or Acr or Fra)
begin
Trq = Bar & Acr ;
Sqb= Trq | Fra
end
|
上面例子中,在always块中对reg型变量Trq进行了赋值,然后在下一句中对Sqb变量赋值表达式中引用了该变量。从Verilgo
HDL的语义上看,在整个仿真过程中Trq会一直保持它的值。但是,在硬件实现时,没有必要将Trq的值保持在硬件存储元件中,因为Trq的值在其赋值完成之后就立即被引用了。因此,综合器综合后生成的逻辑电路如图8所示:
图8:综合后的Trq是导线
现假如将always块中两个赋值语句调换顺序:
always@(Bar or
Acr or Fra)
begin
Sqb= Trq | Fra ;
Trq = Bar & Acr ;
end |
顺序的变动使得变量Trq在赋值之前就要被引用。always语句块的语义很明确,只要出现Bar、Acr、Fra
相关的事件(即一旦Bar、Acr、Fra有变化),就会执行always语句。因为Trq在被赋值前就在表达式中被引用了,因此在重复执行always语句的过程中Trq不得不保持其值,因此会把它推导成存储器()。不过,这还不足以明确如何把Trq构造成锁存器,因为Trq未在任何条件的控制下被赋值。此时的综合器可能无法为其建立锁存器,而有可能生成图9所示的电路。变量Trq再次会被综合成网线。但是,为使得Verilog
HDL模型与综合出的网表功能一致,Trq也必须放入always语句的事件表中。
图9:变量Trq仍然未被综合成锁存器
将变量Trq推导成锁存器的示例:
变量Fox在条件语句的else分支中未被赋值,只有当Sat为假时候为Fox赋值为Ant,那么当Sat为真时,就需要保存变量Fox中原有的值,这时候综合器就会将Fox变量推导成锁存器。注意:敏感列表中包括了条件:即Sat触发电平和驱动Ant。
综合出的电路:
图10:变量Fox综合成锁存器
什么样的HDL才能推导出触发器呢?这也取决于采用 的建模方式和变量被赋值的上下文环境。在(2)从Verilog语句到硬件逻辑门的映射,解释了运算符、表达式和赋值语句是如何映射成硬件的
还会根据这个例子以及其他示例更详细地介绍如何推导出触发器和锁存器。
|