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

SystemVerilog中如何通过modport正确复用接口信号作为输入输出?

如何用modport实现同一接口信号的输入/输出复用并避免X态

解决这个问题的核心是利用modport的端口方向约束能力,给接口定义不同的访问视角,每个视角严格限定信号的驱动/采样方向,从根源上避免无约束访问导致的多驱动冲突(也就是你提到的X态问题)。

针对你的代码,问题出在没有通过modport约束接口的访问方式,直接操作接口实例信号会打破方向规则。以下是修正后的实现:

1. 接口定义(原有定义逻辑正确,保留即可)

interface tx_bfm();
  logic clk;
  logic ch;
  logic [7:0] data;
  
  // 主设备视角:clk、ch、data均为输出,由主设备驱动
  modport tx_mst(output clk, ch, data);
  // 从设备视角:clk、ch为输入(来自主设备),data由接口内部逻辑驱动输出
  modport tx_slv(input clk, ch, output data);
  
  always @(posedge clk)
    if(ch)
      data = data + 1;
    else
      data = 0;

endinterface

interface rx_bfm();
  logic clk;
  logic ch;
  logic [7:0] data;
  bit [7:0] data_q [$];
  
  // 主设备视角:clk、ch输出,data输入(采样外部信号)
  modport rx_mst(output clk, ch, input data);
  // 从设备视角:clk、ch、data全为输入,由接口内部逻辑采样
  modport rx_slv(input clk, ch, data);
  
  always @(posedge clk)
    data_q.push_back(data);
    
endinterface

2. 测试模块的正确连接方式

要通过modport声明接口的访问角色,而非直接赋值接口信号:

module tb;
  
  bit clk;
  
  /** 时钟信号 **/
  always #1 clk = ~clk;
  
  /** 接口实例化 **/
  tx_bfm tx_bfm0();
  rx_bfm rx_bfm0();
  
  initial begin
    $display("::-- Testing tx as master --::");
    // 用modport限定tx_bfm0的主设备视角,驱动clk、ch
    tx_bfm.tx_mst tx_mst_inst(tx_bfm0);
    // 用modport限定rx_bfm0的从设备视角,采样tx_bfm的信号
    rx_bfm.rx_slv rx_slv_inst(rx_bfm0);
    
    tx_mst_inst.clk = clk;
    tx_mst_inst.ch = 1'b1;
    
    // 按modport方向约束完成信号连接
    rx_slv_inst.clk = tx_mst_inst.clk;
    rx_slv_inst.ch = tx_mst_inst.ch;
    rx_slv_inst.data = tx_mst_inst.data;
    
    #10;
    $display("tx_bfm data: %0h", tx_bfm0.data);
    $display("rx_bfm data queue size: %0d", rx_bfm0.data_q.size());
    
    // 切换为rx_bfm作为主设备的场景
    $display("\n::-- Testing rx as master --::");
    // 释放原主设备的驱动,避免信号冲突
    tx_mst_inst.ch = 1'bz;
    tx_mst_inst.clk = 1'bz;
    
    // 切换到rx主设备、tx从设备的视角
    rx_bfm.rx_mst rx_mst_inst(rx_bfm0);
    tx_bfm.tx_slv tx_slv_inst(tx_bfm0);
    
    rx_mst_inst.clk = clk;
    rx_mst_inst.ch = 1'b0;
    
    tx_slv_inst.clk = rx_mst_inst.clk;
    tx_slv_inst.ch = rx_mst_inst.ch;
    rx_mst_inst.data = tx_slv_inst.data;
    
    #10;
    $display("tx_bfm data: %0h", tx_bfm0.data);
    $display("rx_bfm data queue size: %0d", rx_bfm0.data_q.size());
    
    $finish;
  end
  
endmodule

关键注意点

  • 严格遵守modport方向约束:比如tx_mst视角下clk是output,只能由该视角实例驱动,其他视角不能再驱动该信号,彻底避免多驱动导致的X态。
  • 角色切换时释放驱动:切换主设备角色前,需将原主设备的驱动置为高阻(z),防止信号冲突。
  • 接口内部逻辑配合:比如tx_bfm的tx_slv视角下data由内部always块驱动,此时外部不能再驱动data,否则会引发冲突。

通过这种方式,同一接口的信号在不同角色(输入/输出)下都有明确的驱动源,完全规避无约束访问带来的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 19:12:52