4

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?

noobuntu
  • 903
  • 1
  • 18
  • 42
  • 2
    In Modelsim 10.4c SE User's Guide Chapter 9 Mixed Language Simulation there's a section 'Verilog or SystemVerilog Instantiating VHDL' followed by a section 'Sharing User-Defined Types` with a subheading of ' Using a Common VHDL Package' with a Note - *The following types must be defined in a common package if you want to use them at the SystemVerilog-VHDL boundary:* (the list includes enumerations). You can share a package declaration from VHDL although I recall it requires vcom options (in the Usage Notes). A case of 'reading the manual' providing useful results. –  Nov 24 '16 at 01:25

3 Answers3

3

Based on the error message, it sounds like you need to define the equivalently type on the SystemVerilog side and it needs to be defined in a package. Therefore adding the bellow package and modifying the the interface ports should work.

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

Mix language simulations tend to be tricky. I'm not 100% confident this will work, but should get you in the correct direction.

Greg
  • 18,111
  • 5
  • 46
  • 68
  • you pointed me in the right direction but it didn't go exactly as noted. I wrote another answer to show how I managed to get this going. Thanks for your help nonetheless – noobuntu Nov 24 '16 at 18:17
  • Ah, I'm an SV guy and rarely look at vhdl. I didn't know that `package` is a shared concept between the two languages. Glad my attempt of an answer got you towards a solution – Greg Nov 24 '16 at 22:45
2

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.

noobuntu
  • 903
  • 1
  • 18
  • 42
0

The best way is to use a package as described above.

If you have the FSM defined in VHDL as:

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

In case you are using Synopsys, it is important to define your typedef as:

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

otherwise you will have only X. It is important to put the interger mapping =0,=1.... and so on to each state name.

///////////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
//////////////////////////////
Joniale
  • 515
  • 4
  • 17