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 / 蓝牙串口 |
目标与验收标准
- 功能点:
- 性能指标:
- 验收方式:
实施步骤
1. 工程结构与模块划分
- 顶层模块:
motor_control_top,例化以下子模块: - 工程目录结构:
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。
- 常见坑:
4. 验证与仿真
- 编写testbench:
- 仿真时长:至少运行10ms,覆盖多个PWM周期和按键事件。
- 常见坑:
5. 上板调试
- 下载比特流后,用示波器探头连接PWM引脚,测量频率和占空比。
- 连接电机驱动模块:
- 调试步骤:
原理与设计说明
为什么用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标签:如需转载,请注明出处:https://z.shaonianxue.cn/36692.html ![]() ![]() ![]() ![]() FPGA学习四大误区深度解析——金牌培训师教你避坑突围![]() 2026年AI芯片人才缺口分析:FPGA验证工程师需求激增与岗位实践指南![]() FPGA实现AXI4-Stream协议:视频流传输项目上手指南加载中… |




