集成电路流片随笔26:tinyriscv的三级流水线细则pc
`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) beginpc_o <= `CpuResetAddr;// 跳转end else if (jump_flag_i == `JumpEnable) beginpc_o <= jump_addr_i;// 暂停end else if (hold_flag_i >= `Hold_Pc) beginpc_o <= pc_o;// 地址加4end else beginpc_o <= pc_o + 4'h4;endendendmodule
📌 模块功能概述
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)
elsepc_o <= pc_o + 4'h4;
如果无跳转或暂停,PC递增4字节,执行下一条指令。
✅ 总结:状态机行为
条件 | PC更新为 |
---|---|
复位 or JTAG复位 | CpuResetAddr |
跳转使能 | jump_addr_i |
暂停标志 >= Hold_Pc | 保持不变 |
正常 | pc_o + 4 |