Simulation stopped when transmitting with axistream_transmit() VVC

Hi to everyone.
I’ve been trying to find the source of the problem but i wasn’t able to do that. The problem is: simulation is stopped when transmitting using axistream_transmit() VVC, that does not happen with its BFM equivalent. I think some flag/ initialization is missing or some parameters in the function calling. Any help would be appreciated.
The code is the following.


library IEEE;
use     IEEE.std_logic_1164.all;
use     IEEE.numeric_std.all;
use     IEEE.math_real.all;
library uvvm_util;
context uvvm_util.uvvm_util_context;
library uvvm_vvc_framework;
use     uvvm_vvc_framework.ti_vvc_framework_support_pkg.all;
library bitvis_vip_axistream;
context bitvis_vip_axistream.vvc_context;



entity axisvvc_tb is
end;

architecture bench of axisvvc_tb is

  component axis_fifo
    generic(
      constant GC_DATA_WIDTH   : natural := 8;
      constant GC_USER_WIDTH   : natural := 1;
      constant GC_FIFO_DEPTH   : natural := 256
    );
    port(
      clk                      : in  std_logic;
      rst                      : in  std_logic;
      s_axis_tready            : out std_logic;
      s_axis_tvalid            : in  std_logic;
      s_axis_tdata             : in  std_logic_vector(GC_DATA_WIDTH - 1 downto 0);
      s_axis_tuser             : in  std_logic_vector(GC_USER_WIDTH - 1 downto 0);
      s_axis_tkeep             : in  std_logic_vector(GC_DATA_WIDTH / 8 - 1 downto 0);
      s_axis_tlast             : in  std_logic;
      m_axis_tready            : in  std_logic;
      m_axis_tvalid            : out std_logic;
      m_axis_tdata             : out std_logic_vector(GC_DATA_WIDTH - 1 downto 0);
      m_axis_tuser             : out std_logic_vector(GC_USER_WIDTH - 1 downto 0);
      m_axis_tkeep             : out std_logic_vector(GC_DATA_WIDTH / 8 - 1 downto 0);
      m_axis_tlast             : out std_logic;
      empty                    : out std_logic := '1';
      full          : out STD_LOGIC := '0'
    );
  end component;
  constant c_max_bytes         : natural   := 100;
  constant C_CLK_PERIOD        : time      :=10 ns;
  signal   clock_ena           : boolean   :=false;
  signal clk                   : STD_LOGIC;
  signal rst                   : STD_LOGIC :='1';
  constant GC_VVC_IS_MASTER    : boolean   := true;
  constant GC_INSTANCE_IDX     : natural   := 1;
  constant GC_DATA_WIDTH       : natural   := 8;
  constant GC_USER_WIDTH       : natural   := 1;
  constant C_S_AXIS_TDEST_WIDTH: natural   := 1;
  constant C_S_AXIS_TID_WIDTH  : natural   :=1;
  constant GC_FIFO_DEPTH       : natural   := 256;
  signal s_axis_tready         : STD_LOGIC;
  signal s_axis_tvalid         : STD_LOGIC;
  signal s_axis_tdata          : STD_LOGIC_VECTOR(GC_DATA_WIDTH - 1 downto 0);
  signal s_axis_tuser          : STD_LOGIC_VECTOR(GC_USER_WIDTH - 1 downto 0);
  signal s_axis_tkeep          : STD_LOGIC_VECTOR(GC_DATA_WIDTH / 8 - 1 downto 0);
  signal s_axis_tlast          : STD_LOGIC;
  signal m_axis_tready         : STD_LOGIC;
  signal m_axis_tvalid         : STD_LOGIC;
  signal m_axis_tdata          : STD_LOGIC_VECTOR(GC_DATA_WIDTH - 1 downto 0);
  signal m_axis_tuser          : STD_LOGIC_VECTOR(GC_USER_WIDTH - 1 downto 0);
  signal m_axis_tkeep          : STD_LOGIC_VECTOR(GC_DATA_WIDTH / 8 - 1 downto 0);
  signal m_axis_tlast          : STD_LOGIC;
  signal empty                 : STD_LOGIC:= '1' ;
  signal full                  : STD_LOGIC:= '0' ;
  constant C_SCOPE             : string := C_TB_SCOPE_DEFAULT;
  signal axistream_if          : t_axistream_if
  (
    tdata  (GC_DATA_WIDTH-1 downto 0),          
    tkeep  ((GC_DATA_WIDTH / 8) - 1 downto 0),  
	tuser  (GC_USER_WIDTH-1 downto 0),              
    tstrb  ((GC_DATA_WIDTH / 8) - 1 downto 0),
    tdest  (C_S_AXIS_TDEST_WIDTH - 1 downto 0),
    tid    (C_S_AXIS_TID_WIDTH - 1 downto 0)
  );
  signal axistream_if_s      : t_axistream_if
  (
    tdata  (GC_DATA_WIDTH-1 downto 0),           
	tkeep  ((GC_DATA_WIDTH / 8) - 1 downto 0),   
	tuser  (GC_USER_WIDTH-1 downto 0),           
    tstrb  ((GC_DATA_WIDTH / 8) - 1 downto 0),
    tdest  (C_S_AXIS_TDEST_WIDTH - 1 downto 0),
    tid    (C_S_AXIS_TID_WIDTH - 1 downto 0)
  );
  

begin
  axistrm_vvc_m: entity bitvis_vip_axistream.axistream_vvc
                        generic map(
                                    GC_VVC_IS_MASTER=> true, 
                                    GC_DATA_WIDTH   => GC_DATA_WIDTH,
                                    GC_USER_WIDTH   => GC_USER_WIDTH,
                                    GC_INSTANCE_IDX => GC_INSTANCE_IDX
                        )
                        port map(
                              clk                   => clk,
                              axistream_vvc_if      => axistream_if
                        );
  axistrm_vvc_s: entity bitvis_vip_axistream.axistream_vvc
                        generic map(
                                    GC_VVC_IS_MASTER=> false, 
                                    GC_DATA_WIDTH   => GC_DATA_WIDTH,
                                    GC_USER_WIDTH   => GC_USER_WIDTH,
                                    GC_INSTANCE_IDX => GC_INSTANCE_IDX+1
                        )
                         port map(
                              clk                   => clk,
                              axistream_vvc_if      => axistream_if_s
                        );
  uut: axis_fifo generic map ( 
                                    GC_DATA_WIDTH   => GC_DATA_WIDTH,
                                    GC_USER_WIDTH   => GC_USER_WIDTH,  
                                    GC_FIFO_DEPTH   => GC_FIFO_DEPTH )
                    port map (      clk             => clk,
                                    rst             => rst,
                                    s_axis_tready   => axistream_if.tready,
                                    s_axis_tvalid   => axistream_if.tvalid,
                                    s_axis_tdata    => axistream_if.tdata,
                                    s_axis_tuser    => axistream_if.tuser,
                                    s_axis_tkeep    => axistream_if.tkeep,
                                    s_axis_tlast    => axistream_if.tlast,
                                    m_axis_tready   => axistream_if_s.tready,
                                    m_axis_tvalid   => axistream_if_s.tvalid,
                                    m_axis_tdata    => axistream_if_s.tdata,
                                    m_axis_tuser    => axistream_if_s.tuser,
                                    m_axis_tkeep    => axistream_if_s.tkeep,
                                    m_axis_tlast    => axistream_if_s.tlast,
                                    empty           => empty,
                                    full            => full);
  --FRAMEWORK INSTANTIATION
  i_ti_uvvm_engine : entity uvvm_vvc_framework.ti_uvvm_engine;
  --CLOCK AND RESET SIGNALS
  clock_generator(clk, clock_ena, C_CLK_PERIOD, "AXI Stream Clock Signal");
  gen_pulse(rst,'0', 2*C_CLK_PERIOD, "AXI Stream Reset signal");
  
  p_axistream_vvc: process
    variable axistream_bfm_config : t_axistream_bfm_config := C_AXISTREAM_BFM_CONFIG_DEFAULT;
variable v_data_array : t_byte_array(0 to 10);
  begin
  await_uvvm_initialization(VOID);
  axistream_bfm_config.clock_period := C_CLK_PERIOD; 
  log(ID_LOG_HDR, "AXI STREAM VVC BEGINS HERE ");
  clock_ena <= true;    
  for i in 0 to 3 loop
    v_data_array(i):=x"AA";
  end loop;
  axistream_transmit(AXISTREAM_VVCT, GC_INSTANCE_IDX ,v_data_array(0),"Written Data",C_SCOPE);

  std.env.stop;
  wait;
  end process;


end;

The simulation stopped is shown in the following image:

Hi,
The simulation is behaving exactly as it should.
When you run a BFM, you run a procedure that accesses the interface until it is completed, but when sending a command to a VVC you are JUST sending the command to the VVC, telling it to execute the command.
Unfortunately, you have then not allowed any time for the command to execute.
Youy can see this immediately if you just add a normal wait in VHDL for at least the time it takes to execute the BFM.
For a more advanced use, you can use the await_completion() command to wait exactly for that command to finish.

– Espen

Hi.
When adding a simple wait for 100 ns after axistream_transmit() the following error appears.


It doesn’t matter the wait statement used (wait for ,await_any_completion, await_completion and wait_until_given_time_after_rising_edge) the error appears when waiting.

Hi,
It is always difficult to debug when not having access to the simulation itself with wave-view and signal values, but one problem here could be that the clock might still be U or X when calling the axistream_transmit(). Try to wait a few cycles after enabling the clock before calling axistream_transmit(). If that doesn’t work I would have tried to debug this interactively.
That might be easier with a GUI-based simulator. (I assume a basic, slowed-down Modelsim is still free with some tools).
– Espen

Hi.
The problem could be caused by some initialization missing but I’ve checked the given examples at folder UVVM_SUPPLEMENTARY, specifically axistream_vvc_simple_tb.vhd, but I couldn’t find anything related but some configurations (.bfm config) and some extra parameters in axistream_transmit() like: v_id_array(0 to v_numWords - 1), v_dest_array(0 to v_numWords - 1), but i don’t think these can be the problem due to they’re all optional according quick PDF guides. The following image shows how GHDL is complaining about the transmit method(line 367 of axistream_vvc.vhd).

Hi,
Could you provide the complete log?
It would also be easier to differentiate between potential problems if you could also try to run this without the await_completion(), and substitute this with just a wait for a time significantly larger than the expected packet transmission time.
– Espen

Hi.
When adding a wait for 500ns immediately after axistream_transmit, the “Null access dereferenced mode” disappear but a “bound check failure error appeared”.

Good news, the problem was magically solved when migrating to ModelSim, I don’t really know which GHDL incompatiblities or bug may have but whatever it is disappears in ModelSim and works perfectly there.

Good to hear.
Feel free to send this to the GHDL community to see if they can fix it.