上一篇是通过组合逻辑加时序逻辑实现,本文采用纯逻辑实现,可以去对此两者的精度的逻辑资源,本人通过测试随机三万数字,均一样。
module sqrt32(
input wire sys_clk,
input wire sys_rst_n,
input wire start,
input wire [31:0] value,
output reg [15:0] root,
output reg done,
output reg [31:0] rem
);
// 定义状态
localparam IDLE = 2'b00,
CALC = 2'b01,
DONE = 2'b10;
reg [1:0] state, next_state;
reg [4:0] shift; // 用于记录当前处理的位
reg [31:0] temp_root;
reg [31:0] temp_rem;
reg [31:0] sqrt2;
// 状态转换逻辑
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
state <= IDLE;
end else begin
state <= next_state;
end
end
// 状态机逻辑
always @(*) begin
case (state)
IDLE: begin
if (start && value != 0) begin
next_state = CALC;
end else begin
next_state = IDLE;
end
end
CALC: begin
if (shift == 0) begin
next_state = DONE;
end else begin
next_state = CALC;
end
end
DONE: begin
next_state = IDLE;
end
default: begin
next_state = IDLE;
end
endcase
end
// 主计算逻辑
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
root <= 0;
rem <= 0;
shift <= 15;
temp_root <= 0;
temp_rem <= 0;
done <= 0;
end else begin
case (state)
IDLE: begin
if (start && value != 0) begin
temp_rem <= value;
temp_root <= 0;
shift <= 15;
end
end
CALC: begin
sqrt2 = ((temp_root << 1) + (1 << shift)) << shift;
if (sqrt2 <= temp_rem) begin
temp_root <= temp_root + (1 << shift);
temp_rem <= temp_rem - sqrt2;
end
shift <= shift - 1;
end
DONE: begin
root <= temp_root;
rem <= temp_rem;
done <= 1;
end
endcase
end
end
endmodule