Transcript Chapter06

第6章
VHDL设计应用实例
第6章
VHDL设计应用实例
6.1 8位加法器的设计
6.2 8位乘法器的设计
6.3 序列检测器的设计
6.4 正负脉宽数控调制信号发生器的设计
6.5 数字频率计的设计
6.6 秒表的设计
6.7 MCS–51单片机与FPGA/CPLD总线接口逻辑设计
6.8 交通灯信号控制器的设计
6.9 语音信箱控制系统的设计
6.10 PID控制器的设计
6.11 空调系统有限状态自动机的设计
6.12 闹钟系统的设计
第6章
VHDL设计应用实例
6.1 8位加法器的设计
1.设计思路
加法器是数字系统中的基本逻辑器件,减法器和硬件乘法
器都可由加法器来构成。多位加法器的构成有两种方式:并行
进位和串行进位方式。并行进位加法器设有进位产生逻辑,运
算速度较快;串行进位方式是将全加器级联构成多位加法器。
并行进位加法器通常比串行级联加法器占用更多的资源。随着
位数的增加,相同位数的并行加法器与串行加法器的资源占用
差距也越来越大。因此,在工程中使用加法器时,要在速度和
容量之间寻找平衡点。
第6章
VHDL设计应用实例
实践证明,4位二进制并行加法器和串行级联加法器占用
几乎相同的资源。这样,多位加法器由4位二进制并行加法器
级联构成是较好的折中选择。本设计中的8位二进制并行加法
器即是由两个4位二进制并行加法器级联而成的,其电路原理
图如图6.1所示。
第6章
VHDL设计应用实例
图6.1 8位加法器电路原理图
第6章
VHDL设计应用实例
2.VHDL源程序
1) 4位二进制并行加法器的源程序ADDER4B.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY ADDER4B IS
--4位二进制并行加法器
PORT(CIN:IN STD_LOGIC;
--低位进位
A: IN STD_LOGIC_VECTOR(3 DOWNTO 0);
--4位加数
B: IN STD_LOGIC_VECTOR(3 DOWNTO 0);
--4位被加数
S: OUT STD_LOGIC_VECTOR(3 DOWNTO 0); --4位和
CONT: OUT STD_LOGIC);
--进位输出
第6章
VHDL设计应用实例
END ADDER4B;
ARCHITECTURE ART OF ADDER4B IS
SIGNAL SINT:STD_LOGIC_VECTOR(4 DOWNTO 0);
SIGNAL AA,BB: STD_LOGIC_VECTOR(4 DOWNTO 0);
BEGIN
AA<='0'& A; --将4位加数矢量扩为5位,为进位提供空间
BB<='0'& B;
--将4位被加数矢量扩为5位,为进位提供空间
SINT<=AA+BB+CIN ;
S<=SINT(3 DOWNTO 0);
CONT<=SINT(4);
END ART;
第6章
VHDL设计应用实例
2) 8位二进制加法器的源程序ADDER8B.VHD
LIBRARY IEEE;
USE IEEE_STD.LOGIC_1164.ALL;
USE IEEE_STD.LOGIC_UNSIGNED.ALL:
ENTITY ADDER8B IS
--由4位二进制并行加法器级联而成的8位二进制加法器
PORT(CIN:IN STD_LOGIC;
A:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
B:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
S:OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
COUT:OUT STD_LOGIC);
END ADDER8B;
ARCHICTURE ART OF ADDER8B IS
第6章
VHDL设计应用实例
COMPONENET ADDER4B
--对要调用的元件ADDER4B的界面端口进行定义
PORT(CIN:IN STD_LOGIC;
A:IN STD_LOGIC_VECTOR(3 DOWNTO 0);
B:IN STD_LOGIC_VECTOR(3 DOWNTO 0);
S:OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
CONT:OUT STD_LOGIC);
END COMPONENT ;
SIGNAL CARRY_OUT:STD_LOGIC;
--4位加法器的进位标志
BEGIN
U1:ADDER4B
--例化(安装)一个4位二进制加法器U1
第6章
VHDL设计应用实例
PORT MAP(CIN=>CIN,A=>A(3 DOWNTO 0),B=>B(3
DOWNTO0),
S=>S(3 DOWNTO 0),COUT=>CARRY_OUT);
U2:ADDER4B
--例化(安装)一个4位二进制加法器U2
PORT MAP(CIN=>CARRY_OUT,A=>A(7 DOWNTO 4),
B=>B(7 DOWNTO 4),
S=>S (7 DOWNTO 4);CONT=>CONT);
END ART;
第6章
VHDL设计应用实例
3.硬件逻辑验证
选择实验电路结构图NO.1,由5.2的实验电路结构图NO.1和
图6.1确定引脚的锁定。如可取实验电路结构图的PIO3~PIO0接
A[3..0],PIO7~PIO4接A[7..4], PIO11~PIO8接B[3..0],
PIO15~PIO12接B[7..4],PIO49接CIN。此加法器的被加数A和
加数B分别由键2与键1、键4与键3输入,加法器的最低位进位
CIN由键8输入,计算结果将分别通过PIO23~PIO20,PIO19~
PIO16输出并显示于数码管6(高4位)和数码管5(低4位),溢出进
位由PIO39输出,当有进位时,结果显示于发光管D8。
第6章
VHDL设计应用实例
6.2 8位乘法器的设计
1.设计思路
纯组合逻辑构成的乘法器虽然工作速度比较快,但占用硬件
资源多,难以实现宽位乘法器,而基于PLD器件外接ROM九九表
的乘法器则无法构成单片系统,也不实用。这里介绍由8位加法
器构成的以时序逻辑方式设计的8位乘法器,此乘法器具有一定
的实用价值。其乘法原理是:乘法通过逐项位移相加原理来实现,
从被乘数的最低位开始,若为1,则乘数左移后与上一次和相加;
若为0,左移后以全零相加,直至被乘数的最高位。从图6.2的逻
辑图上可以清楚地看出此乘法器的工作原理。
第6章
CLK
VHDL设计应用实例
ARICT L
CLK
ARIEND
U1 CLKOUT
START
START
RST AL L
ARIEND
GND
S2
S1
S3
S7[15. . 8]
S5[7. .0]
ADDER8B
CIN
A[7. . 0]
U4
S[7. . 0]
COUT
S6[7. .0]
S6(8)
B[7. . 0]
SRE G8B
CLK
A[7. . 0]
L OAD
U2
QB
REG16B
DIN[7. . 0]
S4
ANDARITH
B[7. . 0]
ABIN
S7[7. .0]
CLK
DOUT[7.. 0]
DIN[7. . 0] U3
S6[8. .0]
CLR
U5
Q[15.. 0]
S7[15. . 8]
D[8. . 0]
S5[7. .0]
S7[15. . 0]
图6.2 8×8位乘法器电路原理图
OUT [15. .0]
第6章
VHDL设计应用实例
图6.2中,ARICTL是乘法运算控制电路,它的START(可锁定
于引脚I/O 49)信号的上跳沿与高电平有两个功能,即16位寄存器
清零和被乘数A[7..0]向移位寄存器SREG8B加载;它的低电平则作
为乘法使能信号。乘法时钟信号从ARICTL的CLK输入。当被乘数
加载于8位右移寄存器SREG8B后,随着每一时钟节拍,最低位在
前,由低位至高位逐位移出。当为1时,与门ANDARITH打开,8
位乘数B[7..0]在同一节拍进入8位加法器,与上一次锁存在16位锁
存器REG16B中的高8位进行相加,其和在下一时钟节拍的上升沿
被锁进此锁存器。而当被乘数移出位为0时,与门全零输出。如此
往复,直至8个时钟脉冲后,由ARICTL的控制,乘法运算过程自
动中止。ARIEND输出高电平,以此可点亮一发光管,以示乘法
结束。此时REG16B的输出值即为最后乘积。
第6章
VHDL设计应用实例
此乘法器的优点是节省芯片资源,它的核心元件只是一个8
位加法器,其运算速度取决于输入的时钟频率。若时钟频率为
100 MHz,则每一运算周期仅需80 ns。而若利用备用最高时钟,
即12 MHz晶振的MCS-51单片机的乘法指令,进行8位乘法运算,
仅单指令的运算周期就长达4 μs。因此,可以利用此乘法器或
相同原理构成的更高位乘法器完成一些数字信号处理方面的运
算。
第6章
VHDL设计应用实例
2. VHDL源程序
1) 选通与门模块的源程序ANDARITH.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY ANDARITH IS
--选通与门模块
PORT (ABIN:IN STD_LOGIC;
--与门开关
DIN:IN STD_LOGIC_VECTOR (7 DOWNTO 0)
--8位输入
DOUT:OUT STD_LOGIC_VECTOR (7 DOWNTO 0)); --8位输出
END ANDARITH;
ARCHITECTURE ART OF ANDARITH IS
第6章
VHDL设计应用实例
BEGIN
PROCESS (ABIN,DIN)
BEGIN
FOR I IN 0 TO 7 LOOP --循环,分别完成8位数据与一位
DOUT (I)<=DIN (I)AND ABIN;
END LOOP;
END PROCESS;
END ART;
--控制位的与操作
第6章
VHDL设计应用实例
2) 16位锁存器的源程序REG16B.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY REG16B IS
--16位锁存器
PORT (CLK:IN STD_LOGIC;
--锁存信号
CLR:IN STD_LOGIC;
--清零信号
D:IN STD_LOGIC_VECTOR (8 DOWNTO 0)
--8位数据输入
Q:OUT STD_LOGIC_VECTOR(15 DOWNTO 0));--16位数据输出
END REG16B;
ARCHITECTURE ART OF REG16B IS
SIGNAL R16S:STD_LOGIC_VECTOR(15 DOWNTO 0);
--16位寄存器设置
第6章
VHDL设计应用实例
BEGIN
PROCESS (CLK,CLR)
BEGIN
IF CLR = '1' THEN R16S<= "0000000000000000";
--异步复位信号
ELSIF CLK'EVENT AND CLK = '1' THEN
--时钟到来时,锁存输入值
R16S(6 DOWNTO 0)<=R16S(7 DOWNTO 1);
--右移低8位
R16S(15 DOWNTO 7)<=D;
--将输入锁到高能位
END IF;
END PROCESS;
Q<=R16S;
END ART;
第6章
VHDL设计应用实例
3) 8位右移寄存器的源程序SREG8B.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
--8位右移寄存器
ENTITY SREG8B IS
PORT (CLK:IN STD_LOGIC; LOAD :IN STD _LOGIC;
BIN:IN STD_LOGIC_VECTOR(7DOWNTO 0);
QB:OUT STD_LOGIC );
END SREG8B;
ARCHITECTURE ART OF SREG8B IS
SIGNAL REG8B:STD_LOGIC_VECTOR(7 DOWNTO 0);
BEGIN
PROCESS (CLK,LOAD)
第6章
VHDL设计应用实例
BEGIN
IF CLK'EVENT AND CLK= '1' THEN
IF LOAD = '1' THEN REG8<=DIN;
--装载新数据
ELSE REG8(6 DOWNTO0)<=REG8(7 DOWNTO 1);--数据右移
END IF;
END IF;
END PROCESS;
QB<= REG8 (0);
END ART;
--输出最低位
第6章
VHDL设计应用实例
4) 乘法运算控制器的源程序ARICTL.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY ARICTL IS
--乘法运算控制器
PORT ( CLK:IN STD_LOGIC;
START:IN STD_LOGIC;
CLKOUT:OUT STD_LOGIC; RSTALL:OUT STD_LOGIC;
ARIEND:OUT STD_LOGIC );
END ARICTL;
ARCHITECTURE ART OF ARICTL IS
SIGNAL CNT4B:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
第6章
VHDL设计应用实例
RSTALL<=START;
PROCESS (CLK,START)
BEGIN
IF START = '1' THEN CNT4B<= "0000";
--高电平清零计数器
ELSIF CLK'EVENT AND CLK = '1' THEN
IF CNT4B<8 THEN--小于则计数,等于8表明乘法运算已经结束
CNT4B=CNT4B+1;
END IF;
END IF;
END PROCESS;
PROCESS (CLK,CNT4B,START)
BEGIN
第6章
VHDL设计应用实例
IF START = '0' THEN
IF CNT4B<8 THEN
--乘法运算正在进行
CLKOUT <=CLK; ARIEND<= '0';
ELSE CLKOUT <= '0'; ARIEND<= '1';
END IF;
ELSE CLKOUT <=CLK; ARIEND<= '0';
END IF;
END PROCESS;
END ART;
--运算已经结束
第6章
VHDL设计应用实例
5) 8位乘法器的源程序MULTI8X8.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
--8位乘法器顶层设计
ENTITY MULTI8X8 IS
PORT(CLK:IN STD_LOGIC;
START:IN STD_LOGIC;
--乘法启动信号,高电平复位与加载,低电平运算
A:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
--8位被乘数
B:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
--8位乘数
ARIEND:OUT STD_LOGIC;
--乘法运算结束标志位
DOUT:OUT STD_LOGIC_VECTOR(15 DOWNTO 0));--16位乘积输出
END MULTI8X8;
第6章
VHDL设计应用实例
ARCHITECTURE ART OF MULTI8X8 IS
COMPONENT ARICTL --待调用的乘法控制器端口定义
PORT(CLK:IN STD_LOGIC;START:IN STD_LOGIC;
CLKOUT:OUT STD_LOGIC;RSTALL:OUT STD_LOGIC;
ARIEND:OUT STD_LOGIC);
END COMPONENT;
COMPONENT ANDARITH
--待调用的控制与门端口定义
PORT(ABIN:IN STD_LOGIC;
DIN:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
DOUT:OUT_STD_LOGIC_VECTOR( 7 DOWNTO 0) );
END COMPONENT;
COMPONENT ADDER8B
...
--待调用的8位加法器端口定义
第6章
VHDL设计应用实例
COMPONENT SREG8B
--待调用的8位右移寄存器端口定义
...
COMPONENT REG16B
--待调用的16右移寄存器端口定义
...
SIGNAL GNDINT:STD_LOGIC;
SIGNAL INTCLK:STD_LOGIC;
SIGNAL RSTALL:STD_LOGIC;
SIGNAL QB:STD_LOGIC;
SIGNAL ANDSD:STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL DTBIN:STD_LOGIC_VECTOR(8 DOWNTO 0);
SIGNAL DTBOUT:STD_LOGIC_VECTOR(15 DOWNTO 0);
BEGIN
第6章
VHDL设计应用实例
DOUT<=DTBOUT;GNDINT<= '0';
U1:ARICTL PORT MAP(CLK=>CLK, START=>START,
CLKOUT=>INTCLK, RSTALL=>RSTALL, ARIEND=>ARIEND);
U2:SREG8B PORT MAP(CLK=>INTCLK, LOAD=>RSTALL.
DIN=>B, QB=>QB);
U3:ANDARITH PORT MAP(ABIN=>QB,DIN=>A,DOUT=>ANDSD);
U4:ADDER8B PORT
MAP(CIN=>GNDINT,A=>DTBOUT(15 DOWNTO 8),
B=>ANDSD, S=>DTBIN(7 DOWNTO 0),COUT =>DTBIN(8));
U5:REG16B PORT MAP(CLK =>INTCLK,CLR=>RSTALL,
D=>DTBIN, Q=>DTBOUT);
END ART;
第6章
VHDL设计应用实例
3. 硬件逻辑验证
选择实验电路结构图NO.1,由5.2节的实验电路结构图NO.1
和图6.2确定引脚的锁定。如乘法运算时钟CLK接CLOCK0,清
零及启动运算信号START由键8 (PIO49)控制,乘数B[7..0]接
PIO7~PIO0(由键2,键1输入8位二进制数),被乘数A[7..0]接
PIO15~PIO8(由键4,键3输入8位二进制数),乘积输出
DOUT[15..0]接PIO31~PIO16,乘法运算结束信号ARIEND接
PIO39(D8)。
第6章
VHDL设计应用实例
进行硬件验证时方法如下:① 键2和键1分别输入乘数的高
4位和低4位(输入值显示于数码2和数码1);② 键4和键3分别输
入被乘数的高4位和低4位(输入值显示于数码4和数码3);③ 乘
法操作时钟信号输入接CLOCK0;④ 键8输入高电平时,乘积
锁存器清零,乘数和被乘数数值加载,低电平时开始作乘法,
8个脉冲后乘法结束,乘积显示于数码管8~5,高位在左。
第6章
VHDL设计应用实例
6.3 序列检测器的设计
1.设计思路
序列检测器可用于检测一组或多组由二进制码组成的脉冲序
列信号,这在数字通信领域有广泛的应用。当序列检测器连续收
到一组串行二进制码后,如果这组码与检测器中预先设置的码相
同,则输出1,否则输出0。由于这种检测的关键在于正确码的收
到必须是连续的,这就要求检测器必须记住前一次的正确码及正
确序列,直到在连续的检测中所收到的每一位码都与预置数的对
应码相同。在检测过程中,任何一位不相等都将回到初始状态重
新开始检测。如图6.3所示,当一串待检测的串行数据进入检测器
后,若此数在每一位的连续检测中都与预置的密码数相同,则输
出“A”,否则仍然输出“B”。
第6章
DIN
CLK
CLR
D[7 ..0 ]
VHDL设计应用实例
CHK
DIN
CLK
CLR
AB [3..0]
D[7 ..0 ]
图6.3 8位序列检测器逻辑图
AB [3..0]
第6章
VHDL设计应用实例
2.VHDL源程序
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY CHK IS
PORT(DIN:IN STD_LOGIC;
CLK,CLR:IN STD_LOGIC;
--串行输入数据位
--工作时钟/复位信号
D:IN STD_LOGIC_VECTOR(7 DOWNTO 0);--8位待检测预置数
AB:OUT STD_LOGIC_VECTOR(3 DOWNTO 0));--检测结果输出
END CHK;
ARCHITECTURE ART OF CHK IS
第6章
VHDL设计应用实例
SIGNAL Q :INTEGER RANGE 0 TO 8;
BEGIN
PROCESS ( CLK,CLR )
BEGIN
IF CLR= '1' THEN Q<=0;
ELSIF CLK'EVENT AND CLK= '1' THEN
--时钟到来时,判断并处理当前输入的位
CASE Q IS
WHEN 0 => IF DIN =D(7) THEN Q<= 1 ;ELSE Q<=0;END IF;
WHEN 1 => IF DIN =D(6) THEN Q<= 2 ;ELSE Q<=0;END IF;
WHEN 2 => IF DIN =D(5) THEN Q<= 3 ;ELSE Q<=0;END IF;
第6章
WHEN 3=>
VHDL设计应用实例
IF DIN =D(4) THEN Q<= 4 ;ELSE Q<=0;END IF;
WHEN 4 => IF DIN =D(3) THEN Q<= 5 ;ELSE Q<=0;END IF;
WHEN 5 => IF DIN =D(2) THEN Q<= 6 ;ELSE Q<=0;END IF;
WHEN 6 => IF DIN =D(1) THEN Q<= 7 ;ELSE Q<=0;END IF;
WHEN 7 => IF DIN =D(0) THEN Q<= 8 ;ELSE Q<=0;END IF;
WHEN OTHERS => Q<=0;
END IF ;
第6章
VHDL设计应用实例
END PROCESS;
PROCESS(Q)
--检测结果判断输出
BEGIN
IF Q= 8 THEN AB<= "1010";
--序列数检测正确,输出“A”
ELSE AB<= "1011";
--序列数检测错误,输出 “B”
END IF ;
END PROCESS;
END ART;
第6章
VHDL设计应用实例
3.硬件逻辑验证
选择实验电路结构图NO.8,由5.2节的实验电路结构图NO.8
和图6.3确定引脚的锁定。待检测串行序列数输入DIN接
PIO10(左移,最高位在前),清零信号CLR接PIO8,工作时钟
CLK接PIO9,预置位密码D[7..0]接PIO7~PIO0,指示输出
AB[3..0]接PIO39~PIO36(显示于数码管6)。
第6章
VHDL设计应用实例
进行硬件验证时方法如下:① 选择实验电路结构图NO.8,
按实验板“系统复位”键;② 用键2和键1输入两位十六进制待
测序列数;③ 利用键4和键3输入两位十六进制预置码;④ 按
键8,高电平初始化清零,低电平清零结束(平时数码6应显
“B”);⑤ 按键6(CLK)8次,这时若串行输入的8位二进制序列
码与预置码相同,则数码7应从原来的“B”变成“A”,表示序
列检测正确,否则仍为“B”。
第6章
VHDL设计应用实例
6.4 正负脉宽数控调制信号发生器的设计
1.设计思路
图6.4 是脉宽数控调制信号发生器逻辑图,此信号发生器是
由两个完全相同的可自加载加法计数LCNT8组成的,它的输出
信号的高低电平脉宽可分别由两组8位预置数进行控制。
第6章
VHDL设计应用实例
CLK
VCC
LCNT8
LCNT8
CLK
LD
U1 CAO
D[7 ..0 ]
CLK
LD
U2
D[7 ..0 ]
CAO
CAO2
LD2
PRN
Q
D
CLRN
CAO1
LD1
PSINT
I2
A
B
PSOUT
图6.4 脉宽数控调制信号发生器逻辑图
第6章
VHDL设计应用实例
如果将初始值可预置的加法计数器的溢出信号作为本计数
器的初始预置加载信号LD,则可构成计数初始值自加载方式
的加法计数器,从而构成数控分频器。图6.4中D触发器的一个
重要功能就是均匀输出信号的占空比,提高驱动能力,这对驱
动,诸如扬声器或电动机十分重要。
第6章
VHDL设计应用实例
2.VHDL源程序
1) 8位可自加载加法计数器的源程序LCNT8.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164,.ALL;
ENTITY LCNT8 IS
--8位可自加载加法计数器
PORT(CLK,LD:IN STD_LOGIC;
--工作时钟/预置值加载信号
D:IN INTEGER RANGE 0 TO 255;--8位分频预置数
CAO:OUT STD_LOGIC);
--计数溢出输出
END LCNT8;
ARCHITECTURE ART OF LCNT8 IS
SIGNAL COUNT:INTEGER RANGE 0 TO 255; --8位计数器设置
BEGIN
PROCESS ( CLK )
第6章
VHDL设计应用实例
BEGIN
IF CLK'EVENT AND CLK= '1' THEN
IF LD= '1' THEN COUNT<=D;
ELSE COUNT<=COUNT+1;
--LD为高电平时加载预置数
--否则继续计数
END IF;
END IF;
END PROCESS;
PROCESS (COUNT)
BEGIN
IF COUNT=255 THEN CAO<= '1'; --计数满后,置于溢出位
ELSE CAO<= '0';
END IF;
END PROCESS;
END ART;
第6章
VHDL设计应用实例
2) 正负脉宽数控调制信号发生器的源程序PULSE.VHD
LIBRARY IEEE;
--正负脉宽数控调制信号发生器顶层文件
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY PULSE IS
PORT (CLK:IN STD_LOGIC;
--计数时钟
A,B:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
--8位计数预置数
PSOUT:OUT STD_LOGIC);
END PULSE;
ARCHITECTURE ART OF PULSE IS
COMPONENT LCNT8
--计数溢出并分频输出
第6章
VHDL设计应用实例
PORT(CLK,LD:IN STD_LOGIC;
D:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
CAO:OUT STD_LOGIC);
END COMPONENT;
SIGNAL CAO1,CAO2 :STD_LOGIC;
SIGNAL LD1,LD2 :STD_LOGIC;
SIGNAL PSINT:STD_LOGIC;
BEGIN
U1:LCNT8 PORT MAP(CLK=>CLK,LD=>LD1,
D=>A,CAO=>CAO1);
U2:LCNT8 PORT MAP(CLK=>CLK,LD=>LD2,
D=>B,CAO=>CAO2);
第6章
VHDL设计应用实例
PROCESS(CAO1,CAO2)
BEGIN
IF CAO1= '1' THEN PSINT<= '0';
ELSIF CAO2 'EVENT AND CAO2= '1' THEN PSINT<='1';
END IF;
END PROCESS;
LD1<=NOT PSINT;LD2<=PSINT;PSOUT<=PSINT;
END ART;
第6章
VHDL设计应用实例
3. 硬件逻辑验证
选择实验电路结构图NO.1,由5.2节的实验电路结构图
NO.1和图6.4确定引脚的锁定。输入时钟CLK接CLOCK0(用于
发声时,接频率65536 Hz);8位数控预置输入B[7..0]接
PIO15~PIO8,由键4和键3控制输入,输入值分别显示于数码
管4和数码管3;另8位数控预置输入A[7..0]接PIO7~PIO0,由
键1和键2控制输入,输入值分别显示于数码管2和数码管1;
输出PSOUT 接SPEAKER(对应1032E是第5引脚PIN5;对应
EPF10K是第3引脚PIN3)。
第6章
VHDL设计应用实例
进行硬件验证时方法如下:通过键2和键1输入控制高电平
信号脉宽的预置数(显示于数码管2和1);由键4和键3输入控制
低电平信号脉宽的预置数(显示于数码管4和3);取待分频率
F=12 MHz、6 MHz或3 MHz,通过短路帽输入CLK9;频率输
出可利用示波器观察波形随预置数的变化而变化的情况。在没
有示波器时,“CLK”可接低频率信号,然后接通扬声器,通
过声音音调的变化来了解输出频率的变化。
第6章
VHDL设计应用实例
6.5 数字频率计的设计
1. 设计思路
图6.5是8位十进制数字频率计的电路逻辑图,它由一个测频
控制信号发生器TESTCTL、8个有时钟使能的十进制计数器
CNT10、一个32位锁存器REG32B组成。以下分别叙述频率计各
逻辑模块的功能与设计方法。
第6章
VHDL设计应用实例
CNT1 0
F SI N
CLK
CLK
TES TCTL
CLK
TSTEN
RST
U 0 CLR_ CN T
LOA D
SE
SC
CLR
EN
A
CLR
EN
A
G ND
U 1 CQ[ 3 ..0 ]
CARRY_ OU T
CLK
REG 3 2B
LOA D
D OU T[ 3 1..0 ]
D IN [ 31 ..0] U 9
CLR
EN
A
S D[ 3 1..0 ]
D OU T[ 3 1..0 ]
CLR
EN
A
CLR
EN
A
S D[ 7 ..4 ]
CLR
EN
A
S D[ 1 1..8 ]
U 3 CQ[ 3 ..0 ]
CARRY_ OU T
CLR
EN
A
S3
U 4 CQ[ 3 ..0 ]
CARRY_ OU T
S5
S D[ 1 5..1 2]
S6
图6.5 8位十进制数字频率计逻辑图
CLR
EN
A
S D[ 2 7..2 4]
U 7 CQ[ 3 ..0 ]
CARRY_ OU T
S7
CNT1 0
CLK
S D[ 2 3..2 0]
U 6 CQ[ 3 ..0 ]
CARRY_ OU T
CNT1 0
CLK
S D[ 1 9..1 6]
U 5 CQ[ 3 ..0 ]
CARRY_ OU T
CNT1 0
CLK
S2
CNT1 0
CLK
CLK
CQ[ 3 ..0 ]
U2
CARRY_ OU T
CNT1 0
SL
CNT1 0
S4
S1
CNT1 0
CLK
S D[ 3 ..0 ]
U 8 CQ[ 3 ..0 ]
CARRY_ OU T
S D[ 3 1..2 8]
S8
第6章
VHDL设计应用实例
1) 测频控制信号发生器设计
频率测量的基本原理是计算每秒钟内待测信号的脉冲个数。
这就要求TESTCTL的计数使能信号TSTEN能产生一个1秒脉宽
的周期信号,并对频率计的每一计数器CNT10的ENA使能端进
行同步控制。当TSTEN高电平时,允许计数;低电平时,停止
计数,并保持其所计的数。在停止计数期间,首先需要一个锁
存信号LOAD的上跳沿将计数器在前1秒钟的计数值锁存进32位
锁存器REG32B中,并由外部的7段译码器译出并稳定显示。锁
存信号之后,必须有一清零信号CLR_CNT对计数器进行清零,
为下1秒钟的计数操作作准备。测频控制信号发生器的工作时
序如图6.6所示。为了产生这个时序图,需首先建立一个由D触
发器构成的二分频器,在每次时钟CLK上沿到来时其值翻转。
第6章
VHDL设计应用实例
其中控制信号时钟CLK的频率取1 Hz,而信号TSTEN的脉
宽恰好为1 s,可以用作闸门信号。此时,根据测频的时序要求,
可得出信号LOAD和CLR_CNT的逻辑描述。由图6.6可见,在
计数完成后,即计数使能信号TSTEN在1 s的高电平后,利用其
反相值的上跳沿产生一个锁存信号LOAD,0.5 s后,CLR_CNT
产生一个清零信号上跳沿。
高质量的测频控制信号发生器的设计十分重要,设计中要
对其进行仔细的实时仿真(TIMING SIMULATION),防止可能
产生的毛刺。
第6章
VHDL设计应用实例
[I] RST
[I] CLK
[O] TSTEN
[O] LOAD
[O] CLR_ CNT
图6.6 测频控制信号发生器工作时序
第6章
VHDL设计应用实例
2) 寄存器REG32B设计
设置锁存器的好处是,显示的数据稳定,不会由于周期性
的清零信号而不断闪烁。若已有32位BCD码存在于此模块的输
入口,在信号LOAD的上升沿后即被锁存到寄存器REG32B的内
部,并由REG32B的输出端输出,然后由实验板上的7段译码器
译成能在数码管上显示输出的相对应的数值。
第6章
VHDL设计应用实例
3) 十进制计数器CNT10的设计
如图6.5所示,此十进制计数器的特殊之处是,有一时钟使
能输入端ENA,用于锁定计数值。当高电平时计数允许,低电
平时禁止计数。
第6章
VHDL设计应用实例
2. VHDL源程序
1) 有时钟使能的十进制计数器的源程序CNT10.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
--有时钟使能的十进制计数器
ENTITY CNT10 IS
PORT (CLK:IN STD_LOGIC;
--计数时钟信号
CLR:IN STD_LOGIC;
--清零信号
END:IN STD_LOGIC;
--计数使能信号
CQ:OUT INTEGER RANGE 0 TO 15;
--4位计数结果输出
CARRY_OUT:OUT STD_LOGIC);
--计数进位
END CNT10;
ARCHITECTURE ART OF CNT10 IS
第6章
VHDL设计应用实例
SIGNAL CQI :INTEGER RANGE 0 TO 15;
BEGIN
PROCESS(CLK,CLR,ENA)
BEGIN
IF CLR= '1' THEN CQI<= 0;
--计数器异步清零
ELSIF CLK'EVENT AND CLK= '1' THEN
IF ENA= '1' THEN
IF CQI<9 THEN CQI<=CQI+1;
ELSE CQI<=0;END IF;
--等于9,则计数器清零
END IF;
END IF;
END PROCESS;
PROCESS (CQI)
BEGIN
IF CQI=9 THEN CARRY_OUT<= '1';
--进位输出
ELSE CARRY_OUT<= '0';END IF;
END PROCESS;
CQ<=CQI;
END ART;
第6章
VHDL设计应用实例
2) 32位锁存器的源程序REG32B.VHD
LIBRARY IEEE; --32位锁存器
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY REG32B IS
PORT(LOAD:IN STD_LOGIC;
DIN:IN STD_LOGIC_VECTOR(31 DOWNTO 0);
DOUT:OUT STD_LOGEC_VECTOR(31 DOWNTO 0));
END REG32B;
ARCHITECTURE ART OF REG32B IS
BEGIN
PROCESS ( LOAD, DIN )
BEGIN
IF LOAD 'EVENT AND LOAD= '1' THEN DOUT<=DIN;
--锁存输入数据
END IF ;
END PROCESS;
END ART;
第6章
VHDL设计应用实例
3) 测频控制信号发生器的源程序TESTCTL.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
--测频控制信号发生器
USE IEEE.STD_LOGIC_UNSIGNED.ALL
ENTITY TESTCTL IS
PORT (CLK:IN STD_LOGIC;
--1 Hz测频控制时钟
TSTEN:OUT STD_LOGIC;
--计数器时钟使能
CLR_CNT:OUT STD_LOGIC;
--计数器清零
LOAD:OUT STD_LOGIC);
--输出锁存信号
END TESTCTL;
ARCHITECTURE ART OF TESTCTL IS
SIGNAL Dvi2CLK :STD_LOGIC;
BEGIN
第6章
VHDL设计应用实例
PROCESS ( CLK )
BEGIN
IF CLK'EVENT AND CLK= '1' THEN
--1 Hz时钟二分频
Div2CLK<=NOT Div2CLK;
END IF ;
END PROCESS;
PROCESS ( CLK,Div2CLK )
BEGIN
IF CLK= '0' AND Div2CLK = '0' THEN
--产生计数器清零信号
CLR_CNT<= '1';
ELSE CLR_CNT<= '0' ; END IF;
END PROCESS;
LOAD<=NOT Div2CLK; TSTEN<=Div2CLK;
END ART;
第6章
VHDL设计应用实例
4) 数字频率计的源程序FREQ.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY FREQ IS
PORT(FSIN:IN STD_LOGIC;
CLK:IN STD_LOGIC;
DOUT:OUT STD_LOGIC_VECTOR(31 DOWNTO 0));
END FREQ;
ARCHITECTURE ART OF FREQ IS
COMPONENT CNT10 --待调用的有时钟使能的十进制计数器端口定义
PORT(CLK,CLR,ENA:IN STD_LOGIC;
CQ:OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
CARRY_OUT:OUT STD_LOGIC);
第6章
VHDL设计应用实例
END COMPONENT;
COMPONENT REG32B --待调用的32位锁存器端口定义
...
COMPONENT TESTCTL --待调用的测频控制信号发生器端口定义
...
SIGNAL TSTEN:STD_LOGIC;
SIGNAL CLR_CNT:STD_LOGIC;
SIGNAL LOAD:STD_LOGIC;
SIGNAL CARRY1:STD_LOGIC;
SIGNAL CARRY2:STD_LOGIC;
SIGNAL CARRY3:STD_LOGIC;
SIGNAL CARRY4:STD_LOGIC;
SIGNAL CARRY5:STD_LOGIC;
SIGNAL CARRY6:STD_LOGIC;
SIGNAL CARRY7:STD_LOGIC;
SIGNAL CARRY8:STD_LOGIC;
SIGNAL DIN:STD_LOGIC_VECTOR(31 DOWNTO 0);
第6章
VHDL设计应用实例
BEGIN
U0:TESTCTL PORT MAP(CLK=>CLK,TSTEN=>TSTEN,
CLR_CNT=>CLR_CNT,LOAD=>LOAD);
U1:CNT10 PORT MAP(CLK=>FSIN,CLR=>CLR_CNT,ENA=>TSTEN,
CQ=>DIN (3 DOWNTO 0),CARRY_OUT=>CARRY1);
U2:CNT10 PORT MAP(CLK=>CARRY1,CLR=>CLR_CNT,ENA=>TSTEN,
CQ=>DIN (7 DOWNTO 4),CARRY_OUT=>CARRY2);
U3:CNT10 PORT MAP(CLK=>CARRY2,CLR=>CLR_CNT,ENA=>TSTEN,
CQ=>DIN (11 DOWNTO 8),CARRY_OUT=>CARRY3);
U4:CNT10 PORT MAP(CLK=>CARRY3,CLR=>CLR_CNT,ENA=>TSTEN,
CQ=>DIN (15 DOWNTO 12),CARRY_OUT=>CARRY4);
U5:CNT10 PORT MAP(CLK=>CARRY4,CLR=>CLR_CNT,ENA=>TSTEN,
第6章
VHDL设计应用实例
CQ=>DIN (19 DOWNTO 16),CARRY_OUT=>CARRY5);
U6:CNT10 PORT MAP(CLK=>CARRY5,CLR=>CLR_CNT,ENA=>TSTEN,
CQ=>DIN (23 DOWNTO 20),CARRY_OUT=>CARRY6);
U7:CNT10 PORT MAP(CLK=>CARRY6,CLR=>CLR_CNT,ENA=>TSTEN,
CQ=>DIN (27 DOWNTO 24),CARRY_OUT=>CARRY7);
U8:CNT10 PORT MAP(CLK=>CARRY7,CLR=>CLR_CNT,ENA=>TSTEN,
CQ=>DIN (31 DOWNTO 28),CARRY_OUT=>CARRY8);
U9:REG32B PORT MAP(LOAD=>LOAD,DIN=>DIN(31 DOWNTO 0),DOUT=>DOUT);
END ART;
第6章
VHDL设计应用实例
3. 硬件逻辑验证
选择实验电路结构图NO.0,由5.2节的实验电路结构图NO.0
和图6.5确定引脚的锁定,测频控制器时钟信号CLK(1 Hz)可接
CLOCK1,待测频FSIN可接CLOCK0,8位数码显示输出
DOUT[31..0]接PIO47~PIO16。
进行硬件验证时方法如下:选择实验模式0,测频控制器时
钟信号CLK与CLOCK1信号组中的1 Hz信号相接,待测频FSIN
与CLOCK0信号组中的某个信号相接,数码管应显示来自
CLOCK0的频率。
第6章
VHDL设计应用实例
6.6 秒 表 的 设 计
1.设计思路
今需设计一个计时范围为0.01秒~1小时的秒表,首先需要获
得一个比较精确的计时基准信号,这里是周期为1/100 s的计时脉
冲。其次,除了对每一计数器需设置清零信号输入外,还需在6
个计数器设置时钟使能信号,即计时允许信号,以便作为秒表的
计时起停控制开关。因此秒表可由1个分频器、4个十进制计数器
(1/100秒、1/10秒、1秒、1分)以及2个六进制计数器(10秒、10分)
组成,如图6.7所示。6个计数器中的每一计数器的4位输出,通过
外设的BCD译码器输出显示。图6.7中6个4位二进制计数输出的最
小显示值分别为:DOUT[3..0]1/100秒、DOUT[7..4]1/10秒、
DOUT[11..8]1秒、DOUT[15..12]10秒、DOUT[19..16]1分、
DOUT[23..20]10分。
第6章
CLK GE
N
CLK
CLK
U0
N EW CLK
CNT1 0
CLR
ENA
VHDL设计应用实例
CLK
CLR
U1
CQ[ 3 ..0 ]
CLK
CARRY_ OU T
CLR
S1
CNT1 0
CLR
U2
ENA
CQ[ 3 ..0 ]
CARRY_ OU T
S4
CNT1 0
D OU T[ 1 9..1 6
CQ[ 3 ..0 ]
CLK
U5
CARRY_ OU T
CLR
CARRY_ OU T
S2
CNT1 0
CLR
D OU T[ 1 5..1 2
U4
ENA
D OU T[ 7 ..4]
ENA
CLK
CNT6
D OU T[ 3 ..0]
ENA
CLK
D OU T[ 2 3..0 ]
S0
U3
ENA
D OU T[ 1 1..8 ]
CQ[ 3 ..0 ]
CARRY_ OU T
S5
CNT6
CLK
S3
CQ[ 3 ..0 ]
CLR
ENA
图6.7 秒表电路逻辑图
U6
D OU T[ 2 3..2 0]
CQ[ 3 ..0 ]
CARRY_ OU T
第6章
VHDL设计应用实例
2. VHDL源程序
1) 3 MHz→100 Hz分频器的源程序CLKGEN.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY CLKGEN IS
PORT (CLK:IN STD_LOGIC;
NEWCLK:OUT STD_LOGIC );
--3 MHz信号输入
--100 Hz计时时钟信号输出
END CLKGEN;
ARCHITECTURE ART OF CLKGEN IS
SIGNAL CNTER:INTEGER RANGE 0 TO 10#29999#; --十进制计数预制数
BEGIN
PROCESS(CLK)
BEGIN
--分频计数器,由3 MHz时钟产生100 Hz信号
第6章
VHDL设计应用实例
IF CLK'EVENT AND CLK='1' THEN
IF CNTER=10#29999# THEN CNTER<=0;
--3 MHz信号变为100 Hz,计数常数为30 000
ELSE CNTER<=CNTER+1;
END IF;
END IF;
END PROCESS;
PROCESS(CNTER)
--计数溢出信号控制
BEGIN
IF CNTER=10#29999# THEN NEWCLK<='1';
ELSE NEWCLK<='0';
END IF;
END PROCESS;
END ART;
第6章
VHDL设计应用实例
2) 六进制计数器的源程序CNT6.VHD(十进制计数器的源
程序CNT10.VHD与此类似)
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY CNT6 IS
PORT (CLK:IN STD_LOGIC;
CLR:IN STD_LOGIC;
ENA: IN STD_LOGIC;
CQ:OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
第6章
VHDL设计应用实例
CARRY_OUT: OUT STD_LOGIC );
END CNT6;
ARCHITECTURE ART OF CNT6 IS
SIGNAL CQI:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
PROCESS(CLK,CLR,ENA)
BEGIN
IF CLR='1' THEN CQI<="0000";
ELSIF CLK'EVENT AND CLK='1' THEN
IF ENA='1' THEN
IF CQI=“0101” THEN CQI<=“0000”;
第6章
VHDL设计应用实例
ELSE CQI<=CQI+'1';END IF;
END IF;
END IF;
END PROCESS;
PROCESS(CQI)
BEGIN
IF CQI=“0000” THEN CARRY_OUT<='1';
ELSE CARRY_OUT<='0';END IF;
END PROCESS;
CQ<=CQI;
END ART;
第6章
VHDL设计应用实例
3) 秒表的源程序TIMES.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY TIMES IS
PORT(CLR:IN STD_LOGIC;
CLK:IN STD_LOGIC;
ENA:IN STD_LOGIC;
DOUT:OUT STD_LOGIC_VECTOR(23 DOWNTO 0));
END TIMES;
ARCHITECTURE ART OF TIMES IS
COMPONENT CLKGEN
PORT(CLK:IN STD_LOGIC;
NEWCLK:OUT STD_LOGIC);
第6章
VHDL设计应用实例
END COMPONENT;
COMPONENT CNT10
PORT(CLK,CLR,ENA:IN STD_LOGIC;
CQ:OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
CARRY_OUT:OUT STD_LOGIC);
END COMPONENT;
COMPONENT CNT6
PORT(CLK,CLR,ENA:IN STD_LOGIC;
CQ:OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
CARRY_OUT:OUT STD_LOGIC);
END COMPONENT;
第6章
VHDL设计应用实例
SIGNAL NEWCLK:STD_LOGIC;
SIGNAL CARRY1:STD_LOGIC;
SIGNAL CARRY2:STD_LOGIC;
SIGNAL CARRY3:STD_LOGIC;
SIGNAL CARRY4:STD_LOGIC;
SIGNAL CARRY5:STD_LOGIC;
BEGIN
U0:CLKGEN PORT MAP(CLK=>CLK,NEWCLK=>NEWCLK);
U1:CNT10 PORT MAP(CLK=>NEWCLK,CLR=>CLR,ENA=>ENA,
CQ=>DOUT(3 DOWNTO 0),CARRY_OUT=>CARRY1);
第6章
VHDL设计应用实例
U2:CNT10 PORT MAP(CLK=>CARRY1,CLR=>CLR,ENA=>ENA,
CQ=>DOUT(7 DOWNTO 4),CARRY_OUT=>CARRY2);
U3:CNT10 PORT MAP(CLK=>CARRY2,CLR=>CLR,ENA=>ENA,
CQ=>DOUT(11 DOWNTO 8),CARRY_OUT=>CARRY3);
U4:CNT6 PORT MAP(CLK=>CARRY3,CLR=>CLR,ENA=>ENA,
CQ=>DOUT(15 DOWNTO 12),CARRY_OUT=>CARRY4);
U5:CNT10 PORT MAP(CLK=>CARRY4,CLR=>CLR,ENA=>ENA,
CQ=>DOUT(19 DOWNTO 16),CARRY_OUT=>CARRY5);
U6:CNT6 PORT MAP(CLK=>CARRY5,CLR=>CLR,ENA=>ENA,
CQ=>DOUT(23 DOWNTO 20));
END ART;
第6章
VHDL设计应用实例
3. 硬件逻辑验证
选择实验电路结构图NO.0,由5.2节的实验电路结构图
NO.0和图6.7确定引脚的锁定。时钟信号CLK可接CLOCK0,
计数清零信号接键1,计数使能信号接键2,数码管1~6分别显
示以1/100 s、1/10 s、1 s、10 s、1 min、10 min为计时基准的
计数值。
进行硬件验证时方法如下:选择实验模式0,时钟信号
CLK与CLOCK0信号组中的3 MHz信号相接,键1和键2分别为
计数清零信号和计数使能信号,计数开始后时间显示在6个数
码管上。
第6章
VHDL设计应用实例
6.7 MCS-51单片机与FPGA/CPLD总线接口逻辑设计
单片机具有性能价格比高、功能灵活、易于人机对话和良
好的数据处理能力等特点;PLD则具有高速、高可靠以及开发
便捷规范等方面的优点,以此两类器件相结合的电路结构在许
多高性能仪器仪表和电子产品中将被广泛应用。单片机与CPLD
的接口方式一般有两种,即总线方式与独立方式。
单片机以总线方式与FPGA/CPLD进行数据与控制信息通信
有许多优点:
第6章
VHDL设计应用实例
(1) 速度快。其通信工作时序是纯硬件行为,对于MCS-51
单片机,只需一条单字节指令就能完成所需的读/写时序,如:
MOV @DPTR,A;MOV A,@DPTR。
(2) 节省PLD芯片的I/O口线。如图6.9,如果将图中的译码
DECODER设置足够的译码输出,以及安排足够的锁存器,就
能仅通过19根I/O口线在FPGA/CPLD与单片机之间进行各种类
型的数据与控制信息交换。
(3) 相对于非总线方式,单片机的编程简捷,控制可靠。
第6章
VHDL设计应用实例
(4) 在FPGA/CPLD中通过逻辑切换,单片机易于与SRAM
或ROM接口。这种方式有许多实用之处,如利用类似于微处
理器DMA的工作方法,首先由FPGA/CPLD与接口的高速A/D
等器件进行高速数据采样,并将数据暂存于SRAM中,采样结
束后,通过切换,使单片机与SRAM以总线方式进行数据通信,
以便发挥单片机强大的数据处理能力。
第6章
VHDL设计应用实例
1.设计思路
对单片机与FPGA/CPLD以总线方式通信的逻辑设计, 应详细
了解单片机的总线读写时序,根据时序图来设计逻辑结构。图6.8
是MCS-51系列单片机的时序图,其时序电平变化速度与单片机工
作时钟频率有关。图中,ALE为地址锁存使能信号,可利用其下
降沿将低8位地址锁存于FPGA/CPLD中的地址锁存器
(LATCH_ADDRES)中。当ALE将低8位地址通过P0锁存的同时,
高8位地址已稳定建立于P2口,单片机利用读写指令允许信号
PSEN的低电平,从外部ROM中将指令从P0口读入。由时序图可
见,其指令读入的时机是在PSEN的上跳沿之前。接下来,由P2口
和P0口分别输出高8位和低8位数据地址,并由ALE的下沿将P0口
的低8位地址锁存于地址锁存器。
第6章
VHDL设计应用实例
若需从“FPGA/CPLD”中读出数据,单片机则通过指令
“MOV A,@DPTR”使RD信号为低电平,由P0口将图6.9中锁
存器LATCH_IN1中的数据读入累加器A。但若欲将累加器A的
数据写进FPGA/CPLD,需通过指令“MOV @DPRT,A”和写允
许信号WR。这时,DPTR中的高8位和低8位数据作为高低8位
地址分别向P2 和P0口输出,然后由WR的低电平,并结合译码,
将A的数据写入图中相关的锁存器。
第6章
VHDL设计应用实例
地址锁存沿
ALE
指令读允许
PSEN
外部RAM 读/写允许
WR/RD
P2
指令地址 A15¡«A8
数据地址 A15¡«A8
P0
A7¡«A0
低8位指令地址
指令
A7¡«A0
数据
低8位数据地址
图6.8 MCS-51单片机总线接口方式工作时序
A7¡«A0
低8位数据地址
第6章
VHDL设计应用实例
READ
Y
FPGA/CPLD
DECODER
WR
RD
P2
WR
R
D
8031
P2
P0
WR_ENABLE1
WR_ENABLE2
8
RD_ENABLE
8
8
8
AD_CS
DATOUT
WR_ENABLE1
1
LATCH_OUT1 8
DATOUT
WR_ENABLE2
2
LATCH_OUT2 8
ALE
ALE
LATCH_ADDRES
8
LATCH1
I1
P0
L AT CHT_IN1
8
DATAIN
1
8
图6.9 CPLD/FPGA与MCS-51单片机的总线接口通信逻辑图
第6章
VHDL设计应用实例
2. VHDL源程序
LIBRARY IEEE;
--MCS-51单片机读写电路
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY MCS_51 IS
PORT(
--与8031接口的各端口定义:
P0:INOUT STD_LOGIC_VECTOR(7 DOWNTO 0); --双向地址/数据口
P2:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
--高8位地址线
RD,WR:IN STD_LOGIC;
--读、写允许
ALE:IN STD_LOGIC;
-- 地址锁存
READY:IN STD_LOGIC;
AD_CS:OUT STD_LOGIC;
--待读入数据准备就绪标志位
--A/D器件片选信号
DATAIN1:IN STD_LOGIC_VECTOR(7 DOWNTO 0);--单片机待读回信号
LATCH1:IN STD_LOGIC;
--读回信号锁存
第6章
VHDL设计应用实例
DATOUT1:OUT STD_LOGIC_VECTOR(7 DOWNTO 0);--锁存输出数据1
DATOUT2:OUT STD_LOGIC_VECTOR(7 DOWNTO 0);--锁存输出数据2
END MCS-51;
ARCHITECTURE ART OF MCS-51 IS
SIGNAL LATCH_ADDRES:STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL LATCH_OUT1:STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL LATCH_OUT2:STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL LATCH_IN1:STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL WR_ENABLE1:STD_LOGIC;
SIGNAL WR_ENABLE2:STD_LOGIC;
BEGIN
PROCESS ( ALE )
BEGIN
--低8位地址锁存进程
第6章
VHDL设计应用实例
IF ALE'EVENT AND ALE= '0' THEN
LATCH_ADDRES<=P0;
END IF;
--ALE的下降沿将P0口的低8位地址
--锁入锁存器LATCH_ADDRES中
END PROCESS;
PROCESS(P2,LATCH_ADDRES) --WR写信号译码进程1
BEGIN
IF ( LATCH_ADDRES= "11110101") AND ( P2= "01101111" ) THEN
WR_ENABLE1<=WR;
--写允许
ELSE WR_ENABLE1<= '1'; END IF ;--写禁止
END PROCESS;
PROCESS ( WR_ENABLE1 )
--数据写入寄存器1
第6章
VHDL设计应用实例
BEGIN
IF WR_ENABLE1'EVENT AND WR_ENABLE1 = '1'
THEN LLATCH_OUT1<= P0; END IF;
END PROCESS;
PROCESS (P2,LATCH_ADDRES )
--WR写信号译码进程2
BEGIN
IF ( LATCH_ADDRES= "11110011")AND(P2= "00011111" ) THEN
WR_ENABLE2<= WR;
ELSE WR_ ENABLE2<= '1';END IF;
--写允许
--写禁止
END PROCESS;
PROCESS (WR_ENABLE2 )
BEGIN
--数据写入寄存器2
第6章
VHDL设计应用实例
IF WR_ENABLE2'EVENT AND WR_ENABLE2= '1'
THEN LATCH_OUT2<=P0; END IF;
END PROCESS;
PROCESS(P2,LATCH_ADDRES,READY,RD)
--8031对PLD中数据读入进程
BEGIN
IF ( LATCH_ADDRES= "01111110" ) AND ( P2= "10011111" )
AND ( READY= '1') AND ( RD= '0' ) THEN
P0<=LATCH_IN1;
ELSE P0<= "ZZZZZZZZ";END IF ;
--寄存器中的数据读入P0口
--禁止读数,P0口呈高阻态
END PROCESS;
PROCESS(LATCH1 )
--外部数据进入CPLD进程
第6章
VHDL设计应用实例
BEGIN
IF LATCH1'EVENT AND LATCH1= '1'
THEN LATCH_IN1<=DATAIN1; END IF;
END PROCESS;
PROCESS(ALTCH_ADDRES)
--A/D工作控制片选信号输出进程
BEGIN
IF ( LATCH_ADDRES= "00011110" ) THEN
AD_CS<= '0';
--允许A/D工作
ELSE AD_CS<= '1'; END IF;
-- 禁止A/D工作
END PROCESS;
DATOUT1<=LATCH_OUT1; DATOUT2<=LATCH_OUT2;
EDN ART;
第6章
VHDL设计应用实例
这是一个CPLD与8031单片机接口的VHDL电路设计。
8031以总线方式工作,例如,由8031将数据5AH写入目标器件
中的第一个寄存器LATCH_OUT1的指令是:
MOV A,#5AH
MOV DPTR,#6FF5H
MOVX @DPTR,A
当READY为高电平时,8031从目标器件中的寄存器
LATCH_IN1将数据读入的指令是:
MOV DPTR,#9F7EH
MOVX A,@DPTR
第6章
VHDL设计应用实例
6.8 交通灯信号控制器的设计
1. 设计思路
设交通灯信号控制器用于主干道与支道公路的交叉路口,
要求是优先保证主干道的畅通。因此,平时处于“主干道绿灯,
支道红灯”状态,只有在支道有车辆要穿行主干道时,才将交
通灯切向“主干道红灯,支道绿灯”,一旦支道无车辆通过路
口,交通灯又回到“主干道绿灯,支道红灯”的状态。此外,
主干道和支道每次通行的时间不得短于30 s,而在两个状态交换
过程出现的“主黄,支红”和“主红,支黄”状态,持续时间
都为4 s。根据交通灯信号控制的要求,我们可把它分解为定时
器和控制器两部分,其原理方框图如图6.10所示。
第6章
VHDL设计应用实例
图6.10 交通灯信号控制器原理方框图
第6章
VHDL设计应用实例
2. VHDL源程序
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY JTDKZ IS
PORT(CLK,SM,SB;IN BIT;--这里要求CLK为1 kHz
MR,MY,MG,BR,BY,BG:OUT BIT);
END JTDKZ;
ARCHITECTURE ART OF JTDKZ IS
TYPE STATE_TYPE IS (A,B,C,D);
SIGNAL STATE:STATE_TYPE;
BEGIN
第6章
VHDL设计应用实例
CNT:PROCESS(CLK)
VARIABLE S:INTEGER RANGE 0 TO 29;
VARIABLE CLR,EN:BIT;
BEGIN
IF (CLK'EVENT AND CLK='1') THEN
IF CLR = '0' THEN S:=0;
ELSIF EN = '0' THEN S:=S;
ELSE S:=S+1;
END IF;
CASE STATE IS
WHEN A=>MR<='0';MY<='0';MG<='1';
BR<= '1';BY<= '0';BG<= '0';
第6章
VHDL设计应用实例
IF (SB AND SM)= '1' THEN
IF S=29 THEN
STATE<=B;CLR:='0';EN:='0';
ELSE
STATE<=A;CLR:='1';EN: = '1';
END IF;
ELSIF (SB AND (NOT SM)) = '1' THEN
STATE<=B;CLR:='0';EN:='0';
ELSE
STATE<=A;CLR:='1';EN:='1';
END IF;
WHEN B =>MR<= '0';MY<= '1';MG<= '0';
BR<= '1';BY<= '0';BG<= '0';
第6章
VHDL设计应用实例
IF S=3 THEN
STATE <=C;CLR:='0';EN:='0';
ELSE
STATE<=B;CLR:='1';EN:='1';
ENDIF;
WHEN C =>MR<= '1';MY<= '0';MG<= '0';
BR<= '0';BY<= '0';BG <= '1';
IF (SM AND SB) = ' 1' THEN
IF S=29 THEN
STATE<=D;CLR:='0';EN:='0';
ELSE
STATE<=C;CLR:= '1';EN:='1';
ELSIF SB = '0' THEN
STATE <=D;CLR:= '0';EN:='0';
第6章
VHDL设计应用实例
ELSE
STATE<=C;CLR:='1';EN:='1';
END IF ;
WHEN D=>MR<= '1';MY<='0';MG<='0';
BR<='0';BY<='1';BG<= '0';
IF S =3 THEN
STATE<=A;CLR:='0';EN:='0';
ELSE
STATE<=D;CLR:='1';EN:='1';
END IF ;
END CASE;
END IF;
END PROCESS CNT;
END ART;
第6章
VHDL设计应用实例
3. 硬件逻辑验证
选择实验电路结构图NO.1,由5.2节的实验电路结构图
NO.1和图6.10确定引脚的锁定。时钟脉冲CLK可接CLOCK0(1
Hz),主干道和支干道来车信号分别接键7和键8,主干道和支
干道红、黄、绿灯驱动信号MR、MY、MG和BR、BY、BG分
别接D1~D3和D8~D6。
进行硬件验证时方法如下:选择实验模式1,时钟脉冲与
CLOCK0信号组中的1 Hz信号相接,在键7和键8施加相应的信
号,发光二极管D1~D3、D8~D6则按控制要求显示相应的信
号。
第6章
VHDL设计应用实例
6.9 语音信箱控制系统的设计
1.设计思路
语音信箱控制系统用于控制对语音信箱的有关操作,允许
用户发送信息、重阅信息、存储信息和擦除信息,状态转移图
如图6.11所示。
第6章
VHDL设计应用实例
MAIN_S
T
MAIN
ÓïÒôÐÅÏä
1
REVIE W_S
T
2
SEND_ST
SEND
·¢ÐÅ
REVIE W
Ê ÕÐÅÔÄÀÀ
ADDRE SS_S
T
ADDRE SS
Ñ°Ö·
RECORD_ST
RECORD
¼Ç¼
3
1
2
5
REPEA
T
Öظ´
SAVE
´æÐÅ
E RASE
²Á³ý
REPEAT_S
T
SAVE_ST
E RASE _ST
RECORD
ME SSAGE
¼Ç¼ÓïÒô
ME SSAGE _ST
图6.11 语音信箱控制器的状态转移图
BEGIN
RECORD
¿ªÊ ¼Â¼Òô
BIGIN_RE C_ST
第6章
VHDL设计应用实例
正常起始状态是MAIN_ST状态,从MAIN_ST状态,用户
选择究竟是收信息还是发信息。为了得到收阅菜单,用户在按
键电话上按1键;为了选发送信息菜单,用户在按键菜单上按2
键。一旦用户选择了这些选项中的任何一种,下一级菜单允许
用户选择执行进一步(如存储与删除信息)的功能。例如,如果
用户先按键1,选收阅菜单,那么再按键2,将允许用户在收阅
完时存储用户收阅过的信息。
第6章
VHDL设计应用实例
2. VHDL源程序
PACKAGE VM_PACK IS
TYPE T_VM_STATE IS(MAIN_ST,REPEAT_ST,SAVE_ST,
ERASE_ST,SEND_ST,ADDRESS_ST,RECORD_ST,
BEGIN_REC_ST,MESSAGE_ST);
TYPE T_KEY('1','2','3','4','5','6','7','8','9','*','#');
END VM_PACK;
LIBRARY IEEE;
USE WORK.VM_PACK,ALL;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY CONTROL IS
PORT(CLK,KEY:IN STD_LOGIC;
第6章
VHDL设计应用实例
PLAY,RECORD,ERASE,SAVE,ADDRESS:OUT STD_LOGIC);
END CONTROL;
ARCHITECTURE ART OF CONTROL IS
SIGNAL NEXT_STATE,CURRENT_STATE:T_VM_STATE;
BEGIN
PROCESS(CURRENT_STATE,KEY)
BEGIN
PLAY<= '0';SAVE <= '0';ERASE<= '0';
RECORD<= '0';ADDRESS<= '0';
CASE CURRENT_STATE IS
WHEN MAIN_ST =>
--看信箱
IF ( KEY='1') THEN
第6章
VHDL设计应用实例
NEXT_STATE<=REVIEW_ST;
--转到重阅
ELSIF (KEY ='2') THEN
NEXT_STATE<=SEND_ST ;
ELSE
NEXT_STATE<=MAIN_ST;
END IF;
WHEN REVIEW_ST=>
--重阅
IF (KEY='1')THEN
NEXT_STATE<=REPEAT_ST;
ELSIF(KEY='2') THEN
NEXT_STATE<=SAVE_ST;
ELSIF( KEY = '3') THEN
NEXT_STATE =ERASE_ST;
ELSIF( KEY = '#') THEN
转到发送
第6章
VHDL设计应用实例
NEXT_STATE =MAIN_ST;
ELSE
NEXT_STATE<=REVIEW_ST;
END IF;
WHEN REPEAT_ST =>
--重复
PLAY<= '1';
NEXT_STATE<=REVIEW_ST;
WHEN SAVE_ST =>
--存信息
SAVE<= '1';
NEXT_STATE<=REVIEW_ST;
WHEN ERASE_ST =>
--擦掉
ERASE<= '1';
NEXT_STATE<=REVIEW_ST;
第6章
VHDL设计应用实例
WHEN SEND_ST =>
--发送
NEXT_STATE<=ADDRESS_ST;
WHEN ADDRESS_ST =>
--寻址
ADDRESS<= '1';
IF (KEY='#')THEN
NEXT_STATE<=RECORD_ST;
ELSE
NEXT_STATE, =ADDRESS_ST;
END IF ;
WHEN RECORD_ST=>
--记录
IF (KEY='5') THEN
NEXT_STATE<=BEGIN_REC_ST;
ELSE
第6章
VHDL设计应用实例
NEXT_STATE<=RECORD_ST;
END IF;
WHEN BEGIN_REC_ST =>
--开始录音
RECORD<= '1';
NEXT_STATE<=MESSAGE_ST;
WHEN MESSAGE_ST=>
--记录录音
RECORD<= '1';
IF (KEY='#')THEN
NEXT_STATE<=SEND_ST;
发送到信箱
ELSE
NEXT_STATE<=MESSAGE_ST;
第6章
VHDL设计应用实例
END IF;
END CASE;
END PROCESS;
PROCESS
BEGIN
WAIT UNTIL (CLK'EVENT AND CLK = '1');
CURRENT_STATE<=NEXT_STATE;
END PROCESS;
END ART;
第6章
VHDL设计应用实例
程序包VM_PACK含有对状态值的类型说明和语音信箱控
制系统允许用的键盘。必须指出的是,状态是用来表示某些事
件的全过程,而事件的全过程又是由它所对应状态(如STATE1、
STATE2和STATE3 等)来说明,用状态描述将使模块的可读性
更好。
为了实用,这个程序包实体标明了局部信号和键输入端口。
该实体只有一种输入(即键输入),由按键电话的键盘示出可能
的键字,实体除KEY和CLK之外,所有其他的端口都是输出端
口,并且用这些端口控制语音信箱系统的工作。
第6章
VHDL设计应用实例
6.10 PID控制器的设计
1.设计思路
要求设计一个PID控制器,对电机转速进行采样,与额定的
转速进行比较,并通过微积分计算得到电机的控制电流,从而
实现对电机转速的调整。通常,PID控制器用模拟电路实现,但
数字电路的实现方案可以很方便地实现集成。
该PID控制器包括一个完成算术和逻辑功能的ALU以及一个
存储状态变量和有关系数的存储器。其端口说明如图6.12 所示。
第6章
RESET
FSIGNIN
HOSTINTERRUPT
VHDL设计应用实例
PID控制器
POSITIONCHANGE
图6.12 PID控制器示意图
IREFKOUT
第6章
VHDL设计应用实例
其中,RESET 端口为复位端口,当RESET为高电平时,
PID控制器复位;FSIGNIN为输入的偏差方向,转速超过额定转
速时为‘1’,否则为‘0’;HOSTINTERRUPT为主机请求信号,
当此信号为‘1’时,PID开始计算,为‘0’时,则停止计算并输
出结果。POSITIONCHANGE为电机向PID控制器发送的脉冲信
号,每转过一周,POSITONCHANGE 出现一个脉冲;
IREFKOUT为最终输出的控制电流值。
主机向PID控制器发调用请求HOSTINTERRUPT之后,PID
控制器进行采样并开始计算,当HOSTINTERRUPT信号停止时,
PID控制器停止采样计算,并将计算结果输出到主机。
第6章
VHDL设计应用实例
PID控制器的电流计算公式为
Irefk=(Kp+Ek) + Ki×∫Ekdt + Kd×dEk/dt
采用近似的离散方式表示为
Irefk=(Kp+Ek) + Ki ×∑ Ekdt + Kd ×dEk/dt
PID控制器运行时,电机每转过一周,即
POSITIONCHANGE信号发生一次变化时进行采样,得到电机转
过一周所需要的时间,并将其作为积分的dt值,将该dt 值取倒数
计算出转速。然后与标准转速进行比较,得到转速偏差Ek,将该
Ek与前一周得到的Ek-1相减得出d Ek 。将每一周的Ek /dt值相加得
到积分∫ Ek /dt的值。当HOSTINTERRUPT信号出现下降沿时将积
分与当前时刻的(Kp+ Ek)以及Kd×d Ek /dt线性相加得到控制电流
值。然后,在下一个时钟周期将该控制电流值输出到主机。
第6章
VHDL设计应用实例
4.VHDL源程序
LIBRARY WORK;
USE WORK.SYNCHRO.ALL;
USE WORK.OP_PKG.ALL;
ENTITY PID IS
PORT ( RESET:IN BIT;
FSIGNIN:IN BIT;
HOSTINTERRUPT:IN BIT;
POSITIONCHANGE:IN BIT;
IREFKOUT :OUT REAL );
END PID;
ARCHITECTURE ART OF PID IS
COMPONENT FU_FPU
第6章
VHDL设计应用实例
PORT (CLOCK :IN BIT;
RESET :N BIT;
INPUT1 :IN REAL;
INPUT2 :IN REAL;
SEL :IN BIT;
COM :IN INT3BIT;
OUTPUT :OUT REAL;
OUTDONE :OUT BIT);
END COMPONENT;
第6章
VHDL设计应用实例
SIGNAL SIG_IN1,SIG_IN2 :REAL;
SIGNAL SIG_OUT : REAL;
SIGNAL SIG_SEL,SIG_DONE :BIT;
SIGNAL SIG_COM : INT3BIT;
SIGNAL CLOCK : BIT;-- <= '1';
FOR ALL:FU_FPU USE ENTITY WORK.FIXEDPOINTUNIT(ART);
第6章
VHDL设计应用实例
BEGIN
INST_FU :FU_FPU
PORT MAP(CLOCK => CLOCK,
RESET => RESET,
INPUT1 => SIG_IN1,
INPUT2 => SIG_IN2,
SEL
COM
=> SIG_SEL,
=> SIG_COM,
OUTPUT => SIG_OUT,
OUTDONE => SIG_DONE);
第6章
VHDL设计应用实例
PROCESS
VARIABLE N,EK_1,IK,EK,KP,KI,KD,FREF: REAL;
VARIABLE FK,DEK,IREFK, TEMP: REAL;
VARIABLE DONE : BIT;
第6章
VHDL设计应用实例
PROCEDURE MUL(A,B : IN REAL) IS
BEGIN
SIG_IN1 <= A;
SIG_IN2 <= B;
SIG_SEL <='1';
SIG_COM <= 2;
WAIT UNTIL RISING_EDGE(CLOCK);
SIG_SEL <='0';
RETURN;
END MUL;
第6章
VHDL设计应用实例
PROCEDURE REP(A: IN REAL) IS
BEGIN
SIG_IN1 <= A;
SIG_SEL <='1';
SIG_COM <= 1;
WAIT UNTIL RISING_EDGE(CLOCK);
SIG_SEL <='0';
RETURN;
END REP;
第6章
VHDL设计应用实例
PROCEDURE WAITRESULT(X:OUT REAL; Y:OUT BIT) IS
BEGIN
X := SIG_OUT;
Y := SIG_DONE;
WAIT UNTIL RISING_EDGE(CLOCK);
RETURN;
END WAITRESULT;
TYPE ROM IS ARRAY(0 TO 4) OF REAL;
VARIABLE VAL_ROM : ROM := (2.0*2.0**(-20),2.0,3.0*2.0**(20),4.0*2.0**(20),2.0*2.0** (-20));
PROCEDURE GETCONSTKP(X :OUT REAL) IS
第6章
VHDL设计应用实例
BEGIN
X := VAL_ROM(0);
END GETCONSTKP;
PROCEDURE GETCONSTKI(X :OUT REAL) IS
BEGIN
X := VAL_ROM(1);
END GETCONSTKI;
PROCEDURE GETCONSTKD(X : OUT REAL) IS
BEGIN
X := VAL_ROM(2);
END GETCONSTKD;
PROCEDURE GETFREF(X :OUT REAL) IS
BEGIN
X := VAL_ROM(3);
第6章
VHDL设计应用实例
END GETFREF;
PROCEDURE GETN(X :OUT REAL) IS
BEGIN
X := VAL_ROM(4);
END GETN;
BEGIN
GETCONSTKP(KP);
GETCONSTKI(KI);
GETCONSTKD(KD);
GETFREF(FREF);
IK :=0.0;
EK := 0.0;
IREFK := 0.0;
第6章
VHDL设计应用实例
--WAIT FOR 50 NS;
WAIT UNTIL (HOSTINTERRUPT ='0');
WHILE (HOSTINTERRUPT ='0') LOOP
WAIT UNTIL(POSITIONCHANGE ='1');
GETN(N);
REP(N);
EK_1 := EK;
--WAIT UNTIL(DONE ='1')
WAITRESULT(FK,DONE);
WHILE (DONE /='1') LOOP WAITRESULT(FK,DONE); END LOOP;
IF(FSIGNIN ='0')
THEN EK := FREF - FK;
ELSE EK := FREF + FK;
第6章
VHDL设计应用实例
END IF;
MUL(KP,EK);
DEK := EK - EK_1;
WAITRESULT(IREFK,DONE);
WHILE(DONE /='1'') LOOP WAITRESULT(IREFK,DONE); END LOOP;
MUL(DEK,FK);
WAITRESULT(TEMP,DONE);
WHILE(DONE /='1') LOOP WAITRESULT(TEMP,DONE); END LOOP;
MUL(TEMP,KD);
WAITRESULT(TEMP,DONE);
WHILE(DONE /='1') LOOP WAITRESULT(TEMP,DONE); END LOOP;
IREFK := IREFK + TEMP;
第6章
VHDL设计应用实例
MUL(EK,N);
WAITRESULT(TEMP,DONE);
WHILE(DONE /='1') LOOP WAITRESULT(TEMP,DONE); END LOOP;
IK := IK + TEMP;
MUL(IK,KI);
WAITRESULT(TEMP,DONE);
WHILE (DONE /='1') LOOP WAITRESULT(TEMP ,DONE); END LOOP;
-- IREFKOUT <= IREFK + TEMP;
IREFK := IREFK + TEMP;
END LOOP;
IREFKOUT <= IREFK;
END PROCESS;
CLOCK <= NOT CLOCK ;
END ART;
第6章
VHDL设计应用实例
6.11 空调系统有限状态自动机的设计
1.设计思路
设计一个空调系统的有限状态自动机,它的两个输入端
TEMP_HIGH 和TEMP_LOW分别与传感器相连,用于检测室内
温度。如果室内温度正常,则TEMP_HIGH和TEMP_LOW均为
‘0’。如果室内温度过高,则TEMP_HIGH为‘1’,TEMP_LOW
为‘0 ’。如果室内温度过低,则TEMP_HIGH为‘0’,
TEMP_LOW为‘1’。根据TEMP_HIGH 和TEMP_LOW的值来判
断当前的状态(太热TOO_HOT,太冷 TOO_COLD或适中
JUST_RIGHT),并决定HEAT和COOL的输出值。其原理方框图
如图6.13所示。
第6章
VHDL设计应用实例
TEMP_ HIGH
TEMP_ LOW
HEAT
空调有限状态自动机
图6.13 空调有限状态自动机原理方框图
COOL
第6章
VHDL设计应用实例
2.VHDL源程序
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY AIR_CONDITIONER IS
PORT(CLK : IN STD_ULOGIC;
TEMP_HIGH :IN STD_ULOGIC;
TEMP_LOW : IN STD_ULOGIC;
HEAT : OUT STD_ULOGIC;
COOL : OUT STD_ULOGIC);
END AIR_CONDITIONER;
第6章
VHDL设计应用实例
ARCHITECTURE ART OF AIR_CONDITIONER IS
TYPE STATE_TYPE IS (JUST_RIGHT,TOO_COLD,TOO_HOT);
ATTRIBUTE SEQUENTIAL_ENCODING : STRING;
ATTRIBUTE SEQUENTIAL_ENCODING OF STATE_TYPE :TYPE IS “00 01 10”
SIGNAL STVAR: STATE_TYPE;
ATTRIBUTE STATE_VECTOR : STRING;
ATTRIBUTE STATE_VECTOR OF STYLE_B:ARCHITECTURE IS “STVAR”;
BEGIN
CONTROLLER1: PROCESS
BEGIN
WAIT UNTIL CLK='1'; --REVISED BY DLS
第6章
VHDL设计应用实例
IF (TEMP_LOW='1') THEN STVAR<=TOO_COLD;
ELSIF (TEMP_HIGH='1') THEN STVAR<=TOO_HOT;
ELSE STVAR<=JUST_RIGHT;
END IF;
CASE STVAR IS
WHEN JUST_RIGHT=>HEAT<='0';COOL<='0';
WHEN TOO_COLD=>HEAT<='1';COOL<='0';
WHEN TOO_HOT=>HEAT<='0';COOL<='1';
END CASE;
END PROCESS CONTROLLER1;
END ART;
第6章
VHDL设计应用实例
6.12 闹钟系统的设计
6.12.1 闹钟系统的设计要求及设计思路
要求设计一个带闹钟功能的24小时计时器,计时器的外观如
图6.14所示。它包括以下几个组成部分:① 显示屏,由4个七段
数码管组成,用于显示当前时间(时:分)或设置的闹钟时间;②
数字键‘0’~‘9’,用于输入新的时间或新的闹钟时间;③
TIME(时间)键,用于确定新的时间设置;④ ALARM(闹钟)键,
用于确定新的闹钟时间设置,或显示已设置的闹钟时间;⑤ 扬
声器,在当前时钟时间与闹钟时间相同时,发出蜂鸣声。
第6章
VHDL设计应用实例
0
7
8
9
4
5
6
1
2
3
TIME
ALARM
图6.14 计时器外观
第6章
VHDL设计应用实例
该计时器设计要求完成如下功能:
(1) 计时功能:这是本计时器设计的基本功能,每隔一分钟
计时一次,并在显示屏上显示当前时间。
(2) 闹钟功能:如果当前时间与设置的闹钟时间相同,则扬
声器发出蜂鸣声。
(3) 设置新的计时器时间:用户用数字键‘0’~‘9’输入新的
时间,然后按 "TIME"键确认。在输入过程中,输入数字在显示
屏上从右到左依次显示。例如,用户要设置新的时间12:34,
则按顺序输入“1”,“2”,“3”,“4”键,与之对应,显示屏上
依次显示的信息为:“1”,“12”,“123”,“1234"。如果用户
在输入任意几个数字后较长时间内,例如5 s,没有按任何键,
则计时器恢复到正常的计时显示状态。
第6章
VHDL设计应用实例
(4) 设置新的闹钟时间:用户用数字键“0”~“9”输入新的时
间,然后按“ALARM”键确认。过程与(3)类似。
(5) 显示所设置的闹钟时间:在正常计时显示状态下,用户
直接按下“ALARM”键,则已设置的闹钟时间将显示在显示屏
上。
根据上述的设计要求,整个系统大致包括如下几个组成部
分:用于键盘输入的缓冲器;用于时钟计数的计数器;用于保
存闹钟时间的寄存器;用于显示的七段数码显示电路以及控制
以上各个部分协同工作的控制器。
第6章
VHDL设计应用实例
6.12.2 闹钟系统的控制器的设计
1.设计思路
控制器命名为ALARM_CONTROLLER,其外部端口如图
6.15所示。各端口的作用如下:
(1) CLK为外部时钟信号,RESET为复位信号。
(2) 当KEY为高电平(KEY= '1')时,表示用户按下数字键
(“0”~“9”)。
(3) 当ALARM_BUTTON为高电平时,表示用户按下
“ALARM”键。
(4) 当TIME_BUTTON为高电平时,表示用户按下“TIME”
键。
第6章
VHDL设计应用实例
ALARM_ CONTROLLER
KEY
ALARM_ BUTTON
TIME_ BUTTON
CLK
RESET
LOAD_NEW _A
LOAD_NEW _C
SHOW _NEW_ TIME
SHOW _A
图6.15 控制器的外部端口
第6章
VHDL设计应用实例
(5) 当LOAD_NEW_A 为高电平时,控制(闹钟时间寄存器)
加载新的闹钟时间值。
(6) 当LOAD_NEW_C为高电平时,控制(时钟计数器)设置
新的时间值。
(7) 当SHOW_NEW_TIME为高电平时,控制(七段数码显
示电路)显示新的时间值,即用户通过数字键输入的时间;否则,
当SHOW_NEW_TIME为低电平时,根据SHOW_A信号的值控
制显示当前时间或闹钟时间。此时,当SHOW_A为高电平时,
控制显示闹钟时间,否则,显示当前时间。
第6章
VHDL设计应用实例
控制器的功能可以通过有限状态自动机(FSM)的方式来实
现。根据设计要求及端口设置,需要5个状态来实现:
S0: 表示电路初态即正常时钟计数状态,完成前面设计功
能 (1) 的工作。
S1:接收键盘输入状态。在状态S0时用户按下数字键后进
入此状态。在此状态下,显示屏上显示的是用户键入的数字。
S2:设置新的闹钟时间。在状态S1时用户按下ALARM键
后进入此状态。
S3:设置新的计时器时间。在状态S1时用户按下TIME键后
进入此状态。
第6章
VHDL设计应用实例
S4:显示闹钟时间。在状态S0时用户直接按下ALARM键
后进入此状态。在此状态下, 显示屏上显示的是所设置的闹钟
时间。注意:在此状态下,用户按下ALARM键后,显示屏上
保持显示闹钟时间,经过一段时间以后,再返回状态S0显示计
时器时间。
第6章
VHDL设计应用实例
表6.1 控制器状态转换及控制输出表
当前状态
S0
控制输入(条件)
KEY = ‘1’
ALARM_BUTTON = ‘1’
否则
S1
KEY = ‘1’
ALARM_BUTTON = ‘1’
TIME_BUTTON = ‘1’
否
是
ALARM_BUTTON = ‘1’
否则
TIME_BUTTON = ‘1’
否则
ALARM_BUTTON = ‘1’
否
否则(超时)
是
否则(超时)
S2
S3
S4
下一状态
控制输出(动作)
S1
S4
S0
SHOW_NEW_TIME <= ‘1’
SHOW_A <= ‘1’
--
S1
S2
S3
S1
S0
S2
S0
S3
S0
S4
S4
S0
SHOW_NEW_TIME <= ‘1’
LOAD_NEW_A <= ‘1’
LOAD_NEW_C <= ‘1’
SHOW_NEW_TIME <= ‘1’, “超时”判断处理
-LOAD_NEW_A <= ‘1’
-LOAD_NEW_C <= ‘1’
-SHOW_A <= ‘1’
SHOW_A <= ‘1’, “超时”判断处理
--
第6章
VHDL设计应用实例
表6.1中没有显式说明的控制信号赋值,表示信号的值为
零。例如在状态S0,当信号KEY =‘1’时,SHOW_NEW_TIME
信号的赋值为‘1’,而其他信号LOAD_NEW_A,
LOAD_NEW_C和SHOW_A的值此时都赋为‘0’。另外,表中
关于“超时”判断处理的处理细节见VHDL源程序中的有关部
分。
第6章
VHDL设计应用实例
2.VHDL源程序
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE WORK.P_ALARM.ALL;
ENTITY ALARM_CONTROLLER IS
PORT(KEY :IN STD_LOGIC;
ALARM_BUTTON :IN STD_LOGIC;
TIME_BUTTON :IN STD_LOGIC;
CLK :IN STD_LOGIC;
RESET :IN STD_LOGIC;
LOAD_NEW_A :OUT STD_LOGIC;
LOAD_NEW_C :OUT STD_LOGIC;
SHOW_NEW_TIME :OUT STD_LOGIC;
SHOW_A :OUT STD_LOGIC
);
END ALARM_CONTROLLER;
第6章
VHDL设计应用实例
ARCHITECTURE ART OF ALARM_CONTROLLER IS
TYPE
T_STATE IS (S0, S1, S2, S3,S4);
CONSTANT KEY_TIMEOUT :T_SHORT := 500;
CONSTANT SHOW_ALARM_TIMEOUT : T_SHORT := 500;
SIGNAL CURR_STATE : T_STATE;
SIGNAL NEXT_STATE : T_STATE;
SIGNAL COUNTER_K : T_SHORT;
SIGNAL ENABLE_COUNT_K : STD_LOGIC;
SIGNAL COUNT_K_END : STD_LOGIC;
SIGNAL COUNTER_A : T_SHORT;
SIGNAL ENABLE_COUNT_A : STD_LOGIC;
SIGNAL COUNT_A_END : STD_LOGIC;
BEGIN
第6章
VHDL设计应用实例
PROCESS(CLK,RESET)
BEGIN
IF RESET ='1' THEN
CURR_STATE <= S0;
ELSIF RISING_EDGE(CLK) THEN
CURR_STATE <= NEXT_STATE;
END IF;
END PROCESS;
第6章
VHDL设计应用实例
PROCESS(KEY,ALARM_BUTTON,TIME_BUTTON,CURR_STATE,
COUNT_A_END,COUNT_K_END)
BEGIN
NEXT_STATE
<= CURR_STATE;
LOAD_NEW_A
<= '0';
LOAD_NEW_C
<= '0';
SHOW_A
<= '0';
SHOW_NEW_TIME <= '0';
ENABLE_COUNT_K <= '0';
ENABLE_COUNT_A <= '0';
第6章
VHDL设计应用实例
CASE CURR_STATE IS
WHEN S0 =>
IF (KEY = '1') THEN
NEXT_STATE <= S1;
SHOW_NEW_TIME <= '1';
ELSIF (ALARM_BUTTON = '1') THEN
NEXT_STATE <= S4;
SHOW_A <= '1';
ELSE
NEXT_STATE <= S0;
END IF;
WHEN S1 =>
IF (KEY = '1') THEN
NEXT_STATE <= S1;
第6章
VHDL设计应用实例
ELSIF (ALARM_BUTTON = '1') THEN
NEXT_STATE <= S2;
LOAD_NEW_A <= '1';
ELSIF (TIME_BUTTON = '1') THEN
NEXT_STATE <= S3;
LOAD_NEW_C <= '1';
ELSE
IF (COUNT_K_END = '1') THEN
NEXT_STATE <= S0;
ELSE
NEXT_STATE <= S1;
END IF;
ENABLE_COUNT_K <= '1';
END IF;
SHOW_NEW_TIME <= '1';
第6章
VHDL设计应用实例
WHEN S2 =>
IF (ALARM_BUTTON = '1') THEN
NEXT_STATE <= S2;
LOAD_NEW_A <= '1';
ELSE
NEXT_STATE <= S0;
END IF;
WHEN S3 =>
IF (TIME_BUTTON = '1') THEN
NEXT_STATE <= S3;
LOAD_NEW_C <= '1';
ELSE
NEXT_STATE <= S0;
第6章
VHDL设计应用实例
END IF;
WHEN S4 =>
IF (KEY = '1') THEN
NEXT_STATE <= S1;
ELSE
NEXT_STATE
<= S4;
IF (COUNT_A_END = '1') THEN
NEXT_STATE <= S0;
ELSE
NEXT_STATE <= S4;
SHOW_A <= '1';
第6章
VHDL设计应用实例
END IF;
ENABLE_COUNT_A <= '1';
END IF;
WHEN OTHERS =>
NULL;
END CASE;
END PROCESS;
第6章
VHDL设计应用实例
COUNT_KEY : PROCESS(ENABLE_COUNT_K, CLK)
BEGIN
IF (ENABLE_COUNT_K = '0') THEN
COUNTER_K <= 0;
COUNT_K_END <= '0';
ELSIF (RISING_EDGE(CLK)) THEN
IF (COUNTER_K >= KEY_TIMEOUT) THEN
COUNT_K_END <= '1';
ELSE
COUNTER_K <= COUNTER_K + 1;
END IF;
END IF;
END PROCESS;
第6章
VHDL设计应用实例
COUNT_ALARM : PROCESS(ENABLE_COUNT_A, CLK)
BEGIN
IF (ENABLE_COUNT_A = '0') THEN
COUNTER_A <= 0;
COUNT_A_END <= '0';
ELSIF RISING_EDGE(CLK) THEN
IF (COUNTER_A >= SHOW_ALARM_TIMEOUT) THEN
COUNT_A_END <= '1';
ELSE
COUNTER_A <= COUNTER_A + 1;
END IF;
END IF;
END PROCESS;
END ART;
第6章
VHDL设计应用实例
6.12.3 闹钟系统的译码器的设计
1.设计思路
本模块的功能是将每次按下闹钟系统的数字键盘后产生的
一个数字所对应的10位二进制数据信号转换为1位十进制整数
信号,以作为小时、分钟计数的4个数字之一,如图6.16所示。
其中KEYPAD为输入端口,接收10位二进制数据信号;
VALUE为输出端口,输出相应的1位十进制整数信号。输入数
据与输出数据的译码关系见表6.2。
第6章
VHDL设计应用实例
DECODER
KEYPAD
VALUE
图6.16 电路系统示意图
第6章
VHDL设计应用实例
表6.2 输入、输出数据的译码关系
输入
0000000001
0000000010
0000000100
0000001000
0000010000
输出
0
1
2
3
4
输入
0000100000
0001000000
0010000000
0100000000
1000000000
输出
5
6
7
8
9
第6章
VHDL设计应用实例
2.VHDL源程序
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE WORK.P_ALARM.ALL;
ENTITY DECODER IS
PORT(KEYPAD :IN STD_LOGIC_VECTOR(9 DOWNTO 0);
VALUE :OUT T_DIGITAL);
END DECODER;
ARCHITECTURE ART OF DECODER IS
BEGIN
第6章
VHDL设计应用实例
WITH KEYPAD SELECT
VALUE <= 0 WHEN “0000000001”,
1 WHEN “0000000010”,
2 WHEN “0000000100”,
3 WHEN “0000001000”,
4 WHEN “0000010000”,
5 WHEN “0000100000”,
6 WHEN “0001000000”,
7 WHEN “0010000000”,
8 WHEN “0100000000”,
9 WHEN “1000000000”,
0 WHEN OTHERS;
END ART;
第6章
VHDL设计应用实例
6.12.4 闹钟系统的移位寄存器的设计
1.设计思路
本模块的功能是在CLK端口输入信号的上升沿同步下,将
KEY端口的输入信号移入NEW_TIME 端口的输出信号最低位,
原有信息依次向左移,最高位信息丢失;而RESET端口的输入
信号对NEW_TIME端口输出信号进行异步清零复位。电路系统
示意图如图6.17所示。
第6章
VHDL设计应用实例
KEY_BUFFER
KEY
CLK
RESET
NEW_ TIME
图6.17 移位寄存器电路示意图
第6章
VHDL设计应用实例
2.VHDL源程序
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE WORK.P_ALARM.ALL;
ENTITY KEY_BUFFER IS
PORT(KEY :IN T_DIGITAL;
CLK :IN STD_LOGIC;
RESET :IN STD_LOGIC;
NEW_TIME:OUT T_CLOCK_TIME);
END KEY_BUFFER;
ARCHITECTURE ART OF KEY_BUFFER IS
SIGNAL N_T:T_CLOCK_TIME;
BEGIN
第6章
VHDL设计应用实例
SHIFT:PROCESS(RESET,CLK)
BEGIN
IF (RESET = '1') THEN
N_T <= (0,0,0,0);
ELSIF (CLK'EVENT AND CLK = '1' )THEN
FOR I IN 3 DOWNTO 1 LOOP
N_T(I) <= N_T(I-1);
END LOOP;
N_T(0) <= KEY;
END IF;
END PROCESS;
NEW_TIME <= N_T;
END ART;
第6章
VHDL设计应用实例
6.12.5 闹钟系统的闹钟寄存器和时间计数器的设计
1.电路系统工作原理
闹钟寄存器模块的功能是在时钟上升沿同步下,根据LOAD
_NEW _A端口的输入信号控制ALARM _TIME端口的输出,当控
制信号有效(高电平)时,把NEW _ALARM _TIME端口的输入信
号值输出;而RESET端口输入信号对ALARM _TIME 端口的输出
进行异步的清零复位。图6.18是闹钟寄存器模块的示意图。
闹钟系统的闹钟时间由闹钟寄存器保存和传递,而当前时间
由时间计数器保存、传递并按分钟累加推进。这两个组件的功能
和设计描述比较相似,它们之间的区别主要在于自动累加功能的
有无和控制信号的优先作用次序。
第6章
VHDL设计应用实例
ALARM_ REG
LOAD_ NEW_A
NEW_ ALARM_ TIME
CLK
ALARM_ TIME
RESET
图6.18 闹钟寄存器示意图
第6章
VHDL设计应用实例
时间计数器模块的功能是当RESET端口输入信号为高电平
时,对CURRENT _TIME端口输出信号清零复位;当LOAD
_NEW _C端口输入信号为高电平时,将
NEW_CURRENT_TIME端口的输入信号输出给
CURRENT_TIME端口。RESET端口D的控制优先于LOAD
_NEW _C端口。当这两个控制信号都无效时,在时钟上升沿同
步下,对CURRENT _TIME端口输出信号累加1,并根据小时、
分钟的规律处理进位。图6.19是时间计数器模块的示意图。
第6章
VHDL设计应用实例
ALAR M_ COUNTER
NEW_ CURRENT_TIME
LOAD_NEW _C
CLK
CURR ENT_ TIME
RESET
图6.19 时间计数器模块的示意图
第6章
VHDL设计应用实例
2.VHDL源程序
--时间计数器的源程序ALARM_COUNTER.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE WORK.P_ALARM.ALL;
ENTITY ALARM_COUNTER IS
PORT(NEW_CURRENT_TIME:IN T_CLOCK_TIME;
LOAD_NEW_C
CLK
RESET
:IN STD_LOGIC;
:IN STD_LOGIC;
:IN STD_LOGIC;
CURRENT_TIME
:OUT T_CLOCK_TIME);
第6章 VHDL设计应用实例
END ALARM_COUNTER;
ARCHITECTURE ART OF ALARM_COUNTER IS
SIGNAL I_CURRENT_TIME : T_CLOCK_TIME;
BEGIN
PROCESS(CLK,RESET,LOAD_NEW_C)
VARIABLE C_T:T_CLOCK_TIME;
BEGIN
IF RESET = '1' THEN
I_CURRENT_TIME <= (0,0,0,0);
ELSIF LOAD_NEW_C ='1' THEN
I_CURRENT_TIME <= NEW_CURRENT_TIME;
ELSIF RISING_EDGE(CLK) THEN
第6章
VHDL设计应用实例
C_T := I_CURRENT_TIME;
IF C_T(0) < 9 THEN
C_T(0) := C_T(0) + 1;
ELSE
C_T(0) := 0;
IF C_T(1) < 5 THEN
C_T(1) := C_T(1) + 1;
ELSE
C_T(1) := 0;
IF C_T(3) < 2 THEN
IF C_T(2) < 9 THEN
C_T(2) := C_T(2) + 1;
ELSE
C_T(2) := 0;
第6章
VHDL设计应用实例
C_T(3) := C_T(3) + 1;
END IF;
ELSE
IF C_T(2) < 3 THEN
C_T(2) := C_T(2) + 1;
ELSE
C_T(2) := 0;
C_T(3) := 0;
END IF;
END IF;
END IF;
END IF;
I_CURRENT_TIME <= C_T;
第6章
VHDL设计应用实例
END IF;
END PROCESS;
CURRENT_TIME <= I_CURRENT_TIME;
END ART;
--闹钟寄存器的源程序ALARM_REG.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE WORK.P_ALARM.ALL;
ENTITY ALARM_REG IS
PORT(NEW_ALARM_TIME:IN T_CLOCK_TIME;
LOAD_NEW_A :IN STD_LOGIC;
CLK :IN STD_LOGIC;
第6章
VHDL设计应用实例
RESET :IN STD_LOGIC;
ALARM_TIME :OUT T_CLOCK_TIME);
END ALARM_REG;
ARCHITECTURE ART OF ALARM_REG IS
BEGIN
PROCESS(CLK,RESET)
BEGIN
IF RESET = '1' THEN
ALARM_TIME <= (0,0,0,0);
ELSE
IF RISING_EDGE(CLK) THEN
IF LOAD_NEW_A = '1' THEN
ALARM_TIME <= NEW_ALARM_TIME;
第6章
VHDL设计应用实例
ELSIF LOAD_NEW_A /= '0' THEN
ASSERT FALSE REPORT“UNCERTAIN
LOAD_NEW_ALARM CONTROL!”
SEVERITY WARNING;
END IF;
END IF;
END IF;
END PROCESS;
END ART;
第6章
VHDL设计应用实例
6.12.6 闹钟系统的显示驱动器的设计
1.设计思路
本模块的功能是:当SHOW_NEW_TIME端口输入信号有效
(高电平)时,根据NEW_TIME端口输入信号(时间数据),产生相
应的4个七段数码显示器的驱动数据,并在DISPLAY端口输出该
信号。当SHOW_NEW_TIME端口输入信号无效(低电平)时,判断
SHOW_A端口的输入信号,为高电平时,根据ALARM_TIME端
口的输入信号(时间数据)产生相应的4个七段数码显示器的驱动数
据,并在DISPLAY端口输出该信号;为低电平时,根据
CURRENT_TIME端口的输入信号,对DISPLAY端口进行驱动。
当ALARM_TIME 端口的输入信号值与CURRENT_TIME端口的
输入信号值相同时,SOUND_ALARM端口的输出信号有效(高电
平),反之无效。图6.20为显示驱动器示意图。
第6章
VHDL设计应用实例
DISPLAY_DRIVER
NEW_ TIME
CURRENT_ TIME
ALARM_ TIME
SHOW_NEW _TIME
SHOW_A
DISPLAY
SOUND_ ALARM
图6.20 显示驱动器示意图
第6章
VHDL设计应用实例
2.VHDL源程序
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE WORK.P_ALARM.ALL;
ENTITY DISPLAY_DRIVER IS
PORT(ALARM_TIME :IN T_CLOCK_TIME;
CURRENT_TIME :IN T_CLOCK_TIME;
NEW_TIME :IN T_CLOCK_TIME;
SHOW_NEW_TIME:IN STD_LOGIC;
SHOW_A :IN STD_LOGIC;
SOUND_ALARM :OUT STD_LOGIC;
DISPLAY:OUT T_DISPLAY);
第6章
VHDL设计应用实例
END DISPLAY_DRIVER;
ARCHITECTURE ART OF DISPLAY_DRIVER IS
SIGNAL DISPLAY_TIME:T_CLOCK_TIME;
BEGIN
CTRL:PROCESS(ALARM_TIME,CURRENT_TIME,
NEW_TIME,SHOW_A,SHOW_NEW_TIME)
BEGIN
SOUND_LP: FOR I IN ALARM_TIME'RANGE LOOP
IF NOT(ALARM_TIME(I) = CURRENT_TIME(I)) THEN
SOUND_ALARM <= '0';
EXIT SOUND_LP;
第6章
ELSE
VHDL设计应用实例
SOUND_ALARM <= '1';
END IF;
END LOOP SOUND_LP;
IF SHOW_NEW_TIME = '1' THEN
DISPLAY_TIME <= NEW_TIME;
ELSIF SHOW_A = '1' THEN
DISPLAY_TIME <= ALARM_TIME;
ELSIF SHOW_A = '0' THEN
DISPLAY_TIME <= CURRENT_TIME;
ELSE
ASSERT FALSE REPORT “UNCERTAIN
DISPLAY_DRIVER CONTROL!”
第6章
VHDL设计应用实例
SEVERITY WARNING;
END IF;
END PROCESS;
DISP:PROCESS(DISPLAY_TIME)
BEGIN
FOR I IN DISPLAY_TIME'RANGE LOOP
DISPLAY(I) <= SEVEN_SEG(DISPLAY_TIME(I));
END LOOP;
END PROCESS;
END ART;
第6章
VHDL设计应用实例
6.12.7 闹钟系统的分频器的设计
1.设计思路
本模块的功能是将CLK_IN端口输入的时钟信号分频后送给
CLK_OUT端口。当RESET端口输入信号有效(高电平)时,
CLK_OUT端口输出信号清零。图6.21为分频器示意图。
第6章
VHDL设计应用实例
FQ_ DIVIDER
CLK_IN
RESET
CLK_OUT
图6.21 分频器示意图
第6章
VHDL设计应用实例
2.VHDL源程序
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE WORK.P_ALARM.ALL;
ENTITY FQ_DIVIDER IS
PORT(
CLK_IN
:IN STD_LOGIC;
RESET
:IN STD_LOGIC;
CLK_OUT
:OUT STD_LOGIC );
END FQ_DIVIDER;
ARCHITECTURE ART OF FQ_DIVIDER IS
第6章
VHDL设计应用实例
CONSTANT DIVIDE_PERIOD : T_SHORT := 6000;
BEGIN
DIVIDE_CLK: PROCESS(CLK_IN,RESET)
VARIABLE CNT : T_SHORT;
BEGIN
IF (RESET = '1') THEN
CNT := 0;
CLK_OUT <= '0';
ELSIF RISING_EDGE(CLK_IN) THEN
IF (CNT < (DIVIDE_PERIOD/2)) THEN
CLK_OUT <= '1';
第6章
VHDL设计应用实例
CNT := CNT + 1;
ELSIF (CNT < (DIVIDE_PERIOD-1)) THEN
CLK_OUT <= '0';
CNT := CNT + 1;
ELSE
CNT := 0;
END IF;
END IF;
END PROCESS; -- DIVIDE CLK
END ART;
第6章
VHDL设计应用实例
6.12.8 闹钟系统的整体组装
1.整体组装说明
前边已经完成了计时器各个组成部分的设计,下面把这些
组成部分组装起来,形成完整的总体设计。该计时器命名为
ALARM_CLOCK,其外部端口如图6.22所示。
第6章
VHDL设计应用实例
ALARM_ CLOC K
KEYPAD
KEY_DOWN
ALARM_ BUTTON
TIME_ BUTTON
CLK
RESET
DISPLAY
SOUND_ ALARM
图6.22 计时器的外部端口
第6章
VHDL设计应用实例
各个输入输出端口的作用如下:
(1) CLK为外部时钟信号,RESET为复位信号。
(2) KEYPAD是一个10位信号,若其中某一位为高电平,
则表示用户按下了相应下标的数字键。例如,若KEYPAD(5)
= '1',表示用户按下了数字键“5”。本设计不考虑用户同时按
下多个数字键的情况,所以任意时刻KEYPAD中只能有一位
为‘1’。
(3) 当KEYDOWN为高电平时(KEYDOWN= '1'),表示用户
按下某一数字键。
第6章
VHDL设计应用实例
(4) 当ALARM_BUTTON为高电平时,表示用户按下
ALARM键。
(5) 当TIME_BUTTON为高电平时,表示用户按下TIME键。
(6) DISPLAY实际上表示了4个七段数码显示管,用于显示
时间,如12:20。
(7) SOUND_ALARM用于控制扬声器发声,当
SOUND_ALARM = '1' 时,扬声器发出蜂鸣,表示到了设定的
闹钟时间。
设计的总体结构图如图6.23所示。
第6章
VHDL设计应用实例
图6.23 总体结构
第6章
VHDL设计应用实例
下面再简要说明各组成部分的功能:
(1) 译码器(DECODER) 可将KEYPAD信号转换为0~9的整型
数,以直观地表示和处理用户输入的数字。
(2) 键盘缓冲器(KEY_BUFFER)是一个移位寄存器,暂存用
户键入的数字,并且实现用户键入数字在显示器上从右到左的
依次显示。这里需要注意的是,由图6.23可以看出,
KEY_BUFFER的时钟端连接的是外部KEY_DOWN 信号。这表
示用户每输入一个数字,KEY_BUFFER移位一次。
第6章
VHDL设计应用实例
(3) 分频器(FQ_DIVIDER)将较高速的外部时钟频率分频成
每分钟一次的时钟频率,以便进行时钟计数。
(4) 计数器(ALARM_COUNTER)实际上是一个异步复位、
异步置数的累加器,通常情况下进行时钟累加计数,必要时可
置入新的时钟值,然后从该值开始新的计数。
(5) 寄存器(ALARM_REG)用于保存用户设置的闹钟时间,
是一个异步复位寄存器。
第6章
VHDL设计应用实例
(6) 显示器(DISPLAY_DRIVER)根据需要显示当前时间、
用户设置的闹钟时间或用户通过键盘输入的新的时间,同时判
断当前时间是否已到了闹钟时间,实际上是一个多路选择器加
比较器。
(7) 控制器(ALARM_CONTROLLER)是设计的核心部分,
按设计要求产生相应的控制逻辑,以控制其他各部分的工作。
第6章
VHDL设计应用实例
2.VHDL源程序
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE WORK.P_ALARM.ALL;
ENTITY ALARM_CLOCK IS
PORT(KEYPAD :IN STD_LOGIC_VECTOR(9 DOWNTO 0);
KEY_DOWN :IN STD_LOGIC;
ALARM_BUTTON:IN STD_LOGIC;
TIME_BUTTON :IN STD_LOGIC;
CLK :IN STD_LOGIC;
RESET :IN STD_LOGIC;
DISPLAY :OUT T_DISPLAY;
SOUND_ALARM :OUT STD_LOGIC);
END ALARM_CLOCK;
第6章
VHDL设计应用实例
ARCHITECTURE ART OF ALARM_CLOCK IS
COMPONENT DECODER --待调用元件端口定义
PORT(KEYPAD:IN STD_LOGIC_VECTOR(9 DOWNTO 0);
VALUE :OUT T_DIGITAL);
END COMPONENT;
COMPONENT KEY_BUFFER --待调用元件端口定义
...
COMPONENT ALARM_COUNTER --待调用元件端口定义
...
COMPONENT ALARM_REG --待调用元件端口定义
...
COMPONENT ALARM_CONTROLLER --待调用元件端口定义
...
第6章
VHDL设计应用实例
COMPONENT DISPLAY_DRIVER --待调用元件端口定义
...
COMPONENT FQ_DIVIDER --待调用元件端口定义
...
SIGNAL INNER_KEY : T_DIGITAL;
SIGNAL INNER_TIME : T_CLOCK_TIME;
SIGNAL INNER_TIME_C : T_CLOCK_TIME;
SIGNAL INNER_TIME_A : T_CLOCK_TIME;
SIGNAL INNER_L_C : STD_LOGIC;
SIGNAL INNER_L_A : STD_LOGIC;
SIGNAL INNER_S_A : STD_LOGIC;
SIGNAL INNER_S_N : STD_LOGIC;
SIGNAL INNER_SEC_CLK : STD_LOGIC;
第6章
VHDL设计应用实例
FOR ALL: DECODER USE ENTITY WORK.DECODER(ART);
FOR ALL: KEY_BUFFER USE ENTITY
WORK.KEY_BUFFER(ART);
FOR ALL: ALARM_COUNTER USE ENTITY
WORK.ALARM_COUNTER(ART);
FOR ALL: ALARM_REG USE ENTITY
WORK.ALARM_REG(ART);
FOR ALL: ALARM_CONTROLLER USE ENTITY
WORK.ALARM_CONTROLLER(ART);
FOR ALL: DISPLAY_DRIVER USE ENTITY
WORK.DISPLAY_DRIVER(ART);
F OR ALL: FQ_DIVIDER USE ENTITY WORK.FQ_DIVIDER(ART);
第6章
VHDL设计应用实例
BEGIN
U1: DECODER PORT MAP(KEYPAD,INNER_KEY);
U2: KEY_BUFFER PORT MAP(INNER_KEY, KEY_DOWN, RESET,
INNER_TIME);
U3: ALARM_CONTROLLER PORT MAP(KEY_DOWN,
ALARM_BUTTON,TIME_BUTTON,CLK,RESET, INNER_L_A,
INNER_L_C, INNER_S_N, INNER_S_A );
U4: ALARM_COUNTER PORT MAP( INNER_TIME, INNER_L_C,
INNER_SEC_CLK,
RESET, INNER_TIME_C);
U5: ALARM_REG PORT MAP(INNER_TIME,INNER_L_A,CLK,
RESET,INNER_TIME_A);
U6: DISPLAY_DRIVER PORT MAP( INNER_TIME_A,INNER_TIME_C,
INNER_TIME,
INNER_S_N, INNER_S_A, SOUND_ALARM,DISPLAY );
U7: FQ_DIVIDER PORT MAP(CLK,RESET,INNER_SEC_CLK);
END ART;
第6章
VHDL设计应用实例
6.12.9 闹钟系统的硬件验证
若用GW48型EDA实验开发系统进行硬件验证,考虑到实
验开发系统提供的输入信号按键的有限,可将输入数字按键
0~9改为一个按键,该按键的信号作为一个8421码信号发生器
的输入,由8421码信号发生器输出数字0~9。具体验证方案由
读者自行完成。