2024寒假练-基于小脚丫FPGA核心板设计秒表
该项目使用了基于Lattice MXO2的小脚丫FPGA核心板、verilog语言,实现了秒表的设计,它的主要功能为:启动计时、停止计时、使计时器值增加0.1、清除计时。
标签
FPGA
秒表
2024年寒假在家一起练
Lattice MXO2小脚丫核心板
不知fo
更新2024-04-02
北京理工大学
63

项目介绍

使用七段显示器作为输出设备,在小脚丫FPGA核心板上创建一个2位数秒表。 秒表从0.0秒计数到9.9秒,然后翻转,计数值每0.1秒精确更新一次。

秒表使用四个按钮输入:开始、停止、增量和复位。 开始按钮使秒表开始以10Hz时钟速率递增;停止按钮使计数器停止递增,并使数码管显示当前计数器值;增量按钮使显示值增加一次,无论按住增量按钮多长时间;复位按钮强制计数器值为零。

硬件框图

本项目使用基于Lattice MXO2的小脚丫FPGA核心板,可瞬时上电启动,无需外部重新配置FPGA,是学习数字逻辑绝佳的选择。板子的大小兼容标准的DIP40封装,尺寸只有52mm x 18mm,非常便于携带,而且能够直接插在面包板上或以模块的方式放置在其它电路板上以即插即用的方式,大大简化系统的设计。支持Type-C接口供电,适合新手上手,是学习数字逻辑绝佳的选择。


板载资源:

  • 两位7段数码管;
  • 两个RGB三色LED;
  • 8路用户LED;
  • 4路拨码开关;
  • 4路按键;

功能框图

功能框图为状态机逻辑设计,第一部分为时钟计时器逻辑框图:



所有信号均为0/1两种状态,按下按键时为0,松开按键时为1。

第二部分为增量模块逻辑框图:



为了保证一次按压只进行一次增量操作,设计了增量存储状态位。当按下增量按键时,增量信号为0,此时增量存储位由0置1;当松开增量按键时,增量信号为1,此时先判断增量存储位是否为1,若为1,则说明增量按键被按下过,将增量存储位由1置0,并执行进位操作,若为0,则说明增量按键没有被按下,不进行操作。

设计思路

本项目使用的小脚丫FPGA板位12MHz,每秒12000000个时钟周期。为了实现计时功能,可以定义变量来统计时钟周期,时钟周期每1200000次对应时间0.1秒。定义状态位running来控制计时,状态位为1开始计时,为0停止计时。

小脚丫FPGA板上4个轻触按键作为输入,分别是开始、停止、增量和复位。开始模块将状态位running置1,表示开始计时;停止模块将状态位running置0,表示停止计时;增量模块为了保证一次按压只增0.1秒,可以设置状态位inc_store来控制增量大小,一次按压动作分为按下去和抬上来,按下去时,将状态位inc_store置1,表示一次按压的开始,抬起来时,将状态位inc_store置0,表示一次按压的结束,在状态位Inc_store由1变0的过程中,实现加0.1秒的操作,以此保证一次按压动作只加0.1秒;复位模块将状态位running置0,时钟周期统计量置0,以及数码管显示值置0,表示停止计时并准备重新开始。

小脚丫FPGA板上2个数码管作为输出,分别是秒位和0.1秒位。其中秒位需要显示小数点,而0.1秒位不用,其余按照正常数码管显示数字方式即可。

FPGA资源占用报告

image.png

image.png

项目功能描述及演示

将jed文件烧录进小脚丫FPGA板,接电后,初始显示状态如下:

5951e77fba5048a4bd801bede6145e7.jpg

按下开始按键,即第一个轻触按键,开始计时,可以看到数码管上显示的数值以0.1精确递增,在9.9后翻转,详情可见文档最上方的视频演示处。

按下停止按键,即第二个轻触按键,停止计时,此时显示3.4,如下:

80a2d689c49a26808feb7988edc6752.jpg

按下增量按键,即第三个轻触按键,一次按压增加0.1,如下:

78287fbb6f915a265856d1eb0f22d8e.jpg

按下复位按键,即第4个轻触按键,可以看到数码管显示值归0,如下:

cf6884c94e5a30d09ea8efe9d39a3b3.jpg

主要代码片段及说明

module main(
input clk, // 输入时钟信号
input start, // 开始信号
input stop, // 停止信号
input inc, // 增量信号
input rst, // 复位信号
output reg [8:0] led1, // 数码管1输出
output reg [8:0] led2 // 数码管2输出
);

reg [3:0] seconds_s = 4'd0; // 秒位
reg [3:0] seconds_ms = 4'd0; // 0.1秒位
reg [23:0] timer = 24'd0; // 时钟周期计时器
reg running = 1'b0; // 运行状态标志位
reg inc_store = 1'b0; // 增量存储位
reg [8:0] seg [9:0];

以上为初始化代码。先定义好4个输入和2个输出,为了方便显示数值,定义了秒位和0.1秒位;为了统计时钟周期从而计时,定义了时钟周期计时器timer和运行状态标志位running;为了让增量操作一次按压只增0.1秒,定义了增量存储位inc_store。

        if (rst == 1'b0) begin
timer <= 24'd0;
seconds_s <= 4'd0;
seconds_ms <= 4'd0;
running <= 1'd0;
end
else if (start == 1'b0) begin
running <= 1'b1;
end
else if (stop == 1'b0) begin
running <= 1'b0;
end

以上分别为复位模块、开始模块和停止模块。复位模块将时钟周期统计值timer置0,秒位和0.1秒位置0,运动状态标志位running置0;开始模块将运动状态标志位running置1即可;停止模块将运动状态标志位running置0即可。

        else if (inc == 1'b0) begin
if (running == 1'b0) begin
inc_store <= 1'b1;
end
end
else if (inc == 1'b1) begin
if (running == 1'b0) begin
if (inc_store == 1'b1) begin
inc_store <= 1'b0;
if (seconds_ms == 4'd9) begin
seconds_ms <= 4'd0;
if (seconds_s == 4'd9) begin
seconds_s <= 4'd0;
end
else begin
seconds_s <= seconds_s + 4'd1;
end
end
else begin
seconds_ms <= seconds_ms + 4'd1;
end
end
end
end

以上为增量模块。按下去时,inc为0,此时将增量存储位inc_store置1,表示一次增量操作的开始;抬起来时,inc为1,此时先判断增量操作是否已开始,即判断inc_store是否为1,如果是,则将inc_store置0,表示一次增量操作的结束,并让0.1秒位加1,从而实现按一次增量按键只加0.1秒。

        led1 <= {seg[seconds_s][8],1'b1,seg[seconds_s][6:0]};
led2 <= {seg[seconds_ms][8:0]};

以上为led显示模块。其中seg[7]为数码管的小数点部分,秒位需要保持常亮,所以置1,其余部分则不变。

主要困难及解决方法

主要困难:增量模块如果按照开始、停止或复位模块的方式设计,会出现按压一次显示值却增加特别多的情况,这是因为代码以一个时钟周期为循环,而按下去这一动作本身就会经过大量的时钟周期。对于开始、停止和复位模块,这并不会有影响,因为它们只需要让某一变量置0或置1,无论经过多少时钟周期变量值都不会发生变化;但对于增量模块则有影响,因为增量模块需要让0.1秒位加1,时钟周期的变化会导致变量值的变化,从而出现按压一次显示值却增加特别多的情况。

解决方法:定义一个增量存储位,当按下去时,将增量存储位置1,此时无论经过多少时钟周期增量存储位都不会发生变化,当抬上来时,将增量存储位置0,此时增量存储位同样不会发生变化,同时,实现0.1秒位加1的操作,从未确保一次按压显示值只加0.1秒。






附件下载
启动、停止、递增和清除功能的秒表.zip
具有启动、停止、递增和清除功能的秒表
团队介绍
北京理工大学/卓凯麒
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号