实训十七 基本单元电路的VHDL设计.docx
《实训十七 基本单元电路的VHDL设计.docx》由会员分享,可在线阅读,更多相关《实训十七 基本单元电路的VHDL设计.docx(31页珍藏版)》请在冰豆网上搜索。
![实训十七 基本单元电路的VHDL设计.docx](https://file1.bdocx.com/fileroot1/2023-6/6/7df386ee-c3d7-4613-ac5a-9fd4ecdde1c1/7df386ee-c3d7-4613-ac5a-9fd4ecdde1c11.gif)
实训十七基本单元电路的VHDL设计
实训十七基本单元电路的VHDL设计
本章提要:
本章介绍了数字系统设计中经常用到的计数器,分频器,选择器,译码器,编码器,寄存器,存储器,输入电路,显示电路等基本单元电路的VHDL程序设计。
学习要求:
在教师讲授这些基本单元电路的设计思想的基础上,通过上机调试熟练掌握这些基本单元电路的设计。
关键词:
计数器(Counter),分频器(Divder),选择器(Multiplexer),译码器(Decoder),编码器(Encoder),寄存器(Register),存储器(Memory),输入电路(InputCircuit),显示电路(DisplayCircuit)
6.1计数器的设计
6.1.1同步计数器的设计
6.1.2异步计数器的设计
6.2分频器的设计
6.3选择器的设计
6.4译码器的设计
6.5编码器的设计
6.5.1一般编码器的设计
6.5.2优先级编码器的设计
6.6寄存器的设计
6.6.1数码寄存器的设计
6.6.2移位寄存器的设计
6.6.3并行加载移位寄存器的设计
6.7存储器的设计
6.7.1只读存储器ROM的设计
6.7.2读写存储器SRAM的设计
6.8输入电路的设计
6.8.1键盘扫描电路的设计
6.8.2键盘接口电路的设计
6.9显示电路的设计
6.9.1数码管静态显示电路的设计
6.9.2数码管动态显示电路的设计
6.9.2液晶显示控制电路的设计
6.1计数器的设计
计数器是在数字系统中使用最多的时序电路,它不仅能用于对时钟脉冲计数,还可以用于分频,定时,产生节拍脉冲和脉冲序列以及进行数字运算等。
计数器是一个典型的时序电路,分析计数器就能更好地了解时序电路的特性。
计数器分同步计数器和异步计数器两种。
6.1.1同步计数器的设计
所谓同步计数器,就是在时钟脉冲(计数脉冲)的控制下,构成计数器的各触发器状态同时发生变化的那一类计数器。
1)六十进制计数器
众所周知,用一个4位二进制计数器可构成1位十进制计数器,而2位十进制计数器连接起来可以构成一个六十进制的计数器。
六十进制计数器常用于时钟计数。
一个六十进制计数器的外部端口示意图如图6.1所示。
在该六十进制计数器的电路中,BCDLWR和BCD10WR与DATAIN配合,以实现对六十进制计数器的个位和十位值的预置操作。
应注意,在对个位和十位进行预置操作时,DATAIN输入端是公用的,因而个位和十位的预置操作必定要串行进行。
利用VHDL语言描述六十进制计数器的程序如例6.1所示。
图6.1六十进制计数器外部端口示意图
【例6.1】用VHDL设计一个六十进制计数器(方法1)。
--BCD60COUNT.VHD
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITYBCD60COUNTIS
PORT(CLK,BCD1WR,BCD10WR,CIN:
STD_LOGIC;
CO:
OUTSTD_LOGIC;
DATAIN:
INSTD_LOGIC_VECTOR(3DOWNTO0);
BCD1:
OUTSTD_LOGIC_VECTOR(3DOWNTO0);
BCDI0:
OUTSTD_LOGIC_VECTOR(2DOWNTO0));
ENDBCD60COUNT;
ARCHITECTURERTLOFBCD60COUNTIS
SIGNALBCD1N:
STD_LOGIC_VECTOR(3DOWNTO0);
SIGNALBCD10N:
STD_LOGIC_VECTOR(2DOWNTO0);
BEGIN
BCD1<=BCD1N;
BCDI0<=BCD10N;
PROCESS(CLK,BCD1WR)–-个位数处理进程
BEGIN
IF(BCD1WR='1')THEN
BCD1N<=DATAIN;
ELSIF(CLK'EVENTANDCLK='1')THEN
IF(CIN='1')THEN
IF(BCD1N=9)THEN
BCD1N<="0000";
ELSE
BCD1N<=BCD1N+1;
ENDIF;
ENDIF;
ENDIF;
ENDPROCESS;
PROCESS(CLK,BCD10WR)–-十位数处理进程
BEGIN
IF(BCD10WR='1')THEN
BCD10N<=DATAIN(2DOWNTO0);
ELSIF(CLK'EVENTANDCLK='1')THEN
IF(CIN='1'ANDBCD1N=9)THEN
IF(BCD10N=5)THEN
BCD10N<="000";
ELSE
BCD10N<=BCD10N+1;
ENDIF;
ENDIF;
ENDIF;
ENDPROCESS;
PROCESS(BCD10N,BCD1N,CIN)–-进位位处理进程
BEGIN
IF(CIN='1'ANDBCD1N=9ANDBCD10N=5)THEN
CO<='1';
ELSE
CO<='0';
ENDIF;
ENDPROCESS;
ENDRTL;
【例6.2】用VHDL设计一个六十进制计数器(方法2)。
--COUNTER60.vhd
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_ARITH.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITYCOUNTER60IS
PORT(CP:
INSTD_LOGIC;--时钟脉冲
BIN:
OUTSTD_LOGIC_VECTOR(5DOWNTO0);--二进制
S:
INSTD_LOGIC;--输出启动信号
CLR:
INSTD_LOGIC;--清除信号
EC:
INSTD_LOGIC;--使能计数信号
CY60:
OUTSTD_LOGIC);--计数60进位信号
ENDCOUNTER60;
ARCHITECTURERTLOFCOUNTER60IS
SIGNALQ:
STD_LOGIC_VECTOR(5DOWNTO0);
SIGNALRST,DLY:
STD_LOGIC;
BEGIN
PROCESS(CP,RST)--计数60
BEGIN
IFRST='1'THEN
Q<="000000";--复位计数器
ELSIFCP'EVENTANDCP='1'THEN
DLY<=Q(5);
IFEC='1'THEN
Q<=Q+1;--计数值加1
ENDIF;
ENDIF;
ENDPROCESS;
CY60<=NOTQ(5)ANDDLY;--进位信号微分
RST<='1'WHENQ=60ORCLR='1'ELSE--复位信号设定
'0';
BIN<=QWHENS='1'ELSE--计数输出
"000000";
ENDRTL;
2)可逆计数器
在时序应用电路中,计数器的应用十分普遍,如加法计数器,减法计数器,可逆计数器等。
所谓可逆计数器,就是根据计数控制信号的不同,在时钟脉冲作用下,计数器可以进行加1或者减1操作的一种计数器。
可逆计数器有一个特殊的控制端,这就是UPDN端。
当UPDN=‘1’时,计数器进行加1操作,当UPDN=‘0’时,计数器就进行减1操作。
表6.1是一个3位可逆计数器的真值表,它的VHDL语言描述如例6.3所示。
表6.1可逆计数器真值表
输入端输出端
DIRCPQ2Q1Q0
XX000
1计数器加1操作
0计数器减1操作
【例6.3】用VHDL设计一个3位二进制的可逆计数器。
--COUNT3.vhd
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_ARITH.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITYCOUNT3IS
PORT(CP,DIR:
INSTD_LOGIC;
Q:
OUTSTD_LOGIC_VECTOR(2DOWNTO0));
END;
ARCHITECTURERTLOFCOUNT3IS
SIGNALQN:
STD_LOGIC_VECTOR(2DOWNTO0);
BEGIN
PROCESS(CP)
BEGIN
IFCP'EVENTANDCP='1'THEN
IFDIR='0'THEN
QN<=QN+1;
ELSE
QN<=QN-1;
ENDIF;
ENDIF;
ENDPROCESS;
Q<=QN;
ENDRTL;
编写可逆计数器VHDL程序时,在语法上,就是把加法和减法计数器合并,使用一个控制信号决定计数器作加法或减法的动作。
在本例中,利用“控制信号DIR”可以让计数器的计数动作加1或减1。
6.1.2异步计数器的设计
异步计数器又称行波计数器,它将低/高位计数器的输出做为高/低位计数器的时钟信号,这一级一级串行连接起来就构成了一个异步计数器。
异步计数器与同步计数器不同之处就在于时钟脉冲的提供方式,但是,由于异步计数器采用行波计数,从而使计数延迟增加,在要求延迟小的领域受到了很大限制。
尽管如此,由于它的电路简单,仍有广泛的应用。
图6.2是用VHDL语言描述的一个由8个触发器构成的异步计数器.它的程序如例6.4所示,采用元件例化方式生成。
与上述同步计数器不同之处主要表现在对各级时钟脉冲的描述上,这一点请读者在阅读程序时多加注意。
图6.28位异步计数器原理图
【例6.4】用VHDL设计一个由8个触发器构成的8位二进制异步计数器。
--RPLCONT.VHD
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
ENTITYDFFRIS
PORT(CLK,CLR,D:
INSTD_LOGIC;
Q,QB:
OUTSTD_LOGIC);
ENDENTITYDFFR;
ARCHITECTUREART1OFDFFRIS
SIGNALQ_IN:
STD_LOGIC;
BEGIN
QB<=NOTQ_IN;
Q<=Q_IN;
PROCESS(CLK,CLR)IS
BEGIN
IF(CLR='1')THEN
Q_IN<='0';
ELSIF(CLK'EVENTANDCLK='1')THEN
Q_IN<=D;
ENDIF;
ENDPROCESS;
ENDARCHITECTUREART1;
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
ENTITYRPLCONTIS
PORT(CLK,CLR:
INSTD_LOGIC;
COUNT:
OUTSTD_LOGIC_VECTOR(7DOWNTO0));
ENDENTITYRPLCONT;
ARCHITECTUREART2OFRPLCONTIS
SIGNALCOUNT_IN_BAR:
STD_LOGIC_VECTOR(8DOWNTO0);
COMPONENTDFFRIS
PORT(CLK,CLR,D:
INSTD_LOGIC;
Q,QB:
OUTSTD_LOGIC);
ENDCOMPONENT;
BEGIN
COUNT_IN_BAR(0)<=CLK;
GEN1:
FORIIN0TO7GENERATE
U:
DFFRPORTMAP(CLK=>COUNT_IN_BAR(I),CLR=>CLR,
D=>COUNT_IN_BAR(I+1),Q=>COUNT(I),QB=>COUNT_IN_BAR(I+1));
ENDGENERATE;
ENDARCHITECTUREART2;
6.2分频器的设计
一般来说,可以把加法计数器看成一种分频电路,而且是除2的N的次方的分频电路。
但是也常常会有除M(M不是2的N次方)的分频电路需求.
下面就介绍一个除6的加法分频电路。
先建立一个计数器,而这个计数器的大小必须是3位(计数默认范围是0~2^3-1=7),不过将把这样的计数值为6的瞬间,立即复位改变为0,其VHDL程序如例6.5所示
【例6.5】用VHDL设计一个除6的加法分频电路。
--COUNT6.vhd
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_ARITH.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITYCOUNT6is
PORT(CP:
INSTD_LOGIC;
Result:
OUTSTD_LOGIC);
ENDCOUNT6;
ARCHITECTUREaOFCOUNT6IS
SIGNALRST:
STD_LOGIC;
SIGNALQN:
STD_LOGIC_VECTOR(2DOWNTO0);
BEGIN
PROCESS(CP,RST)--***COUNTER
BEGIN
IFRST='1'THEN
QN<="000";--ResetCounter
ELSIFCP'eventANDCP='1'THEN
QN<=QN+1;--COUNTER+1
ENDIF;
ENDPROCESS;
RST<='1'WHENQN=6ELSE--RESETCOUNTER
'0';
Result<=QN
(2);--ResultOutput
ENDa;
以后遇到需要分频是N的同步计数器,需将上述QN=6改成QN=N,而且计数器Xbits数需调整为符合条件2X>=N才可以。
6.3选择器的设计
多路选择器可以从多组数据来源中选取一组送入目的地。
它的应用范围相当广泛,从组合逻辑的执行,到数据路径的选择,经常可以看到它的踪影。
另外在像时钟,计数定时器等的输出显示电路中都可以看到利用多路选择器制作扫描电路来分别驱动输出装置(通常为七段数码显示管,点矩阵或液晶面板),以降低功率的消耗。
有时也希望把两组没有必要同时观察的数据,共享一组显示电路,以降低成本。
多路选择器的结构是2N个输入线,会有N个地址选择线及一个输出线配合。
现以一个四选一的多路选择器为例,其四选一电路的真值表如表6.2所示,其外部端口示意图如图6.3所示。
表6.2四选一电路真值表
选择输入数据输入数据输出
baInput(0)Input
(1)Input
(2)Input(3)y
000XXX0
001XXX1
01X0XX0
01X1XX1
10XX0X0
10XX1X1
11XXX00
11XXX11
图6.3四选一电路外部端口示意图
描述四选一多路选择器的方法有多种,例如在一个进程中使用if-then-else语句;在一个进程中使用case语句;使用withselect构造或使用结构VHDL。
现用if-then-else语句对它进行描述,就可以得到如例6.6所示的程序。
【例6.6】设计一个四选一的多路选择器的VHDL程序(使用if-then-else语句)。
--MUX4.VHD
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
ENTITYMUX4IS
PORT(DATA0,DATA1,DATA2,DATA3:
INSTD_LOGIC_VECTOR(3DOWNTO0);
A,B:
INSTD_LOGIC;
Y:
OUTSTD_LOGIC_VECTOR(3DOWNTO0));
ENDENTITYMUX4;
ARCHITECTUREARTOFMUX4IS
SIGNALSEL:
STD_LOGIC_VECTOR(1DOWNTO0);
BEGIN
SEL<=B&A;
PROCESS(SEL)
BEGIN
IF(SEL="00")THEN
Y<=DATA0;
ELSIF(SEL="01")THEN
Y<=DATA1;
ELSIF(SEL="10")THEN
Y<=DATA2;
ELSE
Y<=DATA3;
ENDIF;
ENDPROCESS;
ARCHITECTUREART;
例6.6中的四选一选择器是用IF语句描述的,程序中的ELSE项作为余下的条件,将选择INPUT(3)从Y端输出,这种描述比较安全。
当然,不用ELSE项也可以,这时必须列出SEL的所有可能出现的情况,加以一一确认。
在进程中使用CASE语句会更清晰易读。
例6.7是用CASE语句描述的四选一选择器。
【例6.7】设计一个四选一的多路选择器的VHDL程序(使用case语句)。
--MUX4.VHD
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
ENTITYMUX4IS
PORT(DATA0,DATA1,DATA2,DATA3:
INSTD_LOGIC_VECTOR(3DOWNTO0);
A,B:
INSTD_LOGIC;
Y:
OUTSTD_LOGIC_VECTOR(3DOWNTO0));
ENDENTITYMUX4;
ARCHITECTUREARTOFMUX4IS
SIGNALSEL:
STD_LOGIC_VECTOR(1DOWNTO0);
BEGIN
SEL<=B&A;
PROCESS(SEL)
BEGIN
CASESELIS
WHEN"00"=>Y<=DATA0;
WHEN"01"=>Y<=DATA1;
WHEN"10"=>Y<=DATA2;
WHEN"11"=>Y<=DATA3;
WHENOTHERS=>Y<=NULL;
ENDCASE;
ENDPROCESS;
ENDARCHITECTUREART;
【例6.8】设计一个四选一的多路选择器的VHDL程序(使用WHEN-ELSE并行条件赋值语句)。
--MUX4.VHD
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
ENTITYMUX4IS
PORT(DATA0,DATA1,DATA2,DATA3:
INSTD_LOGIC_VECTOR(3DOWNTO0);
A,B:
INSTD_LOGIC;
Y:
OUTSTD_LOGIC_VECTOR(3DOWNTO0));
ENDENTITYMUX4;
ARCHITECTUREARTOFMUX4IS
SIGNALSEL:
STD_LOGIC_VECTOR(1DOWNTO0);
BEGIN
SEL<=B&A;
Y<=DATA0WHENSEL="00"ELSE
DATA1WHENSEL="01"ELSE
DATA2WHENSEL="10"ELSE
DATA3WHENSEL="11"ELSE
'0';
ENDARCHITECTUREART;
6.4译码器的设计
译码器是把输入的数码解出其对应的数码,如果有N个二进制选择线,则最多可以译码转换成2N个数据。
译码器也经常被应用在地址总线或用作电路的控制线。
像只读存储器(ROM)中便利用译码器来进行地址选址的工作。
3-8译码器是最常用的种小规模集成电路。
3-8译码器外部端口示意图如图6.9所示,它有3个二进制输入端a,b,c和8个译码输出端y0~y7。
对输入a,b,c的值进行译码,就可以确定输出端y0~y7的哪一个输出端变为有效(低电平),从而达到译码的目的。
另外为方便译码器的控制或便于将来扩充用,在设计时常常会增加一个EN使能输入脚。
3-8译码器的真值表如表6.3所示。
有了真值表,就可以直接用查表法来设计。
在VHDL中,“WITH…SELECT”,“CASE…WHEN”及“WHEN…ELSE”这类指令都是执行查表或对应动作的能手。
图6.43-8译码器外部端口示意图
表6.33-8译码器的真值表
使能二进制输入端译码输出端
encbay0y1y2y3y4y5y6y7
0xxx11111111
100001111111
100110111111
101011011111
101111101111
110011110111
110111111011
111011111101
111111111110
【例6.9】用VHDL设计一个3-8译码器(用“CASE…WHEN”语句)。
--DECODER38.VHD
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
ENTITYDECODER38IS
PORT(A,B,C,EN:
INSTD_LOGIC;
Y:
OUTSTD_LOGIC_VECTOR(7DOWNTO0));
ENDDECODER38;
ARCHITECTURERTLOFDECODER38IS
SIGNALINDATA:
STD_LOGIC_VECTOR(2DOWNTO0);
BEGIN
INDATA<=C&B&A;
PROCESS(INDATA,EN)
BEGIN
IF(EN='1')THEN
CASEINDATAIS
WHEN"000"=>Y<="11111110";
WHEN"001"=>Y<="11111101";
WHEN"010"=>Y<="11111011";
WHEN"011"=>Y<="11110111";
WHEN"100"=>Y<="11101111";
WHEN"101"=>Y<="11011111";
WHEN"110"=>Y<="10111111";
WHEN"111"=>Y<="01111111";
WHENOTHERS=>Y<=NULL;
ENDCASE;
ELSE
Y<="11111111";
ENDIF;
ENDPROCESS;
ENDRTL;
【例6.10】用VHDL设计一个3-8译码器(用“WITH…SELECT”语句)。
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.All;
ENTITYDECODER38IS
PORT(A,B,C,EN:
INS