注释添加和翻译

This commit is contained in:
2026-09-12 16:34:30 +08:00
parent 03ac91bf65
commit abb2e161af
5 changed files with 256 additions and 69 deletions
+121 -68
View File
@@ -2,23 +2,24 @@
`default_nettype none
// -----------------------------------------------------------------------------
// cpu21-riscv-4.circ -> synthesizable Verilog
// cpu21-riscv-4.circ -> 可综合 Verilog 实现
//
// This file keeps the instruction encodings used by the Logisim design. The
// processor is a five-stage IF/ID/EX/MEM/WB pipeline with:
// * EX-stage forwarding and load-use interlock;
// * EX-stage control-flow resolution and pipeline redirect;
// * an eight-entry fully-associative branch target buffer;
// * three sampled interrupt sources with priority and nested URET return;
// * the original ecall convention: a7==34 writes the LED value, otherwise
// the pipeline waits for go_i.
// 本文件保留 Logisim 原设计所使用的指令编码。处理器为五级流水线
// IF/ID/EX/MEM/WB,主要特性:
// * EX 级前递(forwarding)与 load-use 冒险互锁;
// * EX 级控制流裁决与流水线重定向;
// * 八表项全相联分支目标缓冲(BPB);
// * 三路采样的中断源,带优先级与可嵌套的 URET 返回;
// * 沿用原 ecall 约定:a7==34 时写出 LED 值,否则流水线等待 go_i。
//
// Memory interface convention:
// instr_addr_o and data_addr_o are byte addresses. data_wstrb_o is a byte
// write mask, so an external word RAM can use data_addr_o[11:2] as its word
// index and merge bytes according to data_wstrb_o.
// 存储器接口约定:
// instr_addr_o data_addr_o 均为字节地址。data_wstrb_o 是字节写掩码,
// 因此外部字宽 RAM 可用 data_addr_o[11:2] 作为字索引,再依据
// data_wstrb_o 完成字节合并。
// -----------------------------------------------------------------------------
// ALU:纯组合运算单元。result2 作为第二结果输出,用于 MUL 的高 32 位
// 以及 DIVU 的余数;除法则以 b==0 作为除零保护。
module cpu21_riscv_alu (
input wire [ 3:0] op,
input wire [31:0] a,
@@ -70,9 +71,9 @@ module cpu21_riscv_alu (
endmodule
// Eight-entry fully-associative branch target buffer.
// tag = PC[11:2], matching the ten-bit tag splitter in the Logisim BPB.
// count is a two-bit saturating predictor: 00/01 not-taken, 10/11 taken.
// 八表项全相联分支目标缓冲(BPB/BTB)。
// tag = PC[11:2],与 Logisim BPB 中的十位 tag 拆分保持一致。
// count 为两位饱和计数器:00/01 表示不跳转,10/11 表示跳转。
module cpu21_bpb_8 (
input wire clk,
input wire reset,
@@ -103,6 +104,7 @@ module cpu21_bpb_8 (
integer k;
integer selected_index;
// 预测命中查找:按 tag 全相联匹配,命中则给出目标地址与方向预测。
always @* begin
predict_hit = 1'b0;
predict_taken = 1'b0;
@@ -116,8 +118,8 @@ module cpu21_bpb_8 (
end
end
// Find a matching entry, otherwise use the first invalid entry, otherwise
// the oldest entry. The age update below implements an LRU-like policy.
// 更新时先找匹配表项;若无匹配则优先使用无效表项,否则淘汰最旧表项。
// 下方的 age 自增实现了类似 LRU 的替换策略。
always @* begin
update_found = 1'b0;
update_index = 3'd0;
@@ -142,6 +144,7 @@ module cpu21_bpb_8 (
end
end
//
always @(posedge clk or posedge reset) begin
if (reset) begin
for (k = 0; k < 8; k = k + 1) begin
@@ -160,11 +163,13 @@ module cpu21_bpb_8 (
age[selected_index] <= 3'b0;
if (!update_found) begin
// Weak initial state avoids an immediate false prediction.
// 新表项采用较弱的初始状态,避免立刻产生错误预测。
count[selected_index] <= update_taken ? 2'b10 : 2'b01;
end else if (update_taken) begin
// 实际跳转:计数器加一(饱和到 11)。
if (count[selected_index] != 2'b11) count[selected_index] <= count[selected_index] + 2'b01;
end else begin
// 实际不跳转:计数器减一(饱和到 00)。
if (count[selected_index] != 2'b00) count[selected_index] <= count[selected_index] - 2'b01;
end
@@ -176,15 +181,16 @@ module cpu21_bpb_8 (
endmodule
// 顶层模块:五级流水线 RISC-V 处理器,内置分支预测与多级中断支持。
module cpu21_riscv_redirect_int_bpb #(
parameter RESET_PC = 32'h0000_0000,
parameter IRQ1_VECTOR = 32'h0000_30ac,
parameter IRQ2_VECTOR = 32'h0000_31e4,
parameter IRQ3_VECTOR = 32'h0000_3310,
parameter IRQ_STACK_DEPTH = 4,
// ustatus reset value. Bit 0 is MIE. The course interrupt test program
// only sets MIE inside its interrupt handlers, so the mainline would never
// acknowledge the first interrupt unless MIE is enabled right after reset.
// ustatus 复位值。bit0 MIE。课程的中断测试程序只会在中断处理
// 程序中设置 MIE,若复位后不立即置位 MIE,主程序将永远无法响应
// 第一次中断,因此这里默认打开 MIE。
parameter [31:0] USTATUS_INIT = 32'h0000_0001
) (
input wire clk,
@@ -234,7 +240,7 @@ module cpu21_riscv_redirect_int_bpb #(
output wire [15:0] prediction_success_count_o,
output wire [15:0] prediction_failure_count_o
);
// Custom CPU21 opcodes from the supplied truth table.
// CPU21
localparam OP_LOAD = 5'h00;
localparam OP_R = 5'h0c;
localparam OP_I = 5'h04;
@@ -257,14 +263,17 @@ module cpu21_riscv_redirect_int_bpb #(
localparam ALU_SLT = 4'd11;
localparam ALU_SLTU = 4'd12;
// PC
reg [31:0] pc_q;
// IF/ID
reg ifid_valid_q;
reg [31:0] ifid_pc_q;
reg [31:0] ifid_ir_q;
reg ifid_pred_taken_q;
reg [31:0] ifid_pred_target_q;
// ID/EX
reg idex_valid_q;
reg [31:0] idex_pc_q;
reg [31:0] idex_ir_q;
@@ -296,6 +305,7 @@ module cpu21_riscv_redirect_int_bpb #(
reg idex_pred_taken_q;
reg [31:0] idex_pred_target_q;
// EX/MEM ALU/
reg exmem_valid_q;
reg [31:0] exmem_pc_q;
reg [31:0] exmem_ir_q;
@@ -310,6 +320,7 @@ module cpu21_riscv_redirect_int_bpb #(
reg [ 3:0] exmem_wstrb_q;
reg [ 2:0] exmem_wb_sel_q;
// MEM/WB 访
reg memwb_valid_q;
reg [31:0] memwb_pc_q;
reg [31:0] memwb_ir_q;
@@ -322,13 +333,14 @@ module cpu21_riscv_redirect_int_bpb #(
reg memwb_mem_to_reg_q;
reg [ 2:0] memwb_wb_sel_q;
// LED
reg [31:0] regfile [ 0:31];
reg [31:0] led_data_q;
reg led_valid_q;
reg halted_q;
// Interrupt state. ustatus[0] is the circuit's MIE bit. A small stack
// keeps EPC/status/priority so nested interrupts can return correctly.
// ustatus[0] MIE
// EPC//使
reg [31:0] ustatus_q;
reg [31:0] uepc_q;
reg [ 1:0] irq_current_q;
@@ -341,6 +353,7 @@ module cpu21_riscv_redirect_int_bpb #(
reg [ 1:0] priority_stack [0:IRQ_STACK_DEPTH-1];
reg [ 2:0] irq_depth_q;
//
reg [15:0] cycle_count_q;
reg [15:0] stall_count_q;
reg [15:0] bubble_count_q;
@@ -350,10 +363,10 @@ module cpu21_riscv_redirect_int_bpb #(
reg [15:0] prediction_failure_count_q;
// -------------------------------------------------------------------------
// Decode in ID.
// ID
// -------------------------------------------------------------------------
// The Logisim controller receives the standard RISC-V opcode field
// IR[6:2] (the table stores this five-bit field in hexadecimal).
// Logisim RISC-V IR[6:2]
//
wire [ 4:0] d_opcode = ifid_ir_q[6:2];
wire [ 2:0] d_funct3 = ifid_ir_q[14:12];
wire [ 6:0] d_funct7 = ifid_ir_q[31:25];
@@ -384,6 +397,7 @@ module cpu21_riscv_redirect_int_bpb #(
reg [31:0] d_imm;
wire [11:0] d_csr_addr = ifid_ir_q[31:20];
// "/" case
always @* begin
d_reg_write = 1'b0;
d_mem_to_reg = 1'b0;
@@ -411,18 +425,20 @@ module cpu21_riscv_redirect_int_bpb #(
d_imm = {{20{ifid_ir_q[31]}}, ifid_ir_q[31:20]};
case (d_opcode)
// R 型运算:由 funct3/funct7 决定具体操作。
OP_R: begin
d_uses_rs1 = 1'b1;
d_uses_rs2 = 1'b1;
d_reg_write = 1'b1;
// The circuit's extra REMU control is the standard R-type
// funct7=1/funct3=111 form; ALU result2 is the remainder.
// REMU R funct7=1/funct3=111
// ALU result2
if ((d_funct7 == 7'b0000001) && (d_funct3 == 3'b111)) begin
d_aluop = ALU_DIVU;
d_wb_sel = 3'd3;
end else if ((d_funct7 == 7'b0000001) && (d_funct3 == 3'b000)) begin
d_aluop = ALU_MUL;
end else begin
// 标准 R 型 funct3 译码;add/sub 与 sra/srl 由 funct7[5] 区分。
case (d_funct3)
3'b000: d_aluop = (d_funct7[5] ? ALU_SUB : ALU_ADD);
3'b001: d_aluop = ALU_SLL;
@@ -437,22 +453,25 @@ module cpu21_riscv_redirect_int_bpb #(
end
end
// I addi/slli/slti/xori/srai/srli/ori/andi
OP_I: begin
d_uses_rs1 = 1'b1;
d_alu_src = 1'b1;
d_reg_write = 1'b1;
case (d_funct3)
3'b000: d_aluop = ALU_ADD; // addi
3'b001: d_aluop = ALU_SLL; // slli
3'b010: d_aluop = ALU_SLT; // slti
3'b100: d_aluop = ALU_XOR; // xori
3'b101: d_aluop = (d_funct7[5] ? ALU_SRA : ALU_SRL);
3'b110: d_aluop = ALU_OR; // ori
3'b111: d_aluop = ALU_AND; // andi
3'b000: d_aluop = ALU_ADD; // addi
3'b001: d_aluop = ALU_SLL; // slli:立即数逻辑左移
3'b010: d_aluop = ALU_SLT; // slti 1
3'b100: d_aluop = ALU_XOR; // xori:立即数异或
3'b101:
d_aluop = (d_funct7[5] ? ALU_SRA : ALU_SRL); // srai/srli/
3'b110: d_aluop = ALU_OR; // ori:立即数或
3'b111: d_aluop = ALU_AND; // andi
default: d_reg_write = 1'b0;
endcase
end
// 加载指令,当前仅支持 lwfunct3=010)。
OP_LOAD: begin
if (d_funct3 == 3'b010) begin
d_uses_rs1 = 1'b1;
@@ -464,6 +483,7 @@ module cpu21_riscv_redirect_int_bpb #(
end
end
// 存储指令:swfunct3=010)与 sbfunct3=000)。
OP_STORE: begin
if ((d_funct3 == 3'b010) || (d_funct3 == 3'b000)) begin
d_uses_rs1 = 1'b1;
@@ -471,11 +491,12 @@ module cpu21_riscv_redirect_int_bpb #(
d_alu_src = 1'b1;
d_aluop = ALU_ADD;
d_mem_write = 1'b1;
d_mem_byte = (d_funct3 == 3'b000); // sb
d_mem_byte = (d_funct3 == 3'b000); // sb
d_imm = {{20{ifid_ir_q[31]}}, ifid_ir_q[31:25], ifid_ir_q[11:7]};
end
end
// beq000/bne001/bltu110
OP_BRANCH: begin
if ((d_funct3 == 3'b000) || (d_funct3 == 3'b001) || (d_funct3 == 3'b110)) begin
d_uses_rs1 = 1'b1;
@@ -496,6 +517,7 @@ module cpu21_riscv_redirect_int_bpb #(
end
end
// jal PC+4
OP_JAL: begin
d_jal = 1'b1;
d_reg_write = 1'b1;
@@ -510,6 +532,7 @@ module cpu21_riscv_redirect_int_bpb #(
};
end
// jalr
OP_JALR: begin
if (d_funct3 == 3'b000) begin
d_jalr = 1'b1;
@@ -521,33 +544,34 @@ module cpu21_riscv_redirect_int_bpb #(
end
end
// ecall / uret / CSR
OP_SYS: begin
// The circuit uses IR[21] to distinguish URET from ecall.
// IR[21] URET ecall
if (d_funct3 == 3'b000) begin
if (ifid_ir_q[21]) begin
d_uret = 1'b1;
end else begin
d_ecall = 1'b1;
// ecall reads a7 and a0, as documented in the sheet.
// 按文档说明,ecall 读取 a7(rs17) 与 a0(rs10)。
d_uses_rs1 = 1'b1;
d_uses_rs2 = 1'b1;
d_src1_idx = 5'd17;
d_src2_idx = 5'd10;
end
end else if (d_funct3 == 3'b001) begin
d_csr_write = 1'b1; // CSRRW
d_csr_write = 1'b1; // CSRRW:写 CSR,并把旧值写回 rd
d_uses_rs1 = 1'b1;
d_alu_src = 1'b1;
d_imm = {27'b0, ifid_ir_q[19:15]};
d_reg_write = (d_rd != 5'd0);
d_wb_sel = 3'd4;
end else if (d_funct3 == 3'b110) begin
d_csr_set = 1'b1; // CSRRSI
d_csr_set = 1'b1; // CSRRSI CSR
d_imm = {27'b0, ifid_ir_q[19:15]};
d_reg_write = (d_rd != 5'd0);
d_wb_sel = 3'd4;
end else if (d_funct3 == 3'b111) begin
d_csr_clear = 1'b1; // CSRRCI
d_csr_clear = 1'b1; // CSRRCI:清除 CSR 中的指定位
d_imm = {27'b0, ifid_ir_q[19:15]};
d_reg_write = (d_rd != 5'd0);
d_wb_sel = 3'd4;
@@ -559,13 +583,15 @@ module cpu21_riscv_redirect_int_bpb #(
endcase
end
// Register-file read with a write-first bypass for the same cycle's WB.
// wb_sel 0=ALU 1=访2=PC+43=MUL /
// 4=CSR
wire [31:0] wb_value;
assign wb_value = (memwb_wb_sel_q == 3'd1) ? memwb_mem_data_q :
(memwb_wb_sel_q == 3'd2) ? (memwb_pc_q + 32'd4) :
(memwb_wb_sel_q == 3'd3) ? memwb_alu_result2_q :
(memwb_wb_sel_q == 3'd4) ? memwb_csr_old_q :
memwb_alu_result_q;
// ID 级读寄存器:x0 恒为 0,并对同周期 WB 的结果做写优先旁路。
wire [31:0] d_rs1_value = (d_src1_idx == 5'd0) ? 32'b0 :
((memwb_valid_q && memwb_reg_write_q &&
(memwb_rd_q == d_src1_idx)) ? wb_value :
@@ -576,8 +602,8 @@ module cpu21_riscv_redirect_int_bpb #(
regfile[d_src2_idx]);
// -------------------------------------------------------------------------
// IF branch prediction. JAL/JALR are resolved in EX, while conditional
// branches may redirect the fetch PC immediately from a BPB target.
// IF 级分支预测。JAL/JALR 在 EX 级裁决,条件分支则可以直接依据 BPB
// 给出的目标地址重定向取指 PC。
// -------------------------------------------------------------------------
wire [4:0] f_opcode = instr_i[6:2];
wire [2:0] f_funct3 = instr_i[14:12];
@@ -589,10 +615,12 @@ module cpu21_riscv_redirect_int_bpb #(
wire bpb_predict_taken;
wire ex_branch_taken;
wire [31:0] ex_target;
// BPB EX
wire bpb_update_enable = idex_valid_q && idex_branch_q;
wire bpb_update_taken = ex_branch_taken;
wire [31:0] bpb_update_target = ex_target;
//
cpu21_bpb_8 u_bpb (
.clk (clk),
.reset (reset),
@@ -608,12 +636,13 @@ module cpu21_riscv_redirect_int_bpb #(
.update_taken (bpb_update_taken)
);
// 下一取指 PC:预测跳转命中时使用 BPB 目标地址,否则顺序加 4。
wire [31:0] fetch_next_pc =
(f_is_branch && bpb_predict_hit && bpb_predict_taken) ?
bpb_predict_target : (pc_q + 32'd4);
// -------------------------------------------------------------------------
// EX forwarding, ALU, and control-flow resolution.
// EX ALU
// -------------------------------------------------------------------------
reg [31:0] ex_src1;
reg [31:0] ex_src2;
@@ -626,6 +655,8 @@ module cpu21_riscv_redirect_int_bpb #(
(exmem_wb_sel_q == 3'd4) ? exmem_csr_old_q :
exmem_alu_result_q;
// EX/MEM MEM/WB
//
always @* begin
ex_src1 = idex_rs1_value_q;
ex_src2 = idex_rs2_value_q;
@@ -636,12 +667,15 @@ module cpu21_riscv_redirect_int_bpb #(
else if (wb_forward_valid && (memwb_rd_q == idex_rs2_idx_q)) ex_src2 = wb_value;
end
// ALU B rs2
wire [31:0] ex_alu_b = idex_alu_src_q ? idex_imm_q : ex_src2;
wire [31:0] ex_alu_result;
wire [31:0] ex_alu_result2;
// CSR ustatus=0x004uepc=0x041 CSR rd
wire [31:0] ex_csr_old_value =
(idex_csr_addr_q == 12'h004) ? ustatus_q :
(idex_csr_addr_q == 12'h041) ? uepc_q : 32'b0;
// ALU 实例(纯组合逻辑)。
cpu21_riscv_alu u_ex_alu (
.op (idex_aluop_q),
.a (ex_src1),
@@ -650,14 +684,19 @@ module cpu21_riscv_redirect_int_bpb #(
.result2(ex_alu_result2)
);
// 条件分支裁决:beq 相等、bne 不等、bltu 无符号小于。
assign ex_branch_taken = idex_branch_q &&
((idex_beq_q && (ex_src1 == ex_src2)) ||
(idex_bne_q && (ex_src1 != ex_src2)) ||
(idex_bltu_q && (ex_src1 < ex_src2)));
// 跳转目标:jalr 为 (rs1+imm) 且最低位清零;jal 为 PC+imm。
assign ex_target = idex_jalr_q ?
((ex_src1 + idex_imm_q) & 32'hffff_fffe) :
(idex_pc_q + idex_imm_q);
// EX
wire ex_controlflow = idex_valid_q && (idex_branch_q || idex_jal_q || idex_jalr_q);
// /JAL/JALR
// EX
wire ex_redirect_valid = ex_controlflow &&
(idex_branch_q ?
((idex_pred_taken_q != ex_branch_taken) ||
@@ -666,6 +705,7 @@ module cpu21_riscv_redirect_int_bpb #(
wire [31:0] ex_redirect_pc =
(idex_branch_q && !ex_branch_taken) ? (idex_pc_q + 32'd4) : ex_target;
//
reg [31:0] ex_store_data;
reg [3:0] ex_store_wstrb;
always @* begin
@@ -698,24 +738,27 @@ module cpu21_riscv_redirect_int_bpb #(
end
end
// ecall 约定:a7==34 时输出 LED;否则令处理器停机,等待 go_i 重新启动。
wire ex_led_event = idex_valid_q && idex_ecall_q && (ex_src1 == 32'd34);
wire ex_halt_event = idex_valid_q && idex_ecall_q && (ex_src1 != 32'd34);
// A load in EX followed by a consumer in ID needs one bubble. ALU and
// branch dependencies are handled by the forwarding network above.
// EX 级为 load、而 ID 级指令立即使用其结果时,需要插入一个气泡。
// ALU 与分支的数据相关由上面的前递网络解决。
wire load_use_hazard = ifid_valid_q && idex_valid_q && idex_mem_to_reg_q &&
(idex_rd_q != 5'd0) &&
((d_uses_rs1 && (d_src1_idx == idex_rd_q)) ||
(d_uses_rs2 && (d_src2_idx == idex_rd_q)));
// -------------------------------------------------------------------------
// Interrupt sampling and priority selection.
// IRQ3 has the highest priority, then IRQ2, then IRQ1. A nested request
// is admitted only when its priority is higher than the current level.
//
// IRQ3 IRQ2 IRQ1
//
// -------------------------------------------------------------------------
// 沿 irq_i 0 1
wire [2:0] irq_event = irq_sync2_q & ~irq_prev_q;
reg irq_selected_valid;
reg [1:0] irq_selected_level;
//
always @* begin
irq_selected_valid = 1'b0;
irq_selected_level = 2'd0;
@@ -732,20 +775,22 @@ module cpu21_riscv_redirect_int_bpb #(
end
wire ex_uret_redirect = idex_valid_q && idex_uret_q;
// uepc_q is the active context's architectural return PC. The stack
// stores the interrupted outer contexts; using uepc_q here preserves the
// course-book sequence that saves/restores uepc with CSRRW.
// uepc_q 是当前运行上下文的架构返回 PC,栈中缓存的是被中断的外层
// 上下文。这里使用 uepc_q,与课程讲义中用 CSRRW 保存/恢复 uepc 的
// 流程保持一致。
wire [31:0] ex_return_pc = uepc_q;
// 响应中断的条件:有已选中中断、MIE 使能、栈未溢出、未停机,且没有
// 正在处理的重定向/URET/停机事件。
wire take_irq = irq_selected_valid && ustatus_q[0] &&
(irq_depth_q < IRQ_STACK_DEPTH) && !halted_q &&
!ex_redirect_valid && !ex_uret_redirect && !ex_halt_event;
// The EX instruction is allowed to complete when an interrupt is taken.
// Resume at the next architectural PC; if EX is a correctly predicted
// taken branch, that PC is its target. If EX is empty, IF/ID is the
// oldest instruction that has not executed yet.
// 响应中断时允许 EX 级指令正常完成。恢复地址取"下一个架构 PC":若
// EX 是一条预测正确且已跳转的分支,则该 PC 就是它的目标地址;若 EX
// 为空,则 IF/ID 中保存的就是尚未执行的最老指令。
wire [31:0] irq_save_pc = idex_valid_q ?
((idex_branch_q && ex_branch_taken) ? ex_target : (idex_pc_q + 32'd4)) :
(ifid_valid_q ? ifid_pc_q : pc_q);
//
reg [31:0] irq_vector;
always @* begin
case (irq_selected_level)
@@ -756,6 +801,7 @@ module cpu21_riscv_redirect_int_bpb #(
endcase
end
// 组合逻辑计算下一拍的挂起位与 CSR(ustatus/uepc)取值。
reg [ 2:0] irq_pending_d;
reg [31:0] ustatus_d;
reg [31:0] uepc_d;
@@ -792,14 +838,16 @@ module cpu21_riscv_redirect_int_bpb #(
end
// -------------------------------------------------------------------------
// External/debug outputs.
//
// -------------------------------------------------------------------------
// PC// MEM
assign instr_addr_o = pc_q;
assign data_addr_o = exmem_alu_result_q;
assign data_wdata_o = exmem_write_data_q;
assign data_wstrb_o = (exmem_valid_q && exmem_mem_write_q) ? exmem_wstrb_q : 4'b0;
assign data_we_o = |data_wstrb_o;
// LED 输出与流水线各级 PC/指令回显(用于调试与波形观察)。
assign led_data_o = led_data_q;
assign led_valid_o = led_valid_q;
assign if_pc_o = pc_q;
@@ -832,15 +880,18 @@ module cpu21_riscv_redirect_int_bpb #(
assign prediction_success_count_o = prediction_success_count_q;
assign prediction_failure_count_o = prediction_failure_count_q;
// 需要冲刷年轻指令/气泡的情况:中断、URET、ecall 停机、分支重定向。
wire flush_younger = take_irq || ex_uret_redirect || ex_halt_event || ex_redirect_valid;
// load-use 冒险且无需冲刷时,插入一个气泡(停顿一拍)。
wire pipeline_stall = load_use_hazard && !flush_younger && !halted_q;
// -------------------------------------------------------------------------
// State update. Ordering follows the five-stage pipeline: WB commit,
// MEM/WB capture, EX/MEM capture, then ID/EX and IF/ID/PC control.
// 状态更新。顺序遵循五级流水线:先 WB 写回,再捕获 MEM/WB、EX/MEM
// 最后处理 ID/EX IF/ID/PC 的控制。
// -------------------------------------------------------------------------
integer r;
integer s;
// 复位时清空所有流水寄存器、寄存器堆、中断状态与性能计数器。
always @(posedge clk or posedge reset) begin
if (reset) begin
pc_q <= RESET_PC;
@@ -935,12 +986,12 @@ module cpu21_riscv_redirect_int_bpb #(
if (!halted_q) cycle_count_q <= cycle_count_q + 16'd1;
led_valid_q <= 1'b0;
// WB
// WB x0 0
if (memwb_valid_q && memwb_reg_write_q && (memwb_rd_q != 5'd0))
regfile[memwb_rd_q] <= wb_value;
regfile[0] <= 32'b0;
// Interrupt synchronizers and pending latches.
// CSR
irq_sync1_q <= irq_i;
irq_sync2_q <= irq_sync1_q;
irq_prev_q <= irq_sync2_q;
@@ -970,7 +1021,7 @@ module cpu21_riscv_redirect_int_bpb #(
end
end
// MEM/WB
// MEM/WB
memwb_valid_q <= exmem_valid_q;
memwb_pc_q <= exmem_pc_q;
memwb_ir_q <= exmem_ir_q;
@@ -983,7 +1034,7 @@ module cpu21_riscv_redirect_int_bpb #(
memwb_mem_to_reg_q <= exmem_mem_to_reg_q;
memwb_wb_sel_q <= exmem_wb_sel_q;
// EX/MEM
// EX/MEM
exmem_valid_q <= idex_valid_q;
exmem_pc_q <= idex_pc_q;
exmem_ir_q <= idex_ir_q;
@@ -998,8 +1049,8 @@ module cpu21_riscv_redirect_int_bpb #(
exmem_wstrb_q <= ex_store_wstrb;
exmem_wb_sel_q <= idex_wb_sel_q;
// Control priority: interrupt, URET, ecall halt, branch redirect,
// then load-use stall, then ordinary pipeline advance.
// > URET > ecall > >
// load-use >
if (flush_younger || pipeline_stall || halted_q) begin
idex_valid_q <= 1'b0;
idex_pred_taken_q <= 1'b0;
@@ -1076,6 +1127,8 @@ module cpu21_riscv_redirect_int_bpb #(
ifid_pred_target_q <= bpb_predict_target;
end
// /
// /
if (pipeline_stall) begin
stall_count_q <= stall_count_q + 16'd1;
bubble_count_q <= bubble_count_q + 16'd1;
@@ -1,4 +1,3 @@
v2.0 raw
00100493
0100006f
00100493
@@ -0,0 +1,67 @@
00500493
0140006f
00100493
00200913
00300993
00400a13
0140006f
00100493
00200913
00300993
00400a13
0140006f
00100493
00200913
00300993
00400a13
0140006f
00100493
00200913
00300993
00400a13
0140006f
00100493
00200913
00300993
00400a13
0140006f
00100493
00200913
00300993
00400a13
0140006f
00100493
00200913
00300993
00400a13
0140006f
00100493
00200913
00300993
00400a13
fff48493
f80492e3
00100413
0ff00913
00100493
00300993
01240c63
00840a63
00100493
00200913
00300993
00400a13
00949a63
01249863
00100493
00200913
00300993
00c000ef
00a00893
00000073
00000413
00140413
00800533
02200893
00000073
00008067
+67
View File
@@ -0,0 +1,67 @@
00500493
0140006f
00100493
00200913
00300993
00400a13
0140006f
00100493
00200913
00300993
00400a13
0140006f
00100493
00200913
00300993
00400a13
0140006f
00100493
00200913
00300993
00400a13
0140006f
00100493
00200913
00300993
00400a13
0140006f
00100493
00200913
00300993
00400a13
0140006f
00100493
00200913
00300993
00400a13
0140006f
00100493
00200913
00300993
00400a13
fff48493
f80492e3
00100413
0ff00913
00100493
00300993
01240c63
00840a63
00100493
00200913
00300993
00400a13
00949a63
01249863
00100493
00200913
00300993
00c000ef
00a00893
00000073
00000413
00140413
00800533
02200893
00000073
00008067
@@ -17,6 +17,7 @@ module tb_cpu21_riscv_redirect_int_bpb #(
parameter ROM_FILE = "risc-v-benchmark_ccab.hex"
// risc-v-benchmark_ccab.hex
// cpu21_riscv_redirect_int_bpb_rom.hex
// risc-v-branch-predict.hex
);
localparam integer ROM_WORDS = 1024;
localparam integer RAM_WORDS = 1024;