`include "defines.v"
// PC寄存器模块
module pc_reg(
input wire clk,
input wire rst,
input wire jump_flag_i, // 跳转标志
input wire[`InstAddrBus] jump_addr_i, // 跳转地址
input wire[`Hold_Flag_Bus] hold_flag_i, // 流水线暂停标志
input wire jtag_reset_flag_i, // 复位标志
output reg[`InstAddrBus] pc_o // PC指针
);
always @ (posedge clk) begin
// 复位
if (rst == `RstEnable || jtag_reset_flag_i == 1'b1) begin
pc_o <= `CpuResetAddr;
// 跳转
end else if (jump_flag_i == `JumpEnable) begin
pc_o <= jump_addr_i;
// 暂停
end else if (hold_flag_i >= `Hold_Pc) begin
pc_o <= pc_o;
// 地址加4
end else begin
pc_o <= pc_o + 4'h4;
end
end
endmodule
📌 模块功能概述
pc_reg
模块负责控制指令地址(PC)的更新。它根据以下几种情况更新或保持PC值:
- 复位(Reset)
- 跳转(Jump)
- 流水线暂停(Hold)
- 正常递增
📥 输入端口解释
端口名 | 位宽 | 说明 |
---|---|---|
clk |
1 bit | 时钟信号 |
rst |
1 bit | 全局复位信号(高电平有效) |
jump_flag_i |
1 bit | 跳转使能信号(高电平表示需要跳转) |
jump_addr_i |
InstAddrBus |
跳转目标地址 |
hold_flag_i |
Hold_Flag_Bus |
保持流水线的标志位(如取指阶段暂停) |
jtag_reset_flag_i |
1 bit | 来自JTAG接口的调试复位信号 |
📤 输出端口
端口名 | 位宽 | 说明 |
---|---|---|
pc_o |
InstAddrBus |
当前PC值(即指令地址) |
🔁 always 块说明
always @ (posedge clk)
在每个时钟上升沿,根据以下优先级更新 PC 值:
🥇 1. 复位信号优先
if (rst == `RstEnable || jtag_reset_flag_i == 1'b1)
pc_o <= `CpuResetAddr;
当外部复位或JTAG调试复位触发时,PC重置为预设地址(如:0x00000000
)。
🥈 2. 跳转信号
else if (jump_flag_i == `JumpEnable)
pc_o <= jump_addr_i;
当检测到跳转请求时,将PC设置为跳转目标地址。
🥉 3. 流水线暂停(Hold)
else if (hold_flag_i >= `Hold_Pc)
pc_o <= pc_o; // 保持不变
如果当前需要暂停(如因为缓存未命中或其他流水线控制信号),保持PC值不变。
🏁 4. 正常执行(地址加4)
else
pc_o <= pc_o + 4'h4;
如果无跳转或暂停,PC递增4字节,执行下一条指令。
✅ 总结:状态机行为
条件 | PC更新为 |
---|---|
复位 or JTAG复位 | CpuResetAddr |
跳转使能 | jump_addr_i |
暂停标志 >= Hold_Pc |
保持不变 |
正常 | pc_o + 4 |