报告论文:BCD 计数器 数字钟
实验一 组合逻辑电路设计
一、 设计目的
熟悉MAX+plusII的VHDL文本设计流程全过程,学习简单组合逻辑电路的设计﹑多层次电路设计﹑仿真和测试。
二、 设计要求
译码器显示电路设计:
1.设计3-8译码器电路,输入用拔码开关,输出用发光二极管显示。
2.设计BCD-七段译码显示电路,输入用拔码开关,输出用数码管。
3.结合以上两个设计完成两位数码管的显示电路,要求显示00-99。
三、 设计方案与分析
要求一是要设计一个3-8译码器电路,根据数字逻辑课程中所学的知识我们很容易知道该电路的输入–输出关系,即输出要将输入的3位BCD码译成8位二进制码。这样的功能可以用很多串行语句在一个进程中实现,当然也可以用并行语句实现。我选择了在进程中用case语句实现。思想很简单,基本就是用枚举法将所有的输入–输出对应关系描述出来就可以了。题目二是要求设计一个BCD码数码管显示电路,思想同上,选用拨码开关控制输入。设计三要求用两个数码管动态显示“00”到“99”。难点在于如何动态显示。经过老师的指导,我知道动态显示的关键是要用一个人眼很难区分的时钟频率让两个数码管闪烁显示,人眼无法识别,看上去就像是两个数码管同时显示一样。具体设计方法是用8个拨码开关分别控制两个数码管的置数,用时钟的两个逻辑值——“0”和“1”控制片选端的选择信号的值达到动态显示的目的。
四、 硬件测试
任务一的电路在实验箱上有3个输入(SEL0~SEL2)和8个输出(Y7~Y0),定义引脚后下载到芯片。输入接2个拨码开关,以开关的高低控制输入电平的高低,也即是逻辑1和0。而输出则接8个发光二极管,当用开关控制高低电平的输入时,发光二极管就会依次译码显示,高电平对应的二极管亮,整个二极管即为译出的二进制码。任务二输入有4个,也是用拨码开关控制,译码结果则用数码管显示,这样的显示更直观,我们可以容易地看到0到9的显示。任务三的输入端有9个,8个拨码开关分别控制两个数码管的译码显示,另外一个输入是1024Hz的脉冲输入端,用于控制片选。观察的结果是两个数码管同时点亮,通过拨码开关可以控制两个数码管显示“00”到“99”。
五、 设计源代码
1. 3-8译码器VHDL设计源代码
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY DECODER IS
PORT(
A :IN STD_LOGIC_VECTOR(2 DOWNTO 0);
Y :OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END DECODER;
ARCHITECTURE A OF DECODER IS
SIGNAL SEL:STD_LOGIC_VECTOR(2 DOWNTO 0);
BEGIN
SEL(0)<=A(0);
SEL(1)<=A(1);
SEL(2)<=A(2);
PROCESS(SEL)
BEGIN
CASE A IS
WHEN “000”=> Y<=”00000001″;
WHEN “001”=> Y<=”00000010″;
WHEN “010”=> Y<=”00000100″;
WHEN “011”=> Y<=”00001000″;
WHEN “100”=> Y<=”00010000″;
WHEN “101”=> Y<=”00100000″;
WHEN “110”=> Y<=”01000000″;
WHEN “111”=> Y<=”10000000″;
WHEN OTHERS=>NULL;
END CASE;
END PROCESS;
END A;
2. BCD-七段译码显示电路VHDL源代码
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY DECODER47 IS
PORT(
D: IN STD_LOGIC_VECTOR(3 DOWNTO 0);
SEG:OUT STD_LOGIC_VECTOR(6 DOWNTO 0)
);
END DECODER47;
ARCHITECTURE STR OF DECODER47 IS
BEGIN
SEG<=”0111111″ WHEN D=0 ELSE
“0000110” WHEN D=1 ELSE
“1011011” WHEN D=2 ELSE
“1001111” WHEN D=3 ELSE
“1100110” WHEN D=4 ELSE
“1101101” WHEN D=5 ELSE
“1111101” WHEN D=6 ELSE
“0000111” WHEN D=7 ELSE
“1111111” WHEN D=8 ELSE
“1101111” WHEN D=9 ELSE
“0000000” ;
END STR;
3.用两个数码管动态显示“00”到“99”电路VHDL源代码
Library IEEE;
Use IEEE.Std_Logic_1164.All;
Entity muxdecoder Is
Port(a:In std_Logic_Vector(3 downto 0);
b:In Std_Logic_Vector(3 downto 0);
clk:In Std_Logic;
y:out Std_Logic_Vector(6 downto 0);
sel:Out std_Logic_Vector(2 downto 0));
End Entity muxdecoder;
Architecture behaviour Of muxdecoder Is
Begin
Process(clk,a,b)
Begin
If clk=\’1\’ Then
sel<=”001″;
Case a Is
When “0000”=>y<=”0111111″;
When “0001”=>y<=”0000110″;
When “0010”=>y<=”1011011″;
When “0011”=>y<=”1001111″;
When “0100”=>y<=”1100110″;
When “0101”=>y<=”1101101″;
When “0110”=>y<=”1111101″;
When “0111”=>y<=”0000111″;
When “1000”=>y<=”1111111″;
When “1001”=>y<=”1101111″;
When “1010”=>y<=”1110111″;
When Others=>NULL;
End Case;
Else
sel<=”010″;
Case B Is
When “0000”=>y<=”0111111″;
When “0001”=>y<=”0000110″;
When “0010”=>y<=”1011011″;
When “0011”=>y<=”1001111″;
When “0100”=>y<=”1100110″;
When “0101”=>y<=”1101101″;
When “0110”=>y<=”1111101″;
When “0111”=>y<=”0000111″;
When “1000”=>y<=”1111111″;
When “1001”=>y<=”1101111″;
When “1010”=>y<=”1110111″;
When Others=>NULL;
End Case;
End If;
END PROCESS;
End behaviour;
六、 仿真图
1. 3-8译码器波形仿真图
图1-1
2.七段数码管译码显示波形仿真图
图1-2
七、 设计心得与感想
通过此次学习,在对EDA工具有了一定的了解的基础上,对MAX+plusII软件也有了较熟练的操作,为以后深入的学习打下了基础。本次实验的课题不是很难,用上了以前学过的数字电路与逻辑设计知识,它说明了EDA这门课程并不是孤立的,是和其他很多课程都相通的,这为学习也增添了很多趣味,同时对平时学过的书本知识也是一个很好的实践机会。
实验二时序逻辑电路设计
一、 设计目的
1. 学习简单时序逻辑电路的设计﹑仿真和测试;
2. 学习并掌握状态机的设计方法在时序逻辑电路设计中的应用;
3. 掌握计数器的设计方法。
二、 设计要求
设计计数器
1.异步复位同步置数的十进制计数器;
2.用状态机实现上一个设计;
3.设计BCD码的60进制计数器并显示。
三、 设计方案与分析
对于设计要求1,我们用基本的顺序语句(IF语句)就可以实现。在设计置数功能时我主要是用了一个置数使能端,用拨码开关控制,不能置数时就正常计数,当控制置数时就停止正常计数。用状态机实现时主要是设计计数器的几个状态,同时要注意时序逻辑进程和组合逻辑进程间的联系。在设计60进制计数器时我采用了两种方案,一种是原理图的设计方案,及设计好一个六进制计数器和一个十进制计数器,然后按照60进制计数器的功能将它们连起来。另一种方法是用文本输入的方式,即在一个VHDL程序段中控制计数器的十位和个位。下图(图2-1)是用方案1设计时的原理图,图中主要有十进制计数器CNT10模块、六进制计数器CNT6模块、无进位的二进制计数器CN2模块、二选一选择器SEL2模块、译码显示DISP模块,其中CNT10、CNT6、DISP模块代码与数字钟代码相同,SEL2模块和CN2模块代码见附录。文本输入方式的代码见下面的设计源代码。
图2-1 60进制计数器设计原理图
四、 硬件测试
任务一和二的测试过程是一样的,两者都有7个输入端,分别是计数脉冲、复位端、置数使能端和置数端。我选用的计数脉冲为秒脉冲,复位断、置数使能端、置数端都接拨码开关。测试时先将置数端开关打为高电平,这时正常计数停止,开始置数,通过拨码开关可以置0到9间任一数,然后将置数开关打为低电平,计数器正常计数。当把控制复位的开关打为高电平时数码管显示0。以上的测试结果达到预计设计指标。任务三测试过程类似,只是多了一个1024Hz脉冲的输入端。
五、 设计源代码
1.带有置数功能的十进制计数器设计VHDL源代码
LIBRARY IEEE;
Use IEEE.Std_Logic_1164.ALL;
Use IEEE.Std_Logic_Unsigned.All;
Entity cnt10 Is
Port(clk,rst,EN:In Std_Logic;
sdata:In Std_Logic_Vector(3 downto 0);
seg:Out Std_Logic_Vector(6 downto 0);
cout:Out Std_Logic);
End cnt10;
Architecture behav Of cnt10 Is
signal s:Std_Logic_Vector(3 downto 0);
Begin
Process(clk,rst,sdata)
variable QI:Std_Logic_Vector(3 downto 0);
Begin
If rst=\’1\’ Then
QI:=(Others=>\’0\’);
Elsif clk\’event and clk=\’1\’ Then
If EN=\’1\’ THEN
QI:=sdata;
elsif EN=\’0\’ then
If QI<9 Then
QI:=QI+1;
Else QI:=(Others=>\’0\’);
End If;
End IF;
End If;
If QI=9 Then
cout<=\’1\’;
Else
cout<=\’0\’;
End If;
case QI is
When “0000”=>seg<=”0111111″;
When “0001”=>seg<=”0000110″;
When “0010”=>seg<=”1011011″;
When “0011”=>seg<=”1001111″;
When “0100”=>seg<=”1100110″;
When “0101”=>seg<=”1101101″;
When “0110”=>seg<=”1111101″;
When “0111”=>seg<=”0000111″;
When “1000”=>seg<=”1111111″;
When “1001”=>seg<=”1101111″;
When Others=>NULL;
end case;
End Process;
End behav;
2.用状态机的方法实现的带有预置数功能的计数器源代码:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity h31 is
port(cp,rst,EN:in std_logic;
seg:out std_logic_vector(6 downto 0);
op:out std_logic;
indata:In Std_Logic_Vector(3 downto 0));
end h31;
architecture rtl of h31 is
type state is(s0,s1,s2,s3,s4,s5,s6,s7,s8,s9);
signal presentstate:state;
signal nextstate:state;
signal qn:std_logic_vector(3 downto 0);
begin
switchtonextstate:process(cp,rst,EN)
begin
If rst=\’1\’ Then presentstate<=s0;
elsif cp\’event and cp=\’1\’then
if EN<=\’0\’ Then
presentstate<=nextstate;
else
case indata is
When”0000″=> presentstate<=s0;
When”0001″=> presentstate<=s1;
When”0010″=> presentstate<=s2;
When”0011″=> presentstate<=s3;
When”0100″=> presentstate<=s4;
When”0101″=> presentstate<=s5;
When”0110″=> presentstate<=s6;
When”0111″=> presentstate<=s7;
When”1000″=> presentstate<=s8;
When”1001″=> presentstate<=s9;
When others=> null;
end case;
end if;
end if;
end process switchtonextstate;
changestatemode:process(presentstate)
begin
case presentstate is
when s0=>nextstate<=s1;
qn<=”0001″;
op<=\’0\’;
when s1=>nextstate<=s2;
qn<=”0010″;
op<=\’0\’;
when s2=>nextstate<=s3;
qn<=”0011″;
op<=\’0\’;
when s3=>nextstate<=s4;
qn<=”0100″;
op<=\’0\’;
when s4=>nextstate<=s5;
qn<=”0101″;
op<=\’0\’;
when s5=>nextstate<=s6;
qn<=”0110″;
op<=\’0\’;
when s6=>nextstate<=s7;
qn<=”0111″;
op<=\’0\’;
when s7=>nextstate<=s8;
qn<=”1000″;
op<=\’0\’;
when s8=>nextstate<=s9;
qn<=”1001″;
op<=\’0\’;
qn<=”0000″;
op<=\’1\’;
When others=>null;
end case;
case qn is
When “0000”=>seg<=”0111111″;
When “0001”=>seg<=”0000110″;
When “0010”=>seg<=”1011011″;
When “0011”=>seg<=”1001111″;
When “0100”=>seg<=”1100110″;
When “0101”=>seg<=”1101101″;
When “0110”=>seg<=”1111101″;
When “0111”=>seg<=”0000111″;
When “1000”=>seg<=”1111111″;
When “1001”=>seg<=”1101111″;
When Others=>NULL;
end case;
end process changestatemode;
End rtl;
3.用文本输入法设计的60进制计数器VHDL源代码:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY COUNTC IS
PORT(CLK,CLK0,R,BCD1WR,BCD10WR:IN STD_LOGIC;
A:IN STD_LOGIC_VECTOR(3 DOWNTO 0);
Y:OUT STD_LOGIC_VECTOR(6 DOWNTO 0);
SEL:OUT STD_LOGIC_VECTOR(2 DOWNTO 0));
END COUNTC;
ARCHITECTURE ONE OF COUNTC IS
SIGNAL BCD1N:STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL BCD10N:STD_LOGIC_VECTOR(2 DOWNTO 0);
BEGIN
P1:PROCESS(CLK,BCD1WR)
BEGIN
IF R=\’1\’ THEN
BCD1N<=”0000″;
ELSIF BCD1WR=\’1\’ THEN
BCD1N<=A;
ELSIF CLK\’EVENT AND CLK=\’1\’ THEN
IF BCD1N=”1001″ THEN
BCD1N<=”0000″;
ELSE BCD1N<=BCD1N+1;
END IF;
END IF;
END PROCESS P1;
P2:PROCESS(CLK,BCD10WR)
BEGIN
IF R=\’1\’ THEN
BCD10N<=”000″;
ELSIF BCD10WR=\’1\’ THEN
BCD10N<=A(2 DOWNTO 0);
ELSIF CLK\’EVENT AND CLK = \’1\’ THEN
IF(BCD1N = “1001”) THEN
IF BCD10N=”101″ THEN
BCD10N<=”000″;
ELSE BCD10N<=BCD10N+1;
END IF;
END IF;
END IF;
END PROCESS P2;
P3:PROCESS(CLK0,BCD1N,BCD10N)
BEGIN
IF CLK0 = \’1\’ THEN
SEL <= “111”;
CASE BCD1N IS
WHEN “0000”=>Y<=”0111111″;
WHEN “0001”=>Y<=”0000110″;
WHEN “0010”=>Y<=”1011011″;
WHEN “0011”=>Y<=”1001111″;
WHEN “0100”=>Y<=”1100110″;
WHEN “0101”=>Y<=”1101101″;
WHEN “0110”=>Y<=”1111101″;
WHEN “0111”=>Y<=”0000111″;
WHEN “1000”=>Y<=”1111111″;
WHEN “1001”=>Y<=”1101111″;
WHEN “1010”=>Y<=”1110111″;
WHEN “1011”=>Y<=”1111100″;
WHEN “1100”=>Y<=”0111001″;
WHEN “1101”=>Y<=”1011110″;
WHEN “1110”=>Y<=”1111001″;
WHEN “1111”=>Y<=”1110001″;
WHEN OTHERS => NULL;
END CASE;
ELSE SEL <=”110″;
CASE BCD10N IS
WHEN “000”=>Y<=”0111111″;
WHEN “001”=>Y<=”0000110″;
WHEN “010”=>Y<=”1011011″;
WHEN “011”=>Y<=”1001111″;
WHEN “100”=>Y<=”1100110″;
WHEN “101”=>Y<=”1101101″;
WHEN “110”=>Y<=”1111101″;
WHEN “111”=>Y<=”0000111″;
WHEN OTHERS => NULL;
END CASE;
END IF;
END PROCESS P3;
END ONE;
六、 仿真图
1. 带预置数功能的十进制计数器波形仿真图
图2-2
2. 60进制计数器波形仿真图
图2-3
七、 设计心得与感想
通过这次实验,我对计数器的设计的基本方法有了一定的掌握。本次实习还用了状态机,这一直是我认为的EDA课程学习中的难点。通过自己亲自动手使用状态机,我发现它并不是那样难于掌握。在设计60进制计数器时,我用了两种设计方案,每种方案都有它的优点,我的主要目的是通过这样的方式进一步熟悉原理图设计方法和文本输入方法。
实验三简易数字钟设计
一、设计目的
1.掌握多位计数器相连的设计方法;2.
2.掌握十进制,六进制,二十四进制计数器的设计方法;
3.继续巩固多位共用级扫描显示数码管的驱动及编码;
4.掌握扬声器的驱动;
5.LED灯的花样显示;
6.掌握EPLD技术的层次化设计方法。
二、设计要求
基本要求:
一、设计任务(数字钟的功能):
1.具有时、分、秒、计数显示功能,以24小时循环计时;
2.具有清零,调节小时、分钟功能;
3.具有整点报时功能,整点报时的同时LED灯花样显示。
扩展部分:在基础功能上添加以下几个功能:秒表,倒计时和闹钟。
三、设计方案
把整个实验分成如下电路模块:
1.时钟计数:秒——60进制BCD码计数:
分——60进制BCD码计数:
时——24进制BCD码计数:
模块说明:
各种进制的计数及时钟控制模块( 10进制、 6进制、 24进制);
同时获个计数器有清零,调分,调时功能。在接近整数时间能提供报时信号。
2.具有驱动8位八段共阴扫描数码管的片选驱动信号输出和八段字形译码输出。
3.具有校时功能,可以分别对时及分进行单独校时,使其校正到标准时间当重新接通电源或走时出现误差时都需要对时间进行校正。通常,校正时间的方法是:首先截断正常的计数通路,然后再进行人工出触发计数或将频率较高的方波信号加到需要校正的计数单元的输入端,校正好后,再转入正常计时状态即可。
4.计时过程具有报时功能,当时间到达整点前10秒进行蜂鸣报时
5.LED灯按个人爱好在整点时有花样显示信号产生。
四、实现设计过程:.
秒个位计数单元为10进制计数器,无需进制转换,我们采用的是VHDL语言编程实现的.
秒十位计数单元为6进制计数器,需要进制转换。将10进制计数器的程序稍微修改为6进制计数器
分个位和分十位计数单元电路结构分别与秒个位和秒十位计数单元完全相同,只不过分个位计数单元的Q3作为向上的进位信号应与分十位计数单元的CPA相连,分十位计数单元的Q2作为向上的进位信号应与时个位计数单元的CPA相连。
时个位计数单元电路结构仍与秒或个位计数单元相同,但是要求,整个时计数单元应为24进制计数器,不是10的整数倍,因此需将个位和十位计数单元合并为一个整体才能进行
24进制转换.
五、硬件测试
用了两个脉时钟输入,一个是1024Hz,用于完成数码管的片选控制,一个是1 Hz为计数器提供正常计数和校时脉冲。用了4个拨码开关,其中三个用于校时用,另外一个用于系统复位。测试时通电下载后实验箱上即显示“000000”并开始计时,通过控制校时的开关进行调时,调到“235959”等待一秒后显示“000000”,同时蜂鸣器响。在测试整点报时功能时只须将时间调到整点是蜂鸣器都发声,整点报时功能实现。在正常计时时,如果将控制系统复位的拨码开关打到高电平,则不管此时显示的时间为多少,系统都将清0,数码管显示“000000”。
六、设计源代码
LIBRARY IEEE;
USE IEEE.STD_lOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY counter IS
PORT(RST,CLK,SCANCLK:IN STD_LOGIC;
SEL:OUT STD_LOGIC_VECTOR (2 DOWNTO 0);
LED:OUT STD_LOGIC_VECTOR (6 DOWNTO 0));
END;
ARCHITECTURE one OF counter IS
SIGNAL RESULT,OUTPUTA,OUTPUTB:STD_LOGIC_VECTOR (3 DOWNTO 0);
SIGNAL COUT:STD_LOGIC;
BEGIN
SCAN:PROCESS (SCANCLK)
BEGIN
CASE SCANCLK IS
WHEN \’1\’ =>
SEL<=”111″;
RESULT<=OUTPUTA;
WHEN \’0\’ =>
SEL<=”011″;
RESULT<=OUTPUTB;
WHEN OTHERS =>NULL;
END CASE;
END PROCESS SCAN;
OUTPUTI:PROCESS(CLK,RST)
VARIABLE CQI:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
IF RST=\’1\’ THEN CQI:=(OTHERS=>\’0\’);
ELSIF CLK\’EVENT AND CLK=\’1\’ THEN
IF CQI<9 THEN CQI:=CQI+1;
ELSE CQI:=(OTHERS=>\’0\’);
END IF;
END IF;
IF CQI=9 THEN COUT<=\’1\’;
ELSE COUT<=\’0\’;
END IF;
OUTPUTA<=CQI;
END PROCESS OUTPUTI;
OUTPUTII:PROCESS(COUT,RST)
VARIABLE CQII:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
IF RST=\’1\’ THEN CQII:=(OTHERS=>\’0\’);
ELSIF COUT\’EVENT AND COUT=\’0\’ THEN
IF CQII<5 THEN CQII:=CQII+1;
ELSE CQII:=(OTHERS=>\’0\’);
END IF;
END IF;
OUTPUTB<=CQII;
END PROCESS OUTPUTII;
ENCODER:PROCESS(RESULT)
BEGIN
CASE RESULT IS
WHEN “0000”=>LED<=”0111111″;
WHEN “0001”=>LED<=”0000110″;
WHEN “0010”=>LED<=”1011011″;
WHEN “0011”=>LED<=”1001111″;
WHEN “0100”=>LED<=”1100110″;
WHEN “0101”=>LED<=”1101101″;
WHEN “0110”=>LED<=”1111101″;
WHEN “0111”=>LED<=”0000111″;
WHEN “1000”=>LED<=”1111111″;
WHEN “1001”=>LED<=”1101111″;
WHEN OTHERS=>NULL;
END CASE;
END PROCESS ENCODER;
END;
七、数字钟中symbol
八、设计心得与体会
这次实验的题目是一个综合性的课程设计,其中很多模块都是我们在前几次实验中设计过的东西,因此我们的主要任务是将前两次次实验的成果正确、有效地有机连接起来。在计数器的设计上我主要是多加了一个使能端来实现数字钟校时功能的实现。
实验课总体心得与体会
电子设计自动化(EDA)技术是一门对实践能力要求很高的课程,通过这次实习,让我们对用EDA技术进行电子设计有了一个起步,也可以说是入门吧!
这次实习,让我亲身实践了很多接触过的东西,比如VHDL语言语法中的进程、顺序语句、并行语句、状态机等。而这些也是我在学习中感觉困难较大的地方。通过实习,对于状态机的设计有了一个初步的掌握,其实它也没有想象中的那么难,设计出状态机十进制计数器让我的信心大增。另外在实习过程中我通过亲身实践,对VHDL语言的语法规范和MAX+PLUS软件的使用方法有了一个了解和掌握,对于许多在书本中学不到的设计规则通过自己在设计中不断修改错误,也有了深刻的认识。比如说我在设计中经常在一个程序中的两个不同的进程中使用了同一端口,很长时间都没有发现错在那里,后来经过自己的尝试终于发现同一个进程是不能有两个不同的时钟脉冲,像这样的经历我还有很多。
通过这次的实验,让我知道我们前面所学的《数字电路》、《EDA技术》的作用,揭开我们这个专业的前途到底是干吗的。以及如何运用我们所学的知识进行实践。我很幸运当初我选了这门课程,非常感谢王巍老师提供这次实习的机会。