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