data/full_repos/permissive/2084115/rtl/mipsi/jelly_cpu_cop0.v
data/verilator_xmls/5ff244ea-8453-41ea-ae5d-41eef3ff164b.xml
module jelly_cpu_cop0
    #(
        parameter                   DBBP_NUM = 4
    )
    (
        input   wire                clk,
        input   wire                reset,

        input   wire                interlock,
        
        input   wire                in_en,
        input   wire    [4:0]       in_addr,
        input   wire    [2:0]       in_sel,
        input   wire    [31:0]      in_data,
        
        output  reg     [31:0]      out_data,
        
        input   wire                exception,
        input   wire                rfe,
        input   wire                dbg_break,
        
        input   wire    [31:0]      in_cause,
        input   wire    [31:0]      in_epc,
        input   wire    [31:0]      in_debug,
        input   wire    [31:0]      in_depc,
        
        output  wire    [31:0]      out_status,
        output  wire    [31:0]      out_cause,
        output  wire    [31:0]      out_epc,
        output  wire    [31:0]      out_debug,
        output  wire    [31:0]      out_depc,
        
        output  wire    [31:0]      out_debp0,
        output  wire    [31:0]      out_debp1,
        output  wire    [31:0]      out_debp2,
        output  wire    [31:0]      out_debp3
    );
    

    reg     [31:0]  reg_status;
    reg     [31:0]  reg_cause;
    reg     [31:0]  reg_epc;
    reg     [31:0]  reg_debug;
    reg     [31:0]  reg_depc;
    
    reg     [31:0]  reg_debp0;
    reg     [31:0]  reg_debp1;
    reg     [31:0]  reg_debp2;
    reg     [31:0]  reg_debp3;
    
    
    always @ ( posedge clk ) begin
        if ( reset ) begin
            reg_status <= {32{1'b0}};
            reg_cause  <= {32{1'b0}};
            reg_epc    <= {32{1'b0}};
            reg_debug  <= {32{1'b0}};
            reg_depc   <= {32{1'b0}};
            reg_debp0  <= {32{1'b0}};
            reg_debp1  <= {32{1'b0}};
            reg_debp2  <= {32{1'b0}};
            reg_debp3  <= {32{1'b0}};
        end
        else begin
            if ( !interlock ) begin

                if ( exception ) begin
                    reg_status[0] <= 1'b0;
                    reg_status[2] <= reg_status[0];
                    reg_status[4] <= reg_status[2];
                end
                else if ( rfe ) begin
                    reg_status[0] <= reg_status[2];
                    reg_status[2] <= reg_status[4];
                end
                else if ( in_en & (in_addr == 5'd12) ) begin
                    reg_status[0] <= in_data[0];
                    reg_status[2] <= in_data[2]; 
                    reg_status[4] <= in_data[4];
                end


                if ( exception ) begin
                    reg_cause[31]  <= in_cause[31];
                    reg_cause[6:2] <= in_cause[6:2];
                end
                else if ( in_en & (in_addr == 5'd13) ) begin
                    reg_cause[31]  <= in_data[31];
                    reg_cause[6:2] <= in_data[6:2];
                end
                

                if ( exception ) begin
                    reg_epc[31:2] <= in_epc[31:2];
                end
                else if ( in_en & (in_addr == 5'd14) ) begin
                    reg_epc[31:2] <= in_data[31:2];
                end
                

                if ( dbg_break ) begin
                    reg_debug[31] <= in_debug[31];
                end
                else if ( in_en & (in_addr == 5'd23) ) begin
                    reg_debug[31] <= in_data[31];
                    reg_debug[24] <= in_data[24];
                    reg_debug[3]  <= in_data[0] & (DBBP_NUM >= 4);
                    reg_debug[2]  <= in_data[0] & (DBBP_NUM >= 3);
                    reg_debug[1]  <= in_data[0] & (DBBP_NUM >= 2);
                    reg_debug[0]  <= in_data[0] & (DBBP_NUM >= 1);
                end
                

                if ( dbg_break ) begin
                    reg_depc[31:2] <= in_depc[31:2];
                end
                else if ( in_en & (in_addr == 5'd24) ) begin
                    reg_depc[31:2] <= in_data[31:2];
                end
                

                if ( in_en & (in_addr == 5'd16) & (DBBP_NUM >= 1) ) begin
                    reg_debp0[31:2] <= in_data[31:2];
                end
                if ( in_en & (in_addr == 5'd17) & (DBBP_NUM >= 2) ) begin
                    reg_debp1[31:2] <= in_data[31:2];
                end
                if ( in_en & (in_addr == 5'd18) & (DBBP_NUM >= 3) ) begin
                    reg_debp2[31:2] <= in_data[31:2];
                end
                if ( in_en & (in_addr == 5'd19) & (DBBP_NUM >= 4) ) begin
                    reg_debp3[31:2] <= in_data[31:2];
                end
            end
        end
    end
    

    always @* begin
        case ( in_addr )
        5'd12:      out_data <= reg_status;
        5'd13:      out_data <= reg_cause;
        5'd14:      out_data <= reg_epc;
        5'd23:      out_data <= reg_debug;
        5'd24:      out_data <= reg_depc;
        5'd16:      out_data <= reg_debp0;
        5'd17:      out_data <= reg_debp1;
        5'd18:      out_data <= reg_debp2;
        5'd19:      out_data <= reg_debp3;
        default:    out_data <= {32{1'b0}};
        endcase
    end
    
    assign out_status = reg_status;
    assign out_cause  = reg_cause;
    assign out_epc    = reg_epc;
    assign out_debug  = reg_debug;
    assign out_depc   = reg_depc;

    assign out_debp0  = reg_debp0;
    assign out_debp1  = reg_debp1;
    assign out_debp2  = reg_debp2;
    assign out_debp3  = reg_debp3;
    
endmodule
module jelly_cpu_cop0
    #(
        parameter                   DBBP_NUM = 4
    )
    (
        input   wire                clk,
        input   wire                reset,

        input   wire                interlock,
        
        input   wire                in_en,
        input   wire    [4:0]       in_addr,
        input   wire    [2:0]       in_sel,
        input   wire    [31:0]      in_data,
        
        output  reg     [31:0]      out_data,
        
        input   wire                exception,
        input   wire                rfe,
        input   wire                dbg_break,
        
        input   wire    [31:0]      in_cause,
        input   wire    [31:0]      in_epc,
        input   wire    [31:0]      in_debug,
        input   wire    [31:0]      in_depc,
        
        output  wire    [31:0]      out_status,
        output  wire    [31:0]      out_cause,
        output  wire    [31:0]      out_epc,
        output  wire    [31:0]      out_debug,
        output  wire    [31:0]      out_depc,
        
        output  wire    [31:0]      out_debp0,
        output  wire    [31:0]      out_debp1,
        output  wire    [31:0]      out_debp2,
        output  wire    [31:0]      out_debp3
    );

    

    reg     [31:0]  reg_status;
    reg     [31:0]  reg_cause;
    reg     [31:0]  reg_epc;
    reg     [31:0]  reg_debug;
    reg     [31:0]  reg_depc;
    
    reg     [31:0]  reg_debp0;
    reg     [31:0]  reg_debp1;
    reg     [31:0]  reg_debp2;
    reg     [31:0]  reg_debp3;
    
    
    always @ ( posedge clk ) begin
        if ( reset ) begin
            reg_status <= {32{1'b0}};
            reg_cause  <= {32{1'b0}};
            reg_epc    <= {32{1'b0}};
            reg_debug  <= {32{1'b0}};
            reg_depc   <= {32{1'b0}};
            reg_debp0  <= {32{1'b0}};
            reg_debp1  <= {32{1'b0}};
            reg_debp2  <= {32{1'b0}};
            reg_debp3  <= {32{1'b0}};
        end
        else begin
            if ( !interlock ) begin

                if ( exception ) begin
                    reg_status[0] <= 1'b0;
                    reg_status[2] <= reg_status[0];
                    reg_status[4] <= reg_status[2];
                end
                else if ( rfe ) begin
                    reg_status[0] <= reg_status[2];
                    reg_status[2] <= reg_status[4];
                end
                else if ( in_en & (in_addr == 5'd12) ) begin
                    reg_status[0] <= in_data[0];
                    reg_status[2] <= in_data[2]; 
                    reg_status[4] <= in_data[4];
                end


                if ( exception ) begin
                    reg_cause[31]  <= in_cause[31];
                    reg_cause[6:2] <= in_cause[6:2];
                end
                else if ( in_en & (in_addr == 5'd13) ) begin
                    reg_cause[31]  <= in_data[31];
                    reg_cause[6:2] <= in_data[6:2];
                end
                

                if ( exception ) begin
                    reg_epc[31:2] <= in_epc[31:2];
                end
                else if ( in_en & (in_addr == 5'd14) ) begin
                    reg_epc[31:2] <= in_data[31:2];
                end
                

                if ( dbg_break ) begin
                    reg_debug[31] <= in_debug[31];
                end
                else if ( in_en & (in_addr == 5'd23) ) begin
                    reg_debug[31] <= in_data[31];
                    reg_debug[24] <= in_data[24];
                    reg_debug[3]  <= in_data[0] & (DBBP_NUM >= 4);
                    reg_debug[2]  <= in_data[0] & (DBBP_NUM >= 3);
                    reg_debug[1]  <= in_data[0] & (DBBP_NUM >= 2);
                    reg_debug[0]  <= in_data[0] & (DBBP_NUM >= 1);
                end
                

                if ( dbg_break ) begin
                    reg_depc[31:2] <= in_depc[31:2];
                end
                else if ( in_en & (in_addr == 5'd24) ) begin
                    reg_depc[31:2] <= in_data[31:2];
                end
                

                if ( in_en & (in_addr == 5'd16) & (DBBP_NUM >= 1) ) begin
                    reg_debp0[31:2] <= in_data[31:2];
                end
                if ( in_en & (in_addr == 5'd17) & (DBBP_NUM >= 2) ) begin
                    reg_debp1[31:2] <= in_data[31:2];
                end
                if ( in_en & (in_addr == 5'd18) & (DBBP_NUM >= 3) ) begin
                    reg_debp2[31:2] <= in_data[31:2];
                end
                if ( in_en & (in_addr == 5'd19) & (DBBP_NUM >= 4) ) begin
                    reg_debp3[31:2] <= in_data[31:2];
                end
            end
        end
    end
    

    always @* begin
        case ( in_addr )
        5'd12:      out_data <= reg_status;
        5'd13:      out_data <= reg_cause;
        5'd14:      out_data <= reg_epc;
        5'd23:      out_data <= reg_debug;
        5'd24:      out_data <= reg_depc;
        5'd16:      out_data <= reg_debp0;
        5'd17:      out_data <= reg_debp1;
        5'd18:      out_data <= reg_debp2;
        5'd19:      out_data <= reg_debp3;
        default:    out_data <= {32{1'b0}};
        endcase
    end
    
    assign out_status = reg_status;
    assign out_cause  = reg_cause;
    assign out_epc    = reg_epc;
    assign out_debug  = reg_debug;
    assign out_depc   = reg_depc;

    assign out_debp0  = reg_debp0;
    assign out_debp1  = reg_debp1;
    assign out_debp2  = reg_debp2;
    assign out_debp3  = reg_debp3;
    
endmodule