2024年“寒假在家一起练”——fpga实现多功能秒表
该项目使用了Lattice MXO2的小脚丫FPGA核心板,实现了计时时钟的设计,它的主要功能为:10s计时秒表,可控制秒表开启、关闭、增加与重置计时。
标签
FPGA
寒假一起练
计时
张伟伟
更新2024-03-29
204

一.项目介绍

本项目基于Lattice MXO2的小脚丫FPGA核心板,利用板上数码管与按键实现了10s计时秒表,精度为0.1s,可控制秒表开启、关闭、增加与重置计时,具有一定的实用价值。项目的具体要求如下

  • 使用七段显示器作为输出设备,在小脚丫FPGA核心板上创建一个2位数秒表。 秒表应从 0.0 秒计数到 9.9秒,然后翻转,计数值每0.1秒精确更新一次。
  • 秒表使用四个按钮输入:开始、停止、增量和清除(重置)。 开始输入使秒表开始以10Hz时钟速率递增(即每0.1秒计数一次); 停止输入使计数器停止递增,但使数码管显示当前计数器值; 每次按下按钮时,增量输入都会导致显示值增加一次,无论按住增量按钮多长时间; 复位/清除输入强制计数器值为零。

 

二.设计思路

根据项目要求,项目实现思路如下

图片.png

首先将核心板上时钟信号分频为10Hz信号,对脉冲进行计数,同时检测按键状态更改计数状态,最后将计数结果显示在数码管上。

三.对话生成

项目要求使用生成式大模型辅助编写verilog代码,采用Microsoft Copilot来生成上述四个模块,最终在主模块中实例化并连接起来

当然,大模型提供的代码大多无法直接使用,还需要引导与调教后才可以应用在实际场景中,但可以帮助工程师梳理思路并减少简单或重复性的工作。

四.代码与功能展示

代码主模块如下,其中分频模块与消抖模块不再赘述。程序较为简单且注释详细,讲解实际效果可参照项目视频。

module main(
led,hold_flag,
rst,
clk, // 时钟信号
key, // 输入信号,开启,停止,强制
segment_code1, // 八段数码管编码输出十位
segment_code2 // 八段数码管编码输出个位
);

input clk; // 时钟信号
input rst; // 复位信号
input [2:0]key; // 输入信号
output [8:0] segment_code1; // 八段数码管编码输出十位
output [8:0] segment_code2; // 八段数码管编码输出个位
output led;
output reg hold_flag; //按键标志位


wire clk1h; //分频时钟
wire [2:0] hold_key; //按键消抖后信号
reg [6:0] seg [9:0];
reg [4:0] cnt_ge1; //个位
reg [4:0] cnt_shi1; //十位
reg [4:0] cnt_ge2; //个位
reg [4:0] cnt_shi2; //十位
reg [4:0] cnt_ge; //个位
reg [4:0] cnt_shi; //十位


initial
begin
seg[0] = 7'h3f; // 0
seg[1] = 7'h06; // 1
seg[2] = 7'h5b; // 2
seg[3] = 7'h4f; // 3
seg[4] = 7'h66; // 4
seg[5] = 7'h6d; // 5
seg[6] = 7'h7d; // 6
seg[7] = 7'h07; // 7
seg[8] = 7'h7f; // 8
seg[9] = 7'h6f; // 9
end

// 用于分出一个10Hz的频率
divide #(.WIDTH(32),.N(1200000)) U1 (
.clk(clk),
.rst_n(rst),
.clkout(clk1h)
);

// 启动/暂停按键进行消抖
debounce U2 (
.clk(clk),
.rst(rst),
.key(key),
.key_pulse(hold_key)
);


//99计时控制
always @ (posedge clk1h or negedge rst) begin
if (!rst == 1) begin
cnt_ge1 <= 4'd0;
cnt_shi1 <= 4'd0;
end
else if(hold_flag == 1)begin
cnt_ge1 <= cnt_ge1;
cnt_shi1 <= cnt_shi1;
end
else if(cnt_shi1==9 && cnt_ge1==9) begin
cnt_shi1 <= 0;
cnt_ge1 <= 0;
end
else if(cnt_ge1==9)begin
cnt_ge1 <= 4'd0;
cnt_shi1 <= cnt_shi1+1;end
else
cnt_ge1 <= cnt_ge1 +1;
end

always @ (posedge hold_key[2] or negedge rst) begin
if (!rst == 1) begin
cnt_ge2 <= 4'd0;
cnt_shi2 <= 4'd0;
end
else if(cnt_shi2==9 && cnt_ge2==9) begin
cnt_shi2 <= 0;
cnt_ge2 <= 0;
end
else if(cnt_ge2==9)begin
cnt_ge2 <= 4'd0;
cnt_shi2 <= cnt_shi2+1;end
else
cnt_ge2 <= cnt_ge2 +1;
end

always @ (posedge clk or negedge rst) begin
if (!rst == 1) begin
cnt_ge <= 4'd0;
cnt_shi <= 4'd0;
end
cnt_ge<=(cnt_ge1+cnt_ge2)%10;
if (cnt_ge1+cnt_ge2>10)
cnt_shi <= (cnt_shi1+cnt_shi2+1)%10;
else
cnt_shi <= (cnt_shi1+cnt_shi2)%10;
end

//开启/关闭信号
always @ (posedge hold_key[0] or posedge hold_key[1])
if(hold_key[0]==1)
hold_flag <= 0;
else if(hold_key[1]==1)
hold_flag <= 1;

assign segment_code1[8:0] = {2'b01,seg[cnt_shi]};
assign segment_code2[8:0] = {2'b00,seg[cnt_ge]};
assign led = clk1h;

endmodule

资源占用如下

图片.png

五.遇到的问题

开发过程中出现了两个问题:

  1. 工程无法映射编译:由于初次使用stepfpga网页端编写verilog程序,未发现编译报错导致无法下载正常工程,之后阅读了编译日志后发现由于一寄存器变量同时被两个模块驱动无法通过编译
  2. 模块触发条件:从原理来说,增量输入触发的计数增加与时钟触发的计数增加并无区别,可将按键与分频时钟作为计数增加电路的触发条件,但这样写实际会导致数码管闪耀,无法正常显示,目前也未找到解决方法。

六.总结与感受

本项目锻炼了我的信息搜集能力和编程能力,对嵌入式开发有了新的体会,受益匪浅。未来期望再次参加活动,了解并学习更多的知识,掌握更多的技能,开拓电子芯片在生活中运用的视野。


附件下载
implement.jed
团队介绍
某不知名工程师
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号