---
# System prepended metadata

title: Untitled

---

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





















