序号 | 逻辑 | 功能说明 | 操作 |
1 | Shift Left Logic: | 逻辑左移 | Rd = rs1 << rs2 |
2 | Shift right Logic | 逻辑右移 | Rd = rs1 >> rs2 |
3 | Shift right Arithmetci | 算术右移 | Rd = rs1 >> rs2 (arithmetic) |
4 | add | 加,如果溢出给出overflow信号 | Rd = rs1 + rs2 |
5 | Sub | 减,如果溢出给出overflow信号 | Rd = rs1 - rs2 |
6 | Load upper imm | 高位加载立即数 | Rd = {20bitImm, 12'd0} |
7 | Signed set if less than | 有符号数rs1和rs2的比较 | Rd = (signed rs1 < signed rs2) ? 1 : 0 |
8 | Unsigned set if less than | 无符号数rs1和rs2的比较 | Rd = unsigned rs1 < unsigned rs2 ? 1 : 0 |
9 | xor | 异或操作 | Rd = rs1 ^ rs2 |
10 | Or | 或操作 | Rd = rs1 | rs2 |
11 | and | 与操作 | Rd = rs1 & rs2 |
12 | Mul | 乘操作,忽略溢出 | Rd = (rs1 * rs2)[31:0] |
模块的参考接口如下
信号名 | 位宽 | I/O | 描述 |
op | 4 | I | ALU的操作码定义 |
rs1 | 32 | I | 第1操作数 |
rs2 | 32 | I | 第2操作数 |
rd | 32 | O | ALU运算结果操作数 |
overflow | 1 | o | 操作溢出标志 |
代码:
module ALU(
input [3:0] op,
input [31:0] rs1,
input [31:0] rs2,
input [19:0] imm,
output [31:0] rd,
output overflow
);
wire [31:0]out1;
wire [31:0]out2;
wire [31:0]out3;
wire [31:0]out4;
wire [31:0]out5;
wire [31:0]out6;
wire [31:0]out7;
wire [31:0]out8;
wire [31:0]out9;
wire [31:0]out10;
wire [31:0]out11;
wire [32:0]sum;
wire [63:0]mul;
assign sum = rs1 + rs2;
assign mul = rs1 * rs2;
assign overflow = ((op == 4'b0011)) & sum[32] | ((op == 4'b1011) & (mul[63:32] > 0));
//第一层mux
assign out1 = op[0] ? rs1>>rs2 : rs1<<rs2;
assign out2 = op[0] ? sum[31:0] : (( {{31{rs1[31]}}, 1'b0 } << (~rs2[4:0]) ) | (rs1 >> rs2[4:0]));
assign out3 = op[0] ? {imm,12'd0} : rs1-rs2;
assign out4 = op[0] ? rs1<rs2 : ((rs1[31] ^~ rs2[31]) & (rs1 < rs2)) | (rs1[31] & ~rs2[31]);
assign out5 = op[0] ? rs1 | rs2 : rs1^rs2;
assign out6 = op[0] ? mul[31:0] : rs1&rs2;
//第二层mux
assign out7 = op[1] ? out2 : out1;
assign out8 = op[1] ? out4 : out3;
assign out9 = op[1] ? out6 : out5;
//第三层mux
assign out10 = op[2] ? out8 : out7;
assign out11 = op[2] ? {32{1'bZ}} : out9;
//第四层mux
assign rd = op[3] ? out11 : out10;
endmodule
testbench
module ALU_tb(
);
reg [3:0] op;
reg [31:0] rs1;
reg [31:0] rs2;
reg [19:0] imm;
wire [31:0] rd;
wire overflow;
ALU alu0(
.op(op),
.rs1(rs1),
.rs2(rs2),
.imm(imm),
.rd(rd),
.overflow(overflow)
);
initial
begin
op = 0;
rs1 = 32'h0fffffff;
rs2 = 32'hfffffffe;
imm = 3;
#20
op = 1;
#20
op = 2;
#20
op = 3;
#20
op = 4;
#20
op = 5;
#20
op = 6;
#20
op = 7;
#20
op = 8;
#20
op = 9;
#20
op = 10;
#20
op = 11;
#20
op = 12;
end
endmodule