一、任务背景
本实验的目标在于利用Lattice MXO2 FPGA核心板,通过Type C接口实现一个功能丰富的秒表设计。该秒表将具备启动、停止、递增和清除等功能。通过这一实验,深入探究FPGA的设计流程,通过实践掌握如何利用FPGA实现复杂的计时逻辑。这不仅将加深对FPGA技术的理解,也将提升对数字电路设计领域的实践能力。
二、硬件介绍
Lattice MXO2的小脚丫FPGA核心板具有以下特性:
- 采用USB Type C接口,实现了板上+5V供电、FPGA的配置以及UART通信功能,意味着使用者无需再通过其他端口与PC进行数据通信。
- 支持U盘模式下载,只需将核心板连接到上位机的USB端口,上位机便会自动识别StepFPGA的U盘盘符。这使得任何操作系统的电脑都可以在不安装任何驱动程序的情况下,直接将生成的jed配置文件发送到StepFPGA盘中完成编程。
图1 小脚丫STEP-MXO2-LPC
图2模板结构
图3 引脚定义
三、项目功能介绍
在这项实验中,运用Verilog代码和FPGA主板,着手实现一个功能比较齐全的秒表系统。通过利用FPGA内部的时钟资源和计数器,精准地实现秒表的计时的功能。其次,Type C接口为我们提供了与FPGA核心板进行通信的便利渠道,能够轻松地控制秒表的启动、停止、递增和清除功能。因此,这个实验不仅是对数字电路设计的一次深入探索,也是对FPGA技术在实际应用中的有力验证。通过这个项目,加深对FPGA技术的理解,并掌握实现复杂功能的关键技能。
四、设计思路
在Verilog代码中,首先设置了FPGA的时钟资源,以确保秒表的准确性。接着,构建一个计数器模块的代码,用于实现秒表的计时功能。随后,设计一个状态机,负责控制秒表的各种操作,包括启动、停止、递增和清除。最后,通过Type C接口与Lattice MXO2 FPGA核心板进行通信,实现对秒表的控制。
五、实验步骤
1. 功能程序的实现
- 首先,定义了一个名为stopwatch的模块,该模块具有五个输入端口和两个输出端口。输入端口包括时钟信号clk、启动信号start、暂停信号pause、递增信号increase、重置信号restart,而输出端口则为两个7段LED数码管的输出seg_led_1和seg_led_2。
- 其次,接着声明了一个24位的计数器counter,并定义了一些控制信号,包括start_flag和increase_flag。此外,创建了两个寄存器seg_data_1和seg_data_2,用于存储7段LED数码管的数据。
- 在代码中使用always块对时钟上升沿、重置信号下降沿和递增信号下降沿进行敏感处理。主要目的是检查重置信号是否被激活,如果是,则将计数器和段数据重置为0。如果不是,检查递增信号是否被激活,若是,将递增标志设置为1。接着,检查秒表是否已启动,若是,将递增标志设置为0,并检查计数器是否达到限制。若达到限制,则将计数器重置为0,并且递增段数据。然后,如果第二个数字达到9,其将被重置为0并递增第一个数字。如果秒表未启动,则检查递增标志是否为1,若是,则递增段数据并按照类似的逻辑重置数字。
图4 功引脚介绍
2. 按键介绍(轻触按键)
- L14 =启动按钮
- M13 =暂停按钮
- M14 =清零/重新开始
六、资源利用
以下是我在制作项目中的一个访问GPT过程:
七、实验结果
1. 功能代码
module stopwatch(
input wire clk, // 时钟信号
input wire start, // 开始按钮信号
input wire pause, // 暂停按钮信号
input wire increase, // 增加按钮信号
input wire restart, // 重置按钮信号
output reg [8:0] seg_led_1,
output reg [8:0] seg_led_2
);
// 内部变量定义
reg [23:0] counter = 0; // 计时器计数器,初始化为0
reg [3:0] seg_data_1 = 0; // 整数部分值,初始化为0
reg [3:0] seg_data_2 = 0; // 小数部分值,初始化为0
reg start_flag = 0; // 开始标志,初始化为0
// 按钮去抖动模块实例化
debounce debounce_start(
.clk(clk),
.rst(restart),
.key(start),
.key_pulse(start_pulse)
); // 开始按钮去抖动
debounce debounce_pause(
.clk(clk),
.rst(restart),
.key(pause),
.key_pulse(pause_pulse)
); // 暂停按钮去抖动
debounce debounce_increase(
.clk(clk),
.rst(restart),
.key(increase),
.key_pulse(increase_pulse)
); // 增加按钮去抖动
数字递增的逻辑
task display;
begin
seg_data_2 <= (seg_data_2 >= 9) ? 0 : seg_data_2 + 1;
seg_data_1 <= (seg_data_2 >= 9) ? ((seg_data_1 >= 9) ? 0 : seg_data_1 + 1) : seg_data_1;
end
endtask
// 功能实现的代码
always @(posedge clk) begin
start_flag <= (!restart) ? 1'b0 :
(start_pulse) ? 1'b1 :
(pause_pulse) ? 1'b0 : start_flag;
seg_data_1 <= (!restart) ? 4'd0 : seg_data_1;
seg_data_2 <= (!restart) ? 4'd0 : seg_data_2;
counter <= (!restart) ? 24'b0 : counter;
counter <= (start_flag && !(counter == 24'd1200000)) ? counter + 1 :
(start_flag && (counter == 24'd1200000)) ? 24'd0 : counter;
if (start_flag && counter == 24'd1200000) display();
if (increase_pulse) display();
end
// 显示逻辑
function [8:0] seg_code(input [3:0] binary);
begin
case (binary)
4'd0: seg_code = 9'hbf;
4'd1: seg_code = 9'h86;
4'd2: seg_code = 9'hdb;
4'd3: seg_code = 9'hcf;
4'd4: seg_code = 9'he6;
4'd5: seg_code = 9'hed;
4'd6: seg_code = 9'hfd;
4'd7: seg_code = 9'h87;
4'd8: seg_code = 9'hff;
4'd9: seg_code = 9'hef;
default: seg_code = 9'h00;
endcase
end
endfunction
// 显示逻辑
always @* begin
seg_led_1 = seg_code(seg_data_1);
seg_led_2 = seg_code(seg_data_2);
end
endmodule
2. 结果展示
八、实验总结
经过实验,顺利地完成了基于Lattice MXO2 FPGA核心板的秒表设计,并通过Type C接口,实现了对秒表的启动、停止、递增和清除功能的控制。
九、未来需要改善的地方
时序约束的制定并不够完善,需要进一步优化以确保设计满足时序要求。另外,尚未成功添加异步复位逻辑,这导致设计功能尚未达到理想的稳定状态。因此,需要对时序约束进行调整和完善,并添加异步复位逻辑以提高设计的稳定性和可靠性。
十、后记
在代码测试过程中,由于未正确处理输入信号的上升沿,导致影响了后续其他信号未能正确响应其功能。因此,在调试过程中,可以会将尝试再修正了输入信号的存储和处理逻辑,包括对上升沿和下降沿的处理。