`timescale 1ns / 1ps

module FetchUnit(
    input wire [8:0] AddrIn,
    input wire clk, reset, op_idx,
    output wire [8:0] AddrOut
        );
  
    //Wires from mux(result_m) to PC (progC_out) to adder then back to mux (result_a) 
    wire [8:0] progC_out, result_m;
    wire cout;
    
    register PC(
        .clk(clk),
        .reset(reset),
        .En(1'b0),
        .Din(result_m),
        .Dout(progC_out));
    //Adds 1 to the program counter
    add_9bit PCAdder(
        .A(progC_out),
        .B(9'b000000001),
        .Cin(1'b0),
        .Sum(AddrOut),
        .Cout(cout));
        
    mux_2_1 PCmux(
        .A(AddrIn),
        .B(AddrOut),
        .out(result_m),
        .switch(op_idx));
        
endmodule

//testbench
module fetchUnit_tb();
    reg [8:0] addr_in;
    reg opidx,reset,clk;
    wire [8:0] addr_out;

    initial begin
        clk = 1'b0;
    end
    always begin
        #5 clk = ~clk; // Period to be determined
    end

    FetchUnit tb0(
        .clk(clk),
        .reset(reset),
        .op_idx(opidx),
        .AddrIn(addr_in),
        .AddrOut(addr_out));


    
    initial begin
        reset = 0;
        opidx = 1'b1;
        addr_in = 9'b000000000;
        #5
        reset = 1;
        #5
        reset = 0;
        opidx = 1'b0;
        addr_in = 9'b000001111;
        #5
        #5
        addr_in = 9'b011000011;
        #5
        #5
        opidx = 1'b1;
        #5
        #5
        #5
        #5
        opidx = 1'b0;
        addr_in = 9'b000001111;
        #5
        #5
        addr_in = 9'b010010011;
        #5
        opidx = 1'b1;
        #5
        #5
        #5
        #5
        #5
        $finish;

    end
endmodule