我有这个代码确定32位数的整数平方根。
output = floor(sqrt(input))
我希望得到一个定点结果,例如{8 bit integer ,8 bit fractionary}
但是在8位输入上。因此wire[7:0]
输入而不是[31:0]
。
我的问题是我不知道如何修改算法以确定我之前说过的内容。您可以在下面找到代码。
module sqrt32(clk, rdy, reset, x, .y(acc));
input clk;
output rdy;
input reset;
input [31:0] x;
output [15:0] acc;
// acc holds the accumulated result, and acc2 is the accumulated
// square of the accumulated result.
reg [15:0] acc;
reg [31:0] acc2;
// Keep track of which bit I'm working on.
reg [4:0] bitl;
wire [15:0] bit = 1 << bitl;
wire [31:0] bit2 = 1 << (bitl << 1);
// The output is ready when the bitl counter underflows.
wire rdy = bitl[4];
// guess holds the potential next values for acc, and guess2 holds
// the square of that guess. The guess2 calculation is a little bit
// subtle. The idea is that:
//
// guess2 = (acc + bit) * (acc + bit)
// = (acc * acc) + 2*acc*bit + bit*bit
// = acc2 + 2*acc*bit + bit2
// = acc2 + 2 * (acc<<bitl) + bit
//
// This works out using shifts because bit and bit2 are known to
// have only a single bit in them.
wire [15:0] guess = acc | bit;
wire [31:0] guess2 = acc2 + bit2 + ((acc << bitl) << 1);
task clear;
begin
acc = 0;
acc2 = 0;
bitl = 15;
end
endtask
initial clear;
always @(reset or posedge clk)
if (reset)
clear;
else begin
if (guess2 <= x) begin
acc <= guess;
acc2 <= guess2;
end
bitl <= bitl - 1;
end
endmodule
module main;
reg clk, reset;
reg [31:0] value;
wire [15:0] result;
wire rdy;
sqrt32 root(.clk(clk), .rdy(rdy), .reset(reset), .x(value), .y(result));
always #5 clk = ~clk;
always @(posedge rdy) begin
$display("sqrt(%d) --> %d", value, result);
$finish;
end
initial begin
clk = 0;
reset = 1;
$monitor($time,,"%m.acc = %b", root.acc);
#100 value = 63;
reset = 0;
end
endmodule /* main */
改进版本:
根据Matt的建议,我已经设法使算法部分工作。 仍有这个问题:
for input = 70 the result should be output = 8.366
我得到了
for input = 70 the result is output = 8.5
是否有可能获得正确的小数部分?
我没有得到正确的小部分,我不知道为什么或是否可能:这是改进的算法:
module sqrt32(clk, rdy, reset, x, .y(acc));
input clk;
output rdy;
input reset;
input [7:0] x;
output [15:0] acc;
reg [15:0] xholder;
// acc holds the accumulated result, and acc2 is the accumulated
// square of the accumulated result.
reg [15:0] acc;
reg [15:0] acc2;
// Keep track of which bit I'm working on.
reg [4:0] bitl;
wire [15:0] bit = 1 << bitl;
wire [15:0] bit2 = 1 << (bitl << 1);
// The output is ready when the bitl counter underflows.
wire rdy = bitl[4];
// guess holds the potential next values for acc, and guess2 holds
// the square of that guess. The guess2 calculation is a little bit
// subtle. The idea is that:
//
// guess2 = (acc + bit) * (acc + bit)
// = (acc * acc) + 2*acc*bit + bit*bit
// = acc2 + 2*acc*bit + bit2
// = acc2 + 2 * (acc<<bitl) + bit
//
// This works out using shifts because bit and bit2 are known to
// have only a single bit in them.
wire [15:0] guess = acc | bit;
wire [15:0] guess2 = acc2 + bit2 + ((acc << bitl) << 1);
task clear;
begin
acc = 0;
acc2 = 0;
//bitl = 15;
bitl = 7;
assign xholder = x << 8;
end
endtask
initial clear;
always @(reset or posedge clk)
if (reset)
clear;
else begin
$display("xholder is %b", xholder);
if (guess2 <= xholder) begin
acc <= guess;
acc2 <= guess2;
end
bitl <= bitl - 1;
end
endmodule
module sqrtest;
reg clk, reset;
reg [7:0] value;
wire [15:0] result;
wire rdy;
sqrt32 root(.clk(clk), .rdy(rdy), .reset(reset), .x(value), .y(result));
always #5 clk = ~clk;
always @(posedge rdy) begin
$display("sqrt(%d) --> %d,%d", value, result[7:4], result[3:0]);
$finish;
end
initial begin
clk = 0;
reset = 1;
$monitor($time,"%m.acc = %b", root.acc);
#100 value = 70;
reset = 0;
end
endmodule /* main */
答案 0 :(得分:1)
只是使用一些值运行代码模拟,并提出了一个简单的解决方案。
注意:问题中的代码可能无法成功编译,因为bit
是Verilog保留字。此外,wire
在同一行(例如wire [31:0] bit2 = 1 << (bitl << 1);
)上具有作业的实例化应该真正分成两行(wire [15:0] bit2; assign bit2 = 1 << (bitl << 1);
)。
无论如何,你的输入有8位表示整数部分,8位表示小数部分,实际上与16位数相同,唯一的区别是它乘以2 ^ 8。因此,一种可能的解决方案是将“16”位整数提供给sqrt32模块的输入。
通过这样做,你真的在解决sqrt(X * 2^8)
。函数的输出为sqrt(X) * 2^4
。答案是输出的8个LSB,其中[7:4]
是整数部分,[3:0]
是小数部分。