1. 基础组合逻辑IP

任务目标

设计一个可综合的Verilog LED闪烁控制器,支持通过外部输入选择两种闪烁频率(快闪/慢闪),并在FPGA开发板上驱动LED实现视觉验证。本案例聚焦于时钟分频与模式选择的RTL实现,提供完整的仿真测试与板级验证路径。

模块设计与端口定义

控制器采用同步时序逻辑设计,通过计数器对系统时钟分频产生闪烁周期。核心思路:使用一个32位计数器对50MHz系统时钟计数,最高位作为慢闪时钟(周期约1.7s),次高位作为快闪时钟(周期约0.85s),通过外部按键选择输出源。

完整RTL代码

module led_flash_controller (
    input  wire clk,        // 50MHz系统时钟
    input  wire rst_n,      // 异步复位,低有效
    input  wire mode_sel,   // 闪烁模式选择:0=慢闪,1=快闪
    output reg  led_out     // LED驱动输出
);

// 32位计数器,最高位周期 = 2^32 / 50MHz ≈ 85.9s
// 实际使用bit[25]和bit[24]以适配常见开发板观察效果
reg [25:0] counter;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        counter <= 26'd0;
    else
        counter <= counter + 1'b1;
end

// 慢闪:bit[25]翻转周期 = 2^26/50MHz ≈ 1.34s(LED亮灭各0.67s)
// 快闪:bit[24]翻转周期 = 2^25/50MHz ≈ 0.67s(LED亮灭各0.34s)
wire slow_clk = counter[25];
wire fast_clk = counter[24];

always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        led_out <= 1'b0;
    else if (mode_sel)
        led_out <= fast_clk;
    else
        led_out <= slow_clk;
end

endmodule

仿真测试平台

`timescale 1ns/1ps
module tb_led_flash_controller;

reg clk = 0;
reg rst_n = 0;
reg mode_sel = 0;
wire led_out;

// 生成50MHz时钟
always #10 clk = ~clk;

led_flash_controller uut (
    .clk(clk),
    .rst_n(rst_n),
    .mode_sel(mode_sel),
    .led_out(led_out)
);

// 简化计数器以加速仿真:在测试中直接观察模式切换行为
reg [25:0] expected_counter;
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) expected_counter <= 0;
    else expected_counter <= expected_counter + 1;
end

initial begin
    // 复位
    rst_n = 0;
    #100;
    rst_n = 1;
    
    // 验证慢闪模式:等待计数器bit[25]翻转
    mode_sel = 0;
    #1000;  // 观察led_out初始状态
    
    // 切换到快闪模式
    mode_sel = 1;
    #1000;
    
    // 再次切回慢闪
    mode_sel = 0;
    #1000;
    
    $display("仿真完成:验证模式切换功能");
    $finish;
end

// 自动检查:确保led_out跟随所选时钟源
always @(posedge clk) begin
    if (rst_n) begin
        if (mode_sel == 1'b1)
            assert (led_out == counter[24]) else $error("快闪模式输出错误");
        else
            assert (led_out == counter[25]) else $error("慢闪模式输出错误");
    end
end

endmodule

运行与验证方法

仿真验证:使用ModelSim或Vivado XSim运行测试平台,观察led_out波形是否与所选计数器位同步翻转。通过断言自动检查输出正确性,若仿真结束无断言错误即通过功能验证。

板级验证:将代码综合后下载至FPGA开发板,连接LED至led_out引脚。操作步骤:

  1. 将mode_sel连接至板载拨码开关或按键
  2. 复位后观察LED:mode_sel=0时约0.67秒亮灭一次(慢闪)
  3. 切换mode_sel=1时约0.34秒亮灭一次(快闪)
  4. 通过视觉观察两种闪烁频率差异明显,即验证成功

综合约束建议

若使用实际开发板,需在XDC/SDC文件中添加时钟约束:create_clock -period 20.0 [get_ports clk]。本设计为纯时序逻辑,无特殊时序路径要求,满足建立/保持时间即可正常综合。