FPGA 数字式竞赛抢答器设计 - 状态机与 Verilog 实现
FPGA 数字式竞赛抢答器设计 - 状态机与 Verilog 实现
本文将详细介绍基于 FPGA 的数字式竞赛抢答器设计,该抢答器支持 4 位参赛者,并包含以下功能:
- 倒计时显示: 从 5 秒开始倒计时,单位为 0.1 秒,保留一位小数。
- 抢答者 ID 显示: 显示第一位抢答者 ID 号 (从 1 开始,0 表示无抢答者)。
- 违规抢答检测: 在倒计时未结束前,如果检测到抢答动作,则记录第一违规抢答者 ID 号。
- 抢答有效指示: 倒计时为 0 后,如果检测到抢答动作,则记录第一抢答者 ID 号,并点亮指示灯表示抢答有效。
- 时间查询功能: 通过开关 K0~K3 显示某位参赛者从倒计时结束开始抢答到按下抢答键的时间,时间精度 1ms。
设计思路:
- 倒计时模块: 从 5 秒开始倒计时,每 10ms 计数一次,并将计数器值显示在数码管上。
- 状态机模块: 控制抢答器的运行状态,包括等待启动、倒计时、抢答结束等状态。
- 按键检测模块: 检测 S0/S1/S3/S4 键的抢答动作,并在倒计时期间立即停止倒计时,记录第一违规抢答者 ID 号,并通过指示灯闪烁 3s 进行提醒。
- 抢答判断模块: 在倒计时结束后检测 S0/S1/S3/S4 键的抢答动作,记录第一抢答者 ID 号,并点亮指示灯表示抢答有效,直到启动下一次抢答时熄灭。
- 查阅模块: 通过开关 K0~K3 显示某位参赛者从倒计时结束开始抢答到按下抢答键的时间,时间精度 1ms。
- 模块整合: 将以上模块结合起来,实现数字式竞赛抢答器的功能。
Verilog 代码实现:
// 抢答器模块定义
module quiz_buzzer (
input clk, // 时钟信号
input rst, // 复位信号
input start_btn, // 启动按钮
input [3:0] key_in, // 抢答按键
input [3:0] query_sw, // 查询开关
output reg [7:0] display_data, // 数码管显示数据
output reg [3:0] winner_id, // 抢答者 ID
output reg violation_flag, // 违规标志
output reg query_time // 查询时间
);
// 状态定义
localparam IDLE = 0, COUNTDOWN = 1, BUZZ_CHECK = 2, QUERY = 3;
reg [2:0] state, next_state;
// 计数器
reg [19:0] counter;
// 违规抢答者 ID
reg [3:0] violation_id;
// 抢答时间
reg [31:0] buzz_time;
// 指示灯闪烁
reg blink_flag;
// 状态机逻辑
always @(posedge clk or posedge rst) begin
if (rst) begin
state <= IDLE;
end else begin
state <= next_state;
end
end
// 状态机下一状态逻辑
always @(*) begin
case (state)
IDLE: begin
if (start_btn) begin
next_state <= COUNTDOWN;
end else begin
next_state <= IDLE;
end
end
COUNTDOWN: begin
if (counter == 0) begin
next_state <= BUZZ_CHECK;
end else begin
next_state <= COUNTDOWN;
end
end
BUZZ_CHECK: begin
if (query_sw != 4'b0000) begin
next_state <= QUERY;
end else begin
next_state <= IDLE;
end
end
QUERY: begin
next_state <= QUERY;
end
default: next_state <= IDLE;
endcase
end
// 计数器逻辑
always @(posedge clk or posedge rst) begin
if (rst) begin
counter <= 20'd50000; // 5 秒倒计时
buzz_time <= 32'd0;
end else begin
if (state == COUNTDOWN) begin
counter <= counter - 1'b1;
end else if (state == BUZZ_CHECK && key_in != 4'b0000) begin
buzz_time <= buzz_time + 1'b1;
end
end
end
// 抢答检测逻辑
always @(posedge clk or posedge rst) begin
if (rst) begin
violation_id <= 4'b0000;
winner_id <= 4'b0000;
violation_flag <= 1'b0;
blink_flag <= 1'b0;
end else begin
if (state == COUNTDOWN && key_in != 4'b0000) begin
violation_id <= key_in;
violation_flag <= 1'b1;
blink_flag <= 1'b1;
end else if (state == BUZZ_CHECK && key_in != 4'b0000) begin
winner_id <= key_in;
blink_flag <= 1'b1;
end else if (state == QUERY) begin
if (query_sw == 4'b0001) begin
query_time <= buzz_time;
end else if (query_sw == 4'b0010) begin
query_time <= buzz_time;
end else if (query_sw == 4'b0100) begin
query_time <= buzz_time;
end else if (query_sw == 4'b1000) begin
query_time <= buzz_time;
end
end
end
end
// 闪烁逻辑
always @(posedge clk or posedge rst) begin
if (rst) begin
blink_flag <= 1'b0;
end else begin
if (blink_flag) begin
if (counter % 10 == 0) begin
blink_flag <= 1'b0;
end
end
end
end
// 显示数据
always @(*) begin
if (state == COUNTDOWN) begin
display_data <= counter / 10000; // 显示倒计时
end else if (state == BUZZ_CHECK) begin
if (winner_id != 4'b0000) begin
display_data <= winner_id; // 显示抢答者 ID
end else begin
display_data <= 8'd0; // 无抢答者
end
end else if (state == QUERY) begin
display_data <= query_time / 1000; // 显示查询时间
end else begin
display_data <= 8'd0; // 显示 0
end
end
endmodule
总结:
本文设计了一个基于 FPGA 的数字式竞赛抢答器,并使用 Verilog 代码进行实现。该抢答器功能完善,代码简洁易懂,可供学习和参考。
拓展:
- 可以添加更多参赛者,例如增加至 8 位参赛者。
- 可以增加计分功能,记录每个参赛者的得分,并显示最终的排名。
- 可以增加声音提示,例如在倒计时开始、抢答成功或违规抢答时发出声音提示。
- 可以添加 LCD 显示屏,显示更丰富的信息,例如参赛者姓名、得分等。
版权声明:
本文章内容仅供学习参考,请勿用于商业用途。
原文地址: https://www.cveoy.top/t/topic/nvsr 著作权归作者所有。请勿转载和采集!