学院
FPGA设计实践报告
题目:数字秒表的设计
院系:计算机与信息工程学院
专业:电子科学与技术年级
姓名:学号:
指导老师:
一、课程设计目的:
本课程的授课对象是电子科学与技术专业本科生,是电子类专业的一门重要的实践课程,是理论与实践相结合的重要环节。本课程有助于培养学生的数字电路设计方法、掌握模块划分、工程设计思想与电路调试能力,为以后从事各种电路设计、制作与调试工作打下坚实的基础。
二、课程设计要求:
l. 设计用于体育比赛用的数字秒表, 要求:
⑴计时精度应大于l/100S, 计时器能显示1/100S的时间, 提供给计时器内部定时的时钟脉冲频率应大于l00Hz, 这里选用1kHz 。
⑵计时器的最长计时时间为l小时, 为此需要一个6位的显示器, 显示的最长时间为59分59.99秒。
2. 设置有复位和起/停开关
⑴复位开关用来使计时器清零, 并作好计时准备。
⑵起/停开关的使用方法与传统的机械式计时器相同, 即按一下起/停开关, 启动计时器开始计时, 再按一下起/停开关计时终止。
⑶复位开关可以在任何情况下使用,即使在计时过程中, 只要按一下复位开关, 计时进程立刻终止, 并对计时器清零。
3. 复位和起/停开关应有内部消抖处理。
4. 采用VHDL语言用层次化设计方法设计符合上述功能要求的数字秒表。
5. 对电路进行功能仿真, 通过有关波形确认电路设计是否正确。
6. 完成电路全部设计后, 通过系统实验箱下载验证设计课题的正确性。
三、系统组成与工作原理:
数字秒表框图:
1、电路原理图 :
2、工作原理:
l.计时控制器作用是控制计时。计时控制器的输入信号是启动、暂停和清零。为符合惯例, 将启动和暂停功能设置在同一个按键上, 按一次是启动, 按第二次
是暂停, 按第三次是继续。所以计时控制器共有2个开关输入信号, 即启动/暂停和清除。计时控制器输出信号为计数允许/保持信号和清零信号。
2. 计时电路的作用是计时, 其输入信号为lkHz 时钟、计数允许/保持和清零信号, 输出为l0ms、l00ms、s 和min 的计时数据。
3. 时基分频器是一个l0分频器, 产生l0ms周期的脉冲, 用于计时电路时钟信号。
4. 显示电路为动态扫描电路, 用以显示十分位、min、10s、s、100ms 和10ms 信号。
三、系统设计的实现:
要满足数字秒表的精度,首先应该获得精确的计时基准信号,这里的系统精度要求为l/100S, 计时器能显示1/100S的时间, 提供给计时器内部定时的时钟脉冲频率应大于l00Hz, 这里选用1kHz,因此每来1000个外界输入脉冲就输出一个频率,该频率的时间周期正好为0.01S,即先将外界脉冲进行1MHz→100Hz 的分频。
0.1s、1s、1min等计时单位之间的进位转换可以通过十进制与六进制计数器来实现。每位计数器均能输出相应计时单位计数结果,其中十进制计数器可以实现0.01s、0.1s、1s和1min单位单元的计数;六进制可以实现10s、10min为单位的计数。由于秒表需要具有异步清零和启动/暂停功能,因此可以将每个计数器都设置异步清零和启动/暂停输入端口,再将各计数器进行级联,即可同步显示不同量度单位的计时内容,如图所示
图中,U0模块用于将外界脉冲进行1MHz→100Hz的分频,从而得到0.01s 的脉冲信号,U1用于实现0.1s的脉冲信号,U2用于实现1s的脉冲信号,U3和U4用于实现1min的脉冲信号,U5和U6用于实现1H的脉冲信号。除U0外,U1~U6的CQ可驱动显示带译码器的七段LED进行数字显示。
通过上述分析可知,数字秒表的构成实际上依赖于三个基本模块,即1MHz →100Hz的分频模块、十进制计数器模块和六进制计数器模块,然后使用一个顶层模块将这些基本模块通过元件调用与映射的关系进行有机的结合。
总体流程图如下:
Start
1、顶层模块程序
由于十进制计数器模块和六进制计数器模块会产生计数溢出信号,而这些溢出信号有可能作为下一计数器的时钟输入脉冲,因此在顶层模块程序结构体中需要定义相应的暂存计数溢出信号。顶层模块程序编写如下:
--数字秒表的顶层模块程序miaobiao.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY miaobiao IS
PORT(CLR:IN STD_LOGIC; --定义清零输入端
CLK:IN STD_LOGIC; --定义外界时钟脉冲输入端
ENA:IN STD_LOGIC; --定义启动/暂停输入端
DOUT:OUT STD_LOGIC_VECTOR(23 DOWNTO 0)); --定义秒表显示输出端
END miaobiao;
ARCHITECTURE ART OF miaobiao IS
COMPONENT CLKGEN --定义3MHz到100Hz的分频计数器元件
PORT(CLK:IN STD_LOGIC; --定义3MHz到100Hz的分频计数器所使用的端口
NEWCLK:OUT STD_LOGIC);
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;
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);
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;
顶层仿真波形:
2、50MHz→1kHz分频模块程序
50MHz→1kHz分频模块程序流程图如图所示,使用VHDL编写程序时,在实体中应定义1kMHz的时钟频率输入端和100Hz的时钟脉冲输出端。
在结构体的说明语句中,定义一个频率脉冲计数信号(CNTER ),该信号
的类型为整数型,计数范围为0~999。 在结构体的功能描述语句中,可使用2个进程(U1和U2)来完成 50MHz →1kHz 的频率描述。在U1中,每次检测到一个上升沿输入脉冲时,先通过IF 语句检测输入信号是否为上升沿。若是上升沿,再使用IF 语句判断当前计数值(CNTER )是否等于999,如果相等,则将CNTER 清零,为输出下一个100Hz 的频率做准备,否则将CNTER 加1。在U2中判断CNTER 是否等于999,若果相等,将NEWCLK 输出为高电平,否则输出为低电平。1kMHz →100Hz 分频模块程序编写如下: LIBRARY IEEE;
USE IEEE. STD_LOGIC_1164.ALL; ENTITY CLKGEN IS
PORT( CLK:IN STD_LOGIC; -- 定义3MHz 脉冲输入端
NEWCLK:OUT STD_LOGIC ); --定义100Hz 脉冲输出端 END CLKGEN;
ARCHITECTURE ART OF CLKGEN IS
SIGNAL CNTER:INTEGER RANGE 0 TO 10#299999#; --暂存输入脉冲个数
BEGIN
U1: PROCESS(CLK) BEGIN
IF CLK'EVENT AND CLK='1' THEN
IF CNTER=10#299999# THEN CNTER<=0;
--判断输入脉冲个数是否为3000(0~29999) ELSE CNTER<=CNTER+1; END IF; END IF;
1KHz 时钟输入
每来一个脉冲,CNTER 是否为999?
CENTE 清零
NEWCLK 输出为高电平
得到100Hz 的输出脉冲
CNTER+1
NEWCLK 输出为低电平
N
Y
END PROCESS U1;
U2: PROCESS(CNTER) --计数溢出信号控制 BEGIN IF CNTER=10#299999# THEN NEWCLK<='1'; --3MHz 信号变为100Hz ELSE NEWCLK<='0'; END IF;
END PROCESS U2; END ART;
分频仿真波形:
3、十进制计数器模块程序
十进制计数模块程序流程图如下,使用VHDL 编写程序时,在实体中定义时钟脉冲输入端(CLK )、异步清零输入端(CLR )、启动暂停控制端(ENA )、计数脉冲输出端CQ 和计数脉冲溢出端(CARRY_OUT )。
由于CQ 的方向定义为OUT ,在结构体中不能对输入脉冲进行加1计数,因此在结构体的说明语句中应定义一个频率脉冲计数信号(CQI ),通过CQI 来进行加1控制。
在结构体的功能描述语句中可使用2个进程(U1和U2)来完成十进制计数器的功能描述。在U1中,先判断清零信号(CLR )是否有效,若有效时,将CQI 清零,否则检测输入脉冲。每次检测到一个上升沿输入脉冲时,通过IF 语句检测输入信号是否为上升沿。若是上升沿,在判断是否允许计数(即ENA 是否有
Y
开始
清零信号是否有效?
输出脉冲是否为上升沿?
是否允许计数?
CQ 清零
计数值是否等于
计数值加1
溢出信号输出为高电平
计数值清零
溢出信号输出为低电
Y
N
Y N
N
Y
N
效)。若ENA无效,则暂停计数,否则再使用IF语句判断当前计数值(CQI)是否等于“1001”(即整数9),如果相等,则将CQI清零,肉则CQI加1,。在U2中判断CQI是否等于“1001”,如果相等,产生溢出信号(CARRY_OUT<='1'),否则CARRY_OUT输出为低电平(CARRY_OUT<='0').十进制计数器模块程序编写如下:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY CNT10 IS
PORT(CLK:IN STD_LOGIC;
CLR:IN STD_LOGIC;
ENA:IN STD_LOGIC;
CQ:OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
CARRY_OUT:OUT STD_LOGIC);
END CNT10;
ARCHITECTURE ART OF CNT10 IS
SIGNAL CQI:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
U1:PROCESS(CLK,CLR,ENA)
BEGIN
IF CLR='1'THEN CQI<="0000";
ELSIF CLK'EVENT AND CLK='1'THEN
IF ENA='1'THEN
u1:for n in 15 downto 0 loop
u2:for i in 15 downto 0 loop
end loop u2;
end loop u1;
if ENA='1' then
IF CQI="1001" THEN CQI<="0000";
ELSE CQI<=CQI+'1';
END IF;
end if;
END IF;
END IF;
END PROCESS U1;
U2:PROCESS(CQI)
BEGIN
IF CQI="0000" THEN CARRY_OUT<='1';
ELSE CARRY_OUT<='0';
END IF;
END PROCESS U2;
CQ<=CQI;
END ART;
十进制仿真波形:
4、六进制计数器模块程序
六进制计数器模块的程序编写思路与十进制计数器模块类似,只不过将CQI 的判断值由“1001”改为“0101”即可。六进制计数器模块程序编写如下:
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);
CARRY_OUT:OUT STD_LOGIC);
END CNT6;
ARCHITECTURE ART OF CNT6 IS
SIGNAL CQI:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
U1:PROCESS(CLK,CLR,ENA)
BEGIN
IF CLR='1'THEN CQI<="0000";
ELSIF CLK'EVENT AND CLK='1'THEN
IF ENA='1'THEN
u1:for n in 15 downto 0 loop
u2:for i in 15 downto 0 loop
end loop u2;
end loop u1;
if ENA='1' then
IF CQI="0101" THEN CQI<="0000";
ELSE CQI<=CQI+'1';
END IF;
end if;
END IF;
END IF;
END PROCESS U1;
U2:PROCESS(CQI)
BEGIN
IF CQI="0000" THEN CARRY_OUT<='1';
ELSE CARRY_OUT<='0';
END IF;
END PROCESS U2;
CQ<=CQI;
END ART;
六进制仿真波形:
四、结果显示
本设计的结果是通过六个七段数码管来显示,HEX0、HEX1显示0.01s,HEX2和HEX3分别显示1s和10s,HEX4和HEX5分别显示1min和10min,SW1和SW0用来作为ENA和CLR的拨键,当SW1拨动时,开始计时,再拨一次会停止计时,继续拨一次会停止;若SW0拨动则会使显示复位即清零。
五、器件编程与硬件下载
引脚分配
六、实验设备
计算机
Quantuars II 软件
ALTERA DE2
七、心得体会
通过本次课设,我不仅学到了关于FPGA的许多专业知识,同时也让我感觉到思考的重要性。其实如何有效和快速的找到资料也是课设给我的启发,利用好图书馆和网络,是资源的到最好的利用。仿真部分是我遇到问题最多的部分,同时也是我收获最多的部分,只有不断遇到问题并不断解决问题,这样才能有进步,在每次仿真之后我都会对程序进行一定的优化,并加上必要的注解,这样在不管是在检查还是在修改的时候都能立刻知道这部分的内容,非常方便,应该要把这
个习惯好好保持。
通过思考、发问、自己解惑并动手、改进的过程,才能真正的完成课题。经过这次课程设计的过程,我相信在以后的课程设计中我们会吸取经验教训,做出更好的设计来。