设计输入.docx
- 文档编号:5954901
- 上传时间:2023-01-02
- 格式:DOCX
- 页数:26
- 大小:380.68KB
设计输入.docx
《设计输入.docx》由会员分享,可在线阅读,更多相关《设计输入.docx(26页珍藏版)》请在冰豆网上搜索。
设计输入
第3章设计输入
设计输入是FPGA设计的重要部分,用户可以通过前面章节所介绍的QuartusⅡ提供的图形编辑器、文本编辑器、状态机编辑器等输入工具将设计意图用图形方式(原理图或状态图)或文本VHDL程序等方式进行逻辑描述。
希望通过本章的介绍能够让大家掌握电路内部的逻辑关系的基本VHDL描述,电路图、LPM定制、状态机、混合模块以及相互之间的转换方式,熟悉软件工具使用技巧等。
3.1VHDL语言
3.1.1VHDL介绍
(1)简介及设计开发流程
VHDL全名Very-High-SpeedIntegratedCircuitHardwareDescriptionLanguage,翻译成中文就是超高速集成电路硬件描述语言,主要是应用在数字电路的设计中,利用VHDL语言进行可编程逻辑器件设计开发的基本流程如图3.1.1:
图3.1.1VHDL语言进行PLD设计开发流程
VHDL主要用于描述数字系统的结构、行为、功能和接口,它的多层次的设计描述功能可直接生成电路级描述,更能有效的表示硬件电路的特性。
VHDL采用基于库(Library)的设计方法,可以建立各种可再次利用的模块。
这些模块可以预先设计或使用以前设计中的存档模块,将这些模块存放到库中,就可以在以后的设计中进行复用,可以使设计成果在设计人员之间进行交流和共享,减少硬件电路设计。
VHDL语言的一个优势:
对于用VHDL完成的一个确定的设计,可以利用EDA工具进行逻辑综合和优化,并自动的把VHDL描述设计转变成门级网表。
(2)VHDL语言的设计分类
VHDL语言的优点在于功能强大、设计方式多样,具有强大的硬件描述能力,支持广泛、易于修改、共享和复用,具有很强的移植能力;缺点在于有时不能够准确的描述硬件电路,系统级抽象描述能力较差,具有文本操作的局限性以及不具备描述模拟电路的能力。
其设计方法一般分为三类,即结构式,行为式和RTL级代码描述,下面将通过三种语言分别描述各自的编写规则。
1VHDL结构式描述
结构式描述声明了设计中所用的每一种类型的原件以及各个元件间的连接关系,适合将设计对象和原理图描述成网表的数据结构,也适用于多层次设计。
结构描述反映了涉及硬件方面的特征,表达了内部元件之间的连接关系,是通过元件例化语句来描述的。
T触发器
tff元件声明
---portmap端口映射
本章第二节第四部分会详细为大家讲解元件例化。
2VHDL行为式描述
结构描述是根据实体中电路元件的连接关系描述电路的组成;而行为描述不涉及实体的具体结构,只根据输入、输出的行为关系描述其逻辑功能。
行为式描述是按照算法的路径来描述设计对象及模仿行为和功能,属于高层次抽象描述。
一般情况下,行为式代码是类似查找真值表一样根据输出值与输入值的映射关系产生指定输出信号,不考虑是否可综合,只用来测试系统。
行为式描述和RTL级代码都将通过下图3.1.2说明这两种设计代码编写的差别。
图3.1.2“andor”原理图
------真值表描述
whenelse语句会在本章第二节第三部分详细讲述。
3RTL级代码描述
寄存器传输级代码是在较高抽象层次上采用VHDL语法子集描述设计对象,是一种可综合代码。
这种编码形式介于结构式和行为式之间。
RTL级代码采用进程语句顺序描述数据流在控制流作用下的处理过程。
RTL代码编写方式如下:
architecturertlofandoris
begin
process(a,b,c)
begin
if(a='1'andb='1'orc='1')then
q<='1';
else
q<='0';
endif;
endprocess;
endrtl;
RTL级代码在后面的程序中应用很广泛。
(3)VHDL的库与程序包
有C语言或者C++基础的用户会比较容易VHDL语言程序前面的几行代码,比如:
libraryieee,use等,下面我们会对这一部分做一个详细的介绍。
为了方便VHDL编程和提高设计效率,用户可以将预先定义好的数据类型、元件调用声明及一些常用子程序汇集在仪器形成程序包,若干个程序包形成库。
①Library库:
编译后数据的集合,存放包集合定义、实体定义、构造体定义和配置定义,其功能相当于其他操作系统中的目录,经过说明后,设计中就可以使用库中的数据,实现共享;每个实体都应独立进行库的说明;库的说明应该在实体之前;经过说明后,实体和结构体就可以自动调用库中的资源:
例:
libraryieee;
useieee.std_logic_1164.all;
②Ieee库:
含有IEEE的标准包集合“std_logic_1164”以及一些大公司提供的包集合;
例:
libraryieee;Ieee库中的重要包集合:
std_logic_1164:
定义了std_logic数据类型及相应运算;
std_logic_arith:
定义了signed和unsigned数据类型、相应运算和相关类型转换函数;
std_logic_signed与std_logic_unsigned:
定义了一些函数,可以使std_logic_vector类型被当作符号数或无符号数一样进行运算。
③Std库:
VHDL标准所含的资源库,含有“standard”包集合和“textio”包集合,对所有预定义的数据类型、运算规则、函数和语法进行表达.
④work库:
work库为当前设计文件的保存目录;work库使用时通常无须说明;但在结构设计中进行元件的宏调用时需要说明;例:
usework.all;
⑤用户定义库:
由用户自定义生成,使用时需说明(指定库所在的路径);
⑥VHDL程序包:
在设计实体中定义的数据类型、子程序或数据对象对于其他设计实体是不可再利用的。
为了使已定义的数据类型、子程序、原件能被其他设计实体调用或共享,可以把它们汇集在程序包中。
由上面的介绍我们可以知道电路的VHDL描述由两大部分组成:
以关键词entity引导,endentityone结尾的实体部分。
VHDL的实体描述了电路器件的外部情况及各信号端口的基本性质,如信号流动的方向,流动在其上的信号结构方式和数据类型等。
以关键词architecture引导,endarchitectureone为结尾的结构体部分。
结构体负责描述电路器件的内部逻辑功能和电路结构。
3.1.2案例分析
通过以下案例的学习,旨在帮助大家掌握VHDL的基本语法,学习信号与变量的用法和基本逻辑元件的可综合代码的编写。
一、反馈——比较电路
比较电路:
设计一个能实现两个二位数大小比较的电路,根据A数是否大于、小于、等于B数,相应的输出端F1、F2、F3为“1”,设A=A2A1,B=B2B1(A2A1,B2B1表示两位二进制数)当A2A1>B2B1时,F1为“1”;A2A1 F1 比较电路 A2 F2 A1 F3 B2 B1 图3.2.1比较电路元件符号 1、VHDL实现 (1)bijiao.vhd代码实现 Libraryieee;-----------库 Useieee.std_logic_1164.all; Entitybijiaois-----------实体部分 Port(a2,a1: instd_logic;-----------端口说明 b2,b1: instd_logic; f1,f2: bufferstd_logic; f3: outstd_logic); endbijiao; architecturebijiao_archofbijiaois-----------结构体部分 begin f1<=(a2and(notb2))or(a1and(notb1)anda2)or(a1and(notb1)and(notb2)); f2<=((nota2)andb2)or((nota1)andb1and(notb2))or((nota1)andb1andb2); f3<=not(f1orf2); endbijiao_arch; (2)代码原理说明: 根据2位二进制的数比较大小的方法可知,要使a>b,那么有两种情况,一是a的高位为1,而b的高位为0,低位任意,另一种便是a,b高位都为0,同时a的低位大于b的低位,同理a (3)学习使用缓冲buffer ①在VHDL设计时,电路加入需要反馈,那么就应将端口声明为buffer端口,而不是out端口。 在该案例中,因为f3的输出逻辑是在f1,f2均不成立的情况下,此时f1,f2不仅要作为输出,而且也成为了f3的输入也可以叫做激励,那么此时,f3在声明时,需要注意要将类型设置为buffer。 ②缓冲模式的端口与输出模式的端口类似,只是缓冲模式允许内部引用该端口的信号。 缓冲端口既能用于输出,也能用于反馈。 内部反馈的实现方法有: 建立缓冲模式端口; 建立设计实体的内部节点。 缓冲模式用于在实体内部建立一个可读的输出端口,例如计数器输出,计数器的现态被用来决定计数器的次态。 实体既需要输出,又需要反馈,这时设计端口模式应为缓冲模式。 3inout和buffer的区别: INOUT为输入输出双向端口,即从端口内部看,可以对端口进行赋值,即输出数据。 也可以从此端口读入数据,即输入。 BUFFER为缓冲端口,功能与INOUT类似,区别在于当需要读入数据时,只允许内部回读内部产生的输出信号,即反馈。 举个例子,设计一个计数器的时候可以将输出的计数信号定义为BUFFER,这样回读输出信号可以做下一计数值的初始值,要是定义为inout先前的值就被覆盖了! ④在该案例中还要知道,and、or、not等关键字或+、--、×等运算符经综合工具可以被推定成具体的逻辑门,如表3.2.2: 表3.2.2逻辑与案件推进高的关键字和运算符 运算符/关键字最定出的元件运算符/关键字推定出的元件 and与门+加法器 or或门-减法器 not非门*乘法器 nor或非门/除法器 nand与非门 2、编译并波形验证 单击菜单栏Processing—>start—>startanalysis&synthesis,进行语法编译,编译结束后,新建波形文件,按照第二章案例演示的方法将信号导入,进行赋值,并进行仿真,仿真结果如图3.2.3: 图3.2.3比较电路的波形仿真结果 同时选中a2,a1,点击右键,选择“Grouping”—>“group”即可将两个信号进行组合,这样更便于分析仿真结果。 二、case语句译码器(3-8译码器) 译码即编码的逆过程;译码器是一种组合电路,工作状态的改变无需依赖时序脉冲。 译码器可分为数码译码和显示译码两大类。 其中: ·显示译码: 包括驱动液晶显示器(LCD)、发光二极管(LED)、荧光数码管等。 ·数码译码: 主要是用来完成各种码制之间的转换。 例如可用来完成BCD—十进制数、十进制数—BCD之间数制的转换。 图3.2.4二进制译码器一般原理图 设计一个3输入8输出的译码器。 1、VHDL实现 (1)decoder3_8.vhd代码实现 libraryieee; useieee.std_logic_1164.all; entitydecorder3_8is port( a: instd_logic_vector(2downto0); q: outstd_logic_vector(7downto0) ); enddecorder3_8; architecturedecorder3_8_archofdecorder3_8is begin process(a) begin caseais----------case语句 when"000"=>q<="00000001"; when"001"=>q<="00000010"; when"010"=>q<="00000100"; when"011"=>q<="00001000"; when"100"=>q<="00010000"; when"101"=>q<="00100000"; when"110"=>q<="01000000"; when"111"=>q<="10000000"; whenothers=>null;----------whenothers必须有 endcase; endprocess; enddecorder3_8_arch; (2)代码原理说明: 译码器的主要功能是将具有特定含义的二进制码进行辨别,并转换成控制信号译码器是计算机中的基本功能部件,例如地址译码器、指令译码器等。 假设译码器有n根输入线和m根输出线,它们之间满足关系式: 2n m。 n个输入变量,有2n种不同状态,每一根输出线对应于一种输入变量状态。 任何时刻m根输出线中只有一根输出为“1”,而其余为“0”或相反。 (3)学习使用case语句 3-8译码器代码的编写时根据3-8译码真值表的输出结果来进行描述的。 ①case语句对每一种输入组合分别进行复制,是一种全状态描述。 Case语句用于两路或多分支判断结构,它以一个多值表达式为判断条件,依条件式的取值不同而实现多路分支。 格式为: caseexpressionis Whenconstant_value=>statement; Whenothers=>statement; Endcase; ②当case和is之间的表达式的取值满足制定的条件表达式的值时,程序将执行后面的,由符号=>所指的顺序处理语句。 条件表达式的只可以是一个值,或者是多个值的“或”关系,或是一个取值范围,或表示其他的缺省值。 3case语句基本格式: [case标号: ] case表达式is when条件值1=>顺序语句; when条件值2=>顺序语句; when条件值3=>顺序语句; …… [whenothers=>顺序语句;] Endcase[case标号] 根据表达式的取值来确定进行某项操作,条件值不能重复,不能遗漏,others只能在最后出现一次。 ④使用case语句时应注意: 条件句的选择值应在表达式的取值范围内; 除非所有条件句中的选择值能完全覆盖case语句中表达式的取值,否则最后一个条件句中的选择必须用others表示; case语句中每一条件句的选择值只能出现一次,不能有相同选择值的条件语句出现; case语句执行中必须选中且只能选中所列条件语句中的一条。 ④if与case比较 if语句中条件句之间是相与的关系; case语句中条件句之间是相或的关系; case条件语句必须将所哟情况列出而if则不必 if语句可实现优先级,case语句则不可以。 2、编译及波形仿真 编译过程可以选择全编译Processing—>compilertool,可以进行语法编译Processing—>start—>startanalysis&synthesis,接着新建波形文件,将相同类型的组合在一起,和上一个例子组合方法相同,选中要组合的信号,单击鼠标右键,选择“Grouping”—>“group”。 然后信号的赋值,进行全编译之后,然后进行波形仿真。 图3.2.53-8译码器的仿真结果图 三、whenelse语句——多路选择器 设计一个4输入1位的多路选择器,有4位输入信号,2位选择信号,如图3.2.6所示: 4选1 多路 选择 器 S[1..0] a bY c d 图3.2.64选1多路选择器元件符号 1、VHDL实现 (1)mux4.vhd代码实现 libraryieee; useieee.std_logic_1164.all; entitymux4is port(a,b,c,d: instd_logic; sel: instd_logic_vector(1downto0); q: outstd_logic); endmux4; architecturertlofmux4is begin process(a,b,c,d,sel)----------------进程语句 begin caseselis when"00"=>q<=a; when"01"=>q<=b; when"10"=>q<=c; when"11"=>q<=d; whenothers=>null; endcase; endprocess; endrtl; (2)代码原理说明: 数据选择器,通常也称为多路选择器,其功能是通过对输入信号的“选择”或控制,十多路输入信号中只能有一路对外输出。 多路选择器有N路数据输入信号,路选择信号,还有一路输出。 在操作过程中,选择信号决定哪一路输入信号可以输出,该路输入信号的点评是什么样的,输出信号电平也是什么样的。 所有未选中的输入信号都将被忽略,例如本例中4选1多路选择器的两路选择信号S[1..0]就根据既定的选择规则选出要输出的信号。 (3)学习使用进程语句和whenelse语句 ①进程语句: 由process引导的语句成为进程语句,在VHDL中,所哟合法的顺序描述语句都必须放在进程语句中;。 Process旁的(a,b,c,…)成为进程的敏感信号表,通常要求将进程中所有的输入信号都放在敏感信号表中,process语句的执行依赖于敏感信号的变化;在一个结构体中可以包含任意个进程语句,所有的进程语句都是并行语句,而由任一进程process引导的语句(包含在其中的语句)结构属于顺序语句。 ②whenelse语句: 2、编译及波形仿真 与前面方法一致进行编译和方针。 仿真结果如下: 图3.2.7mux4的仿真结果 四、元件例化——计数器 计数器是数字系统常用的一种可统计时钟脉冲个数的时序逻辑部件。 按是否使用一个时钟脉冲源和是否同时翻转分类,可分为同步计数器和异步计数器;按计数器的编码分类,可分为二进制计数器、十进制计数器等;按计数容量来分类,可分为十进制计数器、十六进制计数器、六十进制计数器等。 介绍元件例化就是通过将六十进制计数器来讲解的。 六十进制加法计数器 1、VHDL实现 (1)exp_cnt60.vhd libraryieee; useieee.std_logic_1164.all; useieee.std_logic_unsigned.all; entityexp_cnt60is port(Clk,clrn,En: instd_logic; g: outstd_logic_vector(3downto0);--个位 s: outstd_logic_vector(3downto0);--十位 cout: outstd_logic); endexp_cnt60; architecturertlofexp_cnt60is componentexp_cnt10--counter10元件声明 port(Clk,clrn,En: instd_logic; cq: outstd_logic_vector(3downto0); cout: outstd_logic); endcomponent; componentdff--d触发器元件声明 port(Clk,clrn,d: instd_logic; q: outstd_logic); endcomponent; componentexp_cnt6--counter6元件声明 port(Clk,clrn,En: instd_logic; cq: outstd_logic_vector(3downto0); cout: outstd_logic); endcomponent; signalrco_ten: std_logic; signalrco_six: std_logic; signalq: std_logic; signalq_ten: std_logic_vector(3downto0); signalq_six: std_logic_vector(3downto0); begin--对元件实例进行端口映射 u0: exp_cnt10portmap(Clk,clrn,En,q_ten,rco_ten); u1: dffportmap(rco_ten,Clk,clrn,q); u2: exp_cnt6portmap(q,clrn,En,q_six,rco_six); g<=q_ten; s<=q_six; cout<='1'when(rco_ten='1'andrco_six='1')else--数到59时进位 '0'; endrtl; (2)代码原理说明 六十进制加法计数器,对输入脉冲进行计数,并输出个位十位数值。 使能十位计数 图3.2.860进制计数器设计的原理框图 (3)学习元件例化语句 元件例化是将实现设计好的实体定义为一个元件,然后用专门的语句定义的一种连接关系,将此元件与当前设计实体中指定的端口一一映射。 元件例化是实现自上而下层次化设计的一种重要途径。 元件例化语句有两部分组成,前一部分将实现设计好的实体定义为一个元件。 第二部分则定义此元件与当前设计实体的连接关系。 格式: Component元件名-------------元件定义语句 [generic<参数说明>;] Port<端口说明>; Endcomponent; 元件名portmap([端口名>]连接端口名,…);-----------------元件例化语句 Portmap是端口映射语句,用来说明例化原件与当前实体端口的连接关系。 表示这种连接关系有两种方式,一种是名字关联方式,一种是位置关联方式。 ①名字关联方式: 例化元件的端口名与关联符号“=>”两者都是必须存在的。 这是,端口名与连接端口名的对应形式在Portmap句中的位置可以是任意的。 ②位置关联方式: 端口名与关联连接符号都可省去,在portmap子句中,只要列出当前系统的连接端口名就行了,但要求连接端口的排列方式与所需例化的元件端口定义的端口名一一对应。 运用元件例化语句时,portmap端口映射的端口名是元件已经定义好的端口名字,而连接端口名则是当前系统与接入元件相连的通信端口。 说明: 60进制计数器的实例主要是让大家了解什么是元件例化,以及元件例化在VHDL中的使用,60进制计数器代码当中使用了十进制计数器和六进制计数器,这些都是单独编写的代码,编写完成后
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 设计 输入