基于Lattice MXO2的小脚丫FPGA核心板 - Type C接口的项目实验报告
具有启动、停止、递增和清楚功能的秒表
一、 项目需求
通过小脚丫FPGA核心板上的2个数码管和轻触按键制作一个秒表,通过按键来控制秒表的功能,并在数码管上显示数值。
需要达到以下功能:
1. 使用七段显示器作为输出设备,在小脚丫FPGA核心板上创建一个2位数秒表。
2. 秒表应从 0.0 秒计数到 9.9秒,然后翻转,计数值每0.1秒精确更新一次。
3.秒表使用四个按钮输入:开始、停止、增量和清除(重置)。 开始输入使秒表开始以10Hz时钟速率递增(即每0.1秒计数一次); 停止输入使计数器停止递增,但使数码管显示当前计数器值; 每次按下按钮时,增量输入都会导致显示值增加一次,无论按住增量按钮多长时间; 复位/清除输入强制计数器值为零。
二、 需求分析
(一)功能需求:
1. 显示设备:使用小脚丫FPGA核心板上的两个七段数码管作为显示设备,显示秒表的值。
2. 秒表功能:能够实现从0.0秒计数到9.9秒,在达到9.9秒后自动翻转到0.0秒,精确度为0.1秒,即每0.1秒更新一次数值。
3. 按键输入:设计四个按钮用于控制秒表的功能:
- 开始按钮:按下开始时秒表开始计时,每0.1秒递增一次;
- 停止按钮:按下停止时,停止计时但保持当前计数值显示;
- 增量按钮:按下增量时,显示值立即增加一次,按住增量按钮无效;
- 清除按钮:按下清除时,强制将计数器值归零。
(二)系统设计:
1.模块划分:设计秒表模块、按键输入模块和数码管显示模块。
2.秒表计时:通过时钟信号进行计时,实现从0.0秒到9.9秒的计数,达到9.9秒后自动翻转。
3. 按键控制:根据按键输入控制秒表的开始、停止、增量和清除功能。
4. 数码管显示:根据计数值将对应的数字显示在两个七段数码管上,实现秒表数值的实时显示。
(三)性能需求:
1. 稳定性:秒表功能稳定可靠,显示精确度达到0.1秒。
2. 按键响应:按键响应迅速,操作流畅,确保用户体验友好。
3. 节约资源:设计合理,尽量节约FPGA资源,提高系统性能。
(四)验收标准:
1. 功能验证:秒表能够满足从0.0秒到9.9秒的计时要求,并能正确响应按键控制功能。
2. 显示正确:数码管上显示的数值能够准确反映秒表的计时情况。
3. 用户操作:按键操作顺畅,功能实现符合预期,系统稳定可靠。
三、 实现的方式
在WebIDE环境下进行Verilog代码编程、综合、仿真、生成JED代码并下载到FPGA中进行验证。
每一个功能模块都通过GPT等大模型来生成,进行验证、修改后整合在一起实现所需的功能。
(一)设计方案:
1. 秒表模块设计:
- 使用FPGA内部时钟模块作为计时基准,每0.1秒触发一次计数更新;
- 设计状态机,实现秒表的计数和翻转功能。
2. 按键输入模块设计:
- 使用GPIO接口读取四个轻触按键的状态,分别对应开始、停止、增量和清除功能。
3. 数码管显示模块设计:
- 利用FPGA内部七段数码管驱动器模块控制两个七段数码管的显示;
- 将秒表的计数值转换为数码管对应的显示码,实时显示在数码管上。
(二)实现步骤:
1. 秒表计时功能实现:
- 使用FPGA内部时钟作为时间基准,每0.1秒触发一次计数,实现秒表的计时功能;
- 设计状态机控制计数递增和翻转。
2. 按键控制功能实现:
- 根据按键输入状态,实现开始、停止、增量和清除功能的响应;
- 开始按钮触发计时递增,停止按钮暂停计时并显示当前计数值,增量按钮使计数值增加一次,清除按钮将计数值归零。
3. 数码管显示实现:
- 将计数值转换为数码管对应的显示码,通过七段数码管驱动器在两个数码管上显示秒表数值;确保数码管显示的值与秒表计数值同步更新,保持显示精确度。
通过以上设计和实现,可以实现使用小脚丫FPGA核心板上的两个七段数码管和轻触按键制作一个秒表,并实现开始、停止、增量和清除功能的控制。同时,在数码管上能够准确显示秒表的计数数值,满足所需功能要求。
四、功能框图
五、代码
top.v
module top(
input clk_12M,
input reset_n,
input stop_n,
input start_n,//开始
input add_n,//递增
output [7:0] seg1,//数码管
output [7:0] seg2,//数码管
output [1:0] seg_digit
);
assign seg_digit = 2'b00;
//时钟分频
wire clk_10;
clk_div i_clk_div(
.clk_12M (clk_12M),
.reset_n (reset_n),
.clk_10 (clk_10)
);
//按键消抖
wire stop_pulse;
wire start_pulse;
wire add_pulse;
debounce i1_debounce(clk_12M, reset_n, stop_n, stop_pulse);
debounce i2_debounce(clk_12M, reset_n, start_n, start_pulse);
debounce i3_debounce(clk_12M, reset_n, add_n, add_pulse);
//计时器
wire [3:0] digit1;
wire [3:0] digit2;
clock i_clock(
.clk_12M (clk_12M),
.clk_10 (clk_10),
.reset_n (reset_n),
.stop_pulse (stop_pulse),
.start_pulse (start_pulse),
.add_pulse (add_pulse),
.digit1 (digit1),
.digit2 (digit2)
);
//数码管显示
digit_display i_digit_display(
.digit1 (digit1),
.digit2 (digit2),
.seg1 (seg1),
.seg2 (seg2)
);
endmodule
clk_div.v
`timescale 1ns/1ns
//时钟分频:12MHz -> 10Hz
module clk_div(
input clk_12M,
input reset_n,
output clk_10
);
parameter DIVIDER = 12_000_00;
// parameter DIVIDER = 5;//for test
reg [31:0] cnt;
always @(posedge clk_12M) begin
if(~reset_n)
cnt <= 0;
else begin
if(cnt < DIVIDER - 1)
cnt <= cnt + 32'd1;
else
cnt <= 0;
end
end
assign clk_10 = (cnt == DIVIDER - 1) ? 1 : 0;
endmodule
clock.v
timescale 1ns/1ns
module clock(
input clk_12M,
input clk_10,
input reset_n,
input stop_pulse,
input start_pulse,
input add_pulse,
output reg[3:0] digit1, //0.1秒
output reg[3:0] digit2 //1秒
);
reg [31:0] cnt;
reg if_stop;
always @(posedge clk_12M) begin
if(~reset_n)
if_stop <= 1;
else begin
if(stop_pulse)
if_stop <= 1;
else if(start_pulse)
if_stop <= 0;
else
if_stop <= if_stop;
end
end
always@(posedge clk_12M)begin
if(~reset_n)begin
cnt <= 0;
digit1 <= 0;
end
else begin
if(add_pulse || (clk_10 && if_stop == 0))begin
if(digit1 == 9)
digit1 <= 0;
else
digit1 <= digit1 + 1;
end
else
digit1 <= digit1;
end
end
always @(posedge clk_12M) begin
if(~reset_n)
digit2 <= 0;
else begin
if((add_pulse || (clk_10 && if_stop == 0)) && digit1 == 9)begin
if(digit2 == 9)
digit2 <= 0;
else
digit2 <= digit2 + 1;
end
else
digit2 <= digit2;
end
end
endmodule
debounce.v
`timescale 1ns/1ns
module debounce(
input clk_12M,
input reset_n,
input btn,
output pulse
);
parameter HOLD = 120_000; //10ms
// parameter HOLD = 3; //1for test
reg [31:0] cnt;
reg btn_reg, btn_reg1;
always @(posedge clk_12M) begin
btn_reg1 <= btn_reg;
if(~reset_n)begin
btn_reg <= 1;
cnt <= 0;
end
else begin
if(btn == 0)begin
if(cnt < HOLD)
cnt <= cnt + 1;
else
btn_reg <= 0;
end
else begin
cnt <= 0;
btn_reg <= 1;
end
end
end
assign pulse = btn_reg1 & ~btn_reg;
endmodule
digit_display.v
`timescale 1ns/1ns
module digit_display(
input [3:0] digit1,
input [3:0] digit2,
output reg[7:0] seg1,
output reg[7:0] seg2
);
//个位,无小数点
always@(*)begin
case(digit1)
4'd0: seg1 = 8'b1111_1100;
4'd1: seg1 = 8'b0110_0000;
4'd2: seg1 = 8'b1101_1010;
4'd3: seg1 = 8'b1111_0010;
4'd4: seg1 = 8'b0110_0110;
4'd5: seg1 = 8'b1011_0110;
4'd6: seg1 = 8'b1011_1110;
4'd7: seg1 = 8'b1110_0000;
4'd8: seg1 = 8'b1111_1110;
4'd9: seg1 = 8'b1111_0110;
default: seg1 = 8'b0000_0000;
endcase
end
//十位
always@(*)begin
case(digit2)
4'd0: seg2 = 8'b1111_1101;
4'd1: seg2 = 8'b0110_0001;
4'd2: seg2 = 8'b1101_1011;
4'd3: seg2 = 8'b1111_0011;
4'd4: seg2 = 8'b0110_0111;
4'd5: seg2 = 8'b1011_0111;
4'd6: seg2 = 8'b1011_1111;
4'd7: seg2 = 8'b1110_0001;
4'd8: seg2 = 8'b1111_1111;
4'd9: seg2 = 8'b1111_0111;
default: seg2 = 8'b0000_0000;
endcase
end
endmodule
五、仿 真波形图
进位逻辑
按键效果
七、FPGA的资源利用说明
Design Summary:
Number of registers: 155 out of 4635 (3%)
PFU registers: 155 out of 4320 (4%)
PIO registers: 0 out of 315 (0%)
Number of SLICEs: 163 out of 2160 (8%)
SLICEs as Logic/ROM: 163 out of 2160 (8%)
SLICEs as RAM: 0 out of 1620 (0%)
SLICEs as Carry: 123 out of 2160 (6%)
Number of LUT4s: 326 out of 4320 (8%)
Number used as logic LUTs: 80
Number used as distributed RAM: 0
Number used as ripple logic: 246
Number used as shift registers: 0
Number of PIO sites used: 23 + 4(JTAG) out of 105 (26%)
Number of block RAMs: 0 out of 10 (0%)
Number of GSRs: 0 out of 1 (0%)
EFB used : No
JTAG used : No
Readback used : No
Oscillator used : No
Startup used : No
POR : On
Bandgap : On
Number of Power Controller: 0 out of 1 (0%)
Number of Dynamic Bank Controller (BCINRD): 0 out of 6 (0%)
Number of Dynamic Bank Controller (BCLVDSO): 0 out of 1 (0%)
Number of DCCA: 0 out of 8 (0%)
Number of DCMA: 0 out of 2 (0%)
Number of PLLs: 0 out of 2 (0%)
Number of DQSDLLs: 0 out of 2 (0%)
Number of CLKDIVC: 0 out of 4 (0%)
Number of ECLKSYNCA: 0 out of 4 (0%)
Number of ECLKBRIDGECS: 0 out of 2 (0%)
1. 输入控制:使用轻触按键资源作为输入控制器,通过按键的按下和释放来检测操作员的操作,包括开始、停止、增量和清除功能。
2. 计数器递增:需要使用FPGA内部的计数器模块来实现秒表的计数功能。通过10Hz的时钟信号来控制计数器的递增,实现每0.1秒更新一次计数值的功能。
3. 数码管显示:利用FPGA内部逻辑资源和数码管驱动器模块来实现数码管显示功能。根据计数器的数值,将对应的七段显示编码发送到数码管上,实现秒表值的显示。
4. 按钮状态检测:需要使用FPGA的IO资源来读取轻触按键的状态,判断用户是按下按钮还是释放按钮,从而控制相应的功能。
八、实现的结果