跳转至

ALU

ALU (Arithmetic Logic Unit) 是负责对二进制整数进行算术运算和位运算的组合电路部件,本实验要求你设计一个32位的能够对两个输入进行:无符号数加法/减法与溢出判断、无符号与有符号逻辑/算术移位、按位与/或/异或。

模块实现

报告中需要给出你写出的完整代码。

参考标准第5.1节 Operators,使用运算符完成。你可能需要参考标准第5.5节 Signed expressions,使用 $signed(), $unsigned() 完成实验。

你的模块名与端口名应为:

ALU.v
module ALU (
  input [31:0]  A,
  input [31:0]  B,
  input [3:0]   ALU_operation,
  output[31:0]  res,
  output        zero
);
// Your code

endmodule
思考题

小 Q 同学在 2023 年春夏学期做计算机组成与设计的 ALU 时,为了实现 SRA 指令使用了下面的代码:

assign res = (...) ? ... : (ALU_operation == 4'd7) ? ($signed(A) >>> $signed(B)) : ...;
但是这样在仿真 ALU_opeation = 4′d7, A = 32'hffff_0000, B = 32′d4 时,结果却是 32'h0fff_f000,并没有在高位填充 1(你可以自行进行仿真查看)。

为了确保大家能复现出这样的错误情况,我们提供了下面的模块代码和仿真代码,可以直接用于仿真。

代码
module ALU(
    input [31:0] A,
    input [31:0] B,
    input [3:0] ALU_operation,
    output [31:0] res
);

    assign res = (ALU_operation == 4'd6) ? A >> B :                            // SRL Logic
                (ALU_operation == 4'd7) ? ($signed(A) >>> $signed(B)) :        // SRA Arithmetic
                32'd0;
endmodule
module ALU_tb();
    reg[31:0] A; 
    reg[31:0] B;
    reg[3:0] ALU_operation;
    wire[31:0] res;

    ALU alu(.A(A), .B(B), .ALU_operation(ALU_operation), .res(res));

    initial begin
        ALU_operation = 4'd7;
        A = 32'hffff_0000;
        B = 32'd4;
        #40;
        A = 32'hffff_ffff;
        B = 32'd8;
    end
endmodule

请你帮助可怜的小 Q 解决这个问题😭,完成实验!

  • 你需要说明:
    • 你是通过什么途径了解与解决这个问题?(参考内容请给出链接)
    • 结合你的参考内容,谈谈你认为上面的错误是什么原因导致。
  • 你可能通过以下途径完成本题:
    • 使用搜索引擎(最好不要用 Baidu ),看看能不能借鉴前人的智慧。
    • 查看 Verilog 官方手册,了解 ? :$signed()>>> 的语义和特性可能会有帮助。

感谢你帮小 Q 完成了实验😊!本次思考题内容答案不唯一,言之成理,展现了你思考问题的过程即可。

功能要求

输入端口中 A, B 为数据输入口,ALU_operation 用来选择 ALU 执行的运算类型。输出端口中 res 用来输出运算结果,zero 用来判断运算结果是否为 0。

ALU_operation 与运算类型的对应关系如下:

操作 ALU_operation 值
ADD 4'd0
SUB 4'd1
SLL 4'd2
SLT 4'd3
SLTU 4'd4
XOR 4'd5
SRL 4'd6
SRA 4'd7
OR 4'd8
AND 4'd9

指令解释

算术运算操作

ALU 处理的算术运算操作中 ADD SUB 将两个运算数当作符号数参与运算,分别给出结果 A+BA-B

比较操作 SLT SLTU 用于比较两操作数,若 `A