Files
risc-v-cpu/cpu21_riscv_alu.v
T
Anccend 036a57d907 实现 LUI 指令(加载高位立即数)
- cpu21_riscv_alu.v:新增 ALU_PASSB(4'd15),直接把 B 端送到 result;
- cpu21_riscv_decoder.v:新增 OP_LUI(IR[6:2]=0x0d,即标准 RISC-V opcode 0x37),
  imm = {IR[31:12], 12'b0},用 ALU_SRC 选择立即数、ALU 直通输出写回 rd,
  不读源寄存器(uses_rs1/rs2 保持 0);
- 说明文档补充 lui 的功能说明与编码表行。

验证(xsim + tb_no_intr,自编的小汇编器生成测试程序):
依次输出 12345000 / fffff000 / 80000000,以及 lui+addi 组合得到 12345678,
随后 a7=10 停机(共 21 周期,halted=1),无编译错误与警告。
2026-09-12 18:59:04 +08:00

63 lines
1.9 KiB
Verilog

`timescale 1ns / 1ps
`default_nettype none
// -----------------------------------------------------------------------------
// ALU:纯组合运算单元。
//
// result 为主结果;result2 为第二结果,用于 MUL 的高 32 位与 DIVU 的余数。
// 除法做了除零保护:b==0 时商为 32'hffff_ffff、余数为被除数。
// -----------------------------------------------------------------------------
module cpu21_riscv_alu (
input wire [ 3:0] op,
input wire [31:0] a,
input wire [31:0] b,
output reg [31:0] result,
output reg [31:0] result2
);
localparam ALU_SLL = 4'd0;
localparam ALU_SRA = 4'd1;
localparam ALU_SRL = 4'd2;
localparam ALU_MUL = 4'd3;
localparam ALU_DIVU = 4'd4;
localparam ALU_ADD = 4'd5;
localparam ALU_SUB = 4'd6;
localparam ALU_AND = 4'd7;
localparam ALU_OR = 4'd8;
localparam ALU_XOR = 4'd9;
localparam ALU_NOR = 4'd10;
localparam ALU_SLT = 4'd11;
localparam ALU_SLTU = 4'd12;
localparam ALU_PASSB = 4'd15; // 直接输出 B 端(供 LUI 使用)
reg [63:0] mult_result;
always @* begin
mult_result = a * b;
result2 = 32'b0;
case (op)
ALU_SLL: result = a << b[4:0];
ALU_SRA: result = $signed(a) >>> b[4:0];
ALU_SRL: result = a >> b[4:0];
ALU_MUL: begin
result = mult_result[31:0];
result2 = mult_result[63:32];
end
ALU_DIVU: begin
result = (b == 32'b0) ? 32'hffff_ffff : a / b;
result2 = (b == 32'b0) ? a : a % b;
end
ALU_ADD: result = a + b;
ALU_SUB: result = a - b;
ALU_AND: result = a & b;
ALU_OR: result = a | b;
ALU_XOR: result = a ^ b;
ALU_NOR: result = ~(a | b);
ALU_SLT: result = ($signed(a) < $signed(b)) ? 32'd1 : 32'd0;
ALU_SLTU: result = (a < b) ? 32'd1 : 32'd0;
ALU_PASSB: result = b;
default: result = 32'b0;
endcase
end
endmodule
`default_nettype wire