URL
https://opencores.org/ocsvn/integer_square_root/integer_square_root/trunk
Subversion Repositories integer_square_root
Compare Revisions
- This comparison shows the changes necessary to convert path
/integer_square_root
- from Rev 5 to Rev 6
- ↔ Reverse comparison
Rev 5 → Rev 6
/trunk/src/ISR.sv
20,68 → 20,137
////////////////////////////////////////////////////////////////////////////////// |
|
|
module ISR( |
typedef enum logic [3:0] { |
INIT, |
GUESS, |
MULT_LOAD, |
MULT_WAIT, |
COMPARE, |
CHANGE, |
CHECK, |
INCRE, |
ENDLOOP, |
DONE |
} state; |
|
module ISR_FSM( |
input reset, |
input [63:0] value, |
input clock, |
input mult_done, |
input [63:0] mult_result, |
output logic mult_start, |
output logic mult_reset, |
output logic [63:0] mult_input, |
output logic [31:0] result, |
output logic done |
output logic done |
); |
logic [63:0] new_value, proposed_solution_square; |
logic [31:0] proposed_solution; |
logic [4:0] i; |
logic start, it_done, flush; |
logic reset_sync; |
|
mult Multiplier ( |
.clock(clock), |
.reset(reset), |
.mcand({32'h00000000, proposed_solution}), |
.mplier({32'h00000000, proposed_solution}), |
.start(start), |
.product(proposed_solution_square), |
.done(it_done) |
); |
|
logic [63:0] value_reg; |
logic [31:0] result_next, guess, guess_next; |
integer i, i_next; |
|
state current_state, next_state; |
|
assign mult_input = {32'b0, guess}; |
assign mult_start = current_state == MULT_LOAD | current_state == MULT_WAIT; |
assign done = current_state == DONE; |
assign mult_reset = current_state == INIT | current_state == COMPARE; |
|
|
always_comb begin |
// if (reset_async) begin |
// done = 0; |
// result = 0; |
// end |
// else begin |
// Reduction operator |
// see http://www.asic-world.com/verilog/operators2.html |
// done = ~|i & it_done & ~flush; |
// result[i] = (proposed_solution_square <= new_value) & it_done; |
done = ~|i & it_done & ~flush & ~reset_sync; |
result[i] = (proposed_solution_square <= new_value) & it_done & ~reset_sync; |
// end |
guess_next = guess; |
i_next = i; |
result_next = result; |
case (current_state) |
INIT: begin |
guess_next = 32'h0000_0000; |
i_next = 31; |
result_next = 0; |
next_state = GUESS; |
end |
GUESS: begin |
guess_next = guess + (32'h0000_0001 << i); |
next_state = MULT_LOAD; |
end |
MULT_LOAD: next_state = MULT_WAIT; |
MULT_WAIT: next_state = (mult_done) ? COMPARE : MULT_WAIT; |
COMPARE: next_state = (mult_result > value_reg) ? CHANGE : CHECK; |
CHANGE: begin |
guess_next = guess - (32'h0000_0001 << i); |
next_state = CHECK; |
end |
CHECK: next_state = i ? INCRE : ENDLOOP; |
INCRE: begin |
i_next = i - 1; |
next_state = GUESS; |
end |
ENDLOOP: begin |
result_next = guess; |
next_state = DONE; |
end |
DONE: next_state = DONE; |
default: next_state = INIT; |
endcase |
end |
|
always_ff @(posedge clock or posedge reset) begin |
always_ff @(posedge clock) begin |
if (reset) begin |
// done <= 0; |
// result <= 0; |
reset_sync <= 1; |
start <= 0; |
flush <= 0; |
i <= 5'b11111; |
proposed_solution <= 32'h80000000; |
new_value <= value; |
current_state <= INIT; |
value_reg <= value; |
result <= 32'b0; |
i <= 31; |
guess <= 32'h0000_0000; |
end |
else begin |
reset_sync <= 0; |
start <= !it_done || !flush; |
flush <= it_done; |
// if (!it_done && flush) begin |
// flush <= 0; |
// end |
if (i && it_done && !flush) begin |
// flush <= 1; |
i <= i - 1; |
proposed_solution[i-1] <= 1; |
proposed_solution[i] <= result[i]; |
end |
current_state <= next_state; |
value_reg <= value_reg; |
result <= result_next; |
i <= i_next; |
guess <= guess_next; |
end |
end |
|
endmodule |
|
|
|
module ISR( |
input reset, |
input [63:0] value, |
input clock, |
output logic [31:0] result, |
output logic done |
); |
logic mult_start; |
logic mult_done; |
logic [63:0] mult_result; |
logic [63:0] mult_input; |
logic mult_reset; |
|
|
mult multiplier( |
.clock(clock), |
.reset(mult_reset), |
.mcand(mult_input), |
.mplier(mult_input), |
.start(mult_start), |
.product(mult_result), |
.done(mult_done) |
); |
|
ISR_FSM FSM( |
.reset(reset), |
.value(value), |
.clock(clock), |
.mult_done(mult_done), |
.mult_result(mult_result), |
.mult_start(mult_start), |
.mult_reset(mult_reset), |
.mult_input(mult_input), |
.result(result), |
.done(done) |
); |
|
|
endmodule |
/trunk/src/test_ISR.sv
1,10 → 1,9
`define HALF_CYCLE 1000 |
`timescale 1ns / 1ps |
////////////////////////////////////////////////////////////////////////////////// |
// Company: |
// Engineer: Yihua Liu |
// |
// Create Date: 2022/06/08 16:51:12 |
// Create Date: 2022/10/14 01:01:28 |
// Design Name: |
// Module Name: testbench |
// Project Name: lab_3_b |
16,6 → 15,7
// |
// Revision: |
// Revision 0.01 - File Created |
// Revision 0.02 - Update Testbench |
// Additional Comments: |
// |
////////////////////////////////////////////////////////////////////////////////// |
23,157 → 23,116
|
module testbench(); |
|
logic [63:0] value; |
logic clock, reset; |
logic [63:0] test_input; |
logic clock, reset, quit; |
|
logic [31:0] result; |
logic done; |
|
logic [31:0] cres; |
|
wire correct = (cres===result)|~done|reset; |
|
integer value_test, j; |
time start_time = $time, finish_time; |
integer i; |
|
task ISR_test; |
input [63:0] value; |
output [31:0] cres; |
cres = 0; |
for (integer i = 31; i >= 0; i--) begin |
cres[i] = 1; |
if (cres * cres > value) |
cres[i] = 0; |
end |
endtask |
|
ISR isr( |
ISR UUT( |
.reset(reset), |
.value(value), |
.value(test_input), |
.clock(clock), |
.result(result), |
.done(done) |
); |
|
always @(posedge clock) |
#2 if(!correct) begin |
$display("Incorrect at time %4.0f",$time); |
$display("cres = %h result = %h",cres,result); |
$display("@@@Failed"); |
$finish; |
task compare_correct_result; |
input [63:0] value; |
input [31:0] result; |
|
logic [31:0] guess; |
logic [63:0] multi; |
begin |
// First, calculate the correct result |
guess = 32'h8000_0000; |
for (i = 0; i <= 31; i = i + 1) begin |
guess[31 - i] = 1'b1; |
multi = {32'b0, guess}; |
if ((multi * multi) > value) begin |
guess[31 - i] = 1'b0; |
end |
end |
// Then, compare the result with the correct one |
if (result == guess) begin |
end |
else begin |
$display("@@@Failed"); |
$display("Incorrect at time %4.0f",$time); |
$display("corrent_result = %h result = %h", guess, result); |
$finish; |
end |
end |
endtask |
|
|
always begin |
#`HALF_CYCLE; |
clock=~clock; |
#250; |
clock = ~clock; |
end |
|
// Some users have had problems just using "@(posedge done)" because their |
// "done" signals glitch (even though they are the output of a register). This |
// prevents that by making sure "done" is high at the clock edge. |
task wait_until_done; |
forever begin : wait_loop |
@(posedge done); |
@(negedge clock); |
if(done) begin |
finish_time = $time; |
$display("Done one calculation of ISR"); |
// Calculate the total number of cycles you need to do one calculation of ISR |
// Note that in this way the additional cycles added during simulation will be counted |
// So the displayed value may be 1 to 3 cycles more than 600 cycles |
$display("Number of cycles needed: %d", (finish_time - start_time) / (2 * `HALF_CYCLE)); |
start_time = finish_time; |
disable wait_until_done; |
end |
if (done) disable wait_until_done; |
end |
endtask |
|
|
initial begin |
$monitor("Time:%4.0f done:%b cres:%h result:%h reset:%h",$time,done,cres,result,reset); |
// Test 1 |
value = 0; // square number |
reset = 1; |
$dumpvars; |
$monitor("Time:%4.0f done:%b input:%h result:%h ",$time, done, test_input, result); |
reset = 0; |
clock = 0; |
ISR_test(value, cres); |
#2000; |
|
// First some special cases |
test_input = 64'h0000_0000_0000_03E9; |
@(negedge clock); |
reset = 0; |
wait_until_done(); |
@(negedge clock); |
// Test 2 |
reset = 1; |
value = 4; // square number |
ISR_test(value, cres); |
@(negedge clock); |
reset = 0; |
wait_until_done(); |
@(negedge clock); |
// Test 3 |
reset = 1; |
value = 121; // square number |
ISR_test(value, cres); |
@(negedge clock); |
reset = 0; |
wait_until_done(); |
$display("Calculate done!"); |
compare_correct_result(test_input, result); |
@(negedge clock); |
// Test 4 |
reset = 1; |
value = 1000000; // square number |
ISR_test(value, cres); |
@(negedge clock); |
reset = 0; |
wait_until_done(); |
// Test 5 |
reset = 1; |
value = 130; // non square number |
ISR_test(value, cres); |
test_input = 64'hFFFF_FFFF_FFFF_FFFF; |
@(negedge clock); |
reset = 0; |
wait_until_done(); |
// Test 6 |
compare_correct_result(test_input, result); |
@(negedge clock); |
reset = 1; |
value = 2; // non square number (value to be discarded) |
ISR_test(value, cres); |
test_input = 64'h0000_0000_0000_0000; |
@(negedge clock); |
reset = 0; |
@(negedge clock); |
@(negedge clock); |
@(negedge clock); |
reset = 1; // reset is asserted part way through a computation |
value = 3; // non square number (new value to be latched into) |
ISR_test(value, cres); |
@(negedge clock); |
reset = 0; |
wait_until_done(); |
compare_correct_result(test_input, result); |
|
// Then some random tests |
@(negedge clock); |
@(negedge clock); |
// Test 7 |
reset = 1; |
value = 64'h7FFF_FFFF_FFFF_FFFF; |
ISR_test(value, cres); |
@(negedge clock); |
reset = 0; |
wait_until_done(); |
@(negedge clock); |
value_test = 64'hFFFF_FFFF_FFFF_FFFF; |
// Short loops |
for (j = 0; j < 100; j++) begin |
quit = 0; |
quit <= #100000 1; |
while (~quit) begin |
reset = 1; |
value = value_test; |
ISR_test(value, cres); |
test_input = {$random, $random}; |
@(negedge clock); |
reset = 0; |
wait_until_done(); |
value_test = value_test - 64'h0000_0000_7FFF_FFFF; |
compare_correct_result(test_input, result); |
end |
// Random testing |
for (j = 0; j < 1000; j++) begin |
reset = 1; |
value = {$random, $random}; |
ISR_test(value, cres); |
@(negedge clock); |
reset = 0; |
wait_until_done(); |
end |
$display("@@@Passed"); |
@(negedge clock); |
reset = 1; |
@(negedge clock); |
$display("@@@Passed"); |
$finish; |
end |
|