实现16位整数开方器,使用逐位试探法从MSB到LSB逐位确定结果。
逐位试探开方器:
radicand[15:0] → 比较器 ←── trial^2
│
trial^2 <= radicand?
↓是 ↓否
root[i]=1 root[i]=0
trial_root = root | (1 << bit_pos)
每周期试探1位,8周期完成// Square Root - 逐位试探法
// 从MSB到LSB逐位试探,检查 root^2 <= radicand
module sqrt_newton(
input wire clk,
input wire rst,
input wire start,
input wire [15:0] radicand,
output reg [7:0] sqrt_out,
output reg done
);
reg [7:0] root;
reg [3:0] bit_pos;
reg running;
reg [15:0] rad_reg;
wire [7:0] trial_root = root | (8'd1 << bit_pos[2:0]);
wire [15:0] trial_sq = trial_root * trial_root;
wire can_set = (rad_reg >= trial_sq);
always @(posedge clk or posedge rst) begin
if (rst) begin
sqrt_out <= 8'd0;
done <= 1'b0;
root <= 8'd0;
bit_pos <= 4'd0;
running <= 1'b0;
rad_reg <= 16'd0;
end else begin
done <= 1'b0;
if (start && !running) begin
root <= 8'd0;
bit_pos <= 4'd7;
running <= 1'b1;
rad_reg <= radicand;
end
if (running) begin
if (can_set)
root <= trial_root;
if (bit_pos == 4'd0) begin
// Output the final trial_root (including this step's bit)
sqrt_out <= can_set ? trial_root : root;
done <= 1'b1;
running <= 1'b0;
end else begin
bit_pos <= bit_pos - 4'd1;
end
end
end
end
endmodule
测试4组数据:(1) sqrt(144)=12 (2) sqrt(65535)=255 (3) sqrt(0)=0 (4) sqrt(100)=10。8周期完成计算,结果与Python math.isqrt一致。
本实验所有Verilog代码已通过Verilator编译验证,功能行为正确。测试用例覆盖核心功能路径,确保设计满足规格要求。
开方器在3D图形(向量归一化)、通信(RMS计算)、控制系统中广泛使用。GPU每个ALU内置快速开方/逆开方单元。2024年NVIDIA Blackwell架构的SFPU支持单周期开方。FPGA中常用CORDIC替代Newton法避免除法器。
尝试修改代码中的关键参数,观察仿真结果变化:
💡 Verilator会在位宽不匹配时给出Warning,这是学习的好机会
在现有基础上增加新功能:
🔧 增量开发:每次只改一个地方,验证通过后再改下一个
| 语法 | 说明 | 示例 |
|---|---|---|
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上的资源占用估算:LUT约20-120个,FF约30-100个,无BRAM/DSP依赖(特殊模块除外)。时钟频率可达50-100MHz+。Verilator仿真速度约5-10M周期/秒。