cpld时钟
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
CPLD课程学习报告
CPLD 课程是一门实践性非常强的课程,它要求我们运用基本的VHDL硬件描述语言编程得到我们想要的器件以实现我们所预期的功能。
这次CPLD课程学习的主要任务就是灵活地运用CPLD相关知识来设计一个数字电子钟,其基本要求是时、分、秒在数码管上的显示和小时、分钟的校准,扩展要求包括以下几点:
1、整点报时:55,56,57,58,59低音响,正点高音,间断振铃(嘟--嘟--嘟--嘟--嘟--嘀)
2、跑表:最大计时99分59秒999毫秒。
独立的跑表功能,不影响数字钟正常工作。
3、定时闹钟:可在00:00到23:59之间由用户设定任一时间,到时报警。
4、定时闹钟花样:前10s一般振铃,其后13秒较急促,再其后17秒急促,最后20秒特急促振铃。
并可随时关断。
5、其他(加减调时调分、音乐铃声等,越新奇越好)。
下面我就整个数字电子钟功能的实现过程做一一讲解。
首先,要完成一个最基本的时钟,首要任务就是编写两个计数器(24进制和60进制)。
60进制计数器的VHDL描述如下:library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
ENTITY dl21_cnt60 is
port(clk,reset,en:in bit;
q0,q1:out std_logic_vector(3 downto 0); carry:out std_logic);
end;
architecture one of dl21_cnt60 is
signal m0,m1:std_logic_vector(3 downto 0); begin
process(clk,reset,en)
begin
if reset='1'then m0<="0000";m1<="0000"; elsif clk'event and clk='1' then
if en='0'then
if m0="1001" and m1="0101" then
m1<="0000";m0<="0000";carry<='1';
elsif m0="1001" then m1<=m1+1;m0<="0000"; else m0<=m0+1;carry<='0';
end if;
end if;
end if;
end process;
q0<=m0;q1<=m1;
end;
通过对程序的保存、创建项目、编译之后,我们可以得到下图所示的实体器件:
60进制计数器
到底我们做的这个60进制计数器对不对呢,它能不能达到我们想要的效果呢,下面让我们来用波形仿真试一试就知道了。
我们通过对上面波形的观察,发现计数从00到59后又回到了 00,
反复循环的进行计数,和预期的效果完全相同。
同理,24进制进制计数器的VHDL描述如下:library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
ENTITY dl21_cnt24 is
port(clk,reset,en:in bit;
q0,q1:out std_logic_vector(3 downto 0);
carry:out std_logic);
end;
architecture one of dl21_cnt24 is
signal m0,m1:std_logic_vector(3 downto 0);
begin
process(clk,reset,en)
begin
if reset='1'then m0<="0000";m1<="0000";
elsif clk'event and clk='1' then
if en='0'then
if m0="0011" and m1="0010" then
m1<="0000";m0<="0000";carry<='1';
elsif m0="1001" then m1<=m1+1;m0<="0000";
else m0<=m0+1;carry<='0';
end if;
end if;
end if;
end process;
q0<=m0;q1<=m1;
end;
可以得到下图所示的实体器件:
24进制计数器
接下来的任务当然就是将这两个做出来的器件进行合理的连接组成我们所需要的最基本的时钟,其连接图如下图所示:
基本时钟
这就大体上完成了我们所要求的基本时钟,只要进行适当的引脚分配就能拿到实验箱上试一试它的功能如何,结果正如我们所想的一样,跟一般的数字时钟没什么差别。
既然说到了引脚分配就看一下
到底是怎么回事吧:
下面来完成基本要求的第二个功能:小时分钟校准功能。
这个就不用大费周章地去做很复杂的工作了,只需要运用两个二输入或门就能解决问题。
把秒钟的进位和调分按键相或接分钟的脉冲输入端,同理,把分钟的进位和调时按键相或接到时钟的脉冲输入端,这样就完成了。
但是有一点要注意,在调节完时钟或者分钟的时间后,一定要记得将调时和调分按键按到低电平,否则分钟和时钟就不会产生进位了。
在完成这一步之后,我们就可以得到一个具有基本要求的
时钟电路:
调时和调分功能时钟电路
基本要求到这里就要告一段落了,下面一起来看一下扩展部分的设计过程。
扩展要求1、整点报时:55,56,57,58,59低音响,正点高音,间断振铃(嘟--嘟--嘟--嘟--嘟--嘀)
因为有低音和高音之分,所以要两种频率。
通过编程实现分钟为59,秒钟十位为5,个位大于4时选择低频率;当分钟为0秒钟也为0时选择高频率,两个频率通过或门相连,最后接蜂鸣器。
这样就能达到
设计要求了。
编程实现部分:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
ENTITY dl21_cntzhen is
port(a,b,c,d:in std_logic_vector(3 downto 0);
du,di:out std_logic);
end;
architecture one of dl21_cntzhen is
begin
process(a,b,c,d)
begin
if d="0101"and c="1001"and b="0101" and a>"0100" then
du<='1';
elsif d="0000"and c="0000" and b="0000" and a="0000" then di<='1';
else du<='0';di<='0';
end if;
end process;
end;
所生成的器件:
整点报时功能模块
连接完成后就可以得到下图所示电路:
扩展要求2、跑表:最大计时99分59秒999毫秒。
独立的跑表功能,不影响数字钟正常工作。
说到跑表,它的设计与时钟没有什么本质的区别。
所以这里也就
不再赘述跑表的VHDL语言描述了,根据时钟的设计过程,我们可以的到跑表的实体器件:
跑表
至于让它不影响数字钟的正常工作,我把它留到后面再讲。
要保证跑表的1S就是真正的1S,就要求跑表的时钟脉冲频率为1000HZ,这里就需要采用分频了。
可以将3M三千分频,分频器的VHDL 语言描述如下:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
ENTITY dl21_3fenpin is
port(fh:in std_logic;
fl:out std_logic);
end;
architecture one of dl21_3fenpin is
signal m0,m1,m2,m3:std_logic_vector(3 downto 0);
begin
process(fh)
begin
if fh'event and fh='1' then
if m0<"1001" then m0<=m0+1;fl<='0';
elsif m1<"1001" then m1<=m1+1;m0<="0000";
elsif m2<"1001" then m2<=m2+1;m1<="0000";m0<="0000";
elsif m3<"0010"
then m3<=m3+1;m2<="0000";m1<="0000";m0<="0000";
else m1<="0000";m0<="0000";m2<="0000";m3<="0000";fl<='1'; end if;
end if;
end process;
end;
对应的实体器件如下图:
分频器
好,下面就来看一下
扩展要求3、定时闹钟:可在00:00到23:59之间由用户设定任一时间,到时报警。
定时闹钟设计中,可以先完成一个没有秒钟的基本时钟作为定时基准,只需要将第一个的时钟信号换成调分按键,断开分钟向时钟的进位,将时钟信号换成调时按键就可以了。
基准时钟的图示如下所示:
基准时钟
剩下的任务就是编程控制实现在时钟时间与设定时间相等的时刻让蜂鸣器发声。
考虑到跑表、基准时钟、基本时钟要分时显示在数码管上,所以先在
这里引入选择器的设计。
以二选一为例,选择器的VHDL描述如下:library ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
ENTITY zs64_mux2_1 IS
port(a,b:in std_logic_vector(3 downto 0);
s:in std_logic;
y:out std_logic_vector(3 downto 0);
k:out std_logic);
end;
architecture one of zs64_mux2_1 is
begin
process(a,b,s)
begin
if s='1' then
y<=a;
else
y<=b;
end if;
end process;
process(a,b,s)
begin
if a=b then
k<='1';
else
k<='0';
end if;
end process;
end;
二选一选择器的实体器件如下所示:
那么在这里就需要做一个三选一的选择器了,考虑到这个选择器里面还要实现基本闹钟、花样闹钟功能,所以可以采用多进程编程来实现,这个选择器的VHDL语言描述如下:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
ENTITY dl21_3x is
port(q2,q3,q4,q5,a0,a1,a2,a3,a4,a5,b0,b1,b2,b3,b4,b5,b6:in
std_logic_vector(3 downto 0);
s:in std_logic_vector(3 downto 0);
y0,y1,y2,y3,y4,y5,y6,m:out std_logic_vector(3 downto 0); k:out std_logic);
end;
architecture one of dl21_3x is
begin
process(q2,q3,q4,q5,a0,a1,a2,a3,a4,a5,b0,b1,b2,b3,b4,b5,b6, s)
begin
If s="0000"
then y2<=q2;y3<=q3;y4<=q4;y5<=q5;y0<="0000";y1<="0000"; elsif s="0001"
then y0<=a0;y1<=a1;y2<=a2;y3<=a3;y4<=a4;y5<=a5;y6<="0000"; else y0<=b0;y1<=b1;y2<=b2;y3<=b3;y4<=b4;y5<=b5;y6<=b6; end if;
end process;
process(q2,q3,q4,q5,a0,a1,a2,a3,a4,a5,b0,b1,b2,b3,b4,b5,b6, s)
begin
if a2=q2 and a3=q3 and a4=q4 and a5=q5 then k<='1';
else k<='0';
end if;
end process;
process(q2,q3,q4,q5,a0,a1,a2,a3,a4,a5,b0,b1,b2,b3,b4,b5,b6, s)
begin
if a2=q2 and a3=q3 and a4=q4 and a5=q5 then
if a1="0000" then m<="0000";
elsif a1="0001" then m<="0001";
elsif a1="0010" and a0<"0100" then m<="0001";
elsif a1="0010" and a0>="0100" then m<="0010";
elsif a1="0011" then m<="0010";
else m<="0011";
end if;
end if;
end process;
end;
生成的选择器实体器件如下所示:
三选一模式选择器
上面已经开始涉及到第四个扩展要求,也就是花样闹钟:前10s 一般振铃,其后13秒较急促,再其后17秒急促,最后20秒特急促振铃。
并可随时关断。
这里就需要四个频率,通过时间控制进行选择,在规定的时间段内发出相应的声音。
时间的控制是通过三选一中的进程三来实现的,而频率的控制则是通过四选一频率选择器实现的。
四选一频率选择器的VHDL描述如下:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
ENTITY dl21_3 is
port(f4:in std_logic;
f3:in std_logic;
f2:in std_logic;
f1:in std_logic;
se:in std_logic_vector(3 downto 0); y:out std_logic);
end;
architecture one of dl21_3 is begin
process(f4,f3,f2,f1,se)
begin
if se="0000" then y<=f1;
elsif se="0001" then y<=f2;
elsif se="0010" then y<=f3;
elsif se="0011" then y<=f4;
end if;
end process;
end;
其实体器件如下:
四选一频率选择器
前面说过,跑表功能和时钟功能不相互影响,比如说清零和暂停功能,只要实现在哪种模式下就对哪种功能进行清零和暂停就可以了。
这个可以通过与门来实现,在按下清零按键的时候,可以将两个与门封锁,对另外一个与门开放,就可以达到三种模式下的清零和暂停不相互影响了。
最后,将跑表、基准时钟、基本闹钟组合起来可以得到整个设计图如下:
整个设计的实验效果:
首先把引脚分配如下
8号引脚接en,9号引脚接reset,10号引脚接tiaofen,12号引脚接
tiaoshi,13号引脚接select。
首先,电子钟处于基准时钟模式下,3、4、5、6这几个数码管显示的就是闹钟的时间,不断地按下按键3,可以看到分钟的时间在增加,不断地按下按键4,可以看到时钟的时间在增加。
当我们按下按键2时,闹钟的时间清零。
这时我们按下按键5进行模式选择,这时数码管1、2、3、4、5、6上显示当前的时间并不断地变化,我们不断地按下按键3、4会发现时钟和分钟也在相应的变化,然后按下按键1,这时时间停了下来,按下按键2同样会使得时间清零。
再次按下按键5进入第三种模式,也就是跑表模式,按上面的操作进行,同样可以对跑表进行暂停和清零。
最后来看一下整点报时和花样闹钟,将闹钟时间调整到00:01:00,然后将时钟时间调整到23:59:51。
当时间到了23:59:55时,我们听到了嘟的声音一直持续到23:59:59,00:00:00时我们听到了滴的一声。
当时间到了00:01:00时,花样闹钟开始工作了,前10s一般振铃,其后13秒较急促,再其后17秒急促,最后20秒特急促振铃,与我们要求的完全相符。
学完这门课程的心得体会
虽然为期8周的学习时间不是很长,但我从中还是学到了不少的东西。
刚开始接触这门课程的时候并不知道什么是CPLD和VHDL语言,后来通过老师的讲解和自己对它们的不断认识,加深了对CPLD 和VHDL语言的理解。
在实验过程中,通过不断地提出问题、发现问题
和解决问题,自己的发散思维能力和动手能力得到很大的提高。
我们以小组为单位进行实验,每组两个同学,遇到问题共同讨论,共同交流,尽量采用较为简单的方法来实现相同的功能,整个实验过程,不仅培养了两个人之间的默契,也使得我们的人际交往能力得到一定的提高,体现了一种团队合作精神,为我们以后走上社会与同事友好的相处打下了一定的基础。
当然,整个课程学习过程中,让人印象最为深刻的一点就是
当一个任务放在你面前的时候,不要企图一步来完成,我们应该将它划分成很多小的部分,然后针对小的部分一一解决,当某一个部分出现问题的时候,不要慌张,应该仔细检查,看一看是不是有哪些重要的步骤漏掉了或者是什么地方出了点小错误,因为只有在错误中,我们才能发现自己的缺点和不足,才能得到真正的提升。
在问题实在是得不到解决的时候,我们应该虚心的请教老师,弄清问题的源头,并加深对问题的理解,避免在后面的实验过程中犯相同的错误。
在各个部分的任务完成以后,将它们进行整合以得到我们所预期的实验结果。
最后希望像CPLD这样的课程能够多开一些,因为这门课程让自己各方面的能力得到一定的提高,让自己受益匪浅!。