- rtl/:12 个可综合的处理器源文件(顶层 cpu21_riscv_redirect_int_bpb.v,其余为各功能单元)。 - board/:板级顶层 cpu21_board_top.v、引脚约束 cpu21_board_top.xdc、片内 ROM 初始化 cpu21_board_rom.vh 与短延时版本 cpu21_board_rom_fast.vh。 - testbench/:保留三个测试平台;ROM 镜像统一放到 testbench/rom/,测试程序源码与期望值 仍在 testbench/programs/(其中的 .hex 是 RARS 原始输出,与 rom/ 里改过显示方式的版本 内容不同,两者都保留)。 - 同步更新:两个测试平台的 ROM 探测路径改为 testbench/rom/(并在头注释里补充说明: PowerShell 会把 -generic_top/--testplusarg 参数里的 "=" 拆开、Verilog 字符串中的 路径要用正斜杠);tools/hex2vh.py 的用法示例指向 board/cpu21_board_top.v; 说明文档新增“目录结构”一节并同步所有路径引用;.gitignore 补充 .Xil/。 - 清理:删除 *.hex.lst 中间文件与空的 .Xil/ 目录。 - 验证:isa_test 24/24、lui_test 4/4、mmio_test 5/5 三项回归通过;两个基线(5560 / 6003 周期)与整理前一致;板级仿真(默认 ROM 首次写入 LED=0001、快速 ROM 跑马灯循环)正常; Vivado 工程源文件路径同步到 rtl/ 与 board/ 后综合通过(LUT 5276、23 个引脚,与整理前 完全一致),因此已有 bit 文件仍然有效。
72 lines
2.4 KiB
Verilog
72 lines
2.4 KiB
Verilog
`timescale 1ns / 1ps
|
|
`default_nettype none
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// ALU:纯组合运算单元。
|
|
//
|
|
// result 为主结果;result2 为第二结果(乘法的无符号高 32 位 / DIVU 的余数),
|
|
// 由译码器用 wb_sel=3 选取,用于无符号高位乘法 mulhu 与课程约定的 remu。
|
|
// 除法做了除零保护: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_MULH = 4'd13;
|
|
localparam ALU_MULHSU = 4'd14;
|
|
localparam ALU_PASSB = 4'd15; // 直接输出 B 端(供 LUI 使用)
|
|
reg [63:0] mult_result; // 无符号 32x32 乘积
|
|
reg signed [63:0] mult_ss; // 有符号 x 有符号
|
|
reg signed [63:0] mult_su; // 有符号 x 无符号
|
|
|
|
always @* begin
|
|
mult_result = a * b;
|
|
mult_ss = $signed(a) * $signed(b);
|
|
mult_su = $signed(a) * $signed({32'b0, 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_MULH: result = mult_ss[63:32];
|
|
ALU_MULHSU: result = mult_su[63:32];
|
|
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
|