2024年寒假练-基于STEP-MO2实现具有启动、停止、递增和清除功能的秒表
该项目使用了WebIDE,verilog语言,实现了秒表的设计,它的主要功能为:具有启动、停止、递增和清除功能,使用七段显示器作为输出设备。
标签
数字逻辑
开发板
参加活动/培训
PPdzw
更新2024-04-01
南京信息工程大学
148

一、项目需求:

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

2.秒表使用四个按钮输入:开始、停止、增量和清除(重置)。 开始输入使秒表开始以10Hz时钟速率递增(即每0.1秒计数一次); 停止输入使计数器停止递增,但使数码管显示当前计数器值; 每次按下按钮时,增量输入都会导致显示值增加一次,无论按住增量按钮多长时间; 复位/清除输入强制计数器值为零。

二、设计思路

1.使用分频器,把12M Hz变为10Hz

2.加入一个数码管模块,其中数码管1需要显示小数点,数码管2只需显示0-9

3.写一个0-99的计数器,使其可以翻转。

4.写一个按键防抖的模块,和按钮控制的代码。

三、实现的功能

 1.数码管0.0-9.9的显示且翻转。

2.清零功能。

 3.开始、暂停、递增功能。且长按按钮也只会递增一次。

四、主要代码片段及说明

1.0-99计数器片段

if (run ) begin
if (cnt[3:0] == 4'd9) begin
if (cnt[7:4] == 4'd9) begin
cnt <= 8'd0; // 个位和十位都为9,将计数器重置为0
end else begin
cnt[7:4] <= cnt[7:4] + 1'b1; // 十位加1
cnt[3:0] <= 4'd0;
end
end else begin
cnt[3:0] <= cnt[3:0] + 1'b1; // 个位加1
end
end

这段代码里,cnt占8比特,共8位。其中,前四位用来控制第一个数码管,充当十位,后四位用来控制第二个数码管,也就是个位。当识别到运行标志符“run”为1时,判断个位是否为9,若不为9,则加一个比特;若判断为9,则再判断十位是否为9,若是则置零,反之则十位加一,个位清零。

2.实现启动、停止、递增和清除功能的按键

always @(posedge clk10h or negedge rstn) begin
if (!rstn) begin
cnt <= 8'd0; // 复位计数器
run <= 0; // 清除运行标志位
flag <=1;
end else begin
// 处理按钮按下和释放事件
if (key[3] ==0 ) begin
run<=0;
cnt<=0;
end if (key[0] == 0 ) begin
// 如果按钮0被按下
run <= 1; // 设置运行标志位
end else if (key[1] == 0 ) begin
// 如果按钮1被按下
run <= 0; // 清除运行标志位
end else if (key[2] == 0 && flag==1) begin
// 如果按钮2被按下
begin
if (cnt[3:0] == 4'd9) begin
if (cnt[7:4] == 4'd9) begin
cnt <= 8'd0; // 个位和十位都为9,将计数器重置为0
end else begin
cnt[7:4] <= cnt[7:4] + 1'b1; // 十位加1
cnt[3:0] <= 4'd0;
end
end else begin
cnt[3:0] <= cnt[3:0] + 1'b1; // 个位加1
end
flag <=0;
end
end else if (key [2] == 1) begin
flag=1;
end

key0、1、2、3分别代表了开始、暂停、递增、清零,其中设置了两个运行标志位:run和flag,分别控制key0、1、3和key2。这两个运行标志位的意义是为了识别按键是否按下,若按下则运行下一步;即使按键被长按,该流程也可以仅被执行一次。其中,对于flag,当按键2被按下时,我们分析目前cnt的状态并根据状态选择递增的数字该如何表达(同上面的计数器);在增加0.1后,我们要将flag重新变为0,等待下一次按键2按下时再变为1,再重新运行一遍。而其他按键,则分别识别其对应的按键是否被按下后,再进行run的赋值,以便后续计数器的判断。

3.数码管显示的模块

module segment (seg_data_1,seg_data_2,seg_led_1,seg_led_2);
input [3:0] seg_data_1;
input [3:0] seg_data_2;
output [8:0] seg_led_1;
output [8:0] seg_led_2;
reg [8:0] seg [9:0];
reg [8:0] segment [9:0];

initial
begin
segment[0] = 9'h3f;
segment[1] = 9'h06;
segment[2] = 9'h5b;
segment[3] = 9'h4f;
segment[4] = 9'h66;
segment[5] = 9'h6d;
segment[6] = 9'h7d;
segment[7] = 9'h07;
segment[8] = 9'h7f;
segment[9] = 9'h6f;
end
initial
begin
seg[0] = 9'b10111111;
seg[1] = 9'b10000110;
seg[2] = 9'b11011011;
seg[3] = 9'b11001111;
seg[4] = 9'b11100110;
seg[5] = 9'b11101101;
seg[6] = 9'b11111101;
seg[7] = 9'b10000111;
seg[8] = 9'b11111111;
seg[9] = 9'b11101111;
end
assign seg_led_1 = seg[seg_data_1];
assign seg_led_2 = segment[seg_data_2];
endmodule

因为题目中数码管需要显示小数点,所以让代表十位的数码管“seg”的所有数字都要显示小数点,代表个位的数码管“segment”的所有数字都不显示小数点,最后在模块的最后用assign分别定义。

4.时钟分频

divide#             //Generate a 100ms Clock Signal
(.WIDTH(24),
.N(1200000)
)u1
(
.clk(clk),
.rst(rstn),
.clkout(clk10h)
);

时钟分频我们可以使用stepfpga提供的参考代码,并通过计算填入主要数据,最后得到10Hz的分频时钟。

5.按键防抖

module debounce (clk,rst,key,key_pulse);
input clk;
input rst;
input [3:0] key;
output [3:0] key_pulse;
reg [3:0] key_rst_pre;
reg [3:0] key_rst;
wire [3:0] key_edge;

always@(posedge clk or negedge rst)
begin
if (!rst) begin
key_rst <= {4{1'b1}};
key_rst_pre <= {4{1'b1}};
end
else begin
key_rst<=key;
key_rst_pre <= key_rst;
end
end
assign key_edge = key_rst_pre & (~key_rst);
reg [17:0] cnt;

always@(posedge clk or negedge rst)
begin
if(!rst)
cnt <= 18'h0;
else if(key_edge)
cnt <= 18'h0;
else
cnt <= cnt + 1'h1;
end
reg [3:0] key_sec_pre;
reg [3:0] key_sec;

always@(posedge clk or negedge rst)
begin
if (!rst)
key_sec <= {4{1'b1}};
else if (cnt==18'h3ffff)
key_sec <= key;
end
always @(posedge clk or negedge rst)
begin
if (!rst)
key_sec_pre <= {4{1'b1}};
else
key_sec_pre <= key_sec;
end
assign key_pulse = key_sec_pre & (~key_sec);
endmodule

由于机械触点的弹性作用,一个按键在闭合及断开的瞬间均伴随着一连串的抖动,因此我们采用一个模块来消除这种抖动。监测到按键按下的信号后,进行10-20ms延时,当前的抖动消失后再一次检测按键的状态。如果发现仍然是被按下的信号,我们就让接下来的程序启动;如果发现按键被释放,也做10ms-20ms的延时,以确认这是一次真正的按键释放。

五、关于GPT问询和仿真


以上为部分问询电子森林自带的ai助手的照片,在没有头绪的时候,gpt帮助了我很多。代码并不完全正确,借鉴完它之

后仍需自己整合调试。


上图为我在webid上截下的run.log的资源报告。


上图为对时钟进行的仿真。

六、遇到的主要难题及解决方法

1.如何显示小数点:如上文所述,可以让两个数码管的数字分别显示。

2.如何让按键就算长按也只运行一次:可以增加一个运行标志符,让系统自己识别一下按键是否已经按下了。

七、未来的计划和建议

1.通过未来系统的学习verilog语言,可以挑战难度更高的任务。

2.希望可以更加精简语句,尽量让代码效率更高。

3.希望能养成良好的代码习惯,让代码看起来更加美观、整齐。









附件下载
implement-63.jed
jed文件
archive-3.zip
整个项目的压缩包
test2.txt
txt文件
团队介绍
张颖 南京信息工程大学
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号