ASIC Verification: Hands on Training in Specman - 2

Thursday, March 13, 2008

Hands on Training in Specman - 2

Today is the last day of our Specman Tutorial. The previous section explains the complete verification process of a simple USB packet ID decoder design. Topics discussed are design specification, verification components, verification plan, and test plan. This section completes the example with an explanation of the actual 'e' code for each component required for the verification of the PID Decoder design.

Defining the packet data item

This section shows the 'e' code for the packet data item.

//==========================================================================

<'
-- Define an enumerated type packet_id.
-- The token type is either IN, OUT or SETUP

type
packet_id : [IN, OUT, SETUP, ERR_PID];

-- Define a struct called hub_packet

struct hub_packet
{

-- Define a field syn; The value of sync field is constant

%syn : uint(bits:32);
-- SYNC pattern is 32'h8000_000;
keep soft syn == 32'h8000_0000;
--Define a field pid
%pid : packet_id;

pid_type : uint(bits:8);
-- Endpoint Number
%ep_no : uint(bits:4);
keep soft ep_no in [1..15]; -- Device address
%dev_add : uint(bits:7);

keep soft dev_add == 10;
%data : list of uint(bits:16); -- Packet length pid=8bits; dev_add=7bits; ep_nu=4bits;
keep pid == IN => pid_type == 8'h69;

keep pid == OUT => pid_type == 8'hE1;

keep pid == SETUP => pid_type == 8'h2D;
keep pid == ERR_PID => pid_type == 8'h11;
// Pid error
%crc_5 : uint(bits:5);

keep crc_5 == 5'b10101;

// Keep the CRC fixed as of now
%eop : byte;
keep soft eop == 8'hFE;

event coverage_chk;

};

extend sys
{
packets : list of hub_packet;
keep packets.size() == 2;
};
// End of extend
'>
//==========================================================================

Defining the Transaction Generator

This section shows the 'e' code for the Transaction generator.
//==========================================================================
-- Transaction Generator
//==========================================================================

<'
import hub_packet;
import hub_driver;
unit hub_txgen
{
// Instantiate the struct hub_packet, the static verification object
hub_object : hub_packet;

// Instantiate the unit hub_driver, the dynamic verification object
hub_driver : hub_driver is instance;
keep hub_driver.hdl_path() == "~/pid_dec_TB";

// Define a positive edge of the clock
event posedge_clk is rise('pid_dec_TB.clock_in') @sim;

// Define a TCM, gen_transaction which will start another TCM
gen_transaction()@ posedge_clk is
{
// Start to generate and drive the USB packet
start hub_driver.gen_and_drive();
};
// End of gen_transaction
};
// End of unit
'>
//==========================================================================

Defining the Hub driver

This section shows the 'e' code for the hub driver.
//==========================================================================
// Hub Driver
//==========================================================================
<'
import hub_packet;
-- import the hub_packet here

unit hub_driver
{
!current_packet : hub_packet;
!delay : uint;
keep soft delay in [1..10];
no_of_packets : uint;

event rise_clk is rise ('clock_in') @sim;
event fall_reset is fall ('reset_in') @sim;
event sync_on_bus;
event pid_on_bus;
event packet_ended;

sent_signals() @rise_clk is
{
'rx_last_byte' = 0;
'rx_bs_err' = 0;
'rx_valid' = 0;

wait @sync_on_bus;
'rx_valid' = 1;

wait @pid_on_bus;
'rx_last_byte' = 1;
'rx_valid' = 1;

wait;
'rx_last_byte' = 0;
'rx_bs_err' = 0;
'rx_valid' = 0;
};
// End of sent_signals() method

gen_and_drive () @ rise_clk is
{
for i from 0 to no_of_packets-1
{
gen delay;
wait [delay];
gen current_packet;

wait true ('reset_in' == 0);
drive_packet (current_packet);
};
-- end of for loop
};
-- end of generate_and_drive method

drive_packet (packet : hub_packet) @rise_clk is
{
var packet_packed : list of uint(bits:16);
emit packet.coverage_chk;

packet_packed = pack (packing.low, packet.syn[15:0], packet.syn[31:16], packet.ep_no[0:0], packet.dev_add[6:0], packet.pid_type, packet.crc_5, packet.ep_no[3:1],packet.eop);

for each
(packet_16bit) in packet_packed
{
'data_in' = packet_16bit;
start sent_signals();
wait cycle;

if('data_in' == 16'h8000)
{
emit sync_on_bus;
};

if('data_in'[15:8] == 8'h69 || 'data_in'[15:8] == 8'hE1 || 'data_in'[15:8] == 8'h2D || 'data_in'[15:8] == 8'h11)
{
emit pid_on_bus;
};
};
emit packet_ended;
};
-- end drive_packet
};
'>
//==========================================================================

Defining the hub output monitor

This section shows the 'e' code for the hub's output monitor.
//==========================================================================
// Hub output monitor
//==========================================================================
<'
import hub_env;
unit hub_op_mon
{
!rcv_packet : hub_packet;
rcv_delay : uint;

keep soft rcv_delay == 10;

event posedge_clk is rise ('clock_in') @sim;
event in_token_rcvd is rise ('in_token_out')@ posedge_clk;
event out_token_rcvd is rise ('out_token_out')@ posedge_clk;
event setup_token_rcvd is rise ('setup_token_out')@ posedge_clk;

output_mon() @ posedge_clk is
{
while(TRUE)
{
wait cycle;
if(('in_token_out' == 1 ) || ('out_token_out' == 1) || ('setup_token_out' == 1) || ('pid_error_out' == 1) )
{
if('in_token_out' == 1) then
{
out("IN TOKEN RECEIVED SUCCESSFULLY at ", sys.time);
}
else if ('out_token_out' == 1) then
{
out("OUT TOKEN RECEIVED SUCCESSFULLY at ", sys.time);
}
else if('setup_token_out') then
{
out("SETUP TOKEN RECEIVED SUCCESSFULLY at ", sys.time);
}
else
{
out("PID Error is Occured at ", sys.time); };};};};};
'>
//==========================================================================

Defining the coverage item

This section shows the 'e' code for the coverage item.
//==========================================================================
// Coverage
//==========================================================================
<'
import
hub_env;
import
hub_packet;

extend
hub_packet
{
cover coverage_chk using
count_only,
radix = HEX,
weight = 10 is
{
item pid;
item
ep_no;
cross
pid, ep_no;
};
// End of cover
};
// End of extend
'>
//==========================================================================

Defining the Top level hierarchy


This section shows the 'e' code for the top level verification hierarchy.
//==========================================================================
-- Top level of 'e' verification hierarchy
//==========================================================================

<'
import
hub_packet;
import hub_driver;
import tx_gen;
import hub_cover;
import hub_output_mon;

unit hub_env
{
-- Instantiate hub_tx_gen
hub_tx_gen : hub_txgen is instance;

// Instantiate hub_driver

hub_driver : hub_driver is instance;
keep hub_driver.hdl_path() == "~/pid_dec_TB";

-- Instantiate hub_output_monitor
hub_op_monitor : hub_op_mon is instance;
keep hub_op_monitor.hdl_path() == "~/pid_dec_TB";

event posedge_clk is rise('pid_dec_TB.clock_in') @sim;

// Define a TCM, start_tb which will start all the TCMs
start_tb() @ posedge_clk is
{
start hub_op_monitor.output_mon();
// start output mon
start hub_tx_gen.gen_transaction();
// start method

wait[1200];
stop_run();
// call method
};
// End of start_tb()
};
// End of unit

-- Create an instance of hub_env object in top level
extend sys
{
hub_env : hub_env is instance;
run() is also
{
start hub_env.start_tb();
};
// End of run()
};
// End of extend

extend sys
{
setup() is also
{
set_config( print, scale, ps);
set_config( cover, mode, on);
};
// End of setup()
};
// End of extend

'>
//==========================================================================

Test case 1

This section shows the 'e' code for the test case.
//==========================================================================
//Test

//==========================================================================
<'
import
hub_env;

extend hub_packet
{


keep soft dev_add in [1..10];

keep soft pid == select
{
20: [IN];
30: [OUT];
20: [SETUP];
20: [ERR_PID];
};

extend sys
{
keep hub_env.hub_driver.no_of_packets == 5 ;
};
'>
//==========================================================================

Procedure to run the test case

Create the simulation directory
mkdir sim

Go to the simulation directory
cd sim

Create the work library
vlib work


Create the stubs file in hdl directory
$SPECMAN_HOME -command "write stubs -verilog ../hdl/specman.v"


Compile the stubs and design files
vlog -work ./work ../hdl/specman.v
vlog -wrok ./work ../hdl/pid_dec.v
vlog -wrok ./work ../hdl/pid_dec_TB.v

Run the simulation
Invoking Specman and Modelsim
$SPECMAN_HOME../sn/bin/specview -p "load ../e/test1; test" vsim -pli ../../libmti_sn_boot.so -lib ./work pid_dec_TB &

//==========================================================================


No comments: