module GCD (
input wire CLK,
input wire RST_N,
input wire [7:0] A,
input wire [7:0] B,
input wire START,
output reg [7:0] Y,
output reg DONE,
output reg ERROR
);
wire found, err;
reg [7:0] reg_a, reg_b, next_a, next_b;
reg [7:0] big_one;
reg error_next;
reg [1:0] state, state_next;
parameter [1:0] IDLE = 2'b00;
parameter [1:0] CALC = 2'b01;
parameter [1:0] FINISH = 2'b10;
always @(posedge CLK, negedge RST_N) begin
if (RST_N == 0)
state <= IDLE;
else
state <= state_next;
end
always @*begin
state_next = IDLE;
case(state)
IDLE: begin
if (!START)
state_next = IDLE;
else
state_next = CALC;
end
CALC: begin
if (!found && !ERROR)
state_next = CALC;
else
state_next = FINISH;
end
FINISH: begin
state_next = IDLE;
end
endcase
end
always @*begin
if (state == IDLE) begin
if (!START)
error_next = 0;
else
error_next = ((A == 0) || (B == 0));
end
else if (state == CALC)
error_next = ERROR;
else if (state == FINISH) begin
DONE = 1'd1;
error_next = 0;
end
end
always @(posedge CLK, negedge RST_N) begin
ERROR <= error_next;
end
assign start_A_out = START == 1 ? A : next_a;
assign start_B_out = START == 1 ? B : next_b;
always @(posedge CLK, negedge RST_N) begin
reg_a <= start_A_out;
end
always @(posedge CLK, negedge RST_N) begin
reg_b <= start_B_out;
end
wire cout;
always @*begin
if (reg_a >= reg_b) begin
adder8(cout, next_a, reg_a, reg_b, 1);
next_b = reg_b;
end else begin
adder8(cout, next_b, reg_b, reg_a, 1);
next_a = reg_a;
end
end
assign found = (next_a == 0 || next_b == 0) ? 1 : 0;
always @*begin
if (reg_a > reg_b) begin
big_one = reg_a;
end else begin
big_one = reg_b;
end
end
assign found_out = (found == 0) ? Y : big_one;
always @(posedge CLK, negedge RST_N) begin
Y <= found_out;
end
endmodule
module adder8(
output cout, //MSB, determines if answer is positive or negative
output [7:0] s,
input [7:0] a,
input [7:0] b,
input cin // if 1, subtract, if 0, add. This is XOR'ed with b
);
wire [7:0] bin;
assign bin[0] = b[0]^cin;
assign bin[1] = b[1]^cin;
assign bin[2] = b[2]^cin;
assign bin[3] = b[3]^cin;
assign bin[4] = b[4]^cin;
assign bin[5] = b[5]^cin;
assign bin[6] = b[6]^cin;
assign bin[7] = b[7]^cin;
wire [8:1] carry;
full_adder FA0(carry[1],s[0],a[0],bin[0],cin);
full_adder FA1(carry[2],s[1],a[1],bin[1],carry[1]);
full_adder FA2(carry[3],s[2],a[2],bin[2],carry[2]);
full_adder FA3(carry[4],s[3],a[3],bin[3],carry[3]);
full_adder FA4(carry[5],s[4],a[4],bin[4],carry[4]);
full_adder FA5(carry[6],s[5],a[5],bin[5],carry[5]);
full_adder FA6(carry[7],s[6],a[6],bin[6],carry[6]);
full_adder FA7(carry[8],s[7],a[7],bin[7],carry[7]);
assign cout = cin^carry[8];
endmodule
module full_adder(
output cout,
output sum,
input ain,
input bin,
input cin
);
//assign bin2 = cin^bin; // XORing the inputs to bin with cin. If 1, subtract; if 0, add
assign sum = ain^bin^cin;
assign cout = (ain&bin) | (ain&cin) | (bin&cin);
endmodule