Randomization ... a hot topic in the ASIC/FPGA verification world.
In VHDL, the IEEE math_real package, currently provides a method to generate random numbers through the uniform procedure. Getting a random number from uniform is a multi-step process and is not convenient to use. In the past I have used a LFSR construct coded in a procedure to generate random numbers. In stead of home cooking your own random number generation system or directly using uniform, I strongly recommend you look here: SynthWorks Downloads Specifically the random package RandomPkg_2_0. This free download, of source code and documentation, is a very capable package for generating random numbers. Besides the package content, the package also demonstrates some advanced VHDL 2008 coding techniques. The rest of this post will assume that the reader has reviewed or plans to review the SynthWorks' RandomPkg documentation and is familiar with the package and its definitions of randomization.
The VHDL Test Bench Package does not hinder the implementation of randomization. In fact, randomization may remove the need for scripts altogether. Taking randomization to the fullest, you may find that the tb_bhv file just becomes a container for your randomization objects and BFMs and no script is needed to make your simulations work. Randomization can be viewed from four different “levels”. With level one being simple randomization scripting instructions to enable a general randomization facility in scripts. Level two is the BFMs randomizing their output under the control of the scripting system, i.e. the stimulus bus. Level three is the randomization through randomly generated scripts. Finally at level 4, the system is completely controlled by an object that is able to generate random transaction based interaction with the BFMs. This post will cover the level 1 and 2 implementations and leave the level 3 and 4 for future posts.
The most obvious randomization within the scripting system would be to create a RAND_VAR instruction. Like the EQU_VAR (equate variable) instruction, provided by the test bench template, a RAND_VAR instruction could be created to randomize the contents of a variable. This variable could then be used as the address or data field in a write instruction, for instance. I am sure an implementer can come up with several other randomization type instructions for use in scripting. I have found that randomization be better done within a BFM.
There is an issue with random number generation that has to be addressed by the implementation. If for instance, we want to randomly write, random data, to a RAM as well as read back and verify that data, you will have to implement a more complex random number generation system. To re-state the problem, we want to randomize the address and data for both write and read operations. Lets also assume that we want to start reading and testing after four writes have been done. (This is done to offset the reads from writes, possibly uncovering some functional bug.) This can be done in one of two ways.
First, the write address and data could be stored in a FIFO construct, and reused for the read operations. This implementation causes the implementer to create two random numbers that have different random sequences. This is because the restrictions on address generation may not be the same as the data generation. If the address is sixteen bits wide and the data is only eight bits wide, the constraints on the two numbers being generated will be different. The address will be constrained to a number that fits in sixteen bits where the data generation will be constrained to fit within eight bits. The two numbers could be generated from a single random number stream, but that makes them dependent on each other. For instance, if I change the constraint on the address generation, that will effect the data values generated. The solution is to have more than one random number stream and in this case two. The reason for the two different random number streams, is because you may want to randomize both independent of each other. So, for one randomly generated address stream, you can generate many different random data streams.
Second, four different random number streams could be implemented and used to create a test to randomly test the RAM. The write and read data random variables could be initialize with the same seed and a different seed used for the write and read data.
Confused yet? A review of the SynthWorks' Random_Pkg documentation may help. I will attempt to make it clear here as well. For each random number stream that you want to have concurrently generating random numbers, you need to have a variable of type RandomPType defined. The RAND_VAR instruction will have to be expanded to include an index to random number stream to be used for the random operation. The RAND_VAR instruction should also have, as parameters, the max and min values to constrain generation within. This makes the simple RAND_VAR instruction much more complicated to implement in a script as it requires the script writer to understand and manage random number generation streams. If possible, the implementer should try to avoid complication in the scripts and move it into a BFM.
In a level 2 implementation, as defined above, the randomization is done within a BFM. This can hide complication from the script system. For items to be generated randomly a variable for each can be defined giving complete sequence independence for all fields.
Lets take an ATM signalling BFM as an example. The packet fields include GFC, VPI, VCI, PTI, CLP, HEC and data. One of the modes of operation for this BFM is random generation for any combination of fields. Through the stimulus access port, registers can be written to set the BFM to operate in different modes as well as provide random generation limits. The test case writer now only has to set up the register set for the configuration and not worry about the random number sequences. The sequences of random numbers will be controlled by the implementation of the BFM randomization system.
A simple example of random generation in a BFM is presented in the packet_gen example. This is part of the current Beta VHDL Test Bench Package download: Beta Test Bench Package
In the coming weeks, I will be posting a full set of BFM's for an environment to test a simple self threading switch. This will enable example code of a complete randomization system to be presented, with enough complexity to take the example into a master BFM implementation. I am currently working on coding this example DUT and test bench. Until the example is released, there is enough information in this post to keep some busy playing with randomization.
Sckoarn
In VHDL, the IEEE math_real package, currently provides a method to generate random numbers through the uniform procedure. Getting a random number from uniform is a multi-step process and is not convenient to use. In the past I have used a LFSR construct coded in a procedure to generate random numbers. In stead of home cooking your own random number generation system or directly using uniform, I strongly recommend you look here: SynthWorks Downloads Specifically the random package RandomPkg_2_0. This free download, of source code and documentation, is a very capable package for generating random numbers. Besides the package content, the package also demonstrates some advanced VHDL 2008 coding techniques. The rest of this post will assume that the reader has reviewed or plans to review the SynthWorks' RandomPkg documentation and is familiar with the package and its definitions of randomization.
The VHDL Test Bench Package does not hinder the implementation of randomization. In fact, randomization may remove the need for scripts altogether. Taking randomization to the fullest, you may find that the tb_bhv file just becomes a container for your randomization objects and BFMs and no script is needed to make your simulations work. Randomization can be viewed from four different “levels”. With level one being simple randomization scripting instructions to enable a general randomization facility in scripts. Level two is the BFMs randomizing their output under the control of the scripting system, i.e. the stimulus bus. Level three is the randomization through randomly generated scripts. Finally at level 4, the system is completely controlled by an object that is able to generate random transaction based interaction with the BFMs. This post will cover the level 1 and 2 implementations and leave the level 3 and 4 for future posts.
The most obvious randomization within the scripting system would be to create a RAND_VAR instruction. Like the EQU_VAR (equate variable) instruction, provided by the test bench template, a RAND_VAR instruction could be created to randomize the contents of a variable. This variable could then be used as the address or data field in a write instruction, for instance. I am sure an implementer can come up with several other randomization type instructions for use in scripting. I have found that randomization be better done within a BFM.
There is an issue with random number generation that has to be addressed by the implementation. If for instance, we want to randomly write, random data, to a RAM as well as read back and verify that data, you will have to implement a more complex random number generation system. To re-state the problem, we want to randomize the address and data for both write and read operations. Lets also assume that we want to start reading and testing after four writes have been done. (This is done to offset the reads from writes, possibly uncovering some functional bug.) This can be done in one of two ways.
First, the write address and data could be stored in a FIFO construct, and reused for the read operations. This implementation causes the implementer to create two random numbers that have different random sequences. This is because the restrictions on address generation may not be the same as the data generation. If the address is sixteen bits wide and the data is only eight bits wide, the constraints on the two numbers being generated will be different. The address will be constrained to a number that fits in sixteen bits where the data generation will be constrained to fit within eight bits. The two numbers could be generated from a single random number stream, but that makes them dependent on each other. For instance, if I change the constraint on the address generation, that will effect the data values generated. The solution is to have more than one random number stream and in this case two. The reason for the two different random number streams, is because you may want to randomize both independent of each other. So, for one randomly generated address stream, you can generate many different random data streams.
Second, four different random number streams could be implemented and used to create a test to randomly test the RAM. The write and read data random variables could be initialize with the same seed and a different seed used for the write and read data.
Confused yet? A review of the SynthWorks' Random_Pkg documentation may help. I will attempt to make it clear here as well. For each random number stream that you want to have concurrently generating random numbers, you need to have a variable of type RandomPType defined. The RAND_VAR instruction will have to be expanded to include an index to random number stream to be used for the random operation. The RAND_VAR instruction should also have, as parameters, the max and min values to constrain generation within. This makes the simple RAND_VAR instruction much more complicated to implement in a script as it requires the script writer to understand and manage random number generation streams. If possible, the implementer should try to avoid complication in the scripts and move it into a BFM.
In a level 2 implementation, as defined above, the randomization is done within a BFM. This can hide complication from the script system. For items to be generated randomly a variable for each can be defined giving complete sequence independence for all fields.
Lets take an ATM signalling BFM as an example. The packet fields include GFC, VPI, VCI, PTI, CLP, HEC and data. One of the modes of operation for this BFM is random generation for any combination of fields. Through the stimulus access port, registers can be written to set the BFM to operate in different modes as well as provide random generation limits. The test case writer now only has to set up the register set for the configuration and not worry about the random number sequences. The sequences of random numbers will be controlled by the implementation of the BFM randomization system.
A simple example of random generation in a BFM is presented in the packet_gen example. This is part of the current Beta VHDL Test Bench Package download: Beta Test Bench Package
In the coming weeks, I will be posting a full set of BFM's for an environment to test a simple self threading switch. This will enable example code of a complete randomization system to be presented, with enough complexity to take the example into a master BFM implementation. I am currently working on coding this example DUT and test bench. Until the example is released, there is enough information in this post to keep some busy playing with randomization.
Sckoarn