eda第四章.docx
《eda第四章.docx》由会员分享,可在线阅读,更多相关《eda第四章.docx(28页珍藏版)》请在冰豆网上搜索。
![eda第四章.docx](https://file1.bdocx.com/fileroot1/2023-1/14/f0a4d0bd-c3dd-4605-b423-f2539d3e2682/f0a4d0bd-c3dd-4605-b423-f2539d3e26821.gif)
eda第四章
第四章系统层次化设计
层次化设计在数字系统设计中被广泛地应用,因为它有下面两个主要的优点:
①一些常用的模块可以被单独创建并存储,在以后的设计中可以直接调用该模块,而无需重新设计;
②它使整个设计更结构化,程序也具有更高的可读性;顶层文件只将一些小模块整合在一起,这使整个系统的设计思想比较容易被理解。
本章将介绍如何在MAX+plusII中采用图形法与文本法结合的混合输入方法实现元件重用与系统的层次化设计。
第一节系统层次化设计的概念
层次化设计的示意图如图所示
从图中可以看出,层次化设计的核心有两个,一是模块化,二是元件重用。
系统层次化设计的概念
模块化:
可以将一个大系统划分为几个子模块,而这些子模块又分别由更小的模块组成,如此往下,直至不可再分。
这也正是自顶向下(Top-down)的设计方法。
图中,顶层文件所描述的实体A由B、C、D三个实体组成,而实体B和实体C又分别由实体E、F和实体F、G构成。
每个实体都可以看成上一层实体中的一个模块或元件(Component),就像搭积木一样一层一层地构建。
元件重用:
同一个元件可以被不同的设计实体调用,也可以被同一个设计实体多次调用。
图中,实体F分别被实体B和实体C调用,而实体G则被实体C调用了2次。
元件重用不但大大减轻了设计者的工作量,而且使程序更结构化和具有更高的可读性。
第二节利用图形输入法实现系统层次化设计
一、元件重用
这里先看一个简单的问题:
假设系统中有一个200kHz的时钟,系统要求将其分为100kHz、50kHz和25kHz,并在这4个频率的时钟中选择一个作为输出(如图所示),如何从CLk1(200kHz)生成其他频率的时钟信号呢?
很容易就可以想到两种方案:
①设计一个2分频电路、一个4分频电路和一个8分频电路,直接从200kHz时钟信号分频得到所需的几个频率的时钟信号(如图所示);
②只设计一个2分频电路,用3个2分频电路级联的方式,从200kHz信号中逐级分出所需的时钟信号(如图所示)。
可利用2分频电路和4X1多路复用器实现
在MAX+plusⅡ中实现元件重用步骤
1.生成元件符号
如果想把描述好的2分频电路作为上一层设计实体中的元件,就必须先生成元件符号(Symbol)。
生成元件符号很简单,只要编译这个程序就可以了,MAX+plusⅡ会在编译时自动为此实体生成一个后缀名为sym的元件符号文件,这样就可以在图形编辑器(GraphicEditor)中调用此元件符号了。
特别值得注意的是:
MAX+plusⅡ只在第1次成功编译程序时会自动生成元件符号。
这意味着:
①如果此程序没有通过编译(例如因为语法错误等),那么将得不到它的元件符号,也就无法调用它;
②在第l次成功编译后(即自动生成元件符号后),如果修改这个设计实体的端口(包括端口名、端口数等),就必须更新元件符号(编译时不会自动更新)。
更新元件符号十分简单,将当前文件设为工作文件后,在File菜单中选择CreateDefaultSymbol选项,会出现对话框,问用户是否要将现有的Symbol文件覆盖,选择“确定”后,元件符号就得到了更新。
2.调用元件符号
在MAX十plusII菜单中选择GraphicEditor就启动了图形编辑器。
在图形编辑器中调用元件有3种方法;
①在Symbol菜单中选择EnterSymbol;
②双击“图形编辑区”的空白处;
③右击后选择EnterSymbol。
执行完上面的操作后,会出现如图所示的对话框。
调用元件符号
在SymbolLibraries处列出了很多元件库的目录,这里选择用户工作目录。
这时在左下角的SymbolFiles处会出现所有用户生成的元件,选择所需元件,单击OK键就完成了元件的调用。
这时图形编辑器的“图形编辑区”上就出现了刚才生成的2分频电路的元件符号(见图)。
从图中可以看出,这个元件符号有两个接口,CLOCK为输人端,CLKOUT为输出端,这与在2分频电路中实体的声明部分定义的端口是一致的。
重复调用3次这个元件,同时调用4Xl复用器的元件,接下来就是连线和定义输入/输出端口的工作了。
3.定义输入/输出端口与连线
添加输入/输出引脚的方法是;在EnterSymbol对话框中的SymbolName里输入Input即可添加入引脚,输入Output即可添加输出引脚。
连线的方法是;
如果需要连接两个元件的端口,那么将鼠标移到其中一个端口上,这时鼠标符会自动变为“+”形;然后拖动鼠标到第2个端口,松开鼠标左键后即画好一条线。
删除连线的方法是;
单击点中该线,被点中的线会变成红色,按Delete将调用的元件按图连好线,然后存盘。
存储的文件名不可与调用的任一元件名相同,即本设计不可命名为FreDevider。
gdf,不可命名为MUX4.gdf。
4.编译
其实,图形文件的编译和VHDL程序的编译是一样的,只要把当前文件设成工作文件,再启动编译器进行编译就可以了。
5.图形编辑器注意事项
下面总结一些使用图形编辑器的注意事项和技巧,希望能帮助读者用好这个工具。
(1)可以对连线命名,同名连线在电气上是连接的。
对连线命名的方法是;单击要命名的连线,连线会变成红色,并有闪烁的黑点,此时键入的文字即为连线名。
(2)在进行总线(BUS)与输入/输出端口的连接时,必须从元件的端口处开始引线,不能从输入/输出端口开始引线(见图)。
(3)当VHDL程序的元件符号更新后,必须在图形编辑器中也进行相应的更新。
在Symbol菜单中,选择UpdateSymbol可对本图形文件中的元件符号进行更新(如图示)。
更新方式有两种;①选定一个或几个元件,在图中所示的对话框中选择上面的,这样,只更新选定元件;选择下面的,更新本图形文件中所有用到的元件符号
二、多层次设计的实现
在讨论元件重用的实现时,就用了层次化设计的方法;顶层文件调用3次名为FreDevider底层实体和1次名为MUX4的底层实体。
在此基础上,进一步介绍多层次设计的实现。
其实,多层次设计在MUX+PLUS中的实现十分简单,归结起来就一句话;每个设计实体(包括用HDL设计的和用图形编辑器画成的)都可以生成元件符号,供上一层实体调用。
和文本编辑器中生成元件符号一样,在图形编辑器中生成元件符号的操作步骤是;
①将当前文件存储并设为工作文件;
②创建元件符号。
见图
那么可以创建一个新图形文件(.gdf文件),并在其中调用这个元件符号。
如此一层一层地生成元件符号并供上一层设计实体调用,即实现了多层次设计模型。
在MAX十PlusII中用图形编辑的方法实现层次化设计,实际上是结合了自顶向下和自底向上两种设计方法。
自顶向下即在设计之初画出框图,把所需的子模块以及实现此子模块所需的更底层的模块确定下来,然后用自底向上的方法,先将最底层的模块设计并调试好,然后一层一层向上生成元件符号并供上层文件调用,一直到最顶层文件为止。
例:
根据需要设计一个多用分频器:
可以控制实现四种分频形式:
第一种:
5分频、第二种:
8分频、第三种:
15分频、第四种:
16分频
多用分频器
多用分频器
sel
8分频
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
entityeightis
port(clock;instd_logic;
clk;outstd_logic);
endeight;
architecturertlofeightis
signaltemp1;std_logic;
signalcounter;integerrange0to15;
begin
process(clock)
begin
ifrising_edge(clock)then
ifcounter=3then
counter<=0;
temp1<=nottemp1;
else
counter<=counter+1;
endif;
endif;
endprocess;
clk<=temp1;
endrtl;
5分频
libraryieee;
useieee.std_logic_1164.all;
entityfiveis
port(clock;instd_logic;
clk;outstd_logic);
endfive;
architecturertloffiveis
signaltemp1,temp2;std_logic;
signalcounter;integerrange0to15;
begin
process(clock)
begin
ifrising_edge(clock)then
ifcounter=4then
counter<=0;
temp1<=nottemp1;
else
counter<=counter+1;
endif;
endif;
iffalling_edge(clock)then
ifcounter=2then
temp2<=nottemp2;
endif;
endif;
endprocess;
clk<=temp1xortemp2;
endrtl;
16分频
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
entitysixteenis
port(clock;instd_logic;
clk;outstd_logic);
endsixteen;
architecturertlofsixteenis
signaltemp1;std_logic;
signalcounter;integerrange0to15;
begin
process(clock)
begin
ifrising_edge(clock)then
ifcounter=7then
counter<=0;
temp1<=nottemp1;
else
counter<=counter+1;
endif;
endif;
endprocess;
clk<=temp1;
endrtl;
15分频
libraryieee;
useieee.std_logic_1164.all;
entityfifteenis
port(clock;instd_logic;
clk;outstd_logic);
endfifteen;
architecturertloffifteenis
signaltemp1,temp2;std_logic;
signalcounter;integerrange0to15;
begin
process(clock)
begin
ifrising_edge(clock)then
ifcounter=14then
counter<=0;
temp1<=nottemp1;
else
counter<=counter+1;
endif;
endif;
iffalling_edge(clock)then
ifcounter=7then
temp2<=nottemp2;
endif;
endif;
endprocess;
clk<=temp1xortemp2;
endrtl;
四选一
libraryieee;
useieee.std_logic_1164.all;
entityselectiois
port(a,b,c,d,e,f;instd_logic;
y;outstd_logic);
endselectio;
architecturertlofselectiois
signalsel;std_logic_vector(1downto0);
begin
sel<=e&f;
withselselect
y<=awhen"00",
bwhen"01",
cwhen"10",
dwhen"11",
'0'whenothers;
endrtl;
第三节利用VHDL语言实现系统层次化设计
一、元件例化
元件例化就是引入一种连接关系,将预先设计好的设计实体定义为一个元件,然后利用特定的语句将此元件与当前的设计实体指定的端口或信号进行连接,从而为当前设计实体引入一个新的低一级的设计层次。
元件例化由两部分组成:
前一部分是将一个现成的设计实体定义为一个元件;第二部分则是此元件与当前设计实体中的连接说明。
元件定义语句
它们的语句格式如下:
COMPONENT元件名IS
GENERIC(类属表);
PORT(端口名表);
ENDCOMPONENT元件名;
元件定义语句,相当于对一个现成的设计实体进行封装,使其只留出对外的接口界面。
就像一个集成芯片只留几个引脚在外一样,它的类属表可列出端口的数据类型和参数,端口名表可列出对外通信的各端口名。
元件的连接
例化标号1:
元件名1GENERICMAP(类属表)
PORTMAP(元件端口名=>连接端口名,…);
……
例化标号n:
元件名nGENERICMAP(类属表)
PORTMAP(元件端口名=>连接端口名,…);
元件例化语句,其中的标号是必须存在的,它类似于标在当前系统(电路板)中的一个插座名,而元件名则是准备在此插座上插入的、已定义好的元件名。
元件例化语句包含两部分映射:
类属参数映射GENERICMAP和端口映射PORTMAP。
端口映射PORTMAP
元件的端口名与当前系统的连接端口名的接口表达有两种方式:
名字关联方式和位置关联方式。
在名字关联方式下,例化元件的端口名和关联(连接)符号“=>”两者都是必须存在的。
这时,端口名与连接端口名的对应式,在PORTMAP句中的位置可以是任意的。
位置关联方式下,端口名和关联连接符号都可省去,在PORTMAP子句中,只要列出当前系统中的连接端口名就行了,但要求连接端口名的排列方式与所需例化的元件端口定义中的端口名位置一一对应。
例一用元件例化语句完成的多个D触发器构成移位寄存器
u4
u3
u2
q
d
clk
q
d
clk
q
d
clk
d
clk
q
q
a
串行输入、串行输出的4位移位寄存器
clk
Z(0)
Z
(1)
Z
(2)
Z(3)
Z(4)
b
首先完成一个D触发器的VHDL语言描述
LIBRRYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
ENTITYdffIS
PORT(d,clk;INSTD_LOGIC;
q;OUTSTD_LOGIC);
ENDdff;
ARCHITECTUREbehavOFdffIS
BEGIN
PROCESS(clk)
BEGIN
IF(clk’EVENTANDclk=‘1’)THEN
q<=d;
ENDIF;
ENDPROCESS;
ENDbehav;
然后用元件例化产生如图所示的4位串行移位寄存器
LIBRRYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
ENTITYshiftIS
PORT(clk,a;INSTD_LOGIC;
b;OUTSTD_LOGIC);
ENDshift;
然后用元件例化产生如图所示的4位串行移位寄存器
ARCHITECTURErtlOFshiftIS
COMPONENTdffis
PORT(d,clk;INSTD_LOGIC;
q;OUTSTD_LOGIC);
ENDCOMPONENT;
SIGNALz;STD_LOGIC_VECTOR(0TO4);
BIGIN
z(0)<=a;
u1;dffPORTMAP(z(0),clk,z
(1));
u2;dffPORTMAP(z
(1),clk,z
(2));
u3;dffPORTMAP(z
(2),clk,z(3));
u4;dffPORTMAP(z(3),clk,z(4));
b<=z(4);
ENDrtl;
例二分频器
LIBRARYIEEE;
USEIEEE.Std_Logic_1164.ALL;
ENTITYHierarchy_EgIS
PORT
(Clk:
INStd_Logic;
Sel:
INStd_Logic;
Clkout:
OUTStd_Logi
);
ARCHITECTUREStrucyureOFHierarchy_EgIS
COMPONENTFreDevider4IS
PORT
(Clkin:
INStd_Logic;
Clkout:
OUTStd_Logic
);
ENDCOMPONENTFreDevider4;
COMPONENTmux2is
PORT
(DataA,DataB,Sel:
INStd_Logic;
Dataout;OUTStd_Logic
);
SIGNALClk1,Clk2:
Std_Logic;
BEGIN
u1:
FreDevider4PORTMAP(Clkin=>Clk,Clkout=>Clk1);
u2:
FreDevider10PORTMAP(Clkin=>Clk,Clkout=>Clk2);
u3:
MUX2PORTMAP(DataA=>Clk1,DataB=>Clk2,Sel=>Sel,Dataout=>Clkout);
END;
二、程序包
元件例化语句实现了系统的层次化和结构化设计,但有一个缺点,那就是;如果有N个上层实体用到了同一个下层实体,那么在这N个上层实体的程序中,都必须对该下层实体进行元件定义。
另外,如果一个程序中用到了很多元件,那么元件定义语句要占很大篇幅,使程序显得臃肿,降低程序的可读性。
解决上述两个问题的办法就是用程序包Package。
在VHDL中,在某一设计实体中定义的数据类型、子程序、数据对象和元件定义对于其他设计实体来说是不可见的。
为了使已定义的数据类型、元件定义等能被更多的设计实体共享,避免重复劳动,可将这些定义收集到一个VHDL程序包中。
这样,只要在设计实体中用USE语句调用该程序包,就可以使用这些预定义的数据类型和元件定义等元素了。
程序包首;
PACKAGE包集合名IS[说明语句];
END包集合名;
程序包体
PACKAGEBODY包集合名IS[说明语句];
END包集合名;
程序包首的说明部分收集多个不同VHDL设计所需的常用公共信息,例如数据类型、元件定义、子程序说明等;而程序包体则包括已在程序包首定义了的子程序的子程序体,没有程序的,程序包体可以省略。
这里只关注元件定义的重用,所以未给出程序体说明部分的实例。
LIBRARYIEEE;
USEIEEE.Std_Logic_1164.ALL;
PACKAGEpac_deviderIS
COMPONENTFreDevider4IS
PORT
(Clk:
INStd_Logic;
Clkout:
OUTStd_Logi
);
ENDCOMPONENTFreDevider4;
COMPONENTFreDevider10IS
PORT
(Clk:
INStd_Logic;
Clkout:
OUTStd_Logi
);
ENDCOMPONENTFreDevider10;
COMPONENTMUX2IS
PORT
(DataA,DataB,Sel:
INStd_Logic;
Dataout:
OUTStd_Logic
);
ENDCOMPONENTMUX2;
ENDpac_devider;
注意,本程序包应存为pac_devider.vhd,并编译。
只有编译过的程序包才能被其他设计实体调用。
调用pac_devider。
vhd程序包的时钟选择器程序如下:
LIBRARYIEEE;
USEIEEE.Std_Logic_1164.ALL;
USEWork.Pac_Devider.ALL;
ENTITYHierarchy_EgIS
PORT
(Clk:
INStd_Logic;
Sel:
INStd_Logic;
Clkout:
OUTStd_Logi
);
END;
ARCHITECTUREStrucyureOFHierarchy_EgIS
SIGNALClk1,Clk2:
Std_Logic;
BEGIN
u1:
FreDevider4PORTMAP(Clkin=>Clk,Clkout=>Clk1);
u2:
FreDevider10PORTMAP(Clkin=>Clk,Clkout=>Clk2);
u3:
MUX2PORTMAP(DataA=>Clk1,DataB=>Clk2,Sel=>Sel,Dataout=>Clkout);
END;
Work是一个用户工作库,其路径一般默认为当前工作目录。
此库无需“显式调用”(即不需要用Library语句调用),存在当前工作目录中的一切程序包均默认为用户工作库的一部分。
三、类属参数映射
从分频器的工作原理来说,4分频电路与10分频电路的程序基本相同,只是计数器的上限不同。
在前面的设计中,分别设计了一个4分频电路和一个10分频电路,如果还需要16分频、24分频之类的偶数倍分频电路,难道还要把每个电路都做成一个实体?
显然,需要一个更好的办法,那就是设计一个参数化元件。
所谓“参数化元件”,顾名思义,就是该元件有某些参数是可调的。
通过调整这些参数,可利用一个实体实现结构相似但功能不同的电路。
类属参数映射GENERICMAP
类属参数映射可用于设计从外部端口改变元件内部参数或结构规模的元件,或称类属元件,这些元件在例化中特别方便,在改变电路结构或元件升级方面显得尤为便捷。
类属参数使用方法:
在实体说明中使用类属映射语句GENERIC在进行元件定义时,使用GENERlC定义在使用元件时,进行类属映射。
类属参数映射举例
例1;参数可调的偶数倍分频器的程序,其中的N为分频参数,分频倍数为2*(N+1)。
实体定义
LIBRARYIEEE;
USEIEEE.Std_Logic_1164.ALL;
ENTITYFreDeviderIS
GENERIC(N:
Integer:
=4);
PORT
(Clkin:
INStd_Logic;
Clkout:
OUTStd_Logic
)
ARCHITECTUREBehaviorOFFreDeviderIS
SIGNALCounter:
IntegerRANGE0TON;
SIGNALClk:
Std_Logic;
BEGIN
PROCESS(Clkin)
BEGIN
IFrising_edge(Clkin)THEN
IF