资源描述
数字电路与逻辑设计·实验报告
北京邮电大学
实 验 报 告
实验名称:数码管扫描显示控制器设计与实现
学 院:信息与通信工程学院
班 级: 2011XXXXXX
姓 名: XXX
学 号:
日 期: 2013年5月
一.实验目的
1. 掌握VHDL语言的语法规范,掌握时序电路描述方法
2. 掌握多个数码管动态扫描显示的原理及设计方法
二.实验所用仪器及元器件
1. 计算机
2. 直流稳压电源
3. 数字系统与逻辑设计实验开发板
三.实验任务要求
1. 用VHDL语言设计并实现六个数码管串行扫描电路,要求同时显示0,1,2,3,4,5这六个不同的数字图形到六个数码管上,仿真下载验证其功能。
2. 用VHDL语言设计并实现六个数码管滚动显示电路。(选作)
I. 循环滚动,始终点亮6个数码管,左出右进。状态为:012345-123450-234501-345012-450123-501234-012345
II. 向左滚动,用全灭的数码管充右边,直至全部变灭,然后再依次从右边一个一个地点亮。状态为:012345-12345X-2345XX-345XXX-45XXXX-5XXXXX-XXXXXX-XXXXX0-XXXX01-XXX012-XX0123-X01234-012345,其中’X’表示数码管不显示。
四.实验设计思路及过程
1.实验原理
为使得输入控制电路简单且易于实现,采用动态扫描的方式实现设计要求。动态扫描显示需要由两组信号来控制:一组是字段输出口输出的字形代码,用来控制显示的字形,称为段码;另一组是位输出口输出的控制信号,用来选择第几位数码管工作,称为位码。
各位数码管的段线并联,段码的输出对各位数码管来说都是相同的。因此在同一时刻如果各位数码管的位选线都处于选通状态的话,6位数码管将显示相同的字符。若要各位数码管能够显示出与本位相应的字符,就必须采用扫描显示方式,即在某一时刻,只让某一位的位选线处于导通状态,而其它各位的位选线处于关闭状态。同时,段线上输出相应位要显示字符的字型码。这样在同一时刻,只有选通的那一位显示出字符,而其它各位则是熄灭的,如此循环下去,就可以使各位数码管显示出将要显示的字符。
虽然这些字符是在不同时刻出现的,而且同一时刻,只有一位显示,其它各位熄灭,但由于数码管具有余辉特性和人眼有视觉暂留现象,只要每位数码管显示间隔足够短,给人眼的视觉印象就会是连续稳定地显示。
总之,多个数码管动态扫描显示,是将所有数码管的相同段并联在一起,通过选通信号分时控制各个数码管的公共端,循环一次点亮多个数码管,并利用人眼的视觉暂留现象,只要扫描的频率大于50Hz,将看不到闪烁现象。6个数码管则需要50*6=300Hz以上才能看到持续稳定点亮的现象。
2.设计思路
设计时序电路,选用模值为6的计数器,通过一个3线至6线译码器,产生段码,依次控制6个LED的亮灭,使得某一时刻有且仅有一个LED点亮,同时产生对应的,将点亮的LED数码管赋值显示为相应的数码予以显示。由于扫描频率较高,6位LED数码管序列将显示持续稳定的0至5的数码。
3.VHDL代码
A.实验任务1
①实现代码
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY GKY07P14 IS
PORT(clk,clear:IN STD_LOGIC;
q:OUT STD_LOGIC_VECTOR(6 DOWNTO 0);
countout:OUT STD_LOGIC_VECTOR(5 DOWNTO 0));
END GKY07P14;
ARCHITECTURE behave OF GKY07P14 IS
SIGNAL q_temp:STD_LOGIC_VECTOR(6 DOWNTO 0);
SIGNAL count:STD_LOGIC_VECTOR(5 DOWNTO 0);
SIGNAL cnt:INTEGER RANGE 0 TO 5;
BEGIN
p1:PROCESS(clk)
BEGIN
IF(clk'EVENT AND clk='1')THEN
IF(cnt=5)THEN cnt<=0;
ELSE
cnt<=cnt+1;
END IF;
END IF;
END PROCESS;
p2:PROCESS(cnt)
BEGIN
IF(clear='0')THEN count<="111111";
ELSE
CASE cnt IS
WHEN 1=>count<="101111";q_temp<="0110000";
WHEN 2=>count<="110111";q_temp<="1101101";
WHEN 3=>count<="111011";q_temp<="1111001";
WHEN 4=>count<="111101";q_temp<="0110011";
WHEN 5=>count<="111110";q_temp<="1011011";
WHEN 0=>count<="011111";q_temp<="1111110";
END CASE;
END IF;
END PROCESS;
countout<=count;
q<=q_temp;
END behave;
②代码说明
通过分频器输入产生选通脉冲,控制0至5号LED数码管依次亮灭,同时使用数码显示信号使得数码管显示相应数码。实现时通过连接引入分频信号,通过数据选择器选择数码管。计数器信号触发数据选择器,赋值给位码触发数码管显示数码。最终实现动态扫描显示数字序列。
B.实验任务2-I
①实现代码
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY GKY07P14 IS
PORT( clk,clear:IN STD_LOGIC;
q:OUT STD_LOGIC_VECTOR(6 DOWNTO 0);
countout:OUT STD_LOGIC_VECTOR(5 DOWNTO 0));
END GKY07P14;
ARCHITECTURE behave OF GKY07P14 IS
SIGNAL q_temp:STD_LOGIC_VECTOR(6 DOWNTO 0);
SIGNAL count:STD_LOGIC_VECTOR(5 DOWNTO 0);
SIGNAL cnt,cnt1:INTEGER RANGE 0 TO 5;
SIGNAL tmp:INTEGER RANGE 0 TO 15999;
signal clk1:STD_LOGIC;
BEGIN
p0:PROCESS(clk,clear)
BEGIN
IF clear='0' THEN tmp<=0;
ELSIF clk'EVENT AND clk='1' THEN
IF tmp=15999 THEN
tmp<=0;
ELSE
tmp<=tmp+1;
END IF;
END IF;
END PROCESS p0;
p1:PROCESS(tmp)
BEGIN
IF clk'EVENT AND clk='1' THEN
IF tmp<1000 THEN
clk1<='0';
ELSE
clk1<='1';
END IF;
END IF;
END PROCESS p1;
p2:PROCESS(clk)
BEGIN
IF(clk'EVENT AND clk='1')THEN
IF(cnt=5)THEN cnt<=0;
ELSE
cnt<=cnt+1;
END IF;
END IF;
END PROCESS p2;
p3:PROCESS(clk1)
BEGIN
IF(clk1'EVENT AND clk1='1')THEN
IF(cnt1=5)THEN cnt1<=0;
ELSE
cnt1<=cnt1+1;
END IF;
END IF;
END PROCESS p3;
p4:PROCESS(cnt,cnt1)
BEGIN
IF(clear='0')THEN q_temp<="0000000";
ELSE
CASE cnt+cnt1 IS
WHEN 0=>q_temp<="1111110";
WHEN 1=>q_temp<="0110000";
WHEN 2=>q_temp<="1101101";
WHEN 3=>q_temp<="1111001";
WHEN 4=>q_temp<="0110011";
WHEN 5=>q_temp<="1011011";
WHEN 6=>q_temp<="1111110";
WHEN 7=>q_temp<="0110000";
WHEN 8=>q_temp<="1101101";
WHEN 9=>q_temp<="1111001";
WHEN 10=>q_temp<="0110011";
WHEN 11=>q_temp<="1011011";
WHEN OTHERS =>q_temp<="0000000";
END CASE;
END IF;
END PROCESS p4;
q<=q_temp;
p5:PROCESS(cnt)
BEGIN
IF(clear='0')THEN count<="111111";
ELSE
CASE cnt IS
WHEN 0=>count<="011111";
WHEN 1=>count<="101111";
WHEN 2=>count<="110111";
WHEN 3=>count<="111011";
WHEN 4=>count<="111101";
WHEN 5=>count<="111110";
WHEN OTHERS =>count<="111111";
END CASE;
END IF;
END PROCESS p5;
countout<=count;
END behave;
②代码说明
代码主体和实验任务1中一致,基本思想也一致。为实现移位,关键改动为新增一个计数器,技术周期远远大于扫描周期,这样,在一个大的计数周期内,对于要显示的6位数码进行动态扫描(和实验任务1中相同),显示出6种移位状态中的一种;通过计数器,实现循环移位。
C.实验任务2-II
①实现代码
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY GKY07P14 IS
PORT( clk,clear:IN STD_LOGIC;
q:OUT STD_LOGIC_VECTOR(6 DOWNTO 0);
countout:OUT STD_LOGIC_VECTOR(5 DOWNTO 0));
END GKY07P14;
ARCHITECTURE behave OF GKY07P14 IS
SIGNAL q_temp:STD_LOGIC_VECTOR(6 DOWNTO 0);
SIGNAL count:STD_LOGIC_VECTOR(5 DOWNTO 0);
SIGNAL cnt,cnt1:INTEGER RANGE 0 TO 11;
SIGNAL tmp:INTEGER RANGE 0 TO 15999;
signal clk1:STD_LOGIC;
BEGIN
p0:PROCESS(clk,clear)
BEGIN
IF clear='0' THEN tmp<=0;
ELSIF clk'EVENT AND clk='1' THEN
IF tmp=15999 THEN
tmp<=0;
ELSE
tmp<=tmp+1;
END IF;
END IF;
END PROCESS p0;
p1:PROCESS(tmp)
BEGIN
IF clk'EVENT AND clk='1' THEN
IF tmp<1000 THEN
clk1<='0';
ELSE
clk1<='1';
END IF;
END IF;
END PROCESS p1;
p2:PROCESS(clk)
BEGIN
IF(clk'EVENT AND clk='1')THEN
IF(cnt=11)THEN cnt<=0;
ELSE
cnt<=cnt+1;
END IF;
END IF;
END PROCESS p2;
p3:PROCESS(clk1)
BEGIN
IF(clk1'EVENT AND clk1='1')THEN
IF(cnt1=11)THEN cnt1<=0;
ELSE
cnt1<=cnt1+1;
END IF;
END IF;
END PROCESS p3;
p4:PROCESS(cnt,cnt1)
BEGIN
IF(clear='0')THEN q_temp<="0000000";
ELSE
CASE cnt+cnt1 IS
WHEN 6=>q_temp<="1111110";
WHEN 7=>q_temp<="0110000";
WHEN 8=>q_temp<="1101101";
WHEN 9=>q_temp<="1111001";
WHEN 10=>q_temp<="0110011";
WHEN 11=>q_temp<="1011011";
WHEN OTHERS =>q_temp<="0000000";
END CASE;
END IF;
END PROCESS p4;
q<=q_temp;
p5:PROCESS(cnt)
BEGIN
IF(clear='0')THEN count<="111111";
ELSE
CASE cnt IS
WHEN 0=>count<="011111";
WHEN 1=>count<="101111";
WHEN 2=>count<="110111";
WHEN 3=>count<="111011";
WHEN 4=>count<="111101";
WHEN 5=>count<="111110";
WHEN OTHERS =>count<="111111";
END CASE;
END IF;
END PROCESS p5;
countout<=count;
END behave;
②代码说明
此处为关键部分代码,其余代码同实验任务2-I中基本相同。实现基本思路为:先左移位,方法同实验任务2-I,进行加运算,稍有不同为左移出的数码不从右移入,因而没有取余运算,大于6的数码状态为灭灯,实现了左移且右端数码依次熄灭。待全部灯熄灭后数码依次从右移入,此时进行减运算,右端数码最先达到0,显示数码“0”,然后是右端第二位达到0,显示数码“0”,右端第一位为1,显示数码“1”,其余灯灭,以此类推,实现了右端逐位移入数码的功能。
五.仿真波形及分析
1.仿真波形
1.实验任务1
2.实验任务2-I
3.实验任务2-II
3.波形分析
1实验任务1
clear为高电平时,六个数码管串行扫描。num[n]分别对应着数码管的7段,数码管高电平为亮,低电平暗。Catn为低电平时,数字n即通过num[n]显示。比如,数字5,cat“111110”num=“1011011”.只要数码管闪烁频率足够高,就可以看到六个数码管分别显示0-5六个不同的数字. clear为低电平时,有效,波形清零.
2.实验任务2-I
因为要实现的是循环左滚动,且状态转移的顺序是012345->123450->234501->345012->450123->501234->012345共六个状态.从图中可以清楚地看出这六个状态转移过程中, 发光二极管管脚的变化情况.输入时钟信号后,6个数码管的选通控制端在同一时刻始终保持一个低电平其余高电平,在0-5对应的数码管上输出实验设定的数字并且由地位向高位依次循环移动.
3.实验任务2-II
由波形图可以清楚地看到12个状态的波形,当时钟clk变化一些周期之后,波形就转到下一个状态.如图所示.状态转移关系: 012345->12345X->2345XX->345XXX->45XXXX->5XXXXXX->XXXXXX->XXXXX0 ->XXXX01->XXX012->XX0123->X01234->012345
六.故障及问题分析
我在课前完成了代码的编写,刚开始时使用枚举法,虽然原理简单易于编写,但代码较为冗长。后来在一位同学的启发下尝试用上述方法编写,代码大为简化。并且在课前仿真,波形都没有问题。但在课上下载时却遇见了问题。第一个没有问题,第二个出现的问题是:能够实现显示数字的左移,但无法同时显示所有的数据,只能显示当前状态下的数码管所显示的数据。出现这种现象,说明时钟频率的选择有问题,同时也解释了为什么仿真时没有问题。因为时钟频率选得太低,所以在人眼看来,数字无法全部显示。通过添加中间变量cnt,最终解决了这个问题。
七.实验总结与结论
经过逻辑分析,编写VHDL代码,然后调试,进行波形仿真,最后下载到实验板实现,一系列工序之后,成功实现了本实验。我深深的感受到进行数字电路实验,理论分析是十分重要的一环,只有逻辑分析透彻无误了,才能用语言进行描述,进而用硬件实现。这次实验让我对VHDL这样一门硬件描述语言有了更加深刻的认识。语言是描述设计者逻辑思想的,有什么样的逻辑思维就会产生什么样的代码,换句话说,逻辑思维错误将直接导致描述错误,进而不能实现数字逻辑。应该着重优化逻辑思维,才能写出优秀的硬件代码。而硬件描述语言的学习,不同于一般编程语言的描述,它没有汇编那样深入硬件最底层,但从硬件抽象出来的逻辑却与硬件密不可分。编写硬件描述代码,不仅要符合基本编程语言的规范,更应该时时刻刻联系实现功能的硬件,理解时序和组合的关系,理解同步和异步的差异,理解进程和信号的流程等等,这样才能使写出的代码效率更高。这学期数字电路实验就这样结束了,我在实验操作能力有所提升的同时也更深的理解了数字电路与逻辑设计的理论知识,也体会到了数字电路的强大功能。
第16页
展开阅读全文