Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WaitForTransaction on AXIS Receiver returns after 1 delta - either add a warning or wait until an actual transaction occurs. #20

Open
SkydiverTricky opened this issue Jan 15, 2025 · 7 comments

Comments

@SkydiverTricky
Copy link

Currently, the AXIS Receiver waits for a single delta when the user calls WaitForTransaction(rx_transrec)

when WAIT_FOR_TRANSACTION =>

This returns after a single delta with no warnings etc that this is what is happening.

For me, it would make more sense if it returned after an AXI transaction has occured. Any reason you cannot simply do the following?

when WAIT_FOR_TRANSACTION =>
          
          wait until rising_edge(clk) and TValid = '1' and TReady = '1';
          wait for 0 ns;                -- possibly wait the extra delta to allow internal queues to get filled

My use case here: I am using an external Queue of data for checking because OSVVM does not currently support CheckAsync functionality. I was hoping I could simply wait until a transaction had occured in the AXIS interface to synchronise to the VC.

@JimLewis
Copy link
Member

The current purpose of WaitForTransaction is to wait until any queued transactions have completed.

I am missing something. If we created a WaitForTransaction that blocks until a transaction has completed, and then get the data and check it, why not just do a Get, GetBurst, Check, CheckBurst as they all block and return (or check) something.

@JimLewis
Copy link
Member

There is also a GotBurst to check and see if a burst is available, but does not block.

I will boost up CheckAsync on my list.

@SkydiverTricky
Copy link
Author

SkydiverTricky commented Jan 15, 2025

Currently, I have a stim_proc that generates the source data and generates the expected data from that. Because I need a constant stream of source data, I cannot do a check after a send(), so I have a separate process setup that pulls data out of a ScoreBoard simply to then call a series of check on the receiver. CheckAsync would remove the need for this process.
I was trying to use the WaitOnTransaction on the receiver to deduce when the CheckFifo in testbench had data, as I know by this point in time it should have expected data waiting. otherwise, I have to do the following:

checker_loop : while runTest loop

  while empty(CheckFifo) loop
    waitForClock(rx_transrec);
  end loop;

  while not empty(CheckFifo) loop
    check(rx_transrec, CheckFifo.pop() );
  end loop
end loop checker_loop;

I was hoping I could replace the above with

WaitOnTransaction(rx_transrec);

@JimLewis
Copy link
Member

JimLewis commented Jan 16, 2025

You will find this pattern in my classes and presentations:

architecture Test of Tb is
  signal SB : OSVVM.scoreboardPkg_slv.ScoreboardIDType ; 
begin
  InitProc : process
  begin
    SB<= NewID("SB") ;  -- most simulators allow this as an initialization of SB, but technically I think VHDL says no.
    wait ; 
  end process InitProc ; 

  TxProc : process
    variable TxData : std_logic_vector(7 downto 0) ; 
    variable RV : RandomType  := InitSeed(RV'Path_Name) ; -- 2019
  begin
    wait for 0 ns ; -- allow SB to init
    loop 
      TxData := RandSlv(RV, 0 255) ; 
      Push(SB, TxData) ; 
      Send(TRec, TxData) ;
      exit when SomethingHappens ; 
    end loop ;
  end process TxProc ; 

  RxProc : process 
    variable RxData : std_logic_vector(7 downto 0) ; 
  begin
    wait for 0 ns ; -- allow SB to init
    loop 
      Get(RRec, RxData ) ;
      Check(SB, RxData ) ; 
      exit when SomethingHappens ; 
    end loop ;
  end process RxProc ; 

On the TX side, we always push data into the SB before sending. Hence, on the RX side, if we receive data, the value can be checked against what is in the SB - no need to check for IsEmpty (IsEmpty being the updated name for Empty - but Empty will keep working) on the SB.

Some care needs to be done coordinating the ending as RX may finish after TX (easy) or before TX (like in a UART when it center samples).

This also supports packetizing TX and RX operations with bursts and delays between bursts - or allows that to be handled internally to the VC with Delay Coverage (if the VC supports it).

This pattern will work with SendBurst/CheckBurst - provided we know the packet boundaries (for AxiStream this currently means using TLast). Then Data becomes an array of SLV sized to be the maximum size of a burst. There is a corresponding PushBurstVector (in osvvm_common library) to support this sort of operation. This is not necessarily any better or worse than doing it word by word.

@SkydiverTricky
Copy link
Author

The issue I have with this pattern, is you're wasting all the checking capabilities and reporting already built into the VC, and in the case of the AXIS VC, thats a lot of checking you then have to re-create (tlast, tuser etc)

@JimLewis
Copy link
Member

There is no difference between a FIFO and a Scoreboard. If you are checking TDest, TID, and TUser, then there is that. TUser can be in the FIFO if it changes with every data word.

@JimLewis
Copy link
Member

JimLewis commented Jan 16, 2025

I have thought about all data handling being done by the FIFO. That would allow Tx to push directly to the RRec.BurstFifo and then do a check operation against it. It could also potentially break some things depending on how bursts and single word transfers were built and mixed.

It would also mean someone would need to know that single word checks could be done via the FIFO interface - unless the single word checks were treated as one word bursts - which I suppose is possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants