基于Lattice MXO2的小脚丫FPGA核心板实现具有启动、停止、递增和清除功能的秒表
项目需求及分析
使用七段显示器作为输出设备,在小脚丫FPGA核心板上创建一个2位数秒表。实现如下功能:
1.秒表应从 0.0 秒计数到 9.9秒,然后翻转到0.0后重新开始计数,计数值每0.1秒精确更新一次
2.秒表使用四个轻触按键输入:开始、停止、增量和重置
3.开始输入使秒表开始以10Hz时钟速率递增(即每0.1秒计数一次)
4.停止输入使计数器停止递增,但使数码管显示当前计数器值
5.增量输入使每次按下按钮时,增量输入都会导致显示值增加一次(即0.1s),无论按住增量按钮多长时间
6.重置输入强制计数器值为零。
硬件介绍
小脚丫FPGA团队最新推出的FPGA核心模块,可以直接在浏览器里编程,一个USB Type C端口支持供电、FPGA的配置以及UART通信,管脚完全兼容传统的小脚丫FPGA模块。
如图,小脚丫FPGA核心板由两个数码管、RGB三色灯、单色LED和轻触按键组成。本次活动主要会用到数码管以及轻触按键,数码管用以显示当前秒表的数值,轻触按键用来控制秒表的启动、停止、递增以及清除功能。
实现的功能
实现秒表计数,并通过按键输入来控制秒表的状态:
1.按下开始按键:秒表开始计数,每0.1s计数一次,可从0.0秒计数到9.9秒,然后翻转;
2.按下停止按键:秒表停止计数,显示当前计数器的值;
3.按下增量按键:每按下一次按键,显示器数值增加一次;
4.按下重置按键:计数器置0。
实现方式
1.通过输入的时钟信号,设置计数器开始计数;
2.根据按键信号的输入调整计数器的状态;
3.7段数码显示管显示当前计数器的数值。
功能框图
代码及说明
输入为时钟以及按键信号,输出为7段显示管;计数标志指示计数器的状态处于运行或停止,增量标志用来判断时钟是否有增量,分别计算计数器的整数和小数部分数字,记录增量按键的前一状态用来判断增量信号的下降沿。
module miaobaio(
input clock, //clock signal
input start, //start button
input stop, //stop button
input increase, //increasement button
input reset, //reset button
output reg[8:0] led_zs, //7-segment display
output reg[8:0] led_xs
);
reg [23:0] cnt=24'd0;//counter
reg [3:0] zs=4'd0; //digit
reg [3:0] xs=4'd0;
reg cnt_flag=1'b0;//flag of the counter
reg increase_flag=1'b0;//flag of the increasement
reg pre_inc=1'b1; //the previous state of increasement
1.判断按键输入:启动信号输入时计数标志置1;停止信号输入时计数标志置0;重置信号输入时计数器以及整数和小数数字清零;增量信号输入时,根据增量信号前一状态判断此时是否为增量信号下降沿,若是,则增量标志置1,并改变增量信号前一状态。
2.根据输入信号调整计数状态:根据计数标志调整计数器状态,计数标志为1时,说明按下了开始按键,计数器开始运行,计数标志为0时,说明按下了停止按键,计数器停止运行;计数器处于运行状态时,每满0.1s,小数数字进1,小数数字满9后归零,整数数字进1,满9.9s后清零重新计数;当输入重置信号后,小数数字、整数数字以及当前计数器的数值全部置为0;当增量信号为低有效时,根据记录的增量信号前一状态,判断此时是否是增量信号的下降沿,若是,则增量标志置为1,计数器处于停止状态时,若增量标志为1,则增加1次。
3.数码管分别显示小数和整数部分数字。
always @(posedge clock)begin
//start button is pressed
if (start==1'b0)begin
cnt_flag<=1'b1;
end
//stop button is pressed
else if (stop==1'b0)begin
cnt_flag<=1'b0;
end
//reset button is pressed
else if (reset==1'b0)begin
cnt<=24'd0;
zs<=4'd0;
xs<=4'd0;
end
//increasement button is pressed
else if (increase==1'b0)begin
//ensure it is the negedge of increasement
if(pre_inc==1'b1)begin
increase_flag<=1'b1;
end
pre_inc<=1'b0;
end
//if increasement button is not pressed,reset the previous state of increasement
else if (increase==1'b1)begin
if(pre_inc==1'b0)begin
pre_inc<=1'b1;
end
end
//start button is pressed,start to run
if (cnt_flag==1'b1)begin
//reach 0.1s
if (cnt==24'd1199999)begin
cnt<=24'd0;
//check to carry a number
if(xs==4'd9) begin
xs<=4'd0;
if(zs==4'd9)begin
zs<=4'd0;
xs<=4'd0;
end
else begin
zs<=zs+4'd1;
end
end
else begin
xs<=xs+4'd1;
end
end
//not reach to 0.1s
else begin
cnt<=cnt+24'd1;
end
end
//stop button is pressed
else begin
//increasement button is pressed
if (increase_flag==1'b1)begin
increase_flag<=1'b0;
//check to carry a number
if(xs==4'd9)begin
xs<=4'd0;
if(zs==4'd9)begin
zs<=4'd0;
xs<=4'd0;
end
else begin
zs<=zs+4'd1;
end
end
else begin
xs<=xs+4'd1;
end
end
end
//output 7-segment display codes
case (zs)
4'd0:led_zs = 9'hbf;
4'd1:led_zs = 9'h86;
4'd2:led_zs = 9'hdb;
4'd3:led_zs = 9'hcf;
4'd4:led_zs = 9'he6;
4'd5:led_zs = 9'hed;
4'd6:led_zs = 9'hfd;
4'd7:led_zs = 9'h87;
4'd8:led_zs = 9'hff;
4'd9:led_zs = 9'hef;
endcase
case (xs)
4'd0:led_xs = {2'b00,7'h3f};
4'd1:led_xs = {2'b00,7'h06};
4'd2:led_xs = {2'b00,7'h5b};
4'd3:led_xs = {2'b00,7'h4f};
4'd4:led_xs = {2'b00,7'h66};
4'd5:led_xs = {2'b00,7'h6d};
4'd6:led_xs = {2'b00,7'h7d};
4'd7:led_xs = {2'b00,7'h07};
4'd8:led_xs = {2'b00,7'h7f};
4'd9:led_xs = {2'b00,7'h6f};
endcase
end
endmodule
实现的功能
1.秒表计数功能:最初秒表显示0.0,按下开始按键后,秒表开始计数,每0.1s增加一次,当计数器满9.9s后,重新回到0.0s继续计数;
2.秒表停止功能:按下停止按键后,秒表停止计时,数码管显示当前数值;
3.秒表递增功能:按下递增按键后,秒表显示值增加0.1s,若当前为9.9s,则秒表重新回到0.0s;
4.秒表清除功能:按下清除按键后,数码管显示值为0.0s。
仿真波形
分别将开始、停止、递增和清除信号置为有效后,数码管显示数值如下:
FPGA资源利用
遇到的难题
增量实现
题目要求每按下一次增量按键,显示器数值增加一次,且无论按住多长时间。若在时钟上升沿对增量按键状态进行判断后操作,会导致按下增量按键后,显示值的增加与时间有关。
解决办法
需要记录增量信号的前一状态,在时钟上升沿时,判断增量信号的下降沿是否出现,当处于增量信号下降沿时,增量标志置为1,实现递增操作。
未来的计划建议
该项目成功实现了秒表的开始、停止、递增和清除,达到了预期目标。然而该秒表功能较为单一。FPGA核心板利用部分较少,可设置更多功能,使小脚丫核心板利用更充分。