1. 盘古1K开发板与PWM模块设计概述
盘古1K开发板作为国产FPGA学习平台,凭借其高性价比和丰富的外设接口,已成为数字电路设计入门的首选工具之一。本次练习聚焦PWM(脉冲宽度调制)模块设计,这是嵌入式系统和电机控制领域的核心基础技术。
PWM本质上是通过调节脉冲信号的占空比来实现模拟量控制的技术。在盘古1K上实现PWM模块,我们需要利用Verilog HDL描述硬件电路,通过FPGA的可编程特性生成精确的脉冲波形。这种设计思路与STM32等MCU的PWM外设不同——我们是在用硬件描述语言"从零开始"构建一个PWM控制器。
呼吸灯是验证PWM模块功能的经典案例。当PWM频率高于100Hz时,人眼就无法分辨单个脉冲,只能感知到平均亮度。通过周期性改变占空比,就能实现灯光渐亮渐暗的呼吸效果。这个看似简单的效果,实际上包含了时钟分频、计数器设计、比较器逻辑等数字电路核心知识点。
2. 硬件环境与设计指标
2.1 盘古1K开发板关键参数
- 主芯片:基于国产FPGA芯片,等效逻辑单元约1K LUTs
- 时钟系统:板载24MHz晶振,支持内部PLL倍频
- IO资源:40个通用IO,支持3.3V LVCMOS电平
- 存储资源:内置Block RAM,可配置为FIFO或寄存器文件
- 开发环境:支持Verilog-2001标准,配套综合工具链
2.2 PWM模块设计指标
根据常见应用需求,我们设定以下技术指标:
- 基础频率:1kHz(周期1ms),适合驱动LED和普通舵机
- 分辨率:1μs级精度,占空比调节步进0.1%
- 呼吸周期:完整呼吸过程(亮→暗→亮)2秒
- 控制接口:支持实时调节占空比和呼吸速度
提示:实际设计中,频率和分辨率需要根据系统时钟和计数器位宽折中考虑。24MHz时钟下,要实现1μs精度需要至少24位计数器。
3. Verilog PWM核心模块设计
3.1 顶层模块架构
PWM模块采用分层设计思想,主要包含以下子模块:
module pwm_breathing ( input clk_24m, // 24MHz系统时钟 input rst_n, // 低电平复位 output pwm_out // PWM输出信号 ); // 时钟分频模块 // 呼吸周期控制模块 // PWM生成核心模块 endmodule3.2 时钟分频与计数器链
24MHz时钟直接用于PWM生成会导致计数器位宽过大,因此需要合理分频:
reg [15:0] clk_div_cnt; wire clk_1m_en; // 1MHz使能信号 // 24分频生成1MHz时钟使能 always @(posedge clk_24m or negedge rst_n) begin if(!rst_n) clk_div_cnt <= 0; else clk_div_cnt <= (clk_div_cnt == 23) ? 0 : clk_div_cnt + 1; end assign clk_1m_en = (clk_div_cnt == 23);3.3 呼吸波形生成算法
呼吸效果通过三角波调制实现,核心代码如下:
reg [20:0] breath_cnt; // 2秒呼吸周期计数器 reg breath_dir; // 呼吸方向:0=渐亮,1=渐暗 wire [9:0] duty_cycle; // 当前占空比(0-1000对应0%-100%) // 呼吸周期控制 always @(posedge clk_24m or negedge rst_n) begin if(!rst_n) begin breath_cnt <= 0; breath_dir <= 0; end else if(clk_1m_en) begin if(breath_dir == 0) begin breath_cnt <= breath_cnt + 1; if(breath_cnt == 999999) breath_dir <= 1; end else begin breath_cnt <= breath_cnt - 1; if(breath_cnt == 0) breath_dir <= 0; end end end // 将线性计数器转换为非线性亮度曲线(符合人眼感知) assign duty_cycle = breath_cnt[19:10]; // 简单线性映射3.4 PWM生成核心逻辑
PWM比较器是模块的核心,通过计数器与阈值比较产生脉冲:
reg [9:0] pwm_cnt; reg pwm_out_reg; // PWM计数器 always @(posedge clk_24m or negedge rst_n) begin if(!rst_n) pwm_cnt <= 0; else if(clk_1m_en) pwm_cnt <= (pwm_cnt == 999) ? 0 : pwm_cnt + 1; end // 比较器输出 always @(posedge clk_24m or negedge rst_n) begin if(!rst_n) pwm_out_reg <= 0; else pwm_out_reg <= (pwm_cnt < duty_cycle); end assign pwm_out = pwm_out_reg;4. 关键设计优化与调试技巧
4.1 呼吸曲线的非线性校正
人眼对光强的感知呈对数特性,直接线性调光会导致呼吸不均匀。改进方案:
// 使用查找表实现gamma校正 reg [9:0] gamma_lut [0:1023]; // 初始化时填充查找表 initial begin for(int i=0; i<1024; i=i+1) gamma_lut[i] = 1023 * (i/1023.0)**2.2; // gamma=2.2 end // 修正后的占空比输出 assign duty_cycle = gamma_lut[breath_cnt[19:10]];4.2 消除PWM开关噪声
高频PWM可能引入电磁干扰,可通过以下方式优化:
- IO约束:在约束文件中设置合适的slew rate和驱动强度
- RC滤波:在LED串联22Ω电阻并联0.1μF电容
- 时序优化:寄存器输出信号消除毛刺
4.3 资源占用优化技巧
针对盘古1K有限的逻辑资源:
- 共用计数器:呼吸计数与PWM计数可共享部分位宽
- 位宽压缩:根据实际需要精简计数器位宽
- 状态编码:使用格雷码减少状态机切换功耗
5. 功能扩展与进阶应用
5.1 多通道PWM控制器
扩展为4通道PWM控制器,适用于RGB LED控制:
module pwm_multi_channel ( input clk_24m, input rst_n, output [3:0] pwm_out, input [9:0] duty_cycle [0:3] // 4通道占空比输入 ); genvar i; generate for(i=0; i<4; i=i+1) begin: pwm_gen pwm_core pwm_inst ( .clk(clk_24m), .rst_n(rst_n), .duty(duty_cycle[i]), .pwm_out(pwm_out[i]) ); end endgenerate endmodule5.2 总线接口集成
通过Wishbone总线实现寄存器配置:
// 寄存器映射 parameter PWM_PERIOD = 0; parameter PWM_DUTY = 4; parameter PWM_CTRL = 8; always @(posedge wb_clk_i) begin if(wb_we_i) begin case(wb_adr_i) PWM_PERIOD: period_reg <= wb_dat_i; PWM_DUTY: duty_reg <= wb_dat_i; PWM_CTRL: ctrl_reg <= wb_dat_i; endcase end end5.3 电机控制应用
将PWM模块扩展为直流电机驱动器:
- 增加死区时间控制,防止H桥直通
- 添加编码器反馈接口
- 实现闭环速度控制算法
// 死区时间插入逻辑 always @(*) begin if(pwm_raw) begin pwm_a = 1; pwm_b = 0; end else begin pwm_a = (dead_cnt < DEAD_TIME) ? 1 : 0; pwm_b = (dead_cnt < DEAD_TIME) ? 0 : 1; end end6. 常见问题与解决方案
6.1 PWM输出不稳定
现象:占空比随机跳动或输出毛刺排查步骤:
- 检查时钟域交叉是否同步处理
- 验证复位信号是否干净无抖动
- 用示波器观察时钟信号质量
- 检查电源纹波是否在合理范围
6.2 呼吸灯效果不平滑
可能原因:
- 计数器位宽不足导致量化明显
- 非线性校正不充分
- PWM频率与刷新率不匹配
解决方案:
// 增加呼吸计数器位宽到24位 reg [23:0] breath_cnt; // 采用更高阶的亮度曲线算法 function [9:0] gamma_correction; input [23:0] linear; real x; begin x = linear / 16777215.0; gamma_correction = 1023 * (x*x*x); // 三次方曲线 end endfunction6.3 资源占用过高
优化策略:
- 改用状态机替代并行计数器
- 共享部分计算单元
- 使用Block RAM实现查找表
- 降低非关键路径的位宽
7. 实测验证与性能分析
7.1 测试方案设计
- 静态测试:固定占空比,用示波器测量波形参数
- 测量项目:周期、高电平时间、上升/下降时间
- 动态测试:呼吸灯模式,观察亮度变化连续性
- 使用光敏传感器量化亮度曲线
- 负载测试:驱动不同电流的LED,验证驱动能力
7.2 实测数据示例
| 测试项 | 指标要求 | 实测结果 | 偏差 |
|---|---|---|---|
| PWM频率 | 1kHz±5% | 999.8Hz | 0.02% |
| 最小脉宽 | 1μs | 1.04μs | +4% |
| 呼吸周期 | 2s±5% | 2.01s | +0.5% |
| 电流驱动能力 | 20mA | 22mA | +10% |
7.3 性能瓶颈分析
- 时序约束:在24MHz时钟下,组合逻辑路径需小于41.6ns
- 功耗分布:动态功耗主要集中在计数器切换
- 资源占用:完整设计约占用盘古1K的30%逻辑资源
通过这个PWM模块设计练习,我们不仅掌握了脉冲宽度调制技术的Verilog实现方法,更深入理解了数字系统中时钟管理、计数器设计、非线性转换等核心概念。这些知识在电机控制、电源管理、音频处理等领域都有广泛应用。建议学有余力的读者可以尝试实现互补PWM输出、加入硬件死区控制等功能,为更复杂的电力电子应用打下基础。