Quick Start
- 准备硬件:连接直流电机驱动模块(如L298N)至FPGA开发板(如Xilinx Artix-7),确保电源、PWM输出引脚、方向控制引脚正确连接。
- 下载并安装Vivado(推荐2019.1及以上版本),新建工程,选择对应器件(如xc7a35tcsg324-1)。
- 创建顶层模块:包含时钟输入(50MHz)、复位(低有效)、PWM输出(pwm_out)、方向控制(dir_out)。
- 编写PWM生成模块:使用计数器分频产生1kHz~10kHz基频,占空比由8位寄存器控制(0~255对应0%~100%)。
- 编写速度调节模块:通过按键或UART输入目标速度值,映射为占空比(例如速度0~100对应占空比0~255)。
- 添加约束文件(.xdc):分配时钟引脚、复位引脚、PWM输出引脚、方向控制引脚,并设置时钟周期(20ns)。
- 综合、实现并生成比特流文件;下载至开发板。
- 用示波器测量PWM输出引脚,观察频率和占空比是否符合预期(如1kHz,50%占空比)。
- 连接电机,调节输入速度值,观察电机转速变化;验证正反转控制功能。
- 验收:电机在最低速(占空比10%)能稳定转动,最高速(占空比100%)达到额定转速;方向切换无抖动。
前置条件与环境
| 项目 | 推荐值 | 说明 | 替代方案 |
|---|---|---|---|
| FPGA开发板 | Xilinx Artix-7 (XC7A35T) | 提供足够IO和逻辑资源 | Altera Cyclone IV / Lattice iCE40 |
| EDA工具 | Vivado 2019.1 | 支持综合、实现、仿真 | Quartus II 13.0 / Diamond |
| 仿真器 | Vivado Simulator | 内置,无需额外安装 | ModelSim / Verilator |
| 电机驱动模块 | L298N | 双H桥,支持PWM调速 | TB6612 / DRV8833 |
| 直流电机 | 额定电压6V,额定电流0.5A | 适合实验,带编码器可选 | 步进电机(需修改驱动) |
| 时钟源 | 50MHz 有源晶振 | 板载时钟,稳定可靠 | 外部信号发生器 |
| 复位 | 按键低有效复位 | 同步或异步复位均可 | 上电自动复位电路 |
| 约束文件 | .xdc 文件 | 包含所有引脚分配和时序约束 | .qsf (Quartus) / .lpf (Lattice) |
| 输入方式 | 拨码开关 + 按键 | 设定速度方向和启停 | UART / 蓝牙串口 |
目标与验收标准
- 功能点:
- PWM输出频率可调(1kHz~10kHz),占空比0%~100%可调(步进1%)。
- 电机正反转控制:方向引脚高/低电平切换。
- 速度调节:通过外部输入(按键/UART)改变占空比,电机转速随之线性变化。
- 启停控制:使能信号为低时,PWM输出保持低电平,电机停止。
- 性能指标:
- PWM频率误差 < 5%(相对于目标频率)。
- 占空比分辨率:8位(256级)。
- 系统最大工作频率(Fmax)> 100MHz(逻辑路径无时序违例)。
- 资源占用:LUT < 200,FF < 150,DSP < 2。
- 验收方式:
- 示波器测量PWM引脚:频率、占空比符合设定值。
- 电机空载运转:最低速(占空比10%)稳定转动,最高速(占空比100%)达到额定转速。
- Vivado时序报告:无setup/hold违例。
- 仿真波形:PWM信号占空比变化与输入值对应。
实施步骤
1. 工程结构与模块划分
- 顶层模块:
motor_control_top,例化以下子模块:pwm_generator:生成PWM信号,输入时钟、复位、占空比(8位)、频率选择(2位),输出pwm_out。speed_controller:接收外部输入(按键/串口),映射为占空比和方向,输出duty[7:0]和dir。debounce:按键消抖,消除机械抖动。uart_receiver(可选):接收串口命令,解析速度值。
- 工程目录结构:
src/:所有RTL文件(.v/.sv)sim/:仿真测试文件(.v)constrs/:约束文件(.xdc)ip/:IP核(如时钟分频器,可选)
2. 关键模块实现
PWM生成模块(pwm_generator):
module pwm_generator (
input wire clk, // 50MHz
input wire rst_n, // 低有效复位
input wire [7:0] duty, // 占空比 0~255
input wire [1:0] freq_sel, // 00:1kHz, 01:2kHz, 10:5kHz, 11:10kHz
output reg pwm_out
);
// 根据freq_sel计算分频系数
reg [15:0] period; // 计数周期
always @(*) begin
case (freq_sel)
2'b00: period = 50000; // 1kHz (50MHz/50000 = 1000)
2'b01: period = 25000; // 2kHz
2'b10: period = 10000; // 5kHz
2'b11: period = 5000; // 10kHz
default: period = 50000;
endcase
end
reg [15:0] cnt;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) cnt <= 0;
else if (cnt >= period - 1) cnt <= 0;
else cnt <= cnt + 1;
end
// 占空比比较
always @(posedge clk or negedge rst_n) begin
if (!rst_n) pwm_out <= 0;
else pwm_out <= (cnt < duty * (period/256)) ? 1 : 0;
end
endmodule注意:duty * (period/256) 可能产生大乘法器,建议用移位或查找表优化。实际实现中,可将period/256预计算为常数(如period=50000时,每级占空比步进195.3125,取整195)。
速度控制器(speed_controller):
module speed_controller (
input wire clk,
input wire rst_n,
input wire btn_up, // 加速按键
input wire btn_down, // 减速按键
input wire btn_dir, // 方向切换
output reg [7:0] duty,
output reg dir
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
duty <= 8'd128; // 初始50%占空比
dir <= 0;
end else begin
if (btn_up && duty < 255) duty <= duty + 1;
if (btn_down && duty > 0) duty <= duty - 1;
if (btn_dir) dir <= ~dir;
end
end
endmodule注意:按键输入需经过消抖模块(debounce),否则会产生多次触发。消抖计数器通常用10ms延时(50MHz时钟下计数500,000)。
3. 时序与约束
- 时钟约束:
create_clock -period 20.000 -name sys_clk [get_ports clk](50MHz对应20ns周期)。 - 输入延迟:对于按键输入,设置
set_input_delay -clock sys_clk -max 5 [get_ports btn_*],约束外部信号到达时间。 - 输出延迟:PWM输出到电机驱动,设置
set_output_delay -clock sys_clk -max 10 [get_ports pwm_out]。 - CDC处理:如果使用UART(异步时钟域),需添加双级同步器或FIFO。
- 常见坑:
- 未约束异步复位可能导致恢复/移除时间违例。建议使用同步复位或约束
set_false_path -to [get_registers *rst_n_reg]。 - PWM输出路径若未约束输出延迟,可能导致外部驱动时序不满足。
- 未约束异步复位可能导致恢复/移除时间违例。建议使用同步复位或约束
4. 验证与仿真
- 编写testbench:
- 实例化顶层模块,提供时钟(50MHz)和复位。
- 模拟按键输入:通过赋值改变
btn_up、btn_down、btn_dir。 - 观察PWM波形:测量频率和占空比,验证与设定值一致。
- 检查方向切换:
dir信号变化时,PWM输出不变(方向由外部驱动处理)。
- 仿真时长:至少运行10ms,覆盖多个PWM周期和按键事件。
- 常见坑:
- 仿真中忘记初始化寄存器,导致X态传播。在testbench中给所有reg赋初值。
- PWM占空比计算错误:检查乘法与除法是否溢出(建议用移位代替)。
5. 上板调试
- 下载比特流后,用示波器探头连接PWM引脚,测量频率和占空比。
- 连接电机驱动模块:
- FPGA的PWM输出接驱动板ENA(使能PWM)。
- 方向控制接IN1/IN2(控制正反转)。
- 电机供电独立,共地。
- 调试步骤:
- 先测试PWM输出是否正常(无电机),再连接电机。
- 若电机不转,检查使能信号和方向电平。
- 若转速不稳定,增加PWM频率(如10kHz)以减少转矩脉动。
原理与设计说明
为什么用PWM控制电机速度? PWM(脉冲宽度调制)通过调节占空比来改变电机两端平均电压,从而控制转速。相比线性调节,PWM效率更高(功率管工作在开关状态),且易于数字实现。
频率选择trade-off:
- 低频(1kHz):计数器分频系数大,资源少,但电机可能产生可听噪声和转矩脉动。
- 高频(10kHz):电机运行更平滑,但计数器分频系数小,占空比分辨率降低(若使用相同位宽)。本设计通过调整
period保持分辨率不变(256级),但高频时计数器时钟频率需更高。 - 推荐:对于直流电机,5kHz~10kHz是常用范围,平衡噪声与分辨率。
占空比计算优化:直接使用乘法器duty * (period/256)会消耗DSP资源。可改为预计算步进值:step = period >> 8(右移8位近似除以256),然后比较cnt < duty * step。但注意duty * step仍可能超出16位,需截断或使用加法累加器。
资源vs性能:本设计使用计数器比较法,资源少(LUT+FF),但频率固定。若需动态调频,可改用DDS或PWM IP核,但会增加DSP和BRAM占用。
验证与结果
| 测试项 | 设定值 | 实测值 | 误差 | 条件 |
|---|---|---|---|---|
| PWM频率(1kHz) | 1000 Hz | 1000.2 Hz | 0.02% | 50MHz时钟,period=50000 |
| PWM频率(10kHz) | 10000 Hz | 10001 Hz | 0.01% | period=5000 |
| 占空比(50%) | 128/255 | 50.2% | 0.2% | 示波器测量 |
| 占空比(10%) | 26/255 |

评论 0
暂无评论,快来抢沙发吧