Saturday 2 April 2011

VHDL Test Bench Package: Variables in the Scripting System


One of the more power things about the VHDL Test Bench Package, is the implementation of variables in the scripting system. This facility is provided by the default command “DEFINE_VAR”, which is built into the parsing system and is not part of the else if chain. As one of the latest enhancements to the test bench package, variable definitions were removed from the instruction array. This was done to speed up searching as well as make declaration independent of usage. As in, you can use a variable before it is defined in the script.

Using variables makes scripts more readable. Instead of 1/0 as values to pass, you can use ON/OFF, and as a person reading that, you already know it is a switch value, just from the naming. The user of the variable does not have to worry about the value. If you have some binary words that need to be written to a DUT that cause certain configurations to be enabled, it is better to read “ENABLE_MODEXX”, than it is to read x00234.

Be sure to use meaningful variable names.
Now the team, or you, have bought into the using variables in a big way. At the top of each script everyone pastes in a copy of a nice group of variables they used from the test case before. Now some time later in the project, and many test cases have been created, something happens and a change to the DUT forces the value of one or more of the variables to have to change!! Oh, no, that means editing all the scripts. This problem could be solved by writing a script changer program. Or you could do it by hand. It would have been better to have avoided that situation.

The INCLUDE command solves the above problem. Create a file that only contains the common variable definitions. In your scripts, use the INCLUDE instruction to read and create the common variables. I put my variable includes at the top, like many other languages do. I use this approach for device address maps. This way, if there are any address changes, there is a single place to update, and all the test cases receive that update automatically. Also, as a side benefit (assuming all test case writers use them), the scripts will be more readable as a whole because of the common variable definitions.

Once a variable is defined in a script, it's value can be changed. A variable can be assigned the value of another variable. Below is an example of using variables in a loop.

Lets assume the line below this one, is in a file named “std_vars.stm”:
DEFINE_VAR TABLE_BASE_ADDR x8000 -- define base address of table

This is a simple test case that uses variables in a good way:
INCLUDE stm/std_vars.stm

DEFINE_VAR TABLE_ADDR 0 -- define temp location for changes
DEFINE_VAR DATA 0 -- define data variable with value 0
DEFINE_VAR DATA_INC 1 -- a value to change the data by
DEFINE_VAR ADDR_STEP 4 -- the address increment value
.....
-- copy the default value to a variable you can change
EQU_VAR TABLE_ADDR $TABLE_BASE_ADDR
LOOP 512 -- loop through the table
WRITE $TABLE_ADDR $DATA -- write to address the data.
READ $TABLE_ADDR -- read it back
VERIFY $DATA -- check is a match
ADD_VAR DATA $DATA_INC -- change the data
ADD_VAR TABLE_ADDR $ADDR_STEP -- point to next address
END_LOOP

FINISH

The above example does everything with variables. It is isolated from DUT address changes because it includes a standard variable definition from a single place. If your test had several more loops, and you wanted to change the addressing step value, you can do it in one place if you used the scheme above.

During some rather large verification projects, the use of the default variable “include” file became very important. I took the concept further and created a table defined in tcl code. From this table I generated the standard variables include files and well as several other files ... header file for C and assembly coding, tcl/tk code itself for test case generation code and in generated test cases. I will cover this topic in detail in a future post, test case generation. In one project I found that even the software group was using my table for generating their header files.

How do I produce a walking ones pattern? Simple, add a variable to itself, with a starting value of 1. This is shown in the example below:

DEFINE_VAR ADDR 1 -- 32 bit address range
DEFINE_VAR DATA 0 -- some data

LOOP 32
WRITE $ADDR $DATA -- write the test location
READ $ADDR -- read it back
VERIFY $DATA -- test results
ADD_VAR ADDR $ADDR -- walk the 1
ADD_VAR DATA 1 -- change the test data
END_LOOP

FINISH

Another variable type the VHDL Test Bench Package understands is the in-line variable. These are the variables that contain the line number of the next executable script line. Defining one is shown below:

JUMP $JUMP1
....
....
JUMP1: -- --<< this is an in-line variable
WRITE .....

The JUMP1: statement defines a variable equal to the line number the WRITE statement is found. In all my test case writing I have never had a reason to change a in-line variable value. But, it can be done as it is accessed just like any other variable in the variable link list.

The last kind of variable, which really is not a variable, is the condition operators. They are described in the documentation as Condition Variables, but after thinking about it a bit, they really are not variables. They are predetermined text that will return a specific value. This enables the command code to case on the condition that has been passed from the script.

User defined variable access and modification commands are all part of the scripting system. The test bench creator can use the ADD_VAR and EQU_VAR default commands as templates to create their own. One command I have created several times is a randomize variable command. This is rarely used by me as I like to keep complication out of the script and in BFM's. Again, a future topic, BFM's and the test bench system.

That is about all I can say about variables and the test bench package. I hope that helps some avoid some scripting nightmares.

Sckoarn

No comments:

Post a Comment