单片机基本单元的VHDL设计

单片机基本单元的VHDL设计,第1张

介绍了数字系统设计中经常用到的计数器,分频器,选择器,译码器,编码器寄存器存储器,输入电路,显示电路等基本单元电路的VHDL程序设计。
学习要求:在教师讲授这些基本单元电路的设计思想的基础上,通过上机调试熟练掌握这些基本单元电路的设计。
关键词:计数器(Counter),分频器(Divder),选择器(MulTIplexer),译码器(Decoder),编码器(Encoder),寄存器(Register),存储器(Memory),输入电路(Input Circuit),显示电路(Display Circuit)
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
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY BCD60COUNT IS
PORT(CLK,BCD1WR,BCD10WR,CIN:STD_LOGIC;
COUT STD_LOGIC;
DATAIN:IN STD_LOGIC_VECTOR (3 DOWNTO 0);
BCD1:OUT STD_LOGIC_VECTOR (3 DOWNTO 0);
BCDI0:OUT STD_LOGIC_VECTOR (2 DOWNTO 0));
END BCD60COUNT;
ARCHITECTURE RTL OF BCD60COUNT IS
SIGNAL BCD1N:STD_LOGIC_VECTOR (3 DOWNTO 0);
SIGNAL BCD10N:STD_LOGIC_VECTOR (2 DOWNTO 0);
BEGIN
BCD1<=BCD1N;
BCDI0<=BCD10N;
PROCESS (CLK,BCD1WR) –-个位数处理进程
BEGIN
IF (BCD1WR='1') THEN
BCD1N<=DATAIN;
ELSIF (CLK'EVENT AND CLK='1') THEN
IF (CIN='1') THEN
IF (BCD1N=9) THEN
BCD1N<="0000";
ELSE
BCD1N<=BCD1N+1;
END IF;
END IF;
END IF;
END PROCESS;
PROCESS (CLK,BCD10WR) –-十位数处理进程
BEGIN
IF (BCD10WR='1') THEN
BCD10N<=DATAIN (2 DOWNTO 0);
ELSIF (CLK'EVENT AND CLK='1') THEN
IF (CIN='1' AND BCD1N=9) THEN
IF (BCD10N=5) THEN
BCD10N<="000";
ELSE
BCD10N<=BCD10N+1;
END IF;
END IF;
END IF;
END PROCESS;
PROCESS (BCD10N,BCD1N,CIN) –-进位位处理进程
BEGIN
IF (CIN='1' AND BCD1N=9 AND BCD10N=5) THEN
CO<='1';
ELSE
CO<='0';
END IF;
END PROCESS;
END RTL;

【例6.2】 用VHDL设计一个六十进制计数器(方法2)。
--COUNTER60.vhd
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY COUNTER60 IS
PORT(CP: IN STD_LOGIC; --时钟脉冲
BIN: OUT STD_LOGIC_VECTOR (5 DOWNTO 0); --二进制
S: IN STD_LOGIC; --输出启动信号
CLR: IN STD_LOGIC; --清除信号
EC: IN STD_LOGIC; --使能计数信号
CY60: OUT STD_LOGIC );--计数60进位信号
END COUNTER60;
ARCHITECTURE RTL OF COUNTER60 IS
SIGNAL Q : STD_LOGIC_VECTOR (5 DOWNTO 0) ;
SIGNAL RST, DLY : STD_LOGIC;
BEGIN
PROCESS (CP,RST) -- 计数60
BEGIN
IF RST = '1' THEN
Q <= "000000"; -- 复位计数器
ELSIF CP'EVENT AND CP = '1' THEN
DLY <= Q(5);
IF EC = '1' THEN
Q <= Q+1; -- 计数值加1
END IF;
END IF;
END PROCESS;
CY60 <= NOT Q(5) AND DLY; -- 进位信号微分
RST <= '1' WHEN Q=60 OR CLR='1' ELSE -- 复位信号设定
'0';
BIN <= Q WHEN S = '1' ELSE -- 计数输出
"000000";
END RTL ;
2) 可逆计数器
在时序应用电路中,计数器的应用十分普遍,如加法计数器,减法计数器,可逆计数器等。所谓可逆计数器,就是根据计数控制信号的不同,在时钟脉冲作用下,计数器可以进行加1或者减1 *** 作的一种计数器。可逆计数器有一个特殊的控制端,这就是UPDN端。当UPDN=‘1’时,计数器进行加1 *** 作,当UPDN=‘0’时,计数器就进行减1 *** 作。表6.1是一个3位可逆计数器的真值表,它的VHDL语言描述如例6.3所示。
表6.1 可逆计数器真值表
输入端 输出端
DIR CP Q2 Q1 Q0
X X 0 0 0
1 计数器加1 *** 作
0 计数器减1 *** 作

【例6.3】 用VHDL设计一个3位二进制的可逆计数器。
--COUNT3.vhd
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY COUNT3 IS
PORT (CP,DIR:IN STD_LOGIC;
Q: OUT STD_LOGIC_VECTOR(2 DOWNTO 0));
END;
ARCHITECTURE RTL OF COUNT3 IS
SIGNAL QN:STD_LOGIC_VECTOR(2 DOWNTO 0);
BEGIN
PROCESS(CP)
BEGIN
IF CP'EVENT AND CP='1' THEN
IF DIR='0' THEN
QN<=QN +1;
ELSE
QN<=QN-1;
END IF ;
END IF;
END PROCESS;
Q<=QN;
END RTL;
编写可逆计数器VHDL程序时,在语法上,就是把加法和减法计数器合并,使用一个控制信号决定计数器作加法或减法的动作。在本例中,利用“控制信号DIR”可以让计数器的计数动作加1或减1。
6.1.2 异步计数器的设计
异步计数器又称行波计数器,它将低/高位计数器的输出做为高/低位计数器的时钟信号,这一级一级串行连接起来就构成了一个异步计数器。异步计数器与同步计数器不同之处就在于时钟脉冲的提供方式,但是,由于异步计数器采用行波计数,从而使计数延迟增加,在要求延迟小的领域受到了很大限制。尽管如此,由于它的电路简单,仍有广泛的应用。

图6.2是用VHDL语言描述的一个由8个触发器构成的异步计数器.它的程序如例6.4所示,采用元件例化方式生成。与上述同步计数器不同之处主要表现在对各级时钟脉冲的描述上,这一点请读者在阅读程序时多加注意。


图6.2 8位异步计数器原理图
【例6.4】 用VHDL设计一个由8个触发器构成的8位二进制异步计数器。
--RPLCONT.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY DFFR IS
PORT(CLK,CLR,D:IN STD_LOGIC;
Q,QB:OUT STD_LOGIC);
END ENTITY DFFR;
ARCHITECTURE ART1 OF DFFR IS
SIGNAL Q_IN:STD_LOGIC;
BEGIN
QB<=NOT Q_IN;
Q<=Q_IN;
PROCESS(CLK,CLR) IS
BEGIN
IF (CLR='1') THEN
Q_IN<='0';
ELSIF (CLK'EVENT AND CLK='1') THEN
Q_IN<=D;
END IF ;
END PROCESS;
END ARCHITECTURE ART1;

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY RPLCONT IS
PORT(CLK,CLR:IN STD_LOGIC;
COUNT:OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END ENTITY RPLCONT;
ARCHITECTURE ART2 OF RPLCONT IS
SIGNAL COUNT_IN_BAR:STD_LOGIC_VECTOR(8 DOWNTO 0);
COMPONENT DFFR IS
PORT(CLK,CLR,D:IN STD_LOGIC;
Q,QB:OUT STD_LOGIC);
END COMPONENT;
BEGIN
COUNT_IN_BAR(0)<=CLK;
GEN1:FOR I IN 0 TO 7 GENERATE
U:DFFR PORT MAP (CLK=>COUNT_IN_BAR(I),CLR=>CLR,
D=>COUNT_IN_BAR(I+1),Q=>COUNT(I),QB=>COUNT_IN_BAR(I+1));
END GENERATE;
END ARCHITECTURE ART2;
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
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY COUNT6 is
PORT(CP: IN STD_LOGIC;
Result: OUT STD_LOGIC);
END COUNT6;
ARCHITECTURE a OF COUNT6 IS
SIGNAL RST: STD_LOGIC;
SIGNAL QN: STD_LOGIC_VECTOR(2 DOWNTO 0);
BEGIN
PROCESS (CP,RST) -- *** COUNTER
BEGIN
IF RST = '1' THEN
QN <= "000"; --Reset Counter
ELSIF CP'event AND CP='1' THEN
QN <= QN + 1; --COUNTER + 1
END IF;
END PROCESS;
RST <= '1' WHEN QN = 6 ELSE -- RESET COUNTER
'0';
Result <= QN(2); -- Result Output
END a;
以后遇到需要分频是N 的同步计数器,需将上述QN=6改成QN=N,而且计数器X bits数需调整为符合条件2X>=N才可以。
6.3 选择器的设计
多路选择器可以从多组数据来源中选取一组送入目的地。它的应用范围相当广泛,从组合逻辑的执行,到数据路径的选择,经常可以看到它的踪影。另外在像时钟,计数定时器等的输出显示电路中都可以看到利用多路选择器制作扫描电路来分别驱动输出装置(通常为七段数码显示管,点矩阵或液晶面板),以降低功率的消耗。有时也希望把两组没有必要同时观察的数据,共享一组显示电路,以降低成本。
多路选择器的结构是2N个输入线,会有N个地址选择线及一个输出线配合。现以一个四选一的多路选择器为例,其四选一电路的真值表如表6.2所示,其外部端口示意图如图6.3所示。
表6.2 四选一电路真值表
选择输入 数据输入 数据输出
b a Input(0) Input(1) Input(2) Input(3) y
0 0 0 X X X 0
0 0 1 X X X 1
0 1 X 0 X X 0
0 1 X 1 X X 1
1 0 X X 0 X 0
1 0 X X 1 X 1
1 1 X X X 0 0
1 1 X X X 1 1


图6.3 四选一电路外部端口示意图
描述四选一多路选择器的方法有多种,例如在一个进程中使用if-then-else语句;在一个进程中使用case语句;使用with select构造或使用结构VHDL。现用if-then-else语句对它进行描述,就可以得到如例6.6所示的程序。
【例6.6】设计一个四选一的多路选择器的VHDL程序(使用if-then-else语句)。
--MUX4.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY MUX4 IS
PORT(DATA0,DATA1,DATA2,DATA3:IN STD_LOGIC_VECTOR(3 DOWNTO 0);
A,B:IN STD_LOGIC;
Y:OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END ENTITY MUX4;
ARCHITECTURE ART OF MUX4 IS
SIGNAL SEL:STD_LOGIC_VECTOR(1 DOWNTO 0);
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;
END IF;
END PROCESS;
ARCHITECTURE ART;
例6.6中的四选一选择器是用IF语句描述的,程序中的ELSE项作为余下的条件,将选择INPUT(3)从Y端输出,这种描述比较安全。当然,不用ELSE项也可以,这时必须列出SEL的所有可能出现的情况,加以一一确认。在进程中使用CASE语句会更清晰易读。例6.7是用CASE语句描述的四选一选择器。
【例6.7】设计一个四选一的多路选择器的VHDL程序(使用case语句)。
--MUX4.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY MUX4 IS
PORT(DATA0,DATA1,DATA2,DATA3:IN STD_LOGIC_VECTOR(3 DOWNTO 0);
A,B:IN STD_LOGIC;
Y:OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END ENTITY MUX4;
ARCHITECTURE ART OF MUX4 IS
SIGNAL SEL:STD_LOGIC_VECTOR(1 DOWNTO 0);
BEGIN
SEL<=B&A;
PROCESS(SEL)
BEGIN
CASE SEL IS
WHEN "00"=>Y<=DATA0;
WHEN "01"=>Y<=DATA1;
WHEN "10"=>Y<=DATA2;
WHEN "11"=>Y<=DATA3;
WHEN OTHERS =>Y<=NULL;
END CASE;
END PROCESS;
END ARCHITECTURE ART;
【例6.8】设计一个四选一的多路选择器的VHDL程序(使用WHEN-ELSE并行条件赋值语句)。
--MUX4.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY MUX4 IS
PORT(DATA0,DATA1,DATA2,DATA3:IN STD_LOGIC_VECTOR(3 DOWNTO 0);
A,B:IN STD_LOGIC;
Y:OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END ENTITY MUX4;
ARCHITECTURE ART OF MUX4 IS
SIGNAL SEL : STD_LOGIC_VECTOR(1 DOWNTO 0);
BEGIN
SEL<=B&A;
Y<= DATA0 WHEN SEL="00" ELSE
DATA1 WHEN SEL="01" ELSE
DATA2 WHEN SEL="10" ELSE
DATA3 WHEN SEL="11" ELSE
'0' ;
END ARCHITECTURE ART ;
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.4 3-8译码器外部端口示意图

表6.3 3-8译码器的真值表
使能 二进制输入端 译码输出端
en c b a y0 y1 y2 y3 y4 y5 y6 y7
0 x x x 1 1 1 1 1 1 1 1
1 0 0 0 0 1 1 1 1 1 1 1
1 0 0 1 1 0 1 1 1 1 1 1
1 0 1 0 1 1 0 1 1 1 1 1
1 0 1 1 1 1 1 0 1 1 1 1
1 1 0 0 1 1 1 1 0 1 1 1
1 1 0 1 1 1 1 1 1 0 1 1
1 1 1 0 1 1 1 1 1 1 0 1
1 1 1 1 1 1 1 1 1 1 1 0


【例6.9】 用VHDL设计一个3-8译码器(用“CASE…WHEN”语句)。
--DECODER38.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY DECODER38 IS
PORT (A,B,C, EN : IN STD_LOGIC;
Y : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END DECODER38 ;
ARCHITECTURE RTL OF DECODER38 IS
SIGNAL INDATA :STD_LOGIC_VECTOR(2 DOWNTO 0);
BEGIN
INDATA<=C&B&A;
PROCESS (INDATA,EN)
BEGIN
IF (EN='1')THEN
CASE INDATA IS
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";
WHEN OTHERS=>Y<=NULL;
END CASE;
ELSE
Y<="11111111";
END IF;
END PROCESS;
END RTL;
【例6.10】 用VHDL设计一个3-8译码器(用“WITH…SELECT”语句)。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.All;
ENTITY DECODER38 IS
PORT (A,B,C, EN : IN STD_LOGIC;
Y : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END DECODER38;
ARCHITECTURE RTL OF DECODER38 IS
SIGNAL INDATA :STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
INDATA<=EN&C&B&A; --将EN,A,B,C合并成序列的一种写法
WITH INDATA SELECT
Y<="11111110" WHEN "1000",
"11111101" WHEN "1001",
"11111011" WHEN "1010",
"11110111" WHEN "1011",
"11101111" WHEN "1100",
"11011111" WHEN "1101",
"10111111" WHEN "1110",
"01111111" WHEN "1111",
"11111111" WHEN OTHERS;
END RTL;
在本节中用到的两种描述语句,“WITH…SELECT”是并行同时性语句,“CASE…WHEN”是与其功能相同的顺序性语句,读者在使用时一定要确定需要的是顺序性语句还是并行性语句,否则程序在编译时会发生错误。
6.5 编码器的设计
编码器是将2^N个分离的信息代码以N个二进制码来表示。它的功能和译码器正好相反。编码器常常运用于影音压缩或通信方面,以达到精简传输量的目的。可以将编码器看成压缩电路,译码起看成解压缩电路。传送数据前先用编码器压缩数据后在传送出去,在接收端则由译码器将数据解压缩,还原其原来的数据。这样,在传送过程中,就可以以N个数码来代替2^N个数码的数据量,来提升传输效率。

6.5.1 一般编码器的设计
如果没有特别说明,各编码输入端无优先
区别。图6.5是8-3编码器的外部端口图,
有了外部端口图,就能够做ENTITY的定义,
再根据编码器的真值表如表6.4所示.,再使用
查表法就可以轻松描述结构体了。


图6.5 8-3编码器外部端口图

表6.4 8-3编码器的真值表
输入 二进制编码输出
A7 A6 A5 A4 A3 A2 A1 A0 Y2 Y1 Y0
1 1 1 1 1 1 1 0 1 1 1
1 1 1 1 1 1 0 1 1 1 0
1 1 1 1 1 0 1 1 1 0 1
1 1 1 1 0 1 1 1 1 0 0
1 1 1 0 1 1 1 1 0 1 1
1 1 0 1 1 1 1 1 0 1 0
1 0 1 1 1 1 1 1 0 0 1
0 1 1 1 1 1 1 1 0 0 0

【例6.11】用VHDL设计一个8-3编码器。
--CH_8_3.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY CH_8_3 IS
PORT (A :IN STD_LOGIC_VECTOR(7 DOWNTO 0);
Y :OUT STD_LOGIC_VECTOR(2 DOWNTO 0));
END CH_8_3;
ARCHITECTURE RTL OF CH_8_3 IS
BEGIN
WITH A SELECT
Y<="000" WHEN "11111110",
"001" WHEN "11111101",
"010" WHEN "11111011",
"011" WHEN "11110111",
"100" WHEN "11101111",
"101" WHEN "11011111",
"110" WHEN "10111111",
"111" WHEN "01111111",
"000" WHEN OTHERS;
END RTL;
6.5.2 优先级编码器的设计
优先级编码器长用于中断的优先级控制,例如,74LS148是一个8输入,3位二进制码输出的优先级编码器。当其某一个输入有效时,就可以输出一个对应的3位二进制编码。另外,当同时有几个输入有效时, 将输优先级最高的那个输入所对应的二进制编码。
该优先级编码器的真值表如表6. 5所示。表中的“X”项表示任意项,它可以是“0”,也可以是“1”。INPUT(0)的优先级最高,INPUT(7)的优先级最低。
表6.5 优先级编码器真值表
输入 二进制编码输出
Input(7) Input(6) Input(5) Input(4) Input(3) Input(2) Input(1) Input(0) Y2 Y1 Y0
X X X X X X X 0 1 1 1
X X X X X X 0 1 1 1 0
X X X X X 0 1 1 1 0 1
X X X X 0 1 1 1 1 0 0
X X X 0 1 1 1 1 0 1 1
X X 0 1 1 1 1 1 0 1 0
X 0 1 1 1 1 1 1 0 0 1
X 1 1 1 1 1 1 1 0 0 0

【例6.12】 用VHDL设计一个8-3优先级编码器。
-- CH8_3.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY CH8_3 IS
PORT (INPUT :IN STD_LOGIC_VECTOR(7 DOWNTO 0);
Y: OUT STD_LOGIC_VECTOR(2 DOWNTO 0));
END CH8_3;
ARCHITECTURE RTL OF CH8_3 IS
BEGIN
PROCESS(INPUT)
BEGIN
IF (INPUT(0)='0') THEN
Y<="111";
ELSIF (INPUT(1)='0' THEN
Y<="110";
ELSIF (INPUT(2)='0' THEN
Y<="101";
ELSIF (INPUT(3)='0' THEN
Y<="100";
ELSIF (INPUT(4)='0' THEN
Y<="011";
ELSIF (INPUT(5)='0' THEN
Y<="010";
ELSIF (INPUT(6)='0' THEN
Y<="001";
ELSIF
Y<="000";
END IF;
END PROCESS;
END RTL;
6.6 寄存器的设计
寄存(锁存)器是一种重要的数字电路部件,常用来暂时存放指令、参与运算的数据或运算结果等。它是数字测量和数字控制中常用的部件,是计算机的主要部件之一。寄存器的主要组成部分是具有记忆功能的双稳态触发器。一个触发器可以储存一位二进制代码,要储存N位二进制代码,就在有N个触发器。寄存器从功能上说,通常可分为数码寄存器和移位寄存器两种。
6.6.1 数码寄存器的设计
数码寄存器用于寄存一组二进制代码,广泛用于各类数字系统。下面给出—个8位寄存器的VHDL描述。
【例6.13】 用VHDL设计一个8位的数码寄存器。
--REG.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY REG IS
PORT(D:IN STD_LOGIC_VECTOR(7 TO 0);
CLK:IN STD_LOGIC;
Q:OUT STD_LOGIC_VECTOR(7 TO 0));
END ENTITY REG;
ARCHITECTURE ART OF REG IS
BEGIN
PROCESS(CLK) IS
BEGIN
IF(CLK'EVENT AND CLK='1')THEN
Q<=D;
END IF;
END PROCESS;
END ARCHITECTURE ART;
6.6.2 移位寄存器的设计
移位寄存器除了具有存储代码的功能以外,还具有移位功能。所谓移位功能,是指寄存器里存储的代码能在移位脉冲的作用下依次左移或右移。因此,移位寄存器不但可以用来寄存代码,还可用来实现数据的串并转换、数值的运算以及数据处理等。下面给出一个8位的移位寄存器,其具有左移一位或右移一位、并行输入和同步复位的功能。
【例6.14】用VHDL设计一个8位的移位寄存器,其具有左移一位或右移一位、并行输入和同步复位的功能.
--SHIFT_REG.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY SHIFT_REG IS
PORT(DATA:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
CLK:IN STD_LOGIC;
SHIFT_LEFT,SHIFT_RIGHT:IN STD_LOGIC;
RESET:IN STD_LOGIC;
MODE:IN STD_LOGIC_VECTOR(1 DOWNTO 0);
QOUT:BUFFER STD_LOGIC_VECTOR(7 DOWNTO 0));
END ENTITY SHIFT_REG;
ARCHITECTURE ART OF SHIFT_REG IS
BEGIN
PROCESS IS
BEGIN
WAIT UNTIL(RISING_EDGE(CLK));
IF(RESET='1')THEN
QOUT<="00000000";
ELSE --同步复位功能的实现
CASE MODE IS
WHEN "01"=>QOUT<=SHIFT_RIGHT&QOUT(7 DOWNTO 1);--右移一位
WHEN "10"=>QOUT<=QOUT(6 DOWNTO 0)&SHIFT_LEFT; --左移一位
WHEN "11"=>QOUT<=DATA; --并行输入
WHEN OTHERS=>NULL;
END CASE;
END IF;
END PROCESS;
END ARCHITECTURE ART;
6.6.3 并行加载移位寄存器的设计
在TTL手册中的74LS166是一个带清零端的8位并行加载的移位寄存器,其引脚图及逻辑图如图6.6所示。

图6.6 74LS166的引脚图及逻辑图
图中各引脚名称和功能如下:
A,B,C,D,E,F,G,H:8位并行数据输入端;
SER:串行数据输入端;
QH:串行数据输出端;
CLK: 时钟信号输入端;
CLKINH:时钟信号禁止(FE)端;
SH/LD:移位加载控制(SL)端;
CLR:清零端。
当清零输入端CLR为‘0’时,8个触发器的输出均为‘0’,从而使输出Q为‘0’。CLKINH是时钟禁止端,当它为‘1’时将禁止时钟,即不管时钟信号如何变化,移位寄存器的状态不发生改变。另外,时钟信号只在上升沿时才有效,且CLKINH 为‘0’。当控制端SH/LD =‘1’时是移位状态,在时钟脉冲上升沿的控制下右移,当SH/LD =‘0’时是加载状态,在时钟脉冲上升沿的作用下,数据输入端A~H的信号就是装载到移位寄存器的QA~QH。根据上述描述,就可以用VHDL语言编写出描述74166功能的程序。
【例6.15】用VHDL设计的带清零端的8位并行加载的移位寄存器74LS166。
-- SREG8PARLWCLR.VHD
LIBRARY IEEE;
USE IEEE. STD _ LOGIC _ 1164. ALL;
ENTITY SREG8PARLWCLR IS
PORT(CLR, SL, FE, CLK, SER: IN STD_ LOGIC;
A, B, C, D, E, F,G, H: IN STD_ LOGIC;
Q: OUT STD_ LOGIC);
END SREG8PARLWCLR;
ARCHITECTURE BEHAV OF SREG8PARLWCLR IS
SIGNAL TMPREG8:STD _ LOGIC _ VECTOR (7 DOWNTO O);
BEGIN
PROCESS (CLK, SL, FE, CLR)
IF (CLR= ‘0’) THEN
TMPREG8< = “00000000”;
Q< = TMPREG8 (7);
ELSIF (CLK’EVENT) AND (CLK= ‘1’) AND (FE = ‘0’)THEN
IF (SL= ‘0’) THEN
TMPREG8 (0)< =A;
TMPREG8 (1)< =B;
TMPREG8 (2)< =C;
TMPREG8 (3)< =D;
TMPREG8 (4)< =E;
TMPREG8 (5)< =F;
TMPREG8 (6)< =G;
TMPREG8 (7)< =H;
Q< = TMPREG8 (7);
ELSIF (SL =‘1’)THEN
FOR I IN TMPREG8’HIGH DOWNTO TMPREG8’LOW+ 1 LOOP
TMPREG8 (I)< = TMPREG8(I- 1);
END LOOP;
TMPREG8 (TMPREG8’LOW) < = SE;
Q< = TMPREG8 (7);
END IF;
END IF;
END PROCESS;
END BEHAV;
6.7 存储器的设计
半导体存储器的种类很多,从功能上可以分为只读存储器(READ_ONLY MEMORY,简称ROM)和随机存储器(RANDOM ACCESS MEMORY,简称RAM)两大类。
6.7.1 只读存储器ROM的设计
只读存储器在正常工作时从中读取数据,不能快速地修改或重新写入数,适用于存储固定数据的场合。下面是一个容量为256×4的ROM存储的例子,该ROM有8位地址线ADR(0)~ADR(7),4位数据输出线DOUT(0)~DOUT(3)及使能EN,如图6. 7所示。

图6. 7 ROM
【例6.16】 用VHDL设计一个一个容量为256×4的ROM存储的例子,该ROM有8位地址线ADR(0)~ADR(7),4位数据输出线DOUT(0)~DOUT(3)及使能EN。
-- ROM.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE STD.TEXTIO.ALL;
ENTITY ROM IS
PORT(EN:IN STD_LOGIC;
ADR:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
DOUT: OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END ENTITY ROM;
ARCHITECTURE ART OF ROM IS
SUBTYPE WORD IS STD_LOGIC_VECTOR(3 DOWNTO 0);
TYPE MEMORY IS ARRAY(0 TO 255) OF WORD;
SIGNAL ADR_IN:INTEGER RANGE 0 TO 255;
VARIABLE ROM:MEMORY;
VARIABLE START_UP:BOOLEAN:=TRUE;
VARIABLE L:LINE;
VARIABLE J:INTEGER;
FILE ROMIN:TEXT IS IN “ROMIN”;
BEGIN
PROCESS(EN,ADR) IS
BEGIN
IF START_UP THEN --初始化开始
FOR J IN ROM’RANGE LOOP
READLINE(ROMIN,1);
READ(1,ROM(J));
END LOOP;
START_UP:=FALSE; --初始化结束
END IF;
ADR_IN<=CONV_INTEGER(ADR); --将向量转化成整数
IF(EN=‘1’)THEN
DOUT<=ROM(ADR_IN);
ELSE
DOUT<=“ZZZZ”;
END IF;
END PROCESS;
END ARCHITECTURE ART;
6.7.2 读写存储器SRAM的设计
RAM和ROM的主要区别在于RAM描述上有读和写两种 *** 作,而且在读写上对时间有较严格的要求。下面我们给出一个8×8位的双口SRAM的VHDL描述实例,如图6.8所示。

图6. 8 双口SRAM
【例6.17】 用VHDL设计一个8×8位的双口SRAM。
--DPRAM.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY DPRAM IS
GENERIC(WIDTH:INTEGER :=8;
DEPTH:INTEGER :=8;
ADDER:INTEGER :=3);
PORT(DATAIN:IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
DATAOUT:OUT STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
CLOCK:IN STD_LOGIC;
WE,RE:IN STD_LOGIC;
WADD:IN STD_LOGIC_VECTOR(ADDER-1 DOWNTO 0);
RADD:IN STD_LOGIC_VECTOR(ADDER-1 DOWNTO 0));
END ENTITY DPRAM;
ARCHITECTURE ART OF DPRAM IS
TYPE MEM IS ARRAY(DEPTH-1 TO 0) OF
STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
SIGNAL RAMTMP:MEM;
BEGIN
--写进程
PROCESS(CLOCK) IS
BEGIN
IF (CLOCK'EVENT AND CLOCK='1') THEN
IF(WE='1')THEN
RAMTMP(CONV_INTEGER(WADD))<=DATAIN;
END IF;
END IF;
END PROCESS;
--读进程
PROCESS(CLOCK) IS
BEGIN
IF(CLOCK'EVENT AND CLOCK='1')THEN
IF (RE='1') THEN
DATAOUT<=RAMTMP(CONV_INTEGER(RADD));
END IF;
END IF;
END PROCESS;
END ARCHITECTURE ART;
6.8 输入电路的设计
6.8.1 键盘扫描电路的设计
计算机控制系统中,数据和控制信号的输入主要使用键盘。下面给出—个键盘扫描电路VHDL描述。
【例6.18】 用VHDL设计一个键盘扫描电路。
-- KSCAN.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
ENTITY KSCAN IS
PORT(CLK: IN STD_LOGIC;
KIN1,KIN2 : IN STD_LOGIC;
LEDA,LEDB,LEDC: OUT STD_LOGIC;
LEDD : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END KSCAN;
ARCHITECTURE HAV OF KSCAN IS
SIGNAL SEG : STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL SEL : STD_LOGIC_VECTOR(2 DOWNTO 0);
SIGNAL KNUM : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL COUNT: STD_LOGIC_VECTOR(4 DOWNTO 0);
SIGNAL COUNT0: STD_LOGIC;
BEGIN
LEDD<=SEG;
PROCESS(CLK)
BEGIN
IF CLK’EVENT AND CLK=‘1’ THEN
COUNT<=COUNT+1;
END IF;
END PROCESS;
COUNT0<=COUNT(0);
PROCESS(COUNT0,COUNT,KIN1,KIN2)
BEGIN
IF COUNT0’EVENT AND COUNT0=‘1’THEN
IF (KIN2=‘0’) AND COUNT(1)=‘0’THEN
KNUM<=‘1’ & COUNT(4 DOWNTO 2);
ELSIF (KIN1=‘0’) AND COUNT(1)=‘0’THEN
KNUM<=‘0’ & COUNT (4 DOWNTO 2);
END IF;
END IF;
END PROCESS;
SEL<=COUNT (4 DOWNTO 2);
PROCESS(KNUM)
BEGIN
CASE KNUM IS
WHEN “0000” => SEG<=“00111111”;
WHEN “0001” => SEG<=“00000110”;
WHEN “0010” => SEG<=“01011011”;
WHEN “0011” => SEG<=“01001111”;
WHEN “0100” => SEG<=“01100110”;
WHEN “0101” => SEG<=“01101101”;
WHEN “0110” => SEG<=“01111101”;
WHEN “0111” => SEG<=“00000111”;
WHEN “1000” => SEG<=“01111111”;
WHEN “1001” => SEG<=“01101111”;
WHEN “1010” => SEG<=“01110111”;
WHEN “1011” => SEG<=“01111100”;
WHEN “1100” => SEG<=“00111001”;
WHEN “1101” => SEG<=“01011110”;
WHEN “1110” => SEG<=“01111001”;
WHEN “1111” => SEG<=“01110001”;
WHEN OTHERS => SEG<=“00000000”;
END CASE ;
END PROCESS;
LEDA<=SEL(0);
LEDB<=SEL(1);
LEDC<=SEL(2);
END HAV;
6.8.2 键盘接口电路的设计
PS/2键盘接口通常使用专用芯片实现。由于PS/2键盘或鼠标串行输出信号速度较高,普通单片机无法接收,现利用VHDL在目标器件FPGACPLD上实现一个键码接收部分。PS/2接口的键盘每按下一个键,该键的扫描码即以十六进制形式显示在数码管上。以下为接收PS/2键盘信号的VHDL逻辑描述。
【例6.20】 用VHDL设计一个接收PS/2键盘信号的接口电路。
-- KB2PCL.VHD
LIBRARY IEEE;
USE IEEE.STD_LOG1C_1164.ALL;
ENTITY KB2PCL IS
PORT (SYSCLK:IN STD_LOGIC;RESET:IN STD_LOGIC;
KBCLK: IN STD_LOGIC;KBDATA:IN STD_LOGIC;
PDATA: OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
PARITY:OUT STD_LOGIC;DTOE:BUFFER STD_LOGIC);
END KB2PC1;
ARCHITECTURE ONE OF KB2PC1 IS
SIGNAL COSTATE:STD_LOGIC_VECTOR(1 DOWNTO 0);
SIGNAL SPDATA:STD_LOGIC_VECTOR(8 DOWNTO 0);
SIGNAL START,SWTO02,RECVEN:STD_LOGIC;
SIGNAL CNT8:INTEGER RANGE 0 TO 15;
BEGIN
SLRL:PROCESS(RESET, KBCLK,KBDATA,STAFF,COSTATE )
BEGIN
IF RESET = ‘1’ THEN
START <= ‘0’;
ELSIF KBCLK’EVENT AND KBCLK = ‘0’ THEN
IF COSTATE = “00” AND KBDATA = ‘0’ THEN
STAFF <= ‘1’;
END IF;
END IF;
END PROCESS;
STR2:PROCESS(RESET, KBCLK,KBDATA,STAFF,COSTATE)
BEGIN
IF RESET =‘1’ THEN
SWTO02 <=‘0’;
ELSIF KBCLK’EVENT AND KBCLK =‘1’ THEN
IF COSTATE = “00” AND START = ‘1’ AND KBDATA = ‘0’ THEN
SWTO02 <=‘1’;
END IF;
END IF;
END PROCESS;
CHSTATE:PROCESS(RESET,SYSCLK,COSTATE,SWTO02)
BEGIN
IF RESET =‘1’ THEN
COSTATE <=“00”;
ELSIF SYSCLK’EVENT AND SYSCLK =‘1’ THEN
IF SWTO02 = ‘1’ THEN
COSTATE <= “01”;
ELSIF CNT8 = 9 THEN
COSTATE <= “10”;
END IF;
END IF;
END PROCESS;
RECV:PROCESS(RESET,KBCLK,KBDATA,COSTATE )
BEGIN
IF RESET=‘1’ THEN
CNT8 <= 0;SPDATA <= “000000000”;
ELSIF KBCLK’EVENT AND KBCLK = ‘0’ THEN
IF COSTATE= “01” THEN
IF CNT8/=9 THEN
SPDATA(7 DOWNTO 0 )<= SPDATA(8 DOWNTO 1);
SPDATA(8)<= KBDATA;
CNT8 <= CNT8 + 1;
END IF;
END IF;
END IF;
END PROCESS;
RECVEND:PROCESS(RESET,KBCLK,RECVEN,COSTATE )
BEGIN
IF RESET =‘1’ THEN
DTOE <= ‘0’;
ELSIF KBCLK’EVENT AND KBCLK =‘1’ THEN
IF CNT8 = 9 AND COSTATE = “01” THEN
DTOE <=‘1’;END IF;
END IF;
END PROCESS;
PARITY <= SPDATA(8);PDATA <= SPDATA(7 DOWNTO 0);
END ONE;
6.9 显示电路的设计
常用的显示器件有发光二极管,数码管,液晶显示器等,其中最常用的为数码管。数码管显示数据的方式有静态显示和动态显示之分。所谓静态显示,就是将被显示的数据的BCD码,通过各自的4-7/8显示译码器译码后,分别接到显示译码器的显示驱动段a-g(p),而公共端COM则根据数码管的类型(共阴/共阳)分别接GND/VCC。动态显示,就是将被显示的数据的BCD码,按照一定的变化频率,在不同的时刻周期性地分别送到一个数据总线上,再通过一个公共的4-7/8显示译码器译码后,接到多个显示译码器的公共显示驱动段a-g(p)上,同时,在不同的时刻周期性地选通对应的数码管的公共端COM。
6.9.1 数码管静态显示电路的设计
七段数码显示器由7根显示码管组成,对每一根码管,用一位二进制表示。若该数码管的为共阴数码管,则该位为1时,表示此码管发光,如为0,表示此码管不发光,对7根码管编号。共阳数码管则正好相反。下面用一个7位二进制数表示一个七段显示器的编码,其VHDL程序段描述如下:
CASE CNT4B IS
WHEN 0=> DOUT <= “0111111”;
WHEN 1=> DOUT <= “0000110”;
WHEN 2=> DOUT <= “1011011”;
WHEN 3=> DOUT <= “1001111”;
WHEN 4=> DOUT <= “1100110”;
WHEN 5=> DOUT <= “1101101”;
WHEN 6=> DOUT <= “1111101”;
WHEN 7=> DOUT <= “0000111”;
WHEN 8=> DOUT <= “1111111”;
WHEN 9=> DOUT <= “1101111”;
WHEN OTHERS=> DOUT <= “0000000”;
END CASE;
下面给出一个4位二进制加法计数器静态显示的VHDL程序。
【例6.21】 用VHDL设计一个4位二进制加法计数器,并将计数结果用7段LED显示数码管进行静态显示。
--CNTDISPLAY.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY CNTDISPLAY IS
PORT (CLK:IN STD_LOGIC;
DOUT:OUT STD_LOGIC_VECTOR(6 DOWNTO 0));
END DECLED;
ARCHITECTURE BEHAV OF CNTDISPLAY IS
SIGNAL CNT4B:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
PROCESS(CLK)
BEGIN
IF CLK’EVENT AND CLK =‘1’ THEN
CNT4B <= CNT4B +1;
END IF;
END PROCESS;
PROCESS(CNT4B)
BEGIN
CASE CNT4B IS
WHEN “0000”=> DOUT <= “0111111”;
WHEN “0001”=> DOUT <= “0000110”;
WHEN “0010”=> DOUT <= “1011011”;
WHEN “0011”=> DOUT <= “1001111”;
WHEN “0100”=> DOUT <= “1100110”;
WHEN “0101”=> DOUT <= “1101101”;
WHEN “0110”=> DOUT <= “1111101”;
WHEN “0111”=> DOUT <= “0000111”;
WHEN “1000”=> DOUT <= “1111111”;
WHEN “1001”=> DOUT <= “1101111”;
WHEN “1010”=> DOUT <= “1110111”;
WHEN “1011”=> DOUT <= “1111100”;
WHEN “1100”=> DOUT <= “0111001”;
WHEN “1101”=> DOUT <= “1011110”;
WHEN “1110”=> DOUT <= “1111001”;
WHEN “1111”=> DOUT <= “1110001”;
WHEN OTHERS=> DOUT <= “0000000”;
END CASE;
END PROCESS;
END BEHAV;
6.9.2 数码管动态显示电路的设计
下面我们就通过一个例子来说明数据动态扫描的工作原理和VHDL程序的设计方法。
【例6.22】用VHDL设计一个8位二进制并行半加器,要求将被加数、加数和加法运算和用动态扫描的方式在共阴数码管上同时显示出,该数据动态扫描显示电路的外围器件接线图如图6.9所示。

图6.9?数据动态扫描显示电路外围器件接线图

--DISPLAY.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
--实体说明
ENTITY DISPLAY IS
PORT(CLK:IN STD_LOGIC; --动态扫描显示时钟,24HZ以上
AIN: IN STD_LOGIC_VECTOR(7 DOWNTO 0); --8位被加数
BIN: IN STD_LOGIC_VECTOR(7 DOWNTO 0); --8位加数
SUM0,SUM1,SUM2:OUT STD_LOGIC_VECTOR(3 DOWNTO 0);--仿真观测输出
COM:OUT STD_LOGIC_VECTOR(6 DOWNTO 0);--数码管COM端的选择输出端
SEG: OUT STD_LOGIC_VECTOR(7 DOWNTO 0)); --数码管8段显示驱动输出端
END ENTITY DISPLAY;
ARCHITECTURE ART OF DISPLAY IS
SIGNAL AA, BB,SINT: STD_LOGIC_VECTOR(8 DOWNTO 0);
SIGNAL CNT:STD_LOGIC_VECTOR(2 DOWNTO 0);
SIGNAL BCD:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
--进行运算前的准备及加法运算
AA<='0'&AIN;
BB<='0'&BIN;
SINT<=AA+BB;
SUM0<=SINT(3 DOWNTO 0); --运算结果的仿真观测输出
SUM1<=SINT(7 DOWNTO 4); --运算结果的仿真观测输出
SUM2<="000"&SINT(8); --运算结果的仿真观测输出
--产生动态扫描显示的控制信号
PROCESS(CLK)
BEGIN
IF CLK'EVENT AND CLK='1' THEN
IF CNT="111" THEN
CNT<="000";
ELSE
CNT<=CNT+'1';
END IF ;
END IF;
END PROCESS;
PROCESS(CNT)
BEGIN
--显示数据的选择,对应显示数码管公共端的选通,低电平有效
CASE CNT IS
WHEN "000" =>BCD<=AIN(3 DOWNTO 0);COM<="1111110";
WHEN "001" =>BCD<=AIN(7 DOWNTO 4);COM<="1111101";
WHEN "010" =>BCD<=BIN(3 DOWNTO 0);COM<="1111011";
WHEN "011" =>BCD<=BIN(7 DOWNTO 4);COM<="1110111";
WHEN "100" =>BCD<=SINT(3 DOWNTO 0);COM<="1101111";
WHEN "101" =>BCD<=SINT(7 DOWNTO 4);COM<="1011111";
WHEN "110" =>BCD<="000"&SINT(8);COM<="0111111";
WHEN OTHERS=>BCD<="0000";COM<="1111111";
END CASE;
--将BCD码转换成数码管的8段驱动信息,高电平有效
CASE BCD IS
WHEN "0000" => SEG<="00111111";
WHEN "0001" => SEG<="00000110";
WHEN "0010" => SEG<="01011011";
WHEN "0011" => SEG<="01001111";
WHEN "0100" => SEG<="01100110";
WHEN "0101" => SEG<="01101101";
WHEN "0110" => SEG<="01111101";
WHEN "0111" => SEG<="00000111";
WHEN "1000" => SEG<="01111111";
WHEN "1001" => SEG<="01101111";
WHEN "1010" => SEG<="01110111";
WHEN "1011" => SEG<="01111100";
WHEN "1100" => SEG<="00111001";
WHEN "1101" => SEG<="01011110";
WHEN "1110" => SEG<="01111001";
WHEN "1111" => SEG<="01110001";
WHEN OTHERS => SEG<="00000000";
END CASE ;
END PROCESS;
END ARCHITECTURE ART;

6.9.2 液晶显示控制电路的设计
液晶显示是一种将液晶显示器件、连接件、集成电路、PCB线路板、背光源、结构件装配在一起的组件。下面给出—个液晶显示控制电路的VHDL描述。
【例6.23】 用VHDL设计—个液晶显示控制电路。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY LCD IS
PORT(DP1,DP2,DP3:IN STD_LOGIC;
RS,CS1,CS2: OUT STD_LOGIC;
LCDE:OUT STD_LOGIC;
RW:OUT STD_LOGIC);
END LCD;
ARCHITECTURE HAV OF LCD IS
BEGIN
PROCESS(DP1,DP2,DP3)
BEGIN
IF(DP1=“0” AND DP2=“0” AND DP3=“0”) THEN
LCDE<=“1”;RS<=“0”;RW<=“1”;CS1<=“1”;CS2<=“0”;
ELSIF(DP1=“0” AND DP2=“0” AND DP3=“1”)THEN
LCDE<=“1”;RS<=“0”;RW<=“0”;CS1<=“1”;CS2<=“0”;
ELSIF(DP1=“0” AND DP2=“1” AND DP3=“0”)THEN
LCDE<=“0”;RS<=“1”;RW<=“1”;CS1<=“1”;CS2<=“0”;
ELSIF(DP1=“0” AND DP2=“1” AND DP3=“1”)THEN
LCDE<=“1”;RS<=“1”;RW<=“0”;CS1<=“1”;CS2<=“0”;
ELSIF(DP1=“1” AND DP2=“0” AND DP3=“0”)THEN
LCDE<=“1”;RS<=“0”;RW<=“1”;CS1<=“0”;CS2<=“1”;
ELSIF(DP1=“1” AND DP2=“0” AND DP3=“1”)THEN
LCDE<=“1”;RS<=“0”;RW<=“0”;CS1<=“0”;CS2<=“1”;
ELSIF(DP1=“1” AND DP2=“1” AND DP3=“0”)THEN
LCDE<=“0”;RS<=“1”;RW<=“1”;CS1<=“0”;CS2<=“1”;
ELSIF(DP1=“1” AND DP2=“1” AND DP3=“1”)THEN
LCDE<=“1”;RS<=“1”;RW<=“0”;CS1<=“0”;CS2<=“1”;
ELSE
LCDE<=“0”;RS<=“1”;RW<=“1”;CS1<=“0”;CS2<=“0”;
END IF;
END PROCESS;
END HAV;

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/dianzi/2467909.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-08-04
下一篇 2022-08-04

发表评论

登录后才能评论

评论列表(0条)

保存