Lesson 19

📊 PWM控制器

🏆 占空比精确控制
✅ Verilator仿真验证通过

📖 实验描述

实现8位PWM控制器,可调占空比(0-255)和预分频,精确控制输出占空比。

PWM(Pulse Width Modulation)脉冲宽度调制是通过改变脉冲占空比来控制平均电压/功率的技术。 8位PWM:计数器从0计数到255,当counter<duty时输出高电平,否则输出低电平。 占空比 = duty/256 x 100% duty=0 → 0%占空比(常低) duty=128 → 50%占空比 duty=255 → 99.6%占空比(几乎常高) 预分频器:prescale计数器控制PWM周期。prescale=0时每时钟1步,prescale=N时每N+1时钟1步。 PWM频率 = fclk / (256 x (prescale+1)) 50MHz时钟,prescale=195 → PWM约1kHz。

🧠 核心概念

📐 电路结构

电路与状态图
PWM控制器结构:

  clk → 预分频器 → 8位计数器
                      │
                 counter < duty ?
                 ↓是          ↓否
              pwm=1       pwm=0

  占空比 = duty / 256
  PWM频率 = fclk / (256 x (prescale+1))

📝 设计步骤

  1. 1预分频计数器递增
  2. 2到达prescale值时清零,PWM计数器+1
  3. 3PWM计数器0→255循环
  4. 4比较:counter
  5. 5否则 → pwm_out=0
  6. 6duty可在任意时刻更新

💻 Verilog实现

pwm_controller.svSystemVerilog · Verilator 5.020
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
// PWM Controller - 脉冲宽度调制控制器
// 可调占空比和频率,8位分辨率
module pwm_controller(
    input  wire clk,
    input  wire rst,
    input  wire [7:0] duty,      // 占空比 0-255 (0=0%, 255=100%)
    input  wire [15:0] prescale, // 预分频值
    output reg  pwm_out,
    output reg  [7:0] counter_val
);

reg [15:0] prescale_cnt;
reg [7:0]  counter;

always @(posedge clk or posedge rst) begin
    if (rst) begin
        pwm_out     <= 1'b0;
        counter     <= 8'd0;
        prescale_cnt<= 16'd0;
        counter_val <= 8'd0;
    end else begin
        if (prescale_cnt >= prescale) begin
            prescale_cnt <= 16'd0;
            
            if (counter == 8'd255) begin
                counter <= 8'd0;
            end else begin
                counter <= counter + 8'd1;
            end
            
            // PWM output: high when counter < duty
            if (counter < duty)
                pwm_out <= 1'b1;
            else
                pwm_out <= 1'b0;
            
            counter_val <= counter;
        end else begin
            prescale_cnt <= prescale_cnt + 16'd1;
        end
    end
end

endmodule

🔬 仿真说明

仿真环境与策略

测试4组占空比:duty=128→50.0%(128/256), duty=64→25.0%(64/256), duty=0→0%, duty=255→99.6%(255/256)。占空比精确到1/256。

✅ 验证结果

Verilator 5.020 仿真通过

本实验所有Verilog代码已通过Verilator编译验证,功能行为正确。测试用例覆盖核心功能路径,确保设计满足规格要求。

⚠️ 常见错误

🌍 真实世界

工业应用

PWM在电机驱动(BLDC/步进)、LED调光、电源管理(DC-DC)、音频(D类功放)中无处不在。2024年STM32的TIM外设提供16位PWM+死区+中心对齐模式。Raspberry Pi Pico的PIO可编程生成任意PWM波形。

💡 扩展挑战

🚀 自己动手

# 编译并运行
verilator --cc pwm_controller.sv --exe pwm_controller_tb.cpp --build -j 0
./obj_dir/Vpwm_controller

🎯 试一试

修改参数

尝试修改代码中的关键参数,观察仿真结果变化:

  • 调整位宽,观察不同数据范围
  • 修改初始值/种子,观察不同起始条件
  • 改变时钟分频,测试不同速度

💡 Verilator会在位宽不匹配时给出Warning,这是学习的好机会

添加功能

在现有基础上增加新功能:

  • 添加新的输入信号和控制逻辑
  • 增加状态或修改状态转移条件
  • 扩展输出,增加更多显示信息

🔧 增量开发:每次只改一个地方,验证通过后再改下一个

📋 Verilog速查

语法说明示例
reg [7:0]8位寄存器reg [7:0] data;
wire组合逻辑连线wire valid = cnt > 5;
always @(posedge clk)时序逻辑上升沿触发
always @(*)组合逻辑敏感列表自动推导
localparam局部常量localparam DIV = 50000000;
case多分支选择注意default分支
$display仿真打印不可综合,仅仿真用

📊 性能指标

资源估算(FPGA参考)

本设计在典型FPGA上的资源占用估算:LUT约20-120个,FF约30-100个,无BRAM/DSP依赖(特殊模块除外)。时钟频率可达50-100MHz+。Verilator仿真速度约5-10M周期/秒。

← 上一课 📚 目录 下一课 →