Search code examples
vhdlsystem-veriloguvmquestasim

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


I am trying to bind an interface to my VHDL module. The signal that I want to bind to is defined as follows in the module:

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;

My instantiation of the interface module and bind statement looks something like this:

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)
                              );

I had no idea what length my input signal fsm_state should be, so I just set it to 32 bits.

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

When I try to compile in questasim 10.4, I get the following message:

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

Any idea how to handle this?


Solution

  • I managed to get it working on my simulator Questasim 10.4a.

    1) Move the TYPE definition in the VHDL code to a separate package:

    // 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) I defined my own enum my_fsm_state in my systemVerilog package:

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

    3) My interface module port definition had an input port of 4 bits to accomodate the 6 states of my FSM

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

    4) My bind statement was as before:

    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) Now, in my interface module, I use a static cast to cast fsm_state and prev_fsm_state to m_fsm_states enum variable.

    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
    

    Kinda tacky but it works.

    I used the whitepaper here to get this going: https://www.mentor.com/products/fv/resources/overview/binding-systemverilog-to-vhdl-components-using-questa-f43cc1c4-6607-44e3-8dc0-515bf2c08abc

    Although this didn't work exactly. They use an assign instead of a static_cast, but that didn't work for me. The error message asked me to cast instead of assign.