Previous

Performing Functional Simulation

Perform functional simulation before design implementation to verify that the schematic you designed is logically correct. All components in the Calc design, even the non-schematic LogiBLOX module, have built-in simulation models, reducing the amount of pre-processing.

Using CONCEPT2XIL

The CONCEPT2XIL program both translates the design for implementation and creates a simulatable Verilog netlist. The latter only occurs after running CONCEPT2XIL if the design contains schematic components only. If the design contains any “black boxes” with no underlying schematics, such as VHDL code synthesized and compiled down to an NGO file, functional simulation can only occur after execution of the program NGDBuild. In any case, NGDBuild executes during implementation. The Calc schematic does not contain any non-schematic blocks, so proceed directly to simulation.

At the UNIX prompt in the main design directory, enter the following command.

concept2xil -sim_only -rundir -family \
xilinx.func_sim xce4000e calc

If compiling this for another family, substitute the appropriate family name for “xce4000e” (such as xce9000, xce5200, xce3000, or xce4000x for the 9500,5200,3000A,or 4000EX, respectively).

The -sim_only option causes CONCEPT2XIL not to create an EDIF file, which it normally does so the Xilinx Design Implementation Tools can implement the design.

After CONCEPT2XIL completes, it creates a xilinx.func_sim directory by default, which contains all the output files (except concept2xil.log). The generated output files are a V file (Verilog file that declares the global GSR and GTS signals for a 4000E(X) part), and a VF file (list of paths to all the Verilog files that comprise the design).

Either HDL Direct creates the Verilog files that the VF file points to, or those files are part of the Xilinx-supplied Verilog library of components for all the Xilinx primitives and macros (located in $XILINX/cadence/data/family. A few entries from a sample VF file follow.

   /home/jeremy/m1/cadence_m1tut/calc/logic/verilog.v
   /home/jeremy/m1/cadence_m1tut/alu1/logic/verilog.v
   /xilinxM1/cadence/data/xce4000e/adsu4/logic/verilog.v
   /home/jeremy/m1/cadence_m1tut/andblk2/logic/verilog.v
   /xilinxM1/cadence/data/xce4000e/fd4re/logic/verilog.v

Later, when Verilog-XL executes, the “-f” option causes Verilog-XL to read in all the verilog.v files referenced by calc.vf.

Creating a Verilog Test Fixture

Now that CONCEPT2XIL has created the necessary files, you must create a Verilog test fixture to properly force the inputs for the simulation. The tutorial (calcf.stim) directory includes a sample test fixture, which you modify for the functional simulation. The next subsections provide an analysis of the various parts of the test fixture.

Timescale

Include a `timescale directive near the top of the file. The `timescale directive declares the time unit used, followed by the precision. Smaller precisions result in longer run times, but can provide more accurate results. The following shows a typical `timescale directive.

`timescale 1 ns/100 ps

NOTE

You do not have to use a smaller precision than 1 ps in a timing simulation because the delay numbers given in the .sdf file are not more precise than that. In functional simulation, it is essentially irrelevant (except for longer simulation run times) so long as it is more precise than the time unit (1 ns).


Test Fixture Module Declaration

Use the following test fixture module declaration with Calc.

   module test;
    
      // Design inputs
      reg       notgblreset;
      reg [7:0] switch
    
      // Design outputs
      wire       ofl;
      wire       a, b, c, d, e, f, g;
      wire [3:0] guage;
      wire [3:0] stackled;
    
      // Instantiated design with an instance name of "uut"
      calc uut (.ofl (ofl), .notgblreset (notgblreset), .g (g),
                .f (f), .e (e), .d (d), .c (c), .b (b), .a (a),
                .guage (guage), .stackled (stackled),
                .switch (switch));

The test fixture itself is considered the top-level module (module test;), and the design is considered a component to instantiate (calc uut (...)). All the inputs and outputs of the Calc module connect to signals in the test fixture with the same name (although the name can differ). The inputs of the Calc module (switch and notgblreset) connect to signals in the test fixture of type “reg” because the test fixture stimuli drives the signals. The signals hold their values until driven differently. Outputs go to signals of type “wire.”

The “calc uut” line is the instantiation of the Calc design. The string “uut” is an instance name (any name will do, so long as it conforms to Verilog naming conventions). Generalize the string .ofl (OFL) to mean .port_name (signal_name), where port_name is the name of the I/O port in the Calc module, and signal_name is the name of the signal in the test fixture to which it connects.

Displaying Values

The output signal values of the Verilog-XL simulator can display in the UNIX xterm window where you invoked Verilog-XL, or you can save the signals in a waveform database for display in SimWave later on.

If you want to display the signal values in the xterm window, use a $monitor statement to define a list of signals to display, as shown in the following example.

   $monitor("%t",$realtime,, "| %b", notgblreset,, "%b", switch[7],, "%b", switch[6:0],, "%b", uut.clk,, "| %b", uut.exec,, "| %h", uut.aluval[3:0],, "%h", stackled[3:0]);

The $monitor statement outputs the signal values whenever an event occurs on one of the listed signals (one of the signals toggles). The $realtime function returns the system time as a real number; system time displays via the $timeformat function. A typical $timeformat statement follows.

$timeformat(-9,3,"ns",12);

This $timeformat statement display the system time in units of 1E-9, to 3 decimal digits precision, to end with the string “ns,” and to display at least 12 digits.

The sample Calc test fixture file also uses several $display statements to serve as a header for your output.

Opening a Waveform Database for SimWave

If you use SimWaves to display the output waveforms, make the test fixture write out a waveform database (.shm file), which SimWave can read in later on. Use the $shm_open statement with the following syntax.

$shm_open(“calc.shm”);

You can use any directory and file name as a target. You must include the quotation marks.

In addition, you need a $shm_probe statement indicating which signals to write to the database. An example $shm_probe statement follows.

$shm_probe("AS")

The “AS” argument includes all signals in the test fixture and all instantiations below it (including Calc) in the database, except for the internal signals of library cells.

Defining a Clock

Because most designs have an external clock signal coming in, include a block in the test fixture that generates the pulses without having to manually toggle the clock signal back and forth.

Theoretically, you do not have to create a clock for the Calc schematic because it already has the OSC4 component (inside CLOCKGEN) generating a 15Hz signal. However, the OSC4 component also has a 8MHz pin, and therefore the OSC4 Verilog model has to simulate the toggling of the 8MHz pin (even though the Calc schematic does not use it). Verilog-XL takes an extraordinary amount of time to simulate a 15Hz clock signal. The osc4.v module, located in $XILINX/cadence/data/verilogxce4000e, has a `timescale precision of 100ps, so to make it to the first edge of the 15Hz clock, set at 3.33E10 ps (.0333 seconds), requires 3.33E10 / 100 = 333 million simulation events.

Therefore, define a clock in the test fixture that clocks much slower, and forces its values onto the CLK net, overriding the OSC4 clock. Typically, you define a clock with an “always” block.

always
begin
#10 clock = ~clock;
end


NOTE

Do not use this example in the Calc test fixture; it is only an general example. This previous statement assigns “clock” the value of itself negated, but only after waiting 10 time units (assuming `timescale 1ns, this would mean 10 ns). So if clock is initially 0, then after assigning ~clock to 10ns clock, the value resets as 1. Because this is in an always block, it continuously loops around until simulation halts.


Notice, however, the previous analysis assumed an initial value of 0. You must include a statement inside an “initial” block that defines the value at time 0ns.

initial
begin
clock = 0;

The above assumes a port “clock” on the design, but that is not the case in the Calc design (because OSC4 generates the clock internal to the device). Because of this, you need the following in the test fixture.

// Create a clock for the Oscillator
always
begin
force uut.clk = 0;
#50 force uut.clk = 1
#50;
end

The “always” block immediately forces uut.clk to 0, and then forces uut.clk to 1 after 50ns. The block then pauses for 50ns before looping around to force uut.clk back to 0, creating a clock of period 100ns that begins with 0 at 0ns and has its first rising edge at 50ns.

In the statement “#50 force uut.clk = value” you need the keyword “force” because “force” always overrides the current value on a signal. Because OSC4 still drives the signal, the “force” command prevents contention on the signal. Additionally, you must use the syntax “uut.clk.”If the referenced signal does not exist in the test fixture (or the module where the assignment occurs), then you must specify the hierarchy of the signal by referencing the instance name contained it, followed by a period and the signal name.

Asserting the Global Set/Reset

In a netlist for a 4000E(X) or a Spartan design that uses STARTUP, the Global Set and Reset (“GSR”) net that leads to every flip-flop connects to the STARTUP block implicitly. Toggle the signal that controls the GSR pin to begin simulation and to simulate resetting the device. Even if your design does not utilize the STARTUP block, pulse the GSR line once at the beginning of simulation to simulate the initial behavior of the device.

In the Unified Library functional simulation, you must connect the logic that controls the GSR pin to the underlying global GSR net by using a `define directive.

`define GSR_SIGNAL testfixture.design.signal_on_GSR_pin

Here testfixture is the name of the test fixture module, design is the instance name of the instantiated design, and signal_on_GSR_pin is the net name that sources the STARTUP GSR pin.

The following connects the GSR pin to the GSR net in the Calc design.

`define GSR_SIGNAL test.uut.gblreset

Using “notgblreset”; is not necessary. Instead, you must use the signal that actually hooks up to the STARTUP GSR pin, not the signal that comes in from the IPAD. If you use the signal that comes in from the IPAD, the polarity of GSR in simulation reverses because an inverter exists between the signal NOTGBLRESET and the GSR pin.

However, if you do not use the STARTUP block, you must directly drive the GSR. You can again use the `define directive to define a GSR signal, even though it does not explicitly exist in the schematic or HDL code. To do this, you define a dummy "reg test.GSR" (assuming the test fixture module name is "test," recommended if you want to reuse the test fixture with post-NGDBuild simulation). You then need to use the `define to hook it up to the verilog models, and drive "test.GSR" in your stimulus.

`define GSR_SIGNAL test.GSR
reg GSR
.....
.....
initial
begin
test.GSR=1; // Begin Global Reset
#300 test.GSR=0; // End Global Reset
//assign inputs now

For the 5200 family (which has a STARTUP symbol available), use the following.

`define GR_SIGNAL testfixture.design.signal_on_GR_pin

If you use this statement for the Calc design, and you use STARTUP as discussed in previous sections, then make signal_on_GR_pin “gblreset. ”If you do not use STARTUP, then you must define a dummy signal, as discussed before.

For the 9500 family, use the following.

`define PRLD_SIGNAL test.PRLD
reg PRLD; //no 9K STARTUP, so use this dummy
.....
.....
initial
begin
test.PRLD=1; // Begin Global Reset
#300 test.PRLD=0; // End Global Reset
//assign inputs now

For the 3000A family, use the following.

`define GR_SIGNAL test.GR
reg test.GR;

Use a similar procedure as described previously for the 9500. GR on a 3000A is active-low.

Assigning Values to the Inputs

In the test fixture, you must add a series of stimuli to all the inputs. Typically, you place this series in an “initial” block, and you place timing controls to specify when the inputs change. If one or more of the inputs is periodic (for example, the clock), then you can instead put that signal in an “always” block, as described previously for the clock signal.

The following shows a series of assignments that work with the Calc design (comments appear after “//”).

   initial
   begin
     //Initialize Input Signals
                                 //time=0
          switch[7]   = 1'b1;
          switch[6:0] = 1'h0;
    
          notgblreset = 1'b0 ;   //Apply Global Reset
    
        #200                     //time=200
          notgblreset = 1 ;      //End Reset
          switch[6:0] = 7'b1100001;
     
        #500                     //time=700
          switch[7]   = 0;
          switch[6:0] = 7'b0001101;
     
        #200                     //time=900
          switch[7]   = 1;
     
        #300                     //time=1200
          switch[7]   = 0;
          switch[6:0] = 7'b1111011;
     
        #200                     //time=1400
          switch[7]   = 1;
     
        #400                     //time=1800
          switch[7]   = 0;
          switch[6:0] = 7'b0111111;
     
        #200                     //time=2000
          switch[7]   = 1;
     
        #300                     //time=2300
          switch[7]   = 0;
          switch[6:0] = 7'b1111011;
     
        #200                     //time=2500
          switch[7]   = 1;
     
        #300                     //time=2800
          switch[7]   = 0;
          switch[6:0] = 7'b1010000;
     
        #200                    //time=3000
          switch[7]   = 1;
    
        #200 $stop;             //time=3200
    end

Begin by forcing the “notgblreset” signal low, then assert it high after 200ns. In the Calc design the “notgblreset” net goes through an inverter, which makes the GSR active low, but in the 4000E(X) family GSR is normally active high.

The “switch” signal, the main input (it inputs the opcode and the data), gets assigned various values to test its various functions. See the Hardware Debugger Guide for a complete description of the Calc design, and to understand how the “switch” settings function. Specify the signal “switch[7]” independently only for clarity; it has a separate function (execute).

Time is cumulative when you use the (#xxx) notation (the sequence “#20 statement1; #30 statement2;” means execute statement1 at 20ns, execute statement2 at 50ns).

At the end of the block, you can put a $finish or a $stop. A $finish causes Verilog-XL to terminate. A $stop causes Verilog-XL to terminate simulation from the test fixture, but go into “interactive mode.” See your Cadence documentation for information about using interactive mode.

Invoking the Verilog-XL simulator

After creating the test fixture and running CONCEPT2XIL, you can go into the Verilog-XL simulator. From the xilinx.run directory, invoke the UNIX command line.

verilog +gui calcf.stim calc.v -f calc.vf


NOTE

The +gui switch invokes the Verilog-XL GUI. If you do not have this feature, omit using this switch.


CONCEPT2XIL created the files calc.v and calc.vf. The calcf.stim file is user-generated (a copy exists in the tutorial design directory; copy it to the xilinx.func.sim directory to use it).

After entering the previous command line, the following displays (only the first portion of simulation appears here).

Highest level modules:
    test
    alias_vector
    alias_bit
    
                  Inputs       Internal  Outputs
                 (Binary)      Signals   (HEX)
    ==========|===============|=======|==========
              | n s sssssss c | e s p | a s
      Time    | o w wwwwwww l | x t u | l t
              | t i iiiiiii o | e a s | u a
       in     | g t ttttttt c | c c h | v c
              | b c ccccccc K |   k   | a k
       ns     | l h hhhhhhh   |   e   | l l
              | r             |   n   |  e
              | e 6543210     |       |  d
              | s             |       |
              | e             |       |
              | t             |       |
    ==========|===============|=======|==========
      0.000ns | 0 1 0000000 0 | x x x | x x
      0.100ns | 0 1 0000000 0 | x x x | 0 x
      0.200ns | 0 1 0000000 0 | 0 x x | 0 x
      0.300ns | 0 1 0000000 0 | 0 0 0 | 0 x
      0.400ns | 0 1 0000000 0 | 0 0 0 | 0 f
     50.000ns | 0 1 0000000 1 | 0 0 0 | 0 f
    100.000ns | 0 1 0000000 0 | 0 0 0 | 0 f
    150.000ns | 0 1 0000000 1 | 0 0 0 | 0 f
    200.000ns | 1 1 1100001 0 | 0 0 0 | 0 f
    250.000ns | 1 1 1100001 1 | 0 0 0 | 0 f
    250.000ns | 1 1 1100001 1 | 1 0 0 | 0 f
    250.000ns | 1 1 1100001 1 | 0 0 0 | 0 f
    300.000ns | 1 1 1100001 0 | 0 0 0 | 0 f
    350.000ns | 1 1 1100001 1 | 0 0 0 | 0 f
    400.000ns | 1 1 1100001 0 | 0 0 0 | 0 f
    450.000ns | 1 1 1100001 1 | 0 0 0 | 0 f
    500.000ns | 1 1 1100001 0 | 0 0 0 | 0 f

$display statements specified the header (time, clock, notgblreset, and the rest.) in the test fixture. The “clock” corresponds to uut.clk, now overridden with “force” statements in the test fixture. The simulation outputs are aluval[3:0] and stackled[3:0]. The following intermediate nodes display: exec, stacken, and push. Undefined states are marked with an “x.”

Using SimWave

Cadence shipped the cWaves waveform viewer up to and including its 9604 release. Starting with the 97A release, it replaced cWaves with SimWave. This tutorial uses SimWave to display the waveforms.

Invoking SimWave

To invoke SimWave, follow these steps.

  1. Enter the following at the UNIX prompt (in the xilinx.run directory, or wherever the .shm file resides).

    simwave calc.shm &

    In Verilog-XL you can instead select the Waveform View button from the tool bar.

    This launches the SimWave GUI.

  2. From the SimWave GUI, select Edit Add Signals.

  3. Double-click the instance “test” in the Instance window. If using your own test fixture, this is the instance name of your top-level test fixture module.

  4. All the signals that occur inside the test fixture now display in the Signals window. Click on the “notgblreset” signal.

  5. Click on the Display Signals button on the toolbar (it has a picture of a waveform, next to Close). The waveform for this signal appears in the SimWave display. The label shown for this signal is “test.notgblreset,” the full hierarchial name of the signal (only part of the name can display). Highlight the “stackled” bus in the Signals window, and again click on the Display Signals button. This signal now displays below “notgblreset.”

    Figure 9.41 SimWave Browser/Display Tool

    If you see only flat lines, as shown in the “SimWave Browser/Display Tool” figure, then do a View Zoom Fit in the main SimWave GUI.

  6. Double-click on “uut” in the Instances window (or whatever the instance name is of the “calc” module in the test fixture). All the signals inside the top-level schematic of Calc appear in the Signals window. To select several signals at once, hold down the Control key and highlight the following signals in the Signals window: clk, exec, stacken, push, and aluval. Click on Display Signal, as before. You can add other signals.

  7. Close the Browser/Display Tool by clicking on Close.

Splitting Up and Bundling a Bus in SimWave

The Calc design uses switch[6:0] as an opcode and data, but also uses switch[7] as a toggled execute switch. For convenience, display switch[6:0] separately from switch[7].

  1. In the SimWave Browser (EditAdd Signals), again descend to test as previously described. Select the down arrow beside “switch” in the Signals display to view the bus bits. Highlight “switch[6],” and while holding down the Shift key, highlight “switch[0].” “Switch[6]” through “switch[0]” highlight.

  2. Click on the Create Bus icon on the toolbar (next to Display signals; Create Bus has a picture of truck with binary digits on it). The window now contains an expansion.

  3. Click on the right arrow in the new window. Enter the name on the Bus (“switch[6:0]” for instance), and select Create Bus. The SimWave GUI now displays the new bus, as shown in the following figure.

    Figure 9.42 Splitting up the Switch[7:0] Bus in SimWave

  4. In the Signals Window, highlight the individual “switch[7]” bit, and add that to the display.

  5. To delete the original “switch[7:0]” bus from the display, highlight the waveform name in the main GUI and select right mouse buttonDelete.

I

Figure 9.43 Final SimWave Display of Waveforms

Saving and Exiting SimWave

Select File Database Save to save your setup. This does not save the waveforms themselves; they still exist in the .shm file.

Exiting Verilog-XL

Because the end of the testbench has a $stop function placing Verilog-XL into an interactive mode, exit using one of the following methods.

Changing the View in SimWave

If you cannot easily read the waveforms shown in the display, zoom out to see the entire waveform. Also, the timescale shown at the bottom of the display appears now in picoseconds, compressing their appearance. Arrange the waverforms differently to improve their readability.

  1. From the main SimWave GUI, select View Zoom Fit. Eight waveforms display, shown from 0 ps to approximately 3200000 ps (assuming you used the given test fixture).

  2. To change the Time Scale, click on the button on the upper right corner of the GUI (under Help). Select “nanoseconds.”

    Figure 9.44 Changing the Displayed Time Scale in SimWave

  3. To change the display order of the signals, click on the waveform name using the middle mouse button and drag and drop the signals to the desired display order.

Order the waveforms in the following sequence, from top to bottom: notgblreset, switch[7], switch[6:0], clk, exec, stacken, push, aluval, and stackled.

Next