目录
一:实验要求
二:程序源代码
2.1 CNT6的VHDL源代码
2.2 CLKGEN(分频器)的VHDL源程序
2.3 DTTIMES(数字秒表顶层文件)的VHDL源程序
三:硬件实验现象
四:对实验步骤详细分析
4.1 CNT6代码分析
4.2 DISPLAY的源代码分析
4.3 分频器波形仿真 (重要!)
4.4 顶层文件波形仿真
设计并调试好一个计时范围为0.01s~1h的数字秒表,并用GW48系列或其他EDA实验开发系统(事先应选定拟采用的实验芯片的型号)进行硬件验证。
图1: 实验电路
设计思路:为了能够在数码管上显示,所以需要CTRLS(动态扫描)和DISPLAY(动态显示),相对于DTCNT9999不同的是这时候需要的数码管从四根变到了六根,并且由于我们日常秒表的特性(大家可以打开我们手机自带的时钟,里面就有秒表的功能)其中60s是等于一分钟的,60分钟是等于1h的,从0.01s--1h需要四个10进制的计数器,俩个六进制的计数器。
那么大家想一下,那我最小单元0.01s从哪里而来呢,这时候就用到了分频器。
分频器的功能就是将输入的信号频率进行一个分频(可以当成一个除法器)
NEWCLK=CLK/分频常数
其中我选择3万的分频常数,并且把外部频率作为输入频率,通过不断调整外部频率来达到100hz计数时钟输出。(所以我需要找到3M的外部频率)
部分代码与第一篇一致可以移植
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);
CO:OUT STD_LOGIC);
END ENTITY CNT6;
ARCHITECTURE ART OF CNT6 IS
SIGNAL CQI: STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
PROCESS(CLK, CLR, ENA) IS
BEGIN
IF CLR='1' THEN CQI<="0000";
ELSIF CLK'EVENT AND CLK='1' THEN
IF ENA='1' THEN
IF CQI="0101" THEN CQI<="0000";
ELSE CQI<=CQI+'1'; END IF;
END IF;
END IF;
END PROCESS;
PROCESS(CQI) IS
BEGIN
IF CQI="0000" THEN CO<='1';
ELSE CO<='0'; END IF;
END PROCESS;
CQ<=CQI;
END ARCHITECTURE ART;
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY CLKGEN IS
PORT(CLK: IN STD_LOGIC; --3 MHz信号输入
NEWCLK: OUT STD_LOGIC); --100 Hz计时时钟信号输出
END ENTITY CLKGEN;
ARCHITECTURE ART OF CLKGEN IS
SIGNAL CNT: INTEGER RANGE 0 TO 10#29999#;--十进制计数预制数
--SIGNAL CNT: INTEGER RANGE 0 TO 10#29#;--十进制计数预制数
BEGIN
PROCESS(CLK) IS --分频计数器,由3MHz时钟产生100Hz信号
BEGIN
IF CLK'EVENT AND CLK='1' THEN
IF CNT=10#29999# THEN CNT<=0; --分频常数为 30000
--IF CNT=10#29#THEN CNT<=0;--分频常数为30
ELSE CNT<=CNT+1;
END IF;
END IF;
END PROCESS;
PROCESS(CNT) IS --计数溢出信号控制
BEGIN
IF CNT=10#29999# THEN NEWCLK<='1';
--IF CNT=10#29# THEN NEWCLK<='1';
ELSE NEWCLK<='0';
END IF;
END PROCESS;
END ARCHITECTURE ART;
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY TIMER IS
PORT(CLR: IN STD_LOGIC;
CLK1: IN STD_LOGIC;
ENA: IN STD_LOGIC;
CLK2:IN STD_LOGIC;
COM:OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
SEG:OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END ENTITY TIMER;
ARCHITECTURE ART OF TIMER IS
COMPONENT CLKGEN IS
PORT(CLK: IN STD_LOGIC;
NEWCLK: OUT STD_LOGIC);
END COMPONENT CLKGEN;
COMPONENT CNT10 IS
PORT(CLK, CLR, ENA: IN STD_LOGIC;
CQ:OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
CO: OUT STD_LOGIC);
END COMPONENT CNT10;
COMPONENT CNT6 IS
PORT(CLK, CLR, ENA: IN STD_LOGIC;
CQ:OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
CO: OUT STD_LOGIC);
END COMPONENT CNT6;
COMPONENT CTRLS IS
PORT(CLK:IN STD_LOGIC;
SEL:OUT STD_LOGIC_VECTOR(2 DOWNTO 0));
END COMPONENT CTRLS;
COMPONENT DISPLAY IS
PORT(SEL:IN STD_LOGIC_VECTOR(2 DOWNTO 0);
DATAIN:IN STD_LOGIC_VECTOR(23 DOWNTO 0);
COM: OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
SEG: OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END COMPONENT DISPLAY;
SIGNAL S0: STD_LOGIC;
SIGNAL S1, S2, S3, S4, S5: STD_LOGIC;
SIGNAL S:STD_LOGIC_VECTOR(2 DOWNTO 0);
SIGNAL DOUT:STD_LOGIC_VECTOR(23 DOWNTO 0);
BEGIN
UO: CLKGEN PORT MAP(CLK=>CLK1, NEWCLK=>S0);
U1: CNT10 PORT MAP(S0,CLR,ENA, DOUT(3 DOWNTO 0), S1);
U2: CNT10 PORT MAP(S1, CLR, ENA,DOUT(7 DOWNTO 4), S2);
U3: CNT10 PORT MAP(S2, CLR, ENA, DOUT(11 DOWNTO 8), S3);
U4: CNT6 PORT MAP(S3, CLR, ENA, DOUT(15 DOWNTO 12), S4);
U5: CNT10 PORT MAP(S4, CLR,ENA, DOUT(19 DOWNTO 16), S5);
U6: CNT6 PORT MAP(S5, CLR, ENA, DOUT(23 DOWNTO 20));
U7: CTRLS PORT MAP(CLK2,S(2 DOWNTO 0));
U8: DISPLAY PORT MAP(S,DOUT,COM,SEG);
END ARCHITECTURE ART;
EDA实验数字秒表
对应CNT10、CTRLS部分和DTCNT9999分析一致,可以看我第一篇文章
大家一定要有代码移植的思想,对于之前写过代码要有一个保存,然后当你需要的时候,将该模块代码移植过去即可、引脚锁定与DTCNT9999引脚锁定一致,可参考第一篇文章。
RTL图:可以从RTL图看出整个电路的整体状态,可以看出信号从CLK1进入分频器输入100hz的信号,以0.01s的最小单元进行计数,CNT6一个在第四位和第六位,大家可以可以看到秒表的显示很容易就理解为什么CNT6在第四位和第六位了。
图4.1 RTL 整体电路图
和CNT10代码其实是差不多一致的,只是略有修改,就是进位的数值。CNT10是10进制0-9便会产生一个进行信号,而CNT6是计数从0-5便会产生一个进位信号。
由于DTCNT9999只需要4个数码管显示数字,但是数字秒表大家可以发现是六个数码管显示数字,并且俩个数码管显示一个点。这时候就需要大家对数码管显示数字的驱动端代码进行改动。
由于数码管是六个数码管电亮,那我怎么去显示点然后移动他们的位置呢?(很重要)
控制数码管显示数字的信号从4*4=16变到了4*6=24个信号。然后再对显示数字的数码管进行移位操作。其中俩个点其实就是让数码管一直为点。然后可以看到SEL中000-111分别控制一个数码管其中000代表第一个数码管。而我们要对原来的六位显示数字的数码管移位,第三和第六数码管一直显示为0即可。
举例:由于疫情原因不能超过俩个人聚在一起,所以在每俩个人之间需要放置一个挡板,最开始六个人聚在一起,所以你需要俩个俩个的分别用挡板隔开。其中000-111就是对应位置都在那,但是其中俩个位置需要一直放挡板,然后其他六个位置可以使用,但是需要每隔一个位置。
没有控制数码管显示数字的一直显示为点。
我们硬件部分要实现是100hz,对应3M的信号输入,所以需要30000分频,即30000个CLK上升沿NEWCLK出现一个跳变,当我们用软件仿真的时候根本看不到30000个输入信号的上升沿(除非你是超人) ,所以我们需要减小分频系数,但是注意在硬件时候我们还是需要30000分频的,这时候注释的作用就体现出来了。当软件仿真使用分频系数小的,当硬件仿真的时候使用30000分频。
注意一点:其中CLK2的周期要大于等于8倍的CLK1,这是为什么呢?
答案是:数码管要八个,你需要八个都能点亮的状态,有人会说“哎,小数点不是不用全部点亮么”(小数点也要数码管是一直点亮的状态的,只是不显示数字,而是显示小数点),如果周期小于8倍会出现动态显示的效果,达不到我们所需要的数字秒表效果。
最后:如果需要人数较多,我会对项目进行一个开源,如果对你有用,请给一个点赞,多谢!