OpenCores
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/trunk
    from Rev 4 to Rev 6
    Reverse comparison

Rev 4 → Rev 6

/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
/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
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.