This repository has been archived on 2025-06-06. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
2023-02-28 09:10:42 +08:00

107 lines
3.3 KiB
Verilog

`timescale 1ns / 1ps
module alu(
input [10:0] alu_op ,
input [31:0] alu_src1 ,
input [31:0] alu_src2 ,
output [31:0] alu_result,
output Carry ,
output Sign ,
output Overflow ,
output Zero
);
wire op_lui;
wire op_add;
wire op_sub;
wire op_or;
wire op_slt;
wire op_sltu;
wire op_xor;
wire op_and;
wire op_sll;
wire op_srl;
wire op_sra;
assign op_lui = alu_op[ 0];
assign op_add = alu_op[ 1];
assign op_sub = alu_op[ 2];
assign op_slt = alu_op[ 3];
assign op_sltu = alu_op[ 4];
assign op_xor = alu_op[ 5];
assign op_or = alu_op[ 6];
assign op_and = alu_op[ 7];
assign op_sll = alu_op[ 8];
assign op_srl = alu_op[ 9];
assign op_sra = alu_op[10];
wire [31:0] lui_result;
wire [31:0] add_sub_result;
wire [31:0] slt_result;
wire [31:0] sltu_result;
wire [31:0] xor_result;
wire [31:0] or_result;
wire [31:0] and_result;
wire [31:0] sll_result;
wire [31:0] sr64_result;
wire [31:0] sr_result;
// 32-bit adder
wire [31:0] adder_a;
wire [31:0] adder_b;
wire adder_cin;
wire [31:0] adder_result;
wire adder_cout;
assign adder_a = alu_src1;
assign adder_b = (op_sub | op_slt | op_sltu) ? ~alu_src2 : alu_src2;
assign adder_cin = (op_sub | op_slt | op_sltu) ? 1'b1 : 1'b0;
assign {adder_cout, adder_result} = adder_a + adder_b + adder_cin;
// ADD, SUB result
assign add_sub_result = adder_result;
// SLT result
assign slt_result[31:1] = 31'b0;
assign slt_result[0] = (alu_src1[31] & ~alu_src2[31])
| ((alu_src1[31] ~^ alu_src2[31]) & adder_result[31]);
// SLTU result
assign sltu_result[31:1] = 31'b0;
assign sltu_result[0] = ~adder_cout;
// bitwise operation
assign or_result = alu_src1 | alu_src2;
assign and_result = alu_src1 & alu_src2;
assign xor_result = alu_src1 ^ alu_src2;
assign lui_result = alu_src2;
// SLL result
assign sll_result = alu_src1 << alu_src2[4:0];
// SRL, SRA result
assign sr64_result = {{32{op_sra & alu_src1[31]}}, alu_src1[31:0]} >> alu_src2[4:0];
assign sr_result = sr64_result[31:0];
// final result mux
assign alu_result = ({32{op_add|op_sub}} & add_sub_result)
| ({32{op_slt }} & slt_result)
| ({32{op_sltu }} & sltu_result)
| ({32{op_or }} & or_result)
| ({32{op_xor }} & xor_result)
| ({32{op_and }} & and_result)
| ({32{op_lui }} & lui_result)
| ({32{op_sll }} & sll_result)
| ({32{op_srl|op_sra}} & sr_result);
assign Carry = op_sub ^ adder_cout;
assign Sign = alu_result[31];
assign Overflow = (op_add|op_sub) ? ( adder_a[31] & adder_b[31] & adder_cout)
| (~adder_a[31] & ~adder_b[31] & ~adder_cout)
: 1'b0;
assign Zero = (alu_result == 32'b0);
endmodule