MIPS架构同周期寄存器RAW数据冒险的硬件实现及Verilog代码咨询
同一周期寄存器读写的RAW(Read After Write)硬件实现方案
一、上升沿写+下降沿读的可行性
这种方案完全可行,核心是利用时钟的两个边沿拆分读写时序:
- 寄存器堆写操作绑定时钟上升沿:上升沿触发时完成数据写入寄存器的动作;
- 寄存器堆读操作绑定时钟下降沿:同一周期的下降沿到来时,寄存器已完成写入并稳定输出新值,此时读取即可拿到刚写入的数据,直接解决RAW冲突。
需要注意:这种设计要求器件能在半个时钟周期内完成写操作的电平稳定,需预留足够的时序余量,避免亚稳态问题。
二、上升沿写后添加延迟的实现思路
若要通过延迟实现读操作获取新值,本质是让读触发时刻晚于写操作完成时刻,硬件上有两种常见实现方式:
- 组合逻辑延迟:串联若干反相器或缓冲器,利用门电路固有延时产生固定延迟,让读信号在写操作完成后再触发;
- 时钟相位微调:通过锁相环(PLL)生成滞后于主时钟一定相位的时钟,用该滞后时钟触发读操作,确保写操作已完成。
不过这种方案时序约束更复杂,实际工程中使用频率低于边沿拆分方案。
三、示例场景的硬件实现与Verilog代码
针对你给出的指令场景:
add $r1, $r2, $r3 // 写$r1 Inst 1 Inst 2 add $r2, $r1, $r3 // 读$r1,要求获取刚写入的新值
以下是采用上升沿写+下降沿读的寄存器堆Verilog实现示例:
module register_file #( parameter WIDTH = 32, parameter DEPTH = 32 )( input clk, input we, // 写使能信号 input [$clog2(DEPTH)-1:0] waddr, // 写地址 input [WIDTH-1:0] wdata, // 待写入数据 input [$clog2(DEPTH)-1:0] raddr, // 读地址 output reg [WIDTH-1:0] rdata // 读出数据 ); // 寄存器堆存储单元 reg [WIDTH-1:0] regs [DEPTH-1:0]; // 上升沿触发写操作 always @(posedge clk) begin if (we) begin regs[waddr] <= wdata; end end // 下降沿触发读操作,确保同一周期写后能读取新值 always @(negedge clk) begin rdata <= regs[raddr]; end // 仿真初始化(可选) initial begin $readmemh("regs_init.txt", regs); end endmodule
代码说明
- 写操作在时钟上升沿执行,当
we有效时,将wdata写入waddr对应的寄存器; - 读操作在时钟下降沿执行,此时同一周期的上升沿写操作已完成,寄存器值已更新,读出的是最新数据;
- 该设计无需额外旁路(Bypass)电路,仅通过时钟边沿拆分解决同一周期的RAW冲突。
四、关键注意事项
- 时序验证:需确保寄存器的建立时间、保持时间满足要求,尤其是下降沿读时,寄存器输出已稳定;
- 器件适配:不同工艺的FPGA/ASIC门延时不同,需保证半个时钟周期内写操作能完成并稳定输出;
- 架构兼容:若用于流水线处理器,需结合整体流水线节拍设计调整该寄存器堆的时序逻辑。
内容的提问来源于stack exchange,提问作者user24917762
相关产品推荐
相关产品推荐

