You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SystemVerilog中SRAM索引时钟上升沿切换数据异常问题排查

指令缓存索引切换的SystemVerilog时序问题分析

问题描述

我设计了一个指令缓存,遇到的问题是:时钟上升沿切换SRAM索引时,输出仍为前一索引的数据。单独测试SRAM模块时表现正常,但将其实例化到data_array和tag_array模块后,输出始终保留前一索引的数据,无法定位原因。

在top模块中,输入Program Counter(PC)后,若将提取出的index连线连接到data_array的索引端口会出现该问题,但直接将pc[1:0](索引部分)传入data_array模块则正常。现询问该现象在SystemVerilog(Vivado环境)中的成因,以及这是否属于竞争条件,哪种行为是正确的?

相关代码示例

测试平台代码

module top_tb;

  // Parameters

  // Ports
  logic clk = 0;
  logic rst = 0;
  logic flush = 0;
  logic write_en = 0;
  logic [3:0] i_data;
  logic [9:0] pc;
  logic [3:0] o_data;

  top 
  top_dut (
    .clk      (clk ),
    .rst      (rst ),
    .flush    (flush ),
    .write_en (write_en ),
    .i_data   (i_data ),
    .pc       (pc ),
    .o_data   (o_data)
  );

  initial begin
    begin
      rst      = 1;
      flush    = 0;
      write_en = 0;
      i_data   = 0;
      pc       = 0;
      #10;
      // Flush cycle keep 16 cycle
      rst      = 0;
      flush    = 0; // no change
      write_en = 0;
      i_data   = 0;
      pc       = 0;
      #45;
        
      // end of flush
      write_en = 1;
      i_data   = 1;
      pc       = 1;
      #10;

      write_en = 1;
      i_data   = 2;
      pc       = 2;
      #10;
      write_en = 0;

    end
  end

  always
    #5  clk = ! clk ;

endmodule

异常波形对应的top模块代码

`timescale 1ns / 1ps

module top(
    input  logic       clk,
    input  logic       rst,
    input  logic       flush,
    input  logic       write_en,
    input  logic [3:0] i_data,
    input  logic [9:0] pc,
    output logic [3:0] o_data
    );

  // Ports
  logic [1:0] index;
  assign index = pc[1:0];

  test test_ex (
    .clk         (clk),
    .rst         (rst),
    .i_flush     (flush),
    .i_wr_en     (write_en),
    .i_data      (i_data),
    .i_index     (index),
    .o_data      (o_data)
  );

endmodule

正常波形对应的top模块代码

`timescale 1ns / 1ps

module top(
    input  logic       clk,
    input  logic       rst,
    input  logic       flush,
    input  logic       write_en,
    input  logic [3:0] i_data,
    input  logic [9:0] pc,
    output logic [3:0] o_data
    );

  // Ports
  logic [1:0] index;
  assign index = pc[1:0];

  test test_ex (
    .clk         (clk),
    .rst         (rst),
    .i_flush     (flush),
    .i_wr_en     (write_en),
    .i_data      (i_data),
    .i_index     (pc[1:0]),
    .o_data      (o_data)
  );

endmodule

test模块代码

module test(
    input  logic       clk,
    input  logic       rst,
    input  logic       i_flush,
    input  logic       i_wr_en,
    input  logic [3:0] i_data,
    input  logic [1:0] i_index,
    output logic [3:0] o_data
);
    logic        flush_q;
    logic [15:0] memory [3:0];
    logic [1:0]  flush_index;
    logic [1:0]  wr_index;
    logic [15:0] wr_data;
    
    assign wr_data = flush_q ? '0 : i_data;
    assign wr_index = flush_q ? flush_index : i_index;
    always_ff@(posedge clk)begin
        if(i_wr_en | flush_q)begin
            memory[wr_index] <= wr_data;
        end else begin
          o_data <= memory[wr_index];
        end
    end
    
    always_ff @(posedge clk) begin
    if(rst) begin
      flush_q       <= 1'b1;
      flush_index   <= '0;
    end 
    else begin
      if(flush_q) begin
        if(flush_index == 3) begin  
          flush_index <= '0;
          flush_q     <= 1'b0;
        end else begin
          flush_index <= flush_index + 1'b1;
        end
      end else begin
        flush_q <= i_flush;
      end
    end
  end
endmodule

成因分析与结论

问题成因

这不属于竞争条件,而是Vivado工具在综合/仿真阶段引入的信号路径延迟差异导致的:

  • 直接传递pc[1:0]时,综合器会将该路径视为组合逻辑直通,时钟上升沿到来时,PC的最新值低两位会被test模块内的逻辑直接采样,无额外延迟。
  • 通过中间index连线传递时,尽管代码是纯连线赋值,但工具可能为了布线或时序优化插入微小缓冲,导致index的更新晚于pc[1:0]到达test模块的i_index端口。此时test模块内的wr_index会采样到前一个时钟周期的index值,进而读取旧的内存数据,出现输出不更新的现象。

正确行为判断

直接传递pc[1:0]的行为是符合设计预期的正确行为,它保证了时钟上升沿能准确采样到PC的最新索引值。中间连线导致的延迟是工具引入的非预期时序偏差,并非代码逻辑错误,但会破坏功能正确性。

解决建议

  • 优先直接使用原始信号的位切片作为模块输入,避免不必要的中间组合逻辑连线。
  • 若必须保留中间信号,可添加(* dont_touch *)属性标记该连线,禁止工具插入额外缓冲:
    (* dont_touch *) logic [1:0] index;
    assign index = pc[1:0];
    
  • 添加时序约束,确保pc到i_index的路径满足建立时间要求,避免信号在时钟边沿附近变化。

内容的提问来源于stack exchange,提问作者Kerim Turak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 19:42:46