32-bit ALU [Verilog]

Based on MIPS Instruction Structure

Main Module


module Alu(
    input [31:0] a, // operand 1
    input [31:0] b, // operand 2
    input [3:0] aluc, // control port
    output [31:0] r, // result
    // Flags
    output zero,
    output carry,
    output negative,
    output overflow
    );
// operation definition
parameter DIGIT = 32;
// parameter ENABLE = 1, DISABLE = 0;
parameter ADDU = 4'b0000, ADD = 4'b0010, SUBU = 4'b0001;
parameter SUB  = 4'b0011, AND = 4'b0100, OR   = 4'b0101;
parameter XOR  = 4'b0110, NOR = 4'b0111, LUI  = 4'b100x;
parameter SLTU = 4'b1010, SLT = 4'b1011, SRA  = 4'b1100;
parameter SLL  = 4'b1110, SLR = 4'b1111, SRL  = 4'b1101;
// ---
// output wire
wire [DIGIT-1:0] Addu;
wire [DIGIT-1:0] Add;
wire [DIGIT-1:0] Subu;
wire [DIGIT-1:0] Sub;
// ---
wire [DIGIT-1:0] And;
wire [DIGIT-1:0] Or;
wire [DIGIT-1:0] Xor;
wire [DIGIT-1:0] Nor;
// ---
wire [DIGIT-1:0] Lui;
wire [DIGIT-1:0] Sltu;
wire [DIGIT-1:0] Slt;
// ---
wire [DIGIT-1:0] Sra;
wire [DIGIT-1:0] Sll;
wire [DIGIT-1:0] Srl;
wire [DIGIT-1:0] Slr; // slr instruction is unnecessary...
// ---
// Flags
wire addu_z, addu_c, addu_n, addu_o;
wire add_z, add_c, add_n, add_o;
wire subu_z, subu_c, subu_n, subu_o;
wire sub_z, sub_c, sub_n, sub_o;
// ---
wire and_z, and_c, and_n, and_o;
wire or_z, or_c, or_n, or_o;
wire xor_z, xor_c, xor_n, xor_o;
wire nor_z, nor_c, nor_n, nor_o;
// ---
wire lui_z, lui_c, lui_n, lui_o;
wire sltu_z, sltu_c, sltu_n, sltu_o;
wire slt_z, slt_c, slt_n, slt_o;
// ---
wire sra_z, sra_c, sra_n, sra_o;
wire sll_z, sll_c, sll_n, sll_o;
wire srl_z, srl_c, srl_n, srl_o;
wire slr_z, slr_c, slr_n, slr_o;

// Module instantation
AddSub m_addu(.in_a(a), .in_b(b), .aluc(ADDU), .out(Addu),
                  .zero(addu_z), .carry(addu_c), .negative(addu_n), .overflow(addu_o));
AddSub m_add(.in_a(a), .in_b(b), .aluc(ADD), .out(Add),
                  .zero(add_z), .carry(add_c), .negative(add_n), .overflow(add_o));
AddSub m_subu(.in_a(a), .in_b(b), .aluc(SUBU), .out(Subu),
                  .zero(subu_z), .carry(subu_c), .negative(subu_n), .overflow(subu_o));
AddSub m_sub(.in_a(a), .in_b(b), .aluc(SUB), .out(Sub),
                  .zero(sub_z), .carry(sub_c), .negative(sub_n), .overflow(sub_o));
LogicOpr m_and(.in_a(a), .in_b(b), .aluc(AND), .out(And),
                     .zero(and_z), .carry(and_c), .negative(and_n), .overflow(and_o));
LogicOpr m_or(.in_a(a), .in_b(b), .aluc(OR), .out(Or),
                    .zero(or_z), .carry(or_c), .negative(or_n), .overflow(or_o));
LogicOpr m_xor(.in_a(a), .in_b(b), .aluc(XOR), .out(Xor),
                     .zero(xor_z), .carry(xor_c), .negative(xor_n), .overflow(xor_o));
LogicOpr m_nor(.in_a(a), .in_b(b), .aluc(NOR), .out(Nor),
                     .zero(nor_z), .carry(nor_c), .negative(nor_n), .overflow(nor_o));
Shifter32 m_sll(.in_a(a), .in_b(b), .aluc(SLL), .out(Sll),
                     .zero(sll_z), .carry(sll_c), .negative(sll_n), .overflow(sll_o));
Shifter32 m_slr(.in_a(a), .in_b(b), .aluc(SLR), .out(Slr),
                     .zero(slr_z), .carry(slr_c), .negative(slr_n), .overflow(slr_o));
Shifter32 m_srl(.in_a(a), .in_b(b), .aluc(SRL), .out(Srl),
                     .zero(srl_z), .carry(srl_c), .negative(srl_n), .overflow(srl_o));
Shifter32 m_sra(.in_a(a), .in_b(b), .aluc(SRA), .out(Sra),
                     .zero(sra_z), .carry(sra_c), .negative(sra_n), .overflow(sra_o));
Others m_lui(.in_a(a), .in_b(b), .aluc(LUI), .out(Lui),
                     .zero(lui_z), .carry(lui_c), .negative(lui_n), .overflow(lui_o));
Others m_slt(.in_a(a), .in_b(b), .aluc(SLT), .out(Slt),
                     .zero(slt_z), .carry(slt_c), .negative(slt_n), .overflow(slt_o));
Others m_sltu(.in_a(a), .in_b(b), .aluc(SLTU), .out(Sltu),
                     .zero(sltu_z), .carry(sltu_c), .negative(sltu_n), .overflow(sltu_o));
// select the result to output
Selector m_result(.aluc(aluc), .r_add(Add), .r_addu(Addu), .r_sub(Sub), .r_subu(Subu),
                        .r_lui(Lui), .r_slt(Slt), .r_sltu(Sltu), .r_and(And), .r_or(Or),
                        .r_xor(Xor), .r_nor(Nor), .r_sll(Sll),   .r_slr(Slr), .r_srl(Srl), .r_sra(Sra),
                        // Flags
                        .out(r), .zero(zero), .carry(carry), .negative(negative), .overflow(overflow),
                        .addu_z(addu_z), .addu_c(addu_c), .addu_n(addu_n), .addu_o(addu_o),
                        .add_z(add_z), .add_c(add_c), .add_n(add_n), .add_o(add_o),
                        .subu_z(subu_z), .subu_c(subu_c), .subu_n(subu_n), .subu_o(subu_o),
                        .sub_z(sub_z), .sub_c(sub_c), .sub_n(sub_n), .sub_o(sub_o),
                        // ---
                        .and_z(and_z), .and_c(and_c), .and_n(and_n), .and_o(and_o),
                        .or_z(or_z), .or_c(or_c), .or_n(or_n), .or_o(or_o),
                        .xor_z(xor_z), .xor_c(xor_c), .xor_n(xor_n), .xor_o(xor_o),
                        .nor_z(nor_z), .nor_c(nor_c), .nor_n(nor_n), .nor_o(nor_o),
                        // ---
                        .lui_z(lui_z), .lui_c(lui_c), .lui_n(lui_n), .lui_o(lui_o),
                        .sltu_z(sltu_z), .sltu_c(sltu_c), .sltu_n(sltu_n), .sltu_o(sltu_o),
                        .slt_z(slt_z), .slt_c(slt_c), .slt_n(slt_n), .slt_o(slt_o),
                        // ---
                        .sra_z(sra_z), .sra_c(sra_c), .sra_n(sra_n), .sra_o(sra_o),
                        .sll_z(sll_z), .sll_c(sll_c), .sll_n(sll_n), .sll_o(sll_o),
                        .srl_z(srl_z), .srl_c(srl_c), .srl_n(srl_n), .srl_o(srl_o),
                        .slr_z(slr_z), .slr_c(slr_c), .slr_n(slr_n), .slr_o(slr_o));
endmodule

Add&Sub Module


/* Unsigned Adder */
module AddSub(
    input [31:0] in_a, // operand 1
    input [31:0] in_b, // operand 2
    input [3:0] aluc, // operand 3
    output reg [31:0] out,
    // Flag
    output reg zero,
    output reg carry,
    output reg negative,
    output reg overflow
    );
parameter DIGIT = 32;
parameter ENABLE = 1;
parameter DISABLE = 0;
parameter ADDU = 4'b0000, ADD = 4'b0010, SUBU = 4'b0001, SUB  = 4'b0011;

initial begin
    out = 32'h0000_0000;
    zero = DISABLE;
    carry = DISABLE;
    negative = DISABLE;
    overflow = DISABLE;
end
always @ (*) begin

    case(aluc)
    ADDU: begin // Unsigned add
        out = in_a + in_b;
        // flag judgement
        if(in_a[DIGIT-1] == 0 && in_b[DIGIT-1] == 0)
            carry = DISABLE;
        else begin
            if(out[DIGIT-1] == 0)
                carry = ENABLE;
            else
                carry = DISABLE;
        end
    end
    SUBU: begin // Unsigned sub
        out = in_a - in_b;
        // flag judgement
        if((in_a[DIGIT-1] == 0 && in_b[DIGIT-1] == 1))
            carry = ENABLE;
        else if(in_a[DIGIT-1] == 1 && in_b[DIGIT-1] == 0)
            carry = DISABLE;
        else if(out[DIGIT-1] == 1)
            carry = ENABLE;
        else
            carry = DISABLE;
    end
    ADD: begin // Signed add
        out = in_a + in_b;
        // flag judgement
        if((out[DIGIT-1] != in_a[DIGIT-1]) && (in_a[DIGIT-1] == in_b[DIGIT-1]))
            overflow = ENABLE;
        else
            overflow = DISABLE;
    end
    SUB: begin // Signed sub
        out = in_a + (~in_b + 1);
        // flag judgement
        if((in_a[DIGIT-1] != in_b[DIGIT-1]) && (out[DIGIT-1] != in_a[DIGIT-1]))
            overflow = ENABLE;
        else
            overflow = DISABLE;
    end
    endcase
    if(out == 0) // zero flag
        zero = ENABLE;
    else
        zero = DISABLE;
    if(out[DIGIT-1] == 1) // negative flag
        negative = ENABLE;
    else
        negative = DISABLE;
end

endmodule

Logic Operation Module


module LogicOpr(
    input [31:0] in_a, // operand 1
    input [31:0] in_b, // operand 2
    input [3:0] aluc, // operand 3
    output reg [31:0] out,
    // Flag
    output reg zero,
    output reg carry,
    output reg negative,
    output reg overflow
    );
parameter DIGIT = 32;
parameter AND = 4'b0100, OR   = 4'b0101, XOR  = 4'b0110, NOR = 4'b0111;
parameter ENABLE = 1;
parameter DISABLE = 0;
// initialize
initial begin
    out = 32'h0000_0000;
    zero = DISABLE;
    carry = DISABLE;
    negative = DISABLE;
    overflow = DISABLE;
end
always @ (*) begin
    case(aluc)
    AND:
        out = in_a & in_b;
    OR:
        out = in_a | in_b;
    XOR:
        out = in_a ^ in_b;
    NOR:
        out = ~(in_a | in_b);
    endcase
    if(out == 0)
        zero = ENABLE;
    else
        zero = DISABLE;
    if(out[31] == 1)
        negative = ENABLE;
    else
        negative = DISABLE;
end

endmodule

32-bit Shifter Module


module Shifter32(
    input [31:0] in_a,
    input [31:0] in_b,
    input [3:0]aluc,
    output reg [31:0] out,
    // Flags
    output reg zero,
    output reg carry,
    output reg negative,
    output reg overflow
     );
parameter DIGIT = 32;
parameter ENABLE = 1;
parameter DISABLE = 0;
parameter SRA  = 4'b1100, SRL  = 4'b1101;
// initialize
initial begin
    out = 32'h0000_0000;
    zero = DISABLE;
    carry = DISABLE;
    negative = DISABLE;
    overflow = DISABLE;
end
always @ (*) begin
    case(aluc)
    SRA: begin // sra
        out = in_b >>> (in_a - 1);
        carry = out[0];
        out = in_b >>> 1;
    end
    SRL: begin // srl
        out = in_b >> (in_a - 1);
        carry = out[0];
        out = in_b >> 1;
    end
    default: begin // slr,sll
        out = in_b << (in_a - 1);
        carry = out[DIGIT-1];
        out = out << 1;
    end
    endcase
    if(out == 0) // zero flag
        zero = ENABLE;
    else
        zero = DISABLE;
    if(out[DIGIT-1] == 1) // negative flag
        negative = ENABLE;
    else
        negative = DISABLE;

end

endmodule

Others' Module


module Others(
    input [31:0] in_a, // operand 1
    input [31:0] in_b, // operand 2
    input [3:0] aluc, // control port
    output reg [31:0] out, // result
    // Flags
    output reg zero,
    output reg carry,
    output reg negative,
    output reg overflow
    );
parameter DIGIT = 32;
parameter SLTU = 4'b1010, SLT = 4'b1011;
parameter ENABLE = 1;
parameter DISABLE = 0;
// initialize
initial begin
    out = 32'h0000_0000;
    zero = DISABLE;
    carry = DISABLE;
    negative = DISABLE;
    overflow = DISABLE;
end
always @ (*) begin
    case(aluc)
    SLTU: begin
        out = (in_a < in_b) ? 1 : 0;
    end
    SLT: begin
        if(in_a[31] == 0 && in_b[31] == 0)
            out = (in_a < in_b) ? 1 : 0;
        else if(in_a[31] == 1 && in_b[31] == 0)
            out = 1;
        else if(in_a[31] == 0 && in_b[31] == 1)
            out = 0;
        else
            out = ((~in_b+1) < (~in_a+1)) ? 1 : 0;
    end
    default: begin // lui
        out = {in_b[15:0], 16'b0};
    end
    endcase
    if(out == 0) // zero flag
        zero = ENABLE;
    else
        zero = DISABLE;
    if(out[DIGIT-1] == 1) // negative flag
        negative = ENABLE;
    else
        negative = DISABLE;
end

endmodule

Selector Moudle


module Selector(
    input [3:0] aluc,
    input [31:0] r_add,
    input [31:0] r_addu,
    input [31:0] r_sub,
    input [31:0] r_subu,
    input [31:0] r_and,
    input [31:0] r_or,
    input [31:0] r_xor,
    input [31:0] r_nor,
    input [31:0] r_sll,
    input [31:0] r_slr,
    input [31:0] r_srl,
    input [31:0] r_sra,
    input [31:0] r_lui,
    input [31:0] r_slt,
    input [31:0] r_sltu,
    // Flags
    input addu_z, addu_c, addu_n, addu_o,
    input add_z, add_c, add_n, add_o,
    input subu_z, subu_c, subu_n, subu_o,
    input sub_z, sub_c, sub_n, sub_o,
    // ---
    input and_z, and_c, and_n, and_o,
    input or_z, or_c, or_n, or_o,
    input xor_z, xor_c, xor_n, xor_o,
    input nor_z, nor_c, nor_n, nor_o,
    // ---
    input lui_z, lui_c, lui_n, lui_o,
    input sltu_z, sltu_c, sltu_n, sltu_o,
    input slt_z, slt_c, slt_n, slt_o,
    // ---
    input sra_z, sra_c, sra_n, sra_o,
    input sll_z, sll_c, sll_n, sll_o,
    input srl_z, srl_c, srl_n, srl_o,
    input slr_z, slr_c, slr_n, slr_o,
    output reg [31:0] out,
    output reg zero, negative, carry, overflow
    );
// operation definition
parameter DIGIT = 32;
parameter ENABLE = 1, DISABLE = 0;
parameter ADDU = 4'b0000, ADD = 4'b0010, SUBU = 4'b0001;
parameter SUB  = 4'b0011, AND = 4'b0100, OR   = 4'b0101;
parameter XOR  = 4'b0110, NOR = 4'b0111, LUI_1  = 4'b1001, LUI_2 = 4'b1000;
parameter SLTU = 4'b1010, SLT = 4'b1011, SRA  = 4'b1100;
parameter SLL  = 4'b1110, SLR = 4'b1111, SRL  = 4'b1101;
initial begin
    out = 32'h0000_0000;
    zero = DISABLE;
    carry = DISABLE;
    negative = DISABLE;
    overflow = DISABLE;
end
always @ (*) begin
    case(aluc)
    ADDU: begin
        out = r_addu;
        zero = addu_z;
        carry = addu_c;
        negative = addu_n;
        overflow = addu_o;
    end
    ADD: begin
        out = r_add;
        zero = add_z;
        carry = add_c;
        negative = add_n;
        overflow = add_o;
    end
    SUBU: begin
        out = r_subu;
        zero = subu_z;
        carry = subu_c;
        negative = subu_n;
        overflow = subu_o;
    end
    SUB: begin
        out = r_sub;
        zero = sub_z;
        carry = sub_c;
        negative = sub_n;
        overflow = sub_o;
    end
    AND: begin
        out = r_and;
        zero = and_z;
        carry = and_c;
        negative = and_n;
        overflow = and_o;
    end
    OR: begin
        out = r_or;
        zero = or_z;
        carry = or_c;
        negative = or_n;
        overflow = or_o;
    end
    XOR: begin
        out = r_xor;
        zero = xor_z;
        carry = xor_c;
        negative = xor_n;
        overflow = xor_o;
    end
    NOR: begin
        out = r_nor;
        zero = nor_z;
        carry = nor_c;
        negative = nor_n;
        overflow = nor_o;
    end
    LUI_1: begin
        out = r_lui;
        zero = lui_z;
        carry = lui_c;
        negative = lui_n;
        overflow = lui_o;
    end
    LUI_2: begin
        out = r_lui;
        zero = lui_z;
        carry = lui_c;
        negative = lui_n;
        overflow = lui_o;
    end
    SLT: begin
        out = r_slt;
        zero = slt_z;
        carry = slt_c;
        negative = slt_n;
        overflow = slt_o;
    end
    SLTU: begin
        out = r_sltu;
        zero = sltu_z;
        carry = sltu_c;
        negative = sltu_n;
        overflow = sltu_o;
    end
    SLL: begin
        out = r_sll;
        zero = sll_z;
        carry = sll_c;
        negative = sll_n;
        overflow = sll_o;
    end
    SLR: begin
        out = r_slr;
        zero = slr_z;
        carry = slr_c;
        negative = slr_n;
        overflow = slr_o;
    end
    SRL: begin
        out = r_srl;
        zero = srl_z;
        carry = srl_c;
        negative = srl_n;
        overflow = srl_o;
    end
    SRA: begin
        out = r_sra;
        zero = sra_z;
        carry = sra_c;
        negative = sra_n;
        overflow = sra_o;
    end
    endcase
end

endmodule

Test bench


module alu_tb;

    // Inputs
    reg [31:0] a;
    reg [31:0] b;
    reg [3:0] aluc;

    // Outputs
    wire [31:0] r;
    wire zero;
    wire carry;
    wire negative;
    wire overflow;

    // Instantiate the Unit Under Test (UUT)
    Alu uut (
        .a(a),
        .b(b),
        .aluc(aluc),
        .r(r),
        .zero(zero),
        .carry(carry),
        .negative(negative),
        .overflow(overflow)
    );

    initial begin
        // Initialize Inputs
        a = 0;
        b = 0;
        aluc = 0;

      #20;
        a = 32'hf000_0000;
        b = 32'hffff_ffff;
        aluc = 4'b0000; // addu
        // Add stimulus here
        #20; // 40
        aluc = 4'b0010; // add
        #20; // 60
        aluc = 4'b0001; // subu
        #20; // 80
        aluc = 4'b0011; // sub
        #20; // 100
        aluc = 4'b0100; // and
        #20; // 120
        aluc = 4'b0101; // or
        #20; // 140
        aluc = 4'b0110; // xor
        #20; // 160
        aluc = 4'b0111; // nor
        #20; // 180
        aluc = 4'b1001; // lui
        #20; // 200
        aluc = 4'b1000; // lui
        #20; // 220
        aluc = 4'b1011; // slt
        #20; // 240
        aluc = 4'b1010; // sltu
        #20; // 260
//      aluc = 4'b1100; // sra
        #20;
//      aluc = 4'b1110; // sll
        #20;
//      aluc = 4'b1111; // slr
        #20;
//      aluc = 4'b1101; // srl

        // Wait 100 ns for global reset to finish
        #100;
    end

endmodule
上一篇:java文章显示内容部分(将html转成纯文本)


下一篇:向量自回归模型VS风险价值模型(VAR&VaR)