FPGA 与 Verilog 基础
FPGA 是做数字电路原型和专用控制逻辑时很顺手的器件,Verilog 则负责把这些逻辑描述清楚。这里的实现都走纯 Verilog,不依赖 IP 核,优点是结构直白,缺点也明显:很多细节得自己处理,尤其是浮点运算这种容易把边界条件堆满的部分。
单精度浮点数运算
单精度浮点数用 32 位表示,覆盖加减乘除和开方这类常见运算。e01_fpu_single_precision_float 提供的是一套完整的浮点计算单元,核心还是绕不开符号位、指数位和尾数位的拆解、对齐、归一化。
加法示例
浮点加法最费事的地方不在'相加',而在前后的整理:先看指数谁大,尾数先对齐,再做相加,最后处理进位和规格化。下面这段代码就是这个思路的简化版本。
module float_addition (
input wire [31:0] a,
input wire [31:0] b,
output reg [31:0] result
);
// 提取符号位、指数位和尾数位
wire [30:23] exp_a = a[30:23];
wire [22:0] mantissa_a = a[22:0];
wire [30:23] exp_b = b[30:23];
wire [22:0] mantissa_b = b[22:0];
// 比较指数大小,对尾数进行对齐
reg [22:0] aligned_mantissa_a;
reg [22:0] aligned_mantissa_b;
if (exp_a > exp_b) begin
aligned_mantissa_a = mantissa_a;
aligned_mantissa_b = mantissa_b >> (exp_a - exp_b);
end else begin
aligned_mantissa_a = mantissa_a >> (exp_b - exp_a);
aligned_mantissa_b = mantissa_b;
end
// 尾数相加
reg [23:0] sum_mantissa = {1'b1, aligned_mantissa_a} + {1'b1, aligned_mantissa_b};
// 处理溢出和规格化
if (sum_mantissa[23]) begin
sum_mantissa = sum_mantissa >> 1;
exp_a = exp_a + 1;
end
// 构建结果
assign result = {a[31], exp_a, sum_mantissa[22:0]};
endmodule
数制转换桥梁
浮点和整数之间来回切换,在控制系统里很常见。真正上板之后,你会发现这一步往往比想象中更关键,因为很多外围模块并不接受浮点输入。
浮点数转整数
模块 e02_float_to_int 负责把浮点数转成整数,适合电机转速、位置给定值这类最终要落到整数通道的场景。
整数转浮点数
模块 e03_int_to_float 则把整数转成浮点数。这样做的目的不是'更高级',而是给后续运算留更宽的动态范围,减少某些高精度处理中间步骤的精度损失。
PID 控制算法
PID 是工业控制里最常见的闭环算法之一,P、I、D 三项分别对应响应速度、稳态误差和变化趋势的修正。e04_pid 把这三部分放到 FPGA 上实现,思路并不花哨,重点在于参数配合和时序稳定。实际用的时候,先把控制回路跑通,比追求理论上的最优参数更重要。
验证工具与文档
- fpu.pdf:浮点数计算功能应用说明。
- pid_mat.m:MATLAB 脚本,用于计算 PID 公式并与 FPGA 结果对比。
- u_n_result_mat.xlsx:MATLAB 的 PID 计算输出结果记录。
- 浮点数 - 整数转换.exe:辅助调试工具。
这些工程都带了 Testbench 激励,可以直接在 FPGA 开发环境里做 RTL 仿真。浮点和 PID 这种模块,仿真阶段多看几轮边界输入,后面省下来的时间通常比你想的多。


