Writing testbench tools. Suggestions?

O

o pere o

I am trying to write some helper tools to generate testbench signals.
For instance, I have written this data_stream generator:

procedure data_stream(
signal y : out std_logic; -- Output signal
constant data : std_logic_vector; -- Data, e.g. "11110101"
constant bit_period : time; -- Duration of each bit
constant start_time : time := 0 ns; -- Initial time offset
constant def_out : std_logic := 'U') is
begin
y <= def_out;
wait for start_time;
for ix in data'left to data'right loop (*)
y<=data(ix);
wait for bit_period;
end loop;
y <= def_out;

(*) actually I look if data'left < data'right and iterate "to" or
"downto" otherwise. (Could probably be improved)

Using this procedure, in the test bench I can build:

data_stream(slv(1),"0011",1 us, 0 us,'Z');
data_stream(slv(0),"1101",1 us, 5 us,'Z');

Now, I would like to merge each signal onto one. Thanks to the default
value of 'Z' this is simple. For instance, in the test bench, this code
works fine:

join: for i in slv'range generate
tot <= slv(i);
end generate;
y <='U' when tot='Z' else tot;

where the 'U' could be changed to whatever makes sense. Now, I would
like to have the last lines in a _function_ or _procedure_.
Unfortunately, I only have been able to bring this together, which works
but looks ugly compared to the 4 lines before:

procedure signal_join(
signal y : out std_logic;
constant slv : std_logic_vector;
constant def_out : std_logic := 'U') is

variable tot: std_logic;
begin
tot := 'Z';
join: for i in slv'range loop
if slv(i)/='Z' then
tot := slv(i);
end if;
end loop;
if tot='Z' then
y<=def_out;
else
y<=tot;
end if;
end;

I would appreciate any suggestion on this. Especially, if I am making
big mistakes! Furthermore, I have been unable to find functions that
ease the generation of test signals, say to simulate some bursts of an
SPI master or whatever, which is why I am writing this stuff. Any
pointers on this?

Pere
 
K

KJ

When writing test benches for something that attaches to the top level of adesign, I find it best to simply model the physical part on the actual board. When you do that, you will start building up a library of part models that can be reused down the road. The verification of the part model is done by verifying to the data sheet. Your design then gets verified by usingyour validated part model. Will lead to less surprises when you power up your board. Since you mentioned emulating a SPI master you are likely in this situation.

If writing testbenches for internal modules, you will find it can be productive to standardize on an interface protocol such as Avalon or Wishbone. One benefit will be that testbench writing will be more standardized.

Kevin Jennings
 
O

o pere o

When writing test benches for something that attaches to the top level of a design, I find it best to simply model the physical part on the actual board. When you do that, you will start building up a library of part models that can be reused down the road. The verification of the part model is done by verifying to the data sheet. Your design then gets verified by using your validated part model. Will lead to less surprises when you power up your board. Since you mentioned emulating a SPI master you are likely in this situation.

If writing testbenches for internal modules, you will find it can be productive to standardize on an interface protocol such as Avalon or Wishbone. One benefit will be that testbench writing will be more standardized.

Kevin Jennings
I feel this is exactly what I am doing: My design will talk to an SPI
master, hence I am generating the waveforms that the master is expected
to give, according to the datasheet.

In my post, I included some code that allows me to build an arbitrary
burst (usable for clock, data, whatever). The question remains: what is
the best way to combine these individual bursts onto a single signal, so
that I can model an arbitrary number of occurrences of each stream at
arbitrary time points?

Pere
 
K

KJ

I feel this is exactly what I am doing: My design will talk to an SPI
master, hence I am generating the waveforms that the master is expected
to give, according to the datasheet.

It is not evident in what you posted that there would be any connection with the datasheet at all. Not a very obvious one at least. You don't want to make validating the model to be an even bigger task than using the model to validate your design.
In my post, I included some code that allows me to build an arbitrary
burst (usable for clock, data, whatever).

Not really. Most parts respond to signals from other external parts (i.e. a processor interface to an FPGA). What you have shown is something where you give it a list of outputs and you crank them out at some fixed interval.. In effect it is nothing more than this:

xyz <= '1', '0' after bit_period, '1' after 2*bit_period, '1' after 3*bit_period ...

While use of your procedure would be a better shorthand than the above lineof code, there really isn't much call for the above line of code in the first place so your shorthand procedure wouldn't have much utility.

A SPI master model would instead respond to some higher level control (i.e.a model for the code running in a processor) and then chunk out the bits and clock as they are specified in the datasheet. So a snippet of the SPI master for a processor with a SPI master might look like this...

process
begin
Spi_Cs_n <= '1';
Spi_Sclk <= '0';
wait until Spi_Master_Write_This_Out'event; -- Some example of this SPI master process waiting for something to do
Spi_Cs_n <= '0';
wait for Spi_Cs_To_Sclk_Time; -- Spec'ed on the datasheet
for i in Spi_Data_To_Write'low to Spi_Data_To_Write'high loop
Spi_Sclk <= '1', '0' after Spi_Clock_Period/2; -- Note: Spi_Clock_Period could be a signal so you can vary the Spi clock period during the sim
Spi_Mosi <= Spi_Data_To_Write(i) after Tco; -- Models the clock to output delay per the datasheet, in case that ends up mattering
wait until Spi_Sclk'falling edge Spi_Sclk;
wait for Spi_Clock_Period/2;
end loop;
Spi_Cs_n <= '1';
wait for Spi_Cs_Inactive_To_Spi_Cs_Active_Again; -- Again, likely spec'ed on datasheet
end process;
The question remains: what is
the best way to combine these individual bursts onto a single signal, so
that I can model an arbitrary number of occurrences of each stream at
arbitrary time points?

I don't have an answer for that question since I don't think it's the rightapproach. What physical parts can you think of that would have in their datasheet listed something where it shoots out a particular pattern at some periodic rate? Can you think of more than one part? However, if you
create a model of an actual part instead, then you'll find that you don't need to answer your stated question in order to get a working and reaonably
realistic model. You might not agree, and that's fine, I'm just putting inmy two cents and giving you an example to consider instead.

Kevin Jennings
 
O

o pere o

It is not evident in what you posted that there would be any connection with the datasheet at all. Not a very obvious one at least. You don't want to make validating the model to be an even bigger task than using the model to validate your design.


Not really. Most parts respond to signals from other external parts (i.e. a processor interface to an FPGA). What you have shown is something where you give it a list of outputs and you crank them out at some fixed interval. In effect it is nothing more than this:

xyz <= '1', '0' after bit_period, '1' after 2*bit_period, '1' after 3*bit_period ...

True. A simple helper function for this is exactly the goal that I had
in mind.
While use of your procedure would be a better shorthand than the above line of code, there really isn't much call for the above line of code in the first place so your shorthand procedure wouldn't have much utility.

Well, I have had the need to generate arbitrary data bursts at arbitrary
time positions quite often... Of course, a model for the generator of
these bursts gives more information... As always, it is a balance!
A SPI master model would instead respond to some higher level control (i.e. a model for the code running in a processor) and then chunk out the bits and clock as they are specified in the datasheet. So a snippet of the SPI master for a processor with a SPI master might look like this...

process
begin
Spi_Cs_n <= '1';
Spi_Sclk <= '0';
wait until Spi_Master_Write_This_Out'event; -- Some example of this SPI master process waiting for something to do
Spi_Cs_n <= '0';
wait for Spi_Cs_To_Sclk_Time; -- Spec'ed on the datasheet
for i in Spi_Data_To_Write'low to Spi_Data_To_Write'high loop
Spi_Sclk <= '1', '0' after Spi_Clock_Period/2; -- Note: Spi_Clock_Period could be a signal so you can vary the Spi clock period during the sim
Spi_Mosi <= Spi_Data_To_Write(i) after Tco; -- Models the clock to output delay per the datasheet, in case that ends up mattering
wait until Spi_Sclk'falling edge Spi_Sclk;
wait for Spi_Clock_Period/2;
end loop;
Spi_Cs_n <= '1';
wait for Spi_Cs_Inactive_To_Spi_Cs_Active_Again; -- Again, likely spec'ed on datasheet
end process;

Now I see your point clearer. However, I will still need to to generate
the Spi_Master_Write_This_Out'event at an arbitrary time instant. Then I
will need to be able to change the data that is being written, depending
on the particular data burst. This can be done, and is probably the way
to go if you want maximum flexibility.

However, if I just need a couple of bursts, my quick-and-dirty approach
gives me a suitable waveform without having to go into the SPI
details... Of course your approach gives more insight although at a
higher initial coding cost.

I don't have an answer for that question since I don't think it's the right approach. What physical parts can you think of that would have in their datasheet listed something where it shoots out a particular pattern at some periodic rate? Can you think of more than one part? However, if you
create a model of an actual part instead, then you'll find that you don't need to answer your stated question in order to get a working and reaonably
realistic model. You might not agree, and that's fine, I'm just putting in my two cents and giving you an example to consider instead.

I really appreciate your inputs and thank you for your time. My effort
is just to have something a little more elaborate than the practice of
just drawing waveforms in a waveform editor.

The SPI example I mentioned is however just one of the inputs of my
current design. The other will be a physical IEEE 802.15.4 frame. Here,
I am currently able to generate a burst corresponding to some data,
following the original idea I posted. Again, a simple combination of
individual signals might do the job of simulating a typical transaction.
Perhaps I can come up with something similar as the example you posted...

Pere
 
P

Paul Uiterlinden

o said:
I am trying to write some helper tools to generate testbench signals. [snip]

I would appreciate any suggestion on this. Especially, if I am making
big mistakes! Furthermore, I have been unable to find functions that
ease the generation of test signals, say to simulate some bursts of an
SPI master or whatever, which is why I am writing this stuff. Any
pointers on this?

I would suggest reading a book like "Writing Testbenches" by Janick Bergeron
and look at the client/server model suggested there.
 
O

o pere o

o said:
I am trying to write some helper tools to generate testbench signals. [snip]

I would appreciate any suggestion on this. Especially, if I am making
big mistakes! Furthermore, I have been unable to find functions that
ease the generation of test signals, say to simulate some bursts of an
SPI master or whatever, which is why I am writing this stuff. Any
pointers on this?

I would suggest reading a book like "Writing Testbenches" by Janick Bergeron
and look at the client/server model suggested there.

Thanks for this pointer. I just had the opportunity to have a quick look
at this book and it looks *very* promising.

OTOH, I just keep wondering why there is so little material on this
subject out there... Especially considering that a lot of the
development effort is spent here -Janick Bargeron even puts figures into
this in the book's preface: reportedly, 60% to 80% of the design effort
goes into verification...

Pere
 
A

Andy

I would suggest reading a book like "Writing Testbenches" by Janick Bergeron and look at the client/server model suggested there. -- Paul Uiterlinden www.aimvalley.nl

Excellent book recommendation! However, the second edition was revised to cover more SystemVerilog, at the expense of VHDL/Verilog. The first edition (light blue cover, rather than red for the 2nd edition) is just VHDL & verilog, and more appropriate if you are working on VHDL testbenches.

Jim Lewis/Synthworks has an excellent advanced VHDL verification class, andhis freely available Open Source VHDL Verification Methodology (OSVVM.org)is a huge step in the right direction. Other than being a very satisfied student, I have no connection with Synthworks.

The use of protected types/methods is extremely powerful for testbenches (too bad they are not synthesizeable yet). The constrained randomization and coverage packages in OSVVM provide great examples to illustrate some of theuses of protected types.

Andy
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,571
Members
45,045
Latest member
DRCM

Latest Threads

Top