EDA抢答器课程设计如何实现?

99ANYc3cd6 课程介绍 1

EDA课程设计:多功能数字抢答器

设计任务与要求

  1. 基本功能:

    • 设计一个可供4名选手(或4个队)参加抢答的竞赛抢答器。
    • 主持人控制一个“开始”按钮和“复位”按钮。
    • 选手每人一个“抢答”按钮。
    • 主持人按下“开始”按钮后,抢答器进入抢答状态,选手方可抢答。
    • 任何一位选手按下抢答按钮后,抢答器立即锁定,并显示该选手的编号(如1-4号)。
    • 抢答封锁功能: 一旦有选手成功抢答,其他选手的抢答按钮将被无效化,即使按下也不再响应,直到主持人复位。
    • 违规提示: 在主持人按下“开始”按钮前,若有选手提前按下抢答按钮,应能识别并提示“违规”。
  2. 扩展功能(可选,用于提高设计档次):

    EDA抢答器课程设计如何实现?-第1张图片-指南针培训网
    • 计时功能: 主持人按下“开始”按钮后,启动一个倒计时(例如30秒),若倒计时结束仍无人抢答,则抢答器自动宣布本轮抢答无效,并显示“时间到”。
    • 声光提示:
      • 选手成功抢答时,对应的选手指示灯亮起,并伴有蜂鸣器提示音。
      • 选手违规时,违规指示灯亮起,并伴有不同的蜂鸣器提示音(急促的“嘀嘀”声)。
      • 倒计时结束时,发出提示音。
    • 分数显示: 设计一个简单的计分模块,可以为答对或答错的选手加分或减分。

设计思路与方案论证

本设计的核心是状态控制优先级判断,我们将整个抢答过程划分为几个不同的状态,并通过状态机来管理。

  1. 状态划分:

    • S_IDLE (空闲状态): 系统初始状态或复位后的状态,等待主持人按下“开始”按钮。
    • S_READY (准备状态): 主持人已按下“开始”按钮,系统允许选手抢答。
    • S_ANSWERED (已抢答状态): 已有选手成功抢答,系统锁定,显示获胜者编号。
    • S_VIOLATION (违规状态):S_IDLE状态下,有选手提前按下按钮,系统锁定,显示违规信息。
    • S_TIMEOUT (超时状态):S_READY状态下,倒计时结束,无人抢答,系统锁定,显示超时信息。
  2. 核心模块划分:

    • 控制模块: 整个系统的“大脑”,负责状态切换、控制其他模块的使能和复位。
    • 优先编码器模块: 用于在S_READY状态下,4个选手信号同时到来时,判断出优先级最高的一个(编号最小的)。
    • 锁存/显示模块: 用于在抢答成功后,锁存并稳定显示获胜选手的编号。
    • 计时模块:S_READY状态下,启动倒计时计数器。
    • 声光提示模块: 根据当前状态,驱动LED和蜂鸣器。
  3. 方案选择:

    • 硬件平台: 采用 FPGA (Field-Programmable Gate Array)CPLD (Complex Programmable Logic Device),FPGA/CPLD的并行处理能力和可重构性使其非常适合实现这种逻辑控制电路,推荐使用 Altera (Intel) Quartus II 软件配合 DE2-115 或类似的开发板,资源丰富,易于实现。
    • 设计方法: 采用 自顶向下 的设计方法。
      • Top-Level (顶层模块): 例化所有底层模块,连接输入输出端口。
      • 底层模块: 分别实现优先编码器、计时器、显示控制等功能,使设计结构清晰,易于调试。

硬件设计与模块划分

以下是顶层模块的接口定义和内部模块连接示意图。

顶层模块 接口定义:

端口名 方向 描述
clk Input 系统时钟,如50MHz
rst_n Input 异步复位信号,低电平有效
start_btn Input 主持人“开始”按钮
reset_btn Input 主持人“复位”按钮
player_btn[3:0] Input 4位选手抢答按钮
seg_sel[3:0] Output 数码管位选信号 (用于选择显示哪一位)
seg_data[7:0] Output 数码管段选信号 (用于显示数字)
led_answer[3:0] Output 选手抢答成功指示灯
led_violation Output 违规指示灯
led_timeout Output 超时指示灯
buzzer Output 蜂鸣器控制信号

内部模块划分与连接:

+-------------------------------------------------------------------+
|                          TOP_LEVEL_MODULE                         |
|                                                                   |
|  +----------------+    +----------------+    +-----------------+  |
|  |   Control      |    | Priority       |    |  Display &      |  |
|  |   FSM          |<-->| Encoder        |<-->|  Lock           |  |
|  +----------------+    +----------------+    +-----------------+  |
|      ^         ^           ^                    ^          ^      |
|      |         |           |                    |          |      |
| +----+----+ +--+---+  +----+----+    +--------+ +--------+ +-----+ |
| | Debounce| |Timer |  |Input |    |LED Ctrl | |Buzzer Ctrl|  |    |
| |  Module | |Module|  | Logic|    |Module   | |Module      |  |    |
| +---------+ +------+  +------+    +---------+ +------------+  |    |
|                                                                   |
|  Inputs: clk, rst_n, start_btn, reset_btn, player_btn[3:0]        |
|  Outputs: seg_sel, seg_data, led_answer, led_violation, led_timeout, buzzer |
+-------------------------------------------------------------------+

核心模块 Verilog HDL 代码实现

这里提供关键模块的Verilog HDL代码示例。

顶层模块 (top_responder.v)

module top_responder (
    input               clk,            // 50MHz clock
    input               rst_n,          // Active-low reset
    input       [3:0]   player_btn,     // Player buttons
    input               start_btn,      // Host start button
    input               reset_btn,      // Host reset button
    output      [3:0]   seg_sel,       // 7-segment display select
    output      [7:0]   seg_data,      // 7-segment data
    output      [3:0]   led_answer,    // Player answer LEDs
    output              led_violation,  // Violation LED
    output              led_timeout,    // Timeout LED
    output              buzzer          // Buzzer
);
    // Internal signals
    wire [3:0]  winner;
    wire        is_answered;
    wire        is_violation;
    wire        is_timeout;
    wire        timer_en;
    wire        timer_rst;
    wire [3:0]  display_data;
    // Instantiate Control FSM
    control_fsm u_fsm (
        .clk          (clk),
        .rst_n        (rst_n),
        .start_btn    (start_btn),
        .reset_btn    (reset_btn),
        .player_btn   (player_btn),
        .winner       (winner),
        .is_answered  (is_answered),
        .is_violation (is_violation),
        .is_timeout   (is_timeout),
        .timer_en     (timer_en),
        .timer_rst    (timer_rst),
        .led_answer   (led_answer),
        .led_violation(led_violation),
        .led_timeout  (led_timeout),
        .buzzer       (buzzer)
    );
    // Instantiate Priority Encoder
    priority_encoder u_encoder (
        .btns      (player_btn),
        .is_pressed(is_answered),
        .winner    (winner)
    );
    // Instantiate Timer Module (e.g., 30s countdown)
    timer_module u_timer (
        .clk      (clk),
        .rst_n    (rst_n),
        .en       (timer_en),
        .rst      (timer_rst),
        .timeout  (is_timeout),
        .count    (display_data) // Use timer value for display
    );
    // Instantiate Display Controller
    // This module would mux between winner number, timer, and status messages
    display_controller u_display (
        .clk      (clk),
        .rst_n    (rst_n),
        .winner   (winner),
        .is_violation(is_violation),
        .is_timeout(is_timeout),
        .timer_val(display_data),
        .seg_sel  (seg_sel),
        .seg_data (seg_data)
    );
endmodule

控制状态机 (control_fsm.v)

这是设计的核心,负责管理所有状态和逻辑。

module control_fsm (
    input               clk,
    input               rst_n,
    input       [3:0]   player_btn,
    input               start_btn,
    input               reset_btn,
    output      [3:0]   winner,
    output              is_answered,
    output              is_violation,
    output              is_timeout,
    output              timer_en,
    output              timer_rst,
    output      [3:0]   led_answer,
    output              led_violation,
    output              led_timeout,
    output              buzzer
);
    // Define states
    parameter S_IDLE      = 4'b0001;
    parameter S_READY     = 4'b0010;
    parameter S_ANSWERED  = 4'b0100;
    parameter S_VIOLATION = 4'b1000;
    parameter S_TIMEOUT   = 4'b0000; // Or any other unused state
    reg [3:0]  current_state, next_state;
    reg [3:0]  winner_reg;
    reg        is_answered_reg, is_violation_reg, is_timeout_reg;
    // --- State Register ---
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            current_state <= S_IDLE;
        end else begin
            current_state <= next_state;
        end
    end
    // --- Next State & Output Logic (Combinational) ---
    always @(*) begin
        // Default outputs
        next_state    = current_state;
        winner        = 4'd0;
        is_answered   = 1'b0;
        is_violation  = 1'b0;
        is_timeout    = 1'b0;
        timer_en      = 1'b0;
        timer_rst     = 1'b0;
        led_answer    = 4'b0000;
        led_violation = 1'b0;
        led_timeout   = 1'b0;
        buzzer        = 1'b0;
        case (current_state)
            S_IDLE: begin
                timer_rst = 1'b1; // Keep timer reset
                if (|player_btn) begin // If any player button is pressed
                    next_state = S_VIOLATION;
                    is_violation = 1'b1;
                    led_violation = 1'b1;
                    buzzer = 1'b1; // Violation beep
                end else if (start_btn) begin
                    next_state = S_READY;
                    timer_en = 1'b1; // Start timer
                end
            end
            S_READY: begin
                timer_en = 1'b1; // Timer is counting
                if (|player_btn) begin // If any player answers
                    next_state = S_ANSWERED;
                    // Priority logic: find the first pressed button
                    if (player_btn[0]) begin winner = 4'd1; end
                    else if (player_btn[1]) begin winner = 4'd2; end
                    else if (player_btn[2]) begin winner = 4'd3; end
                    else if (player_btn[3]) begin winner = 4'd4; end
                    is_answered = 1'b1;
                    led_answer = winner; // Light up the winner's LED
                    buzzer = 1'b1; // Success beep
                end
                // is_timeout is an output from timer module, checked in top level
                // or you can bring it into the FSM here
            end
            S_ANSWERED: begin
                // Display winner, wait for reset
                winner = winner_reg;
                led_answer = winner_reg;
                // No state change until reset
            end
            S_VIOLATION: begin
                // Display violation, wait for reset
                is_violation = 1'b1;
                led_violation = 1'b1;
                // No state change until reset
            end
            S_TIMEOUT: begin
                // Display timeout, wait for reset
                is_timeout = 1'b1;
                led_timeout = 1'b1;
                buzzer = 1'b1; // Timeout beep
                // No state change until reset
            end
            default: next_state = S_IDLE;
        endcase
        // Handle reset button (asynchronous)
        if (!reset_btn) begin
            next_state = S_IDLE;
            timer_rst = 1'b1;
        end
    end
    // Register outputs that need to be held
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            winner_reg <= 4'd0;
            is_answered_reg <= 1'b0;
            is_violation_reg <= 1'b0;
            is_timeout_reg <= 1'b0;
        end else begin
            if (next_state == S_ANSWERED) begin
                winner_reg <= winner;
            end
            if (next_state == S_VIOLATION) begin
                is_violation_reg <= 1'b1;
            end
            if (next_state == S_TIMEOUT) begin
                is_timeout_reg <= 1'b1;
            end
        end
    end
endmodule

优先编码器 (priority_encoder.v)

module priority_encoder (
    input      [3:0]   btns,
    output             is_pressed,
    output     [3:0]   winner
);
    // Priority: btn[0] > btn[1] > btn[2] > btn[3]
    assign is_pressed = |btns; // If any button is pressed
    assign winner = (btns[0]) ? 4'd1 :
                    (btns[1]) ? 4'd2 :
                    (btns[2]) ? 4'd3 :
                    (btns[3]) ? 4'd4 : 4'd0;
endmodule

计时器模块 (timer_module.v)

一个简单的倒计时器,例如从30秒开始倒计时。

module timer_module (
    input               clk,      // 50MHz clock
    input               rst_n,
    input               en,       // Enable counting
    input               rst,      // Reset counter to 30
    output reg          timeout,  // Goes high when count reaches 0
    output reg  [4:0]   count     // 5-bit counter for 0-30
);
    // Clock divider for 1-second tick (approximate)
    // 50,000,000 / 50,000,000 = 1 second
    parameter CLK_DIV = 25'd50_000_000; // Adjust for your exact clock frequency
    reg [24:0] counter_div;
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            counter_div <= 25'd0;
        end else if (en) begin
            if (counter_div == CLK_DIV - 1) begin
                counter_div <= 25'd0;
            end else begin
                counter_div <= counter_div + 1;
            end
        end else begin
            counter_div <= 25'd0;
        end
    end
    wire tick_second = (counter_div == CLK_DIV - 1) && en;
    // Main counter logic
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            count <= 5'd30;
            timeout <= 1'b0;
        end else begin
            if (rst) begin
                count <= 5'd30;
                timeout <= 1'b0;
            end else if (en && tick_second) begin
                if (count == 5'd0) begin
                    timeout <= 1'b1;
                end else begin
                    count <= count - 1;
                end
            end
        end
    end
endmodule

仿真与硬件实现

  1. 仿真:

    • 使用 ModelSimQuartus II 自带 Simulator 对每个模块和顶层模块进行功能仿真。
    • 编写 Testbench,模拟所有可能的输入场景:
      • 正常抢答流程。
      • 选手提前抢答。
      • 超时无人抢答。
      • 多人同时抢答(验证优先级)。
      • 复位功能。
    • 检查仿真波形,确保输出信号完全符合设计要求。
  2. 硬件实现:

    • 创建新工程: 在 Quartus II 中新建一个工程,选择你的FPGA型号。
    • 添加文件: 将所有 .v 文件添加到工程中。
    • 引脚分配: 打开 Pin Planner,根据你的开发板原理图,将顶层模块的端口分配到FPGA的物理引脚上。
      • player_btn -> 连接到按键或拨码开关。
      • start_btn, reset_btn -> 连接到按键。
      • led_answer, led_violation, led_timeout -> 连接到LED灯。
      • seg_sel, seg_data -> 连接到数码管。
      • buzzer -> 连接到蜂鸣器(通常需要一个小三极管驱动)。
    • 编译: 执行 Start Compilation,Quartus II 会进行综合、布局布线。
    • 下载: 编译成功后,通过 USB-Blaster 将生成的 .sof 文件下载到FPGA开发板中。

设计总结与展望

本设计成功实现了一个基于FPGA的多功能数字抢答器,通过采用自顶向下的模块化设计方法,将复杂的系统划分为控制状态机、优先编码器、计时器等独立模块,使设计结构清晰,易于理解和调试,Verilog HDL的使用提供了强大的硬件描述能力,精确实现了抢答、封锁、违规提示和计时等核心功能,仿真和硬件实现验证了设计的正确性和可行性。

展望: 本设计还有进一步优化的空间:

  1. 更精确的计时: 使用FPGA内部的PLL锁相环产生更精确的1Hz时钟信号。
  2. 动态分数显示: 扩展显示模块,实现选手分数的动态更新和显示。
  3. 无线抢答: 将选手按钮替换为无线模块(如蓝牙、WiFi),实现更灵活的抢答方式。
  4. 语音提示: 使用语音播报芯片,实现“X号选手抢答成功”、“时间到”等语音提示。
  5. 题目显示模块: 增加一个LCD或VGA模块,用于显示竞赛题目。

这个项目不仅涵盖了数字逻辑设计的核心知识,还锻炼了FPGA开发的全流程能力,是一个非常优秀的EDA课程设计,祝你设计顺利!

标签: FPGA逻辑控制 Verilog HDL

抱歉,评论功能暂时关闭!