data/full_repos/permissive/177233467/alu.v
data/verilator_xmls/3b5ce786-8c7c-4a5b-b8e9-0cf6b370ea11.xml
module alu(
    input wire clk, resetn,

    input wire [3:0] cc,
    input wire [7:0] ALU_sel,
    input wire [31:0] A, B,
    input wire [31:0] cpsr_in,

    output wire [31:0] cpsr_out,
    output wire VF,
    output wire [31:0] ALU_out,

    output wire [7:0] debug_alu
);

reg [1:0] branch_ps, branch_ns;

reg [31:0] ALU_result;

wire N, Z, C, V;
wire cond_status;

reg ret_result;
reg islogical;
reg write_cpsr;

assign cond_status = check_cond(cc, cpsr_in[31:28]);

always @(*) begin
    ALU_result = 0;
    ret_result = 1;
    islogical = 0;
    write_cpsr = 0;

    branch_ns = 2'b00;
    
  


    if(cond_status) begin
        casez(ALU_sel)


            8'b000_0000?: begin
                    ALU_result = A & B; 
                    islogical = 1;
                    write_cpsr = ALU_sel[0];
                end

            8'b000_0001?: begin
                    ALU_result = A ^ B; 
                    islogical = 1;
                    write_cpsr = ALU_sel[0];                   
                end

            8'b000_0010?: begin
                    ALU_result = A + (~B + 1); 
                    write_cpsr = ALU_sel[0];
                end

            8'b000_0100?: begin
                    ALU_result = A + B;
                    write_cpsr = ALU_sel[0]; 
                end

            8'b000_10001: begin
                    ALU_result = A & B; 
                    ret_result = 0;
                    write_cpsr = ALU_sel[0];
                end

            8'b000_10011: begin
                    ALU_result = A ^ B; 
                    ret_result = 0;
                    write_cpsr = ALU_sel[0];
                end

            8'b000_10101: begin
                    ALU_result = A + (~B + 1); 
                    ret_result = 0;
                    write_cpsr = ALU_sel[0];
                end

            8'b000_10001: begin
                    ALU_result = A + B; 
                    ret_result =  0;
                    write_cpsr = ALU_sel[0];
                end

            8'b000_1100?: begin
                    ALU_result = A | B;
                    islogical = 1;
                    write_cpsr = ALU_sel[0];
                end

            8'b0011101?: begin
                    ALU_result = B;
                    write_cpsr = ALU_sel[0];
                end


            8'b1010_????: begin
                    branch_ns = 2'b10;
                    ALU_result = A + B;
                end     
            8'b1011_????: begin
                    branch_ns = 2'b10;
                    ALU_result = A + B;
                end     
            8'b0001_0010: begin
                    branch_ns = 2'b10;
                    ALU_result = B;
                end

            8'b010??0?1: begin
                    if(ALU_sel[3])
                        ALU_result = A + B;
                    else
                        ALU_result = A - B;
                end
            8'b010??0?0: begin
                    if(ALU_sel[3])
                        ALU_result = A + B;
                    else
                        ALU_result = A - B;
                end   
            default:
                ret_result = 0;            
        endcase
    end else begin
        ret_result = 0;
    end




end

assign N = ALU_result[31];
assign Z = ALU_result == 0;
assign C = (A[31] & B[31]) ^ ALU_result[31];
assign V = islogical ? cpsr_in[28] : (~A[31] & ~B[31] & ALU_result[31]) | (A[31] & B[31] & ~ALU_result[31]);






assign VF = ~(branch_ps[1] | ~ret_result);
assign cpsr_out = write_cpsr ? {N, Z, C, V, cpsr_in[27:0]} : cpsr_in;
assign ALU_out = ret_result ? ALU_result : 32'hFC_FC_FC_FC;

assign debug_alu = {3'b0, cond_status, branch_ns, branch_ps};



always @(posedge clk) begin
    if(!resetn)
        branch_ps <= 2'b00;
    else if (branch_ps[1])
        branch_ps <= branch_ps + 1;
    else if(branch_ns[1])
        branch_ps <= branch_ns;
end


function check_cond;
    input [3:0] cc;
    input [3:0] cpsr;

    reg result;

    begin
        result = 0;
        case(cc[3:1])
            3'b000: result = (cpsr[2] == 1);
            3'b001: result = (cpsr[1] == 1);
            3'b010: result = (cpsr[3] == 1);
            3'b011: result = (cpsr[0] == 1);
            3'b100: result = (cpsr[1] == 1) & (cpsr[2] == 0);
            3'b101: result = (cpsr[3] == cpsr[0]);
            3'b110: result = (cpsr[3] == cpsr[0]) & (cpsr[2] == 0);
            3'b111: result = 1'b1;
        endcase
        if (cc[0])
            result = !result;
        check_cond = result;
    end
endfunction

endmodule
module alu(
    input wire clk, resetn,

    input wire [3:0] cc,
    input wire [7:0] ALU_sel,
    input wire [31:0] A, B,
    input wire [31:0] cpsr_in,

    output wire [31:0] cpsr_out,
    output wire VF,
    output wire [31:0] ALU_out,

    output wire [7:0] debug_alu
);


reg [1:0] branch_ps, branch_ns;

reg [31:0] ALU_result;

wire N, Z, C, V;
wire cond_status;

reg ret_result;
reg islogical;
reg write_cpsr;

assign cond_status = check_cond(cc, cpsr_in[31:28]);

always @(*) begin
    ALU_result = 0;
    ret_result = 1;
    islogical = 0;
    write_cpsr = 0;

    branch_ns = 2'b00;
    
  


    if(cond_status) begin
        casez(ALU_sel)


            8'b000_0000?: begin
                    ALU_result = A & B; 
                    islogical = 1;
                    write_cpsr = ALU_sel[0];
                end

            8'b000_0001?: begin
                    ALU_result = A ^ B; 
                    islogical = 1;
                    write_cpsr = ALU_sel[0];                   
                end

            8'b000_0010?: begin
                    ALU_result = A + (~B + 1); 
                    write_cpsr = ALU_sel[0];
                end

            8'b000_0100?: begin
                    ALU_result = A + B;
                    write_cpsr = ALU_sel[0]; 
                end

            8'b000_10001: begin
                    ALU_result = A & B; 
                    ret_result = 0;
                    write_cpsr = ALU_sel[0];
                end

            8'b000_10011: begin
                    ALU_result = A ^ B; 
                    ret_result = 0;
                    write_cpsr = ALU_sel[0];
                end

            8'b000_10101: begin
                    ALU_result = A + (~B + 1); 
                    ret_result = 0;
                    write_cpsr = ALU_sel[0];
                end

            8'b000_10001: begin
                    ALU_result = A + B; 
                    ret_result =  0;
                    write_cpsr = ALU_sel[0];
                end

            8'b000_1100?: begin
                    ALU_result = A | B;
                    islogical = 1;
                    write_cpsr = ALU_sel[0];
                end

            8'b0011101?: begin
                    ALU_result = B;
                    write_cpsr = ALU_sel[0];
                end


            8'b1010_????: begin
                    branch_ns = 2'b10;
                    ALU_result = A + B;
                end     
            8'b1011_????: begin
                    branch_ns = 2'b10;
                    ALU_result = A + B;
                end     
            8'b0001_0010: begin
                    branch_ns = 2'b10;
                    ALU_result = B;
                end

            8'b010??0?1: begin
                    if(ALU_sel[3])
                        ALU_result = A + B;
                    else
                        ALU_result = A - B;
                end
            8'b010??0?0: begin
                    if(ALU_sel[3])
                        ALU_result = A + B;
                    else
                        ALU_result = A - B;
                end   
            default:
                ret_result = 0;            
        endcase
    end else begin
        ret_result = 0;
    end




end

assign N = ALU_result[31];
assign Z = ALU_result == 0;
assign C = (A[31] & B[31]) ^ ALU_result[31];
assign V = islogical ? cpsr_in[28] : (~A[31] & ~B[31] & ALU_result[31]) | (A[31] & B[31] & ~ALU_result[31]);






assign VF = ~(branch_ps[1] | ~ret_result);
assign cpsr_out = write_cpsr ? {N, Z, C, V, cpsr_in[27:0]} : cpsr_in;
assign ALU_out = ret_result ? ALU_result : 32'hFC_FC_FC_FC;

assign debug_alu = {3'b0, cond_status, branch_ns, branch_ps};



always @(posedge clk) begin
    if(!resetn)
        branch_ps <= 2'b00;
    else if (branch_ps[1])
        branch_ps <= branch_ps + 1;
    else if(branch_ns[1])
        branch_ps <= branch_ns;
end


function check_cond;
    input [3:0] cc;
    input [3:0] cpsr;

    reg result;

    begin
        result = 0;
        case(cc[3:1])
            3'b000: result = (cpsr[2] == 1);
            3'b001: result = (cpsr[1] == 1);
            3'b010: result = (cpsr[3] == 1);
            3'b011: result = (cpsr[0] == 1);
            3'b100: result = (cpsr[1] == 1) & (cpsr[2] == 0);
            3'b101: result = (cpsr[3] == cpsr[0]);
            3'b110: result = (cpsr[3] == cpsr[0]) & (cpsr[2] == 0);
            3'b111: result = 1'b1;
        endcase
        if (cc[0])
            result = !result;
        check_cond = result;
    end
endfunction

endmodule