URL
https://opencores.org/ocsvn/isqrt_dbd/isqrt_dbd/trunk
Subversion Repositories isqrt_dbd
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/isqrt_dbd/isqrt_dbd.sv
0,0 → 1,94
`ifndef _isqrt_dbd_ |
`define _isqrt_dbd_ |
|
// Digit-by-digit method |
`define M(W, I) (W'('h1)<<(W - 2*(I + 1))) |
|
module isqrt_dbd #(parameter DATA_WIDTH = 32) (clk, data, q); |
localparam WIDTH = (DATA_WIDTH & 1) ? DATA_WIDTH + 1 : DATA_WIDTH; |
|
input clk; |
input [DATA_WIDTH-1:0] data; |
output [WIDTH/2-1:0] q; |
|
reg [WIDTH-1:0] data_reg; |
reg [WIDTH/2 - 1:0][31:0] x, y; |
logic [WIDTH/2 - 2:0][31:0] b; |
|
always_ff @(posedge clk) |
data_reg <= data; |
|
always_ff @(posedge clk) begin |
if (data_reg >= `M(WIDTH, 0)) |
begin |
x[0] <= data_reg - `M(WIDTH, 0); |
y[0] <= `M(WIDTH, 0); |
end |
else |
begin |
x[0] <= data_reg; |
y[0] <= '0; |
end |
end |
|
genvar i; |
generate for (i = 1; i < WIDTH/2; i++) |
begin :gen |
always_comb |
b[i-1] = y[i-1] | `M(WIDTH, i); |
|
always_ff @(posedge clk) |
if (x[i-1] >= b[i-1]) |
begin |
x[i] <= x[i-1] - b[i-1]; |
y[i] <= (y[i-1] >> 1'b1) | `M(WIDTH, i); |
end |
else |
begin |
x[i] <= x[i-1]; |
y[i] <= y[i-1] >> 1'b1; |
end |
end |
endgenerate |
|
assign q = y[WIDTH/2 - 1][WIDTH/2 - 1:0]; |
|
endmodule |
|
//unsigned x, y; |
//unsigned sqrt(){ |
// y = 0; |
// unsigned m = 1 << 30; |
// while( m ){ |
// unsigned b = y | m; |
// y >>= 1; |
// if( x >= b ){ |
// x -= b; |
// y |= m; |
// } |
// m >>= 2; |
// } |
//} |
|
// https://en.wikipedia.org/wiki/Methods_of_computing_square_roots |
//short isqrt(short num) { |
// short res = 0; |
// short bit = 1 << 14; // The second-to-top bit is set: 1 << 30 for 32 bits |
// |
// // "bit" starts at the highest power of four <= the argument. |
// while (bit > num) |
// bit >>= 2; |
// |
// while (bit != 0) { |
// if (num >= res + bit) { |
// num -= res + bit; |
// res = (res >> 1) + bit; |
// } |
// else |
// res >>= 1; |
// bit >>= 2; |
// } |
// return res; |
//} |
|
`endif |
/isqrt_dbd/isqrt_dbd_tb.sv
0,0 → 1,31
timeunit 1ns; |
timeprecision 1ns; |
|
module isqrt_dbd_tb; |
|
bit clk = 0; |
bit [31:0] data = 0; |
wire [15:0] q; |
|
always #10ns clk++; |
|
initial begin |
repeat(10) @(posedge clk); |
|
Test(32'd241125431); |
|
repeat(10) @(posedge clk); |
$stop(2); |
end |
|
isqrt_dbd dut(.*); |
|
task Test(bit [31:0] value); |
int q_ref; |
data = value; |
|
repeat(100) @(posedge clk); |
q_ref = longint'($sqrt(value)); |
$display("x = %d, rtl: %d, ref: %d", value, q, q_ref); |
endtask |
endmodule :isqrt_dbd_tb |