序号 |
逻辑 |
功能说明 |
操作 |
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