Reply To: Writing a Test Plan, Identifying Transactions, and Documenting BFMs/MIT

Why OSVVM™? Forums OSVVM Writing a Test Plan, Identifying Transactions, and Documenting BFMs/MIT Reply To: Writing a Test Plan, Identifying Transactions, and Documenting BFMs/MIT

#2230
Jim Lewis
Member

Lets address, 2. Identifying Transactions:

A transaction is an abstract representation of an atomic action on an interface. For a UART transmitter, it is sending one word on the interface. For an Axi4Lite interface, it is Write and Read operations on the interface.

For the simple interface we look at in our Comprehensive VHDL Introduction, it is drive the device select line active for one clock cycle and put a value on the command interface. There also needs to be some time between driving a values, so we added a wait time before accepting the next cycle.

From a signal wiggling perspective, this is our sequence:

LedFlasherSel  <= 
    '1' after tpd_Clk_LedFlasherSel, 
    '0' after tperiod_Clk + tpd_Clk_LedFlasherSel ;
Addr           <= FLASH_ONE_CMD after tpd_Clk_Addr ;
wait for (3 * TIME_BASE) - 1 ns ; 
wait until Clk = '1' ;

I call tests written using signal wiggling, brute force testing. Abstractly a test for this device looks like the following code. When we write tests this way, we are challenged to understand what each step does, so comments focus on exactly that.

TestProc : process
begin
  wait until nReset = '1' ;
  wait until Clk = '1' ;

  -- Cmd = FLASH_ONE_CMD  WAIT = 1 TIME_BASE
  ... -- block of code that does the above

  -- Cmd = FLASH_ONE_CMD  WAIT = 5 TIME_BASE
  ... -- block of code that does the above

  -- Cmd = FLASH_ONE_CMD  WAIT = 1 TIME_BASE
  . . . 
  -- Cmd = FLASH_ONE_CMD  WAIT = 4 TIME_BASE
  -- Cmd = FLASH_ONE_CMD  WAIT = 3 TIME_BASE
  -- Cmd = FLASH_CONT_CMD WAIT = 7 TIME_BASE
  -- Cmd = FLASH_OFF_CMD  WAIT = 5 TIME_BASE
  -- Cmd = FLASH_CONT_CMD WAIT = 7 TIME_BASE
  -- Cmd = FLASH_OFF_CMD  WAIT = 2 TIME_BASE

Transactions abstract the behavior. With transactions our test sequence becomes the following. Note that by using a good set of constants, all of the comments of the brute force approach were replaced by transaction calls. Since we are still inclined to comment, we write appropriate constants that illuminate the intent of the sequences.

TestProc : process
begin
  wait until nReset = '1' ;
  wait until Clk = '1' ;

  -- verify basic Flash One functionality
  SendCmd(FLASH_ONE_CMD, 1 * TIME_BASE, Clk, LedFlasherSel, Addr) ;
  SendCmd(FLASH_ONE_CMD, 5 * TIME_BASE, Clk, LedFlasherSel, Addr) ;
  SendCmd(FLASH_ONE_CMD, 1 * TIME_BASE, Clk, LedFlasherSel, Addr) ;
  SendCmd(FLASH_ONE_CMD, 4 * TIME_BASE, Clk, LedFlasherSel, Addr) ;
  SendCmd(FLASH_ONE_CMD, 3 * TIME_BASE, Clk, LedFlasherSel, Addr) ;

  -- verify Flash Continuously and Flash Off functionality
  SendCmd(FLASH_CONT_CMD, 7 * TIME_BASE, Clk, LedFlasherSel, Addr) ;
  SendCmd(FLASH_OFF_CMD,  5 * TIME_BASE, Clk, LedFlasherSel, Addr) ;
  SendCmd(FLASH_CONT_CMD, 7 * TIME_BASE, Clk, LedFlasherSel, Addr) ;
  SendCmd(FLASH_OFF_CMD,  5 * TIME_BASE, Clk, LedFlasherSel, Addr) ;

When we work on the IEEE standard, our proposals include the presentation of a new language feature and use models that show how the feature will be used. The use model gives us more insight into the proposed language feature.

In the same way, writing the test cases gives us more insight into the test plan – and perhaps what is missing. For example, in the design above, the FlashOne functionality was intended to be implemented separately from the FlashContinuous functionality. So testing took this perspective and tested the two features independently. What happens if the hardware was implemented in another way? What do we expect to happen if FLASH_ONE is issued while the Led is already flashing continuously. Should it continue flashing continuously or should it stop after flashing once? We should know. Therefore, we should verify.

By using transactions, we are able to get a deeper understanding of what the test is doing and see its potential limitations. Also by explaining what the transactions do, people other than hardware design and verification engineers can read the test (at least somewhat).

Is it always this easy? No. The interesting thing about testing this way is that we must have a transaction that supports everything that is gracefully handled by the interface. So for UART, this includes generating errors such as break, stop, and parity.