Home Documentation: Introduction Python Perl PCI_Model Demo Future Other: Download Contact_Info |
Sorry, but these have not been updated, and currently only show
the most basic functionality.
The Python demos have been updated, and the same functionality is
also available with perl.
These are real working demos which you will find in the installation 'demo' directory.
Driver Application - Showing a basic bus controller.
Slave Application - Showing a typical memory.
Monitor Application - Displays simulation activity in a Tk window.
Demo.v - Verilog code using all 3 applications.
Resulting Display using this verilog
and these 3 scripts.
# Here it is assumed that the verilog code generates the clock and
# also has a memory. As a demo, a separate perl program implements
the memory.
# You need to add the following line to your verilog code,
# specifying the name of the perl program to run and the names
# of the verilog nets.
$scriptsim("master.pl", clk, control, address, data_in, data_out);
# Now lets create a perl program which drives the control, address,
# and (for writes) data. You must use the ScriptSim module which
# provides all the interfaces to the simulator and display:
use ScriptSim;
# The $sim object will be used later to control the simulation
$sim = new ScriptSim::Sim;
# Now lets make some magic variables which directly link to the verilog
nets.
# The number at the end of the 'tie' commands is the verilog $scriptsim
# argument number, with the first argument being argument 0.
tie $clk, ScriptSim::Arg, $sim, 1;
tie $control, ScriptSim::Arg, $sim, 2;
tie $address, ScriptSim::Arg, $sim, 3;
tie $data_in, ScriptSim::Arg, $sim, 4;
tie $data_out, ScriptSim::Arg, $sim, 5;
# Lets tell the simulator to do everything on the rising edge of the clock:
$sim->event(tied $clk, 'rising');
# Lets randomly create read, write, and idle operations on the bus.
# Lets make the address and write data random as well.
srand 0; # lets not be too unpredictable
# lets make some defines for the idle, read, write, and read_data bus cycles
($OP_IDLE, $OP_WRITE, $OP_READ, $OP_DATA) = (0 .. 3);
# initialize the nets:
$control = $OP_IDLE; # start with idle on the control
bus
$address = 0;
$data_out = 'z'; # sets ALL data bits to 'z'
$op = $OP_IDLE;
while (1) {
$sim->wait(); # wait for the next rising clock edge
# if we were doing a read, the next bus cycle is always
'read_data'
if ($op == $OP_READ) {
$op = $OP_DATA;
}
# otherwise select some operation at random
# which will be 'idle', 'write', or 'read'
else { $op = int(rand 3); }
$control = $op; # drive the control bus
# for writes, lets send some random data
if ($op == $OP_WRITE) {
$data_out = rand 0x10000;
} else {
$data_out = 'z'; # otherwise tri-state
the data bus
}
# select an address for reads or writes at random
if (($op == $OP_WRITE) || ($op == $OP_READ)) {
$address = rand 16;
}
}
You need to add the following line to your verilog code, specifying the name of the perl program to run and the names of the verilog nets.
$scriptsim("slave.pl", clk, control, address, data_in, data_out);
#
# This is the memory model
#
# It implements a memory such that:
# for writes, the write data is saved in memory
# and later returned for a read
# reading an uninitialized location returns 'x'
#
use ScriptSim;
# The $sim object will be used later to control the simulation
$sim = new ScriptSim::Sim;
# give names to the $scriptsim() arguments
tie $clk, ScriptSim::Arg, $sim, 1;
tie $control, ScriptSim::Arg, $sim, 2;
tie $address, ScriptSim::Arg, $sim, 3;
tie $data_in, ScriptSim::Arg, $sim, 4;
tie $data_out, ScriptSim::Arg, $sim, 5;
# $time holds the current simulation time
tie $time, ScriptSim::Time, $sim;
# Lets tell the simulator to do everything on the rising edge of the clock:
$sim->event(tied $clk, 'rising');
# lets make some defines for the idle, read, write, and read_data bus cycles
($OP_IDLE, $OP_WRITE, $OP_READ, $OP_DATA) = (0 .. 3);
#
# initialize all outputs
#
$data_out = 'z'; # sets ALL data bits to 'z'
#
# A hash will be used as a memory
#
# This memory is infinite size and supports any
# address or data width (even vector sizes > 64 bits)
#
while (1) {
$sim->wait();
# lets wait until resetting is done
if ($time < 10) { next }
# nothing to do for idle and DATA cycles
# except tri-state data
if ($control == $OP_IDLE or $control == $OP_DATA) {
$data_out = 'z';
} elsif ($control == $OP_READ) {
# read from the memory
# but if that location is uninitialized,
return '0'
$data_out = $mem{$address};
} else { # OP_WRITE
# simply save the write data in memory
# so it can be retrieved later on a read
$mem{$address} = $data_in;
}
}
#
# BUT WHAT ABOUT THOSE NAGGING 'X' VALUES?
#
# In the example above, 'x' is treated as '0', which is a very 'perl'
# thing to do. But checking for 'x' values is very easy. First set
up
# some 'magic' variables which have the value '1' if the net has
# 'x' or 'z' bits, otherwise the magic variables are '0'.
tie $control_x, ScriptSim::Arg, $sim, 2, "x";
tie $address_x, ScriptSim::Arg, $sim, 3, "x";
tie $data_x, ScriptSim::Arg, $sim, 4, "x";
# And then test these variables inside the preceding loop and print appropriate messages, such as:
if ($control_x) {
print "At time $time, the control bus has 'x'
bits\n";
} elsif ($address_x) {
print "At time $time, the address bus has 'x' bits\n";}
elsif ($data_x) {
} elsif ($data_x) {
print "At time $time, the data bus has 'x' bits\n";
}
use ScriptSim;
# The $sim object will be used later to control the simulation
$sim = new ScriptSim::Sim;
# give names to the $scriptsim() arguments
# some have 2 aliases. Normally getting the value on the bus
# returns a decimal number, but if
# 'x' is specified, a '1' is returned if unknown bits are present,
# otherwise 0 is returned.
# and format 'h0' says return a hex number with leading zeros
tie $clk, ScriptSim::Arg, $sim, 1;
tie $control, ScriptSim::Arg, $sim, 2;
tie $control_x, ScriptSim::Arg, $sim, 2, 'x'; # TRUE if control
bus has 'x'
tie $address, ScriptSim::Arg, $sim, 3, '%0x'; # hex with leading
zeros
tie $data, ScriptSim::Arg, $sim, 4, '%0x'; #
hex with leading zeros
# $time holds the current simulation time
tie $time, ScriptSim::Time, $sim;
# Lets tell the simulator to do everything on the rising edge of the clock:
$sim->event(tied $clk, 'rising');
# lets make some defines for the idle, read, write, and read_data bus cycles
($OP_IDLE, $OP_WRITE, $OP_READ, $OP_DATA) = (0 .. 3);
#
# infinite loop handling operations
#
while (1) {
$sim->wait();
if ($time < 10) { next } # ignore everything at
start of simulation
if ($control_x) {
printf ("%8s Command is 'x'\n", $time);
} elsif ($control == $OP_WRITE) {
printf ("%8s Write adr=%s data=%s\n", $time,
$address, $data);
} elsif ($control == $OP_DATA) {
printf ("%8s Read adr=%s data=%s\n", $time,
$address, $data);
}
}
module Demo;
wire clock;
wire [1:0] #1 op;
wire [15:0] #1 adr;
wire [31:0] #1 data;
reg clock_reg;
reg [1:0] op_reg;
reg [15:0] adr_reg;
reg [31:0] data_read;
reg [31:0] data_write;
assign clock = clock_reg;
assign op = op_reg;
assign adr = adr_reg;
assign data = data_write;
assign data = data_read;
initial begin: main_block
clock_reg = 1;
$scriptsim("monitor.pl", clock,
op, adr, data);
$scriptsim("master.pl",
clock, op_reg, adr_reg, data_write);
$scriptsim("slave.pl",
clock, op, adr, data, data_read);
end // block: main_block
// generate a clock with 10ns period
always begin: clock_gen
#5 clock_reg = 1;
#5 clock_reg = 0;
end // block: clock_gen
endmodule // Demo
Copyright 2000-2002 NelSim Software Inc. All Rights Reserved.