This commit is contained in:
2025-06-18 16:55:36 +08:00
parent 07c0b18e4c
commit 621c973a4a
10 changed files with 168 additions and 230 deletions

View File

@@ -17,8 +17,17 @@
**
** [FIXED] Restructured the case statement to correctly handle instructions
** that share the same opcode, such as LD.W and ST.W.
** [FIXED] ADDI.W decoding now correctly uses opcode 000000 + func4.
** [FIXED] Added new control signal 'ALUAsrc' to force ALU's A-operand to 0
** for LUI12I.W instruction.
** [FINAL FIX] Corrected the logic within the opcode '000000' group.
** The previous version incorrectly evaluated func fields, causing 3R-type
** instructions to fail after the ADDI.W fix. This version ensures both
** ADDI.W and all 3R instructions are decoded correctly according to the ISA.
**
** Revision:
** Revision 0.04 - Fixed logic for 3R-type instructions.
** Revision 0.03 - Fixed ADDI.W decoding and shared opcode logic.
** Revision 0.02 - Corrected case statement logic for shared opcodes.
** Revision 0.01 - File Created
**
@@ -36,131 +45,84 @@ module control_unit (
output reg src_reg, // 选择寄存器堆的第二读地址源 (Selects Register File's second read address source)
output reg [2:0] ext_op, // 立即数扩展控制 (Immediate extender control)
output reg [3:0] alu_op, // ALU操作控制 (ALU operation control)
output reg alu_asrc, // [NEW] 选择ALU第一操作数源 (Selects ALU's first operand source)
output wire pcsource // PC下一个地址来源选择 (PC next address source selection)
);
// 提取指令中的关键字段
// Extract key fields from the instruction
wire [5:0] opcode = instr[31:26];
wire [1:0] func2 = instr[21:20]; // for 3R-type per ISA document
wire [4:0] func5 = instr[19:15]; // for 3R-type per ISA document
wire [3:0] func4 = instr[25:22]; // for 2RI12-type
// -- 功能码字段 --
wire [3:0] func_2ri12 = instr[25:22]; // For ADDI.W, LD.W, ST.W
wire [1:0] func_3r_f2 = instr[21:20]; // For 3R-type
wire [4:0] func_3r_f5 = instr[19:15]; // For 3R-type
// 定义指令操作码 (Opcode Definitions)
localparam OP_GROUP_00 = 6'b000000; // Contains 3R instructions
localparam OP_ADDI_W = 6'b000010;
// -- 操作码定义 --
localparam OP_GROUP_00 = 6'b000000; // Contains 3R & ADDI.W
localparam OP_LUI12I = 6'b000101;
localparam OP_GROUP_0A = 6'b001010; // Contains LD.W, ST.W
localparam OP_B = 6'b010100;
localparam OP_BEQ = 6'b010110;
localparam OP_BLT = 6'b011000;
// 定义ALU操作码 (ALU Operation Definitions)
localparam ALU_ADD = 4'b0000;
localparam ALU_SUB = 4'b0001;
localparam ALU_AND = 4'b0010;
localparam ALU_OR = 4'b0011;
localparam ALU_NOR = 4'b0100;
localparam ALU_SLT = 4'b0101;
localparam ALU_SLTU = 4'b0110;
localparam ALU_ADD = 4'b0000, ALU_SUB = 4'b0001, ALU_AND = 4'b0010,
ALU_OR = 4'b0011, ALU_NOR = 4'b0100, ALU_SLT = 4'b0101,
ALU_SLTU= 4'b0110;
// 定义立即数扩展类型 (Immediate Extension Type Definitions)
localparam EXT_SI12 = 3'b001;
localparam EXT_SI16 = 3'b010;
localparam EXT_UI20 = 3'b011;
localparam EXT_SI26 = 3'b100;
localparam EXT_SI12 = 3'b001, EXT_SI16 = 3'b010, EXT_UI20 = 3'b011, EXT_SI26 = 3'b100;
// 主译码逻辑 (Main Decoding Logic)
always @(*) begin
// --- 控制信号默认值,防止生成锁存器 ---
// Default values for control signals to prevent latches
reg_write_en = 1'b0;
mem_to_reg = 1'b0;
mem_write_en = 1'b0;
alu_src = 1'b0;
src_reg = 1'b0;
ext_op = 3'bxxx;
alu_op = 4'bxxxx;
// -- 默认值 --
reg_write_en = 1'b0; mem_to_reg = 1'b0; mem_write_en = 1'b0;
alu_src = 1'b0; src_reg = 1'b0; alu_asrc = 1'b0;
ext_op = 3'bxxx; alu_op = 4'bxxxx;
case (opcode)
OP_GROUP_00: begin
// Differentiate based on func2 field
if (func2 == 2'b01) begin // This is a 3R-type arithmetic/logic instruction
// 3R 和 ADDI.W 共享主操作码 000000
if (func_2ri12 == 4'b1010) begin // ADDI.W
reg_write_en = 1'b1;
alu_src = 1'b0; // B operand comes from register
src_reg = 1'b0; // Second read address comes from rk field
// Further decode based on func5
case(func5)
5'b00000: alu_op = ALU_ADD;
5'b00010: alu_op = ALU_SUB;
5'b00100: alu_op = ALU_SLT;
5'b00101: alu_op = ALU_SLTU;
5'b01000: alu_op = ALU_NOR;
5'b01001: alu_op = ALU_AND;
5'b01010: alu_op = ALU_OR;
default: alu_op = 4'bxxxx;
alu_src = 1'b1;
ext_op = EXT_SI12;
alu_op = ALU_ADD;
end
// 对于3R指令, func_2ri12 ([25:22]) 字段为 '0000'
// 并且 func_3r_f2 ([21:20]) 字段为 '01'
else if (instr[25:22] == 4'b0000 && func_3r_f2 == 2'b01) begin // 3R-type
reg_write_en = 1'b1;
alu_src = 1'b0;
src_reg = 1'b0;
case(func_3r_f5)
5'b00000: alu_op = ALU_ADD; 5'b00010: alu_op = ALU_SUB;
5'b00100: alu_op = ALU_SLT; 5'b00101: alu_op = ALU_SLTU;
5'b01000: alu_op = ALU_NOR; 5'b01001: alu_op = ALU_AND;
5'b01010: alu_op = ALU_OR; default: alu_op = 4'bxxxx;
endcase
end
end
OP_ADDI_W: begin
// ADDI.W has its own opcode
reg_write_en = 1'b1;
alu_src = 1'b1; // B operand comes from immediate
ext_op = EXT_SI12;
alu_op = ALU_ADD;
end
OP_LUI12I: begin
reg_write_en = 1'b1;
alu_src = 1'b1;
mem_to_reg = 1'b0; // ALU result writes back
ext_op = EXT_UI20;
alu_op = ALU_ADD; // ALU adds immediate to zero
reg_write_en = 1'b1; alu_src = 1'b1; alu_asrc = 1'b1;
ext_op = EXT_UI20; alu_op = ALU_ADD;
end
OP_GROUP_0A: begin
// Differentiate LD.W and ST.W based on func4
if (func4 == 4'b0010) begin // LD.W
reg_write_en = 1'b1;
mem_to_reg = 1'b1; // Data from memory writes back
alu_src = 1'b1;
ext_op = EXT_SI12;
alu_op = ALU_ADD; // Calculate address
if (func_2ri12 == 4'b0010) begin // LD.W
reg_write_en = 1'b1; mem_to_reg = 1'b1;
alu_src = 1'b1; ext_op = EXT_SI12; alu_op = ALU_ADD;
end
else if (func4 == 4'b0110) begin // ST.W
mem_write_en = 1'b1;
alu_src = 1'b1;
src_reg = 1'b1; // Second read address comes from rd field
ext_op = EXT_SI12;
alu_op = ALU_ADD; // Calculate address
else if (func_2ri12 == 4'b0110) begin // ST.W
mem_write_en = 1'b1; alu_src = 1'b1; src_reg = 1'b1;
ext_op = EXT_SI12; alu_op = ALU_ADD;
end
end
OP_B: begin
// Unconditional branch
ext_op = EXT_SI26;
end
OP_BEQ: begin
alu_src = 1'b0;
src_reg = 1'b1; // Second read address comes from rd field
ext_op = EXT_SI16;
alu_op = ALU_SUB; // Compare
end
OP_BLT: begin
alu_src = 1'b0;
src_reg = 1'b1; // Second read address comes from rd field
ext_op = EXT_SI16;
alu_op = ALU_SUB; // Compare
end
default: begin
// All signals keep their default values
end
OP_B: ext_op = EXT_SI26;
OP_BEQ: begin alu_src = 1'b0; src_reg = 1'b1; ext_op = EXT_SI16; alu_op = ALU_SUB; end
OP_BLT: begin alu_src = 1'b0; src_reg = 1'b1; ext_op = EXT_SI16; alu_op = ALU_SUB; end
default: begin end
endcase
end
// PC下一个地址来源的逻辑
// Logic for PC's next address source
wire beq_cond = (opcode == OP_BEQ) && zero_flag;
wire blt_cond = (opcode == OP_BLT) && lt_flag;
wire b_cond = (opcode == OP_B);
assign pcsource = beq_cond || blt_cond || b_cond;
endmodule
endmodule

View File

@@ -16,129 +16,72 @@
** immediate extender, and the control unit. The connections follow the
** datapath diagram provided in the course design guide.
**
** [FIXED] Added a multiplexer for the ALU's first operand (A-operand) to
** support the LUI12I.W instruction by allowing it to select 0.
**
** Revision:
** Revision 0.02 - Added ALUAsrc control signal to support LUI12I.W instruction.
** Revision 0.01 - File Created
** Additional Comments:
** - This file integrates the entire design.
**
*******************************************************************************/
`timescale 1ns / 1ps
module cpu_top (
input wire clk,
input wire rst
);
// --- 内部连线声明 (Internal Wire Declarations) ---
wire [31:0] pc_out;
wire [31:0] instr;
wire [31:0] imm_ext;
wire [31:0] read_data1;
wire [31:0] read_data2;
wire [31:0] alu_result;
wire [31:0] mem_read_data;
wire [31:0] write_back_data;
wire [31:0] alu_b_operand;
wire [31:0] pc_out, instr, imm_ext, read_data1, read_data2, alu_result,
mem_read_data, write_back_data, alu_a_operand, alu_b_operand;
wire [4:0] reg_write_addr;
wire [4:0] reg_read_addr1;
wire [4:0] reg_read_addr2;
wire [4:0] reg_read_addr2_final;
// 控制信号
// Control Signals
wire reg_write_en;
wire mem_to_reg;
wire mem_write_en;
wire alu_src;
wire src_reg;
wire pcsource;
wire zero_flag;
wire lt_flag;
// 控制信号 (Control Signals)
wire reg_write_en, mem_to_reg, mem_write_en, alu_src, src_reg,
alu_asrc, pcsource, zero_flag, lt_flag;
wire [2:0] ext_op;
wire [3:0] alu_op;
// --- 模块实例化 (Module Instantiation) ---
// PC (程序计数器)
pc u_pc (
.clk (clk),
.rst (rst),
.pcsource (pcsource),
.imm_ext (imm_ext),
.pc_out (pc_out)
);
pc u_pc (.clk(clk), .rst(rst), .pcsource(pcsource), .imm_ext(imm_ext), .pc_out(pc_out));
// Instruction Memory (指令存储器)
instruction_memory u_inst_mem (
.addr (pc_out),
.instr (instr)
);
instruction_memory u_inst_mem (.addr(pc_out), .instr(instr));
// Control Unit (控制单元)
control_unit u_ctrl_unit (
.instr (instr),
.zero_flag (zero_flag),
.lt_flag (lt_flag),
.reg_write_en (reg_write_en),
.mem_to_reg (mem_to_reg),
.mem_write_en (mem_write_en),
.alu_src (alu_src),
.src_reg (src_reg),
.ext_op (ext_op),
.alu_op (alu_op),
.pcsource (pcsource)
.instr(instr), .zero_flag(zero_flag), .lt_flag(lt_flag),
.reg_write_en(reg_write_en), .mem_to_reg(mem_to_reg), .mem_write_en(mem_write_en),
.alu_src(alu_src), .src_reg(src_reg), .ext_op(ext_op), .alu_op(alu_op),
.alu_asrc(alu_asrc), .pcsource(pcsource)
);
// Immediate Extender (立即数扩展单元)
imm_extender u_imm_ext (
.instr (instr),
.ext_op (ext_op),
.imm_ext (imm_ext)
);
imm_extender u_imm_ext (.instr(instr), .ext_op(ext_op), .imm_ext(imm_ext));
// MUX for Register File's second read address (src_reg_mux)
assign reg_read_addr2_final = src_reg ? instr[4:0] : instr[14:10];
wire [4:0] reg_read_addr2_final = src_reg ? instr[4:0] : instr[14:10];
// Register File (寄存器堆)
register_file u_reg_file (
.clk (clk),
.rst (rst),
.reg_write_en (reg_write_en),
.read_addr1 (instr[9:5]),
.read_addr2 (reg_read_addr2_final),
.write_addr (instr[4:0]),
.write_data (write_back_data),
.read_data1 (read_data1),
.read_data2 (read_data2)
.clk(clk), .rst(rst), .reg_write_en(reg_write_en),
.read_addr1(instr[9:5]), .read_addr2(reg_read_addr2_final),
.write_addr(instr[4:0]), .write_data(write_back_data),
.read_data1(read_data1), .read_data2(read_data2)
);
// MUX for ALU's second operand (alu_src_mux)
// [NEW] MUX for ALU's first operand (A)
assign alu_a_operand = alu_asrc ? 32'b0 : read_data1;
// MUX for ALU's second operand (B)
assign alu_b_operand = alu_src ? imm_ext : read_data2;
// ALU (算术逻辑单元)
alu u_alu (
.a (read_data1),
.b (alu_b_operand),
.alu_op (alu_op),
.result (alu_result),
.zero (zero_flag),
.lt (lt_flag)
.a(alu_a_operand), .b(alu_b_operand), .alu_op(alu_op),
.result(alu_result), .zero(zero_flag), .lt(lt_flag)
);
// Data Memory (数据存储器)
data_memory u_data_mem (
.clk (clk),
.mem_write_en (mem_write_en),
.addr (alu_result),
.write_data (read_data2), // ST.W指令的数据来自第二个读端口(rd)
.read_data (mem_read_data)
.clk(clk), .mem_write_en(mem_write_en), .addr(alu_result),
.write_data(read_data2), .read_data(mem_read_data)
);
// MUX for write-back data (mem_to_reg_mux)
assign write_back_data = mem_to_reg ? mem_read_data : alu_result;
endmodule