TkGate handling of VPDs is designed to be user extensible. Users
create a VPD by writing a Tcl/Tk script to define the physical
behavior of the device, and a Verilog library file containing a stub
module that interacts with the Tcl script. The Tcl/Tk script can
create its own GUI through which the user can interact.
7.1 Overview of Virtual Peripheral Device Design
Virtual Peripheral Devices are comprised of a Tcl/Tk script file, and
a Verilog stub module. The script file implements the graphical
interface for the device and handles user interaction. The Verilog
stub module encapsulates the behavior of the device into a module that
can be included in user circuits. The VPD Tcl/Tk script files are
read both from a read-only directory that is part of the TkGate
installation, and from a user-defined list of directories that can be
specified through the Library
Options dialog box. These script files are read at start-up time,
so you must restart TkGate if you change the Tcl/Tk portion of a VPD.
Since a Verilog description can contain multiple instances of a VPD, the Tcl script must be written in such a way so as to allow multiple instances of that interface. This is done by giving each instance a unique instance name. The VPD instance name is typically the same as the Verilog instance name of the stub module for the VPD. The fully instantiated Verilog instance name is dot separated path such as "top.bus1.dm1".
Because of the potential security issues and the fact the a user could
choose to use a "high" security policy, it is generally recommended
that VPD implementers should avoid use of $tkg$exec() and use
only named channels when possible.
To place your VPD files a user defined location, you must set the
paths for library and VPD files. Open the Library Options dialog box and add
the directory containing your "name.v" file to the
"Verilog Library Path", and the directory containing your
"name.tcl" file to the "VPD () File Path".
7.2 Installing VPDs
To install a VPD named name, you must install both the
"name.tcl" file containing the Tcl implementation, and
the "name.v" file containing the Verilog stub module.
You can place these files either in the TkGate home directory, or in a
user defined directory. To place them in the TkGate home directory,
put the "name.tcl" file in the "vpd"
sub-directory, and the "name.v" file in the
"vlib" sub-directory.
Command | Description |
---|---|
VPD::register name | Register a new VPD named name. Registering a VPD allows it to be posted using the Verilog $tkg$post() task. |
VPD::allow names... | Register Tcl commands that can be executed from the Verilog simulation when running TkGate with medium or lower security. The '*' character can be used as a wildcard. |
VPD::disallow names... | Register Tcl commands for which execution from the Verilog simulation is explicitly disallowed when running TkGate with medium or higher security. The '*' character can be used as a wildcard. |
VPD::isallowed name | Test a procedure name to see if it can be executed from the Verilog simulation. |
VPD::shutdownnotify script | Register a script to be executed when TkGate exits simulation mode. The registration is deleted after executing the script. |
VPD::createWindow title [options] | Create a top-level window that can be used for a VPD and return the name of the window. The window name is automatically generated. Top-level windows created with this command are automatically destroyed when TkGate exits simulation mode. A command to be executed when the simulator shuts down can be specified with the -shutdowncommand option. The shut-down command does any additional cleanup needed by the VPD besides destroying the window. |
VPD::outsignal chan var | Cause any value assigned to var to be sent to the simulator over the named channel chan. The channel name is typically formed by using the VPD instance name as a prefix and appending a local name with a dot separator. By default, values assigned to var are interpreted as a decimal integer, but Verilog format constants can also be assigned as well. For example, assigning a value of "8'h3f" would cause the value to be interpreted as the 8-bit hexadecimal value '3F'. The association between the channel and the variable is automatically deleted when TkGate exits simulation mode. |
VPD::insignal chan [options] | Register an action to be taken when data is available on the named channel chan. Channel names are chosen in the same manner as VPD::outsignal. One or more options are usually given with this command. The -command option takes a Tcl command to be executed when data is received on chan. The value received on the channel is appended to the command before execution. The -variable option indicates a variable to be assigned. Additionally, the -format switch indicates the format in which data should be reported. The format is given as a Verilog style format string such as "%d" for decimal or "%h" for hexadecimal. The association between the channel and the variable is automatically deleted when TkGate exits simulation mode. |
(1) module TTY(..., TD, RD, ...); (2) output [7:0] TD; (3) reg [7:0] RD; (4) input RD; (5) (6) // (7) // Execute the TTY::post command to start up the Tcl/Tk interface. (8) // (9) initial $tkg$post("TTY","%m"); (10) (11) ... (12) (13) // (14) // Respond to changes in the Tcl/Tk TD variable. (15) // (16) always #10 TD = $tkg$recv("%m.TD"); (17) (18) // (19) // Send updated value of RD signal to Tcl/Tk side of VPD. (20) // (21) always @ (RD) $tkg$send("%m.RD",RD); (22) (23) endmoduleVerilog modules implementing a VPD should invoke the $tkg$post() task in a Verilog "initial" block as shown at Line (9). This will cause each instance of the VPD include in the user design to execute the "TTY::post" method of the Tcl/Tk side as soon as the simulation is started. The $tkg$post() task takes two or more arguments. The first argument is the name of the VPD to be created. The name must be the name of a registered VPD. The second argument is the instance name of the VPD. It must be unique for each instance that VPD. You can use the string "%m", which will be replaced with the name of the module instance in which $tkg$post is invoked. This will guarantee a unique name for the VPD instance. Additional optional arguments of $tkg$post are passed as additional parameters to the VPD::post command.
Signals received from the Tcl side of the VPD can be handled using a Verilog "always" block as shown on Line (16). An "always" block is essentially an infinite loop executed in its own thread. The "\#10" in this example indicates a delay of 10 time units after which the $tkg$recv task will be executed to read data on the named channel "%m.TD". Again, the "%m" is replaced with the name of the current module instance. The naming convention of prefixing each channel name with "%m." ensures that each instance of the TTY device has its own set of named channels. When a value is received on the named channel, it is placed in the Verilog variable TD, which is declared as a register output.
Line 21 is an example of how to transmit a Verilog variable to the Tcl side of the VPD implementation. The "always @(RD)" causes the "$tkg$send" task to be called every time the "RD" variable changes value. This will cause the action associated with that channel by the "VPD::insignal" command to be executed in the Tcl side of the VPD implementation.
The input/output examples at Lines (16) and (21) represent the most simple and direct methods of communication between the Verilog-side and Tcl-side of a VPD implementation. You can also define more complex interactions by encoding some of the communication protocol in Verilog. For example:
(1) input CTS; (2) reg output RTS; (3) reg output [7:0] TD; (4) (5) always (6) begin (7) @ (negedge CTS); // Wait for CTS falling edge (8) # 10 TD = $tkg$recv("%m.TD"); // Get the next character data (9) # 10 RTS = 1'b1; // Indicate that data is ready (10) @ (posedge CTS); // Wait for peer to acknowledge (11) # 10 RTS = 1'b0; // Reset the protocol (12) endThis fragment encodes the protocol for receiving data from a TTY as described in the discussion on Simulation of TTYs. The lines in the "always" block perform the following functions in the protocol:
Line | Description |
---|---|
(7) | Wait for a falling edge of the "CTS" signal. This signal indicates that the peer device is ready to receive data. |
(8) | Wait 10 epochs, read the next available character from the "%m.TD" channel, and place it in the "TD" variable. |
(9) | Wait 10 epochs, then assert the "RTS" signal to indicate to the peer that new data is available on the "TD" line. |
(10) | Wait for the "CTS" line go high, indicating that the peer has read the data from "TD | ".
(11) | Wait 10 epochs, then unassert the "RTS" line to reset the protocol for the next character. |
module top; wire [7:0] TD1, TD2; wire [7:0] RD1, RD2; ... TTY tty1(..., TD1, RD1, ...); TTY tty2(..., TD2, RD2, ...); ... endmoduleincludes two instances of the TTY VPD. When this Verilog description is simulated, two windows will pop-up with the the titles "TTY top.dm1" and "TTY top.dm2". The names "top.dm1" and "top.dm2" are the instance names of the VPDs (and of their module instances). Each instance can be connected to a separate set of input and output signals.