如何将 SV 接口信号绑定到 VHDL 类型?

How to bind a SV interface signal to a VHDL type?

我正在尝试将接口绑定到我的 VHDL 模块。我要绑定的信号在模块中定义如下:

TYPE dut_fsm_type is (
                           IDLE_STATE,
                           WAIT_STATE,
                           IDENTIFY_STATE,
                           LATCH_STATE,
                           DONE_STATE,
                           ERROR_STATE
                          );
signal dut_fsm_state       : dut_fsm_type;
signal prev_dut_fsm_state  : dut_fsm_type;

我的接口模块实例化和绑定语句如下所示:

bind my_dut my_intf my_intf_0 (.*,
                               .fsm_state     (tb.u_dut.dut_fsm_state),
                               .prev_fsm_state(tb.u_dut.prev_dut_fsm_state)
                              );

我不知道我的输入信号 fsm_state 应该是多长,所以我只是将它设置为 32 位。

interface my_intf (
  input bit[31:0] fsm_state,
  input bit[31:0] prev_fsm_state
);

当我尝试在 questasim 10.4 中编译时,我收到以下消息:

(vopt-2245) Type ('dut_fsm_type') of VHDL hierarchical reference, used as actual expression in bind statement, must be defined in a package.

知道如何处理吗?

根据错误消息,听起来您需要在 SystemVerilog 端定义等效类型,并且需要在包中定义它。因此添加波纹管包并修改接口端口应该可以工作。

package typdef_pkg;
  typedef enum  {
    IDLE_STATE,
    WAIT_STATE,
    IDENTIFY_STATE,
    LATCH_STATE,
    DONE_STATE,
    ERROR_STATE
  } dut_fsm_type;
endpackage : typdef_pkg

interface my_intf (
  input typdef_pkg::dut_fsm_type fsm_state,
  input typdef_pkg::dut_fsm_type prev_fsm_state
);
...
endinterface

混合语言模拟往往很棘手。我不是 100% 相信这会奏效,但应该会让你朝着正确的方向前进。

我设法让它在我的模拟器 Questasim 10.4a 上运行。

1) 将VHDL代码中的TYPE定义移到单独的包中:

// File: types_pkg.vhd
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;

package types_pkg is
    TYPE dut_fsm_type is (
                          IDLE_STATE,
                          WAIT_STATE,
                          IDENTIFY_STATE,
                          LATCH_STATE,
                          DONE_STATE,
                          ERROR_STATE
                         );
end types_pkg;

2) 我在我的 systemVerilog 包中定义了我自己的 enum my_fsm_state

//my_pkg.sv
typedef enum {
             IDLE_STATE,
             WAIT_STATE,
             IDENTIFY_STATE,
             LATCH_STATE,
             DONE_STATE,
             ERROR_STATE        
             } my_fsm_states;

3) 我的接口模块端口定义有一个 4 位的输入端口来容纳我的 FSM 的 6 种状态

interface my_intf (
  input          clk,
  input [4:0]    fsm_state,
  input [4:0]    prev_fsm_state
);

4) 我的绑定语句和以前一样:

bind my_dut my_intf my_intf_0 (.*,
                               .fsm_state     (tb.u_dut.dut_fsm_state),
                               .prev_fsm_state(tb.u_dut.prev_dut_fsm_state)
                              );

5) 现在,在我的接口模块中,我使用静态转换将 fsm_stateprev_fsm_state 转换为 m_fsm_states 枚举变量。

interface my_intf (
  input          clk,
  input [4:0]    fsm_state,
  input [4:0]    prev_fsm_state
);

always @(posedge clk)
begin
  if (my_fsm_states'(fsm_state) == WAIT_STATE) begin
    // Do something
  end
  else if (my_fsm_states'(fsm_state) == IDLE_STATE) begin
    // Do something
  end
  else if .... // So on..

end

有点俗气,但很管用。

我使用这里的白皮书来实现这一点:https://www.mentor.com/products/fv/resources/overview/binding-systemverilog-to-vhdl-components-using-questa-f43cc1c4-6607-44e3-8dc0-515bf2c08abc

尽管这并不完全有效。他们使用 assign 而不是 static_cast,但这对我不起作用。错误消息要求我转换而不是分配。

最好的方法是使用如上所述的包。

如果您在 VHDL 中将 FSM 定义为:

TYPE state_type IS (idle,shift_wait, shift_dio, shift_sync, sync_ready, sync_update);
state_type  CURSTATE_I;//your signal to bind

如果您使用的是 Synopsys,请务必将您的 typedef 定义为:

typedef enum {idle=0,shift_wait=1, shift_dio=2, shift_sync=3, sync_ready=4, sync_update=5} my_fsm_states; //it should be in a package

否则你将只有 X。重要的是将整数映射 =0,=1... 依此类推到每个州名称。

///////////my_pkg.sv
typedef enum {idle=0,shift_wait=1, shift_dio=2, shift_sync=3, sync_ready=4, sync_update=5} my_fsm_states; //it should be in a package

/////////// if_in_internals.sv
interface if_in_internals;
     my_fsm_states shift_fsm;     
endinterface
 
 
MODULE EXPOSER
/////////// module_in_internals_exposer.sv
module in_internals_exposer#(string expose_name, string expose_path_format) ( 
        my_fsm_states shift_fsm 
    );
    if_in_internals intf();  
    assign intf.shift_fsm                       =  shift_fsm;
    initial begin
    ..... e.g.  uvm_config_db#(virtual if_in_internals)::set(uvm_root::get(), expose_path, {"internals", ".if"},  intf);
    end
endmodule
 
///////////top_level.sv - where you want to place your hierarchy bind interface
bind i_top_wrp in_internals_exposer#("3",  "*.i_%0d.*") if_internals_expose (        
            .shift_fsm                      (dut.U01.U06.U02.U_USE_U03.U03.U01.CURSTATE_I)        
        );
end
//////////////////////////////