Digital VLSI Design

Tutorial on Timed Simulation

 

 

 

In this tutorial you’ll learn some things about circuit timing models, and different ways to incorporate timing information into your Verilog-XL simulations. In order for all of this to work, there needs to be agreement on what the different views of the circuits in Cadence mean. The following views are used in our design flow:

 

q       Behavioral: This is a Verilog view. It is a piece of Verilog code that describes the behavior of the circuit using Verilog behavioral code (continuous assignments, procedural “always” blocks, and built-in gate primitives). These views can be simulated directly using Verilog-XL, and if they exist are chosen first in a netlist expansion of a schematic. If you want to ignore the behavioral view and simulate the transistors instead, you need to remove this from the Netlist “netlist these views” list.

q       Schematic: A graphical schematic view drawn in Composer. The symbols (gates and other hierarchical schematics) in this view are symbol views from circuits or schematics defined in this, or in other, libraries.

q       Symbol: A graphical wrapper for a schematic. These can be generated automatically from the schematic, and manipulated in the symbol editor if you want something besides a box shape.

q       Functional: This view is reserved for the switch-level view of a transistor. It is used by the NCSU_Analog_Parts library to define the behavior of nmos and pmos transistors as built-in Verilog switch models.

q       Cmos_sch: This is a special schematic view that contains nothing but nmos and pmos devices from the NCSU_Analog_Parts library. Our use of this view is as the internal view for a CMOS standard cell. The netlister should descend into this view if you want to simulate the transistors (either as switches or as analog devices), but it should stop before this view if you’re netlisting to the place and route tool. The place and route tool wants to deal with the library cells, not the individual transistors so you need to tell it where to stop.

q       Config: This is a sort of meta-view of the cell. It’s a view of the cell that interacts with the schematic view to define how different parts of the schematic are treated. In particular, it defines which is the preferred view to use when netlisting that schematic for various simulators. It’s part of the “hierarchy browser” feature in cadence library manager.

 

There are many ways to get timing into your Verilog-XL simulations that interact with which views of the cells you use. Here are some examples.

 


Example Circuit

 

As an example for this tutorial  I’ll use a simple moore-style state machine (that you may have seen in other tutorials). The Verilog code for the example machine is in the /uusoc/facility/cad_common/local/class/5830/examples directory. The file name is moore.v. Here’s the code for this example

 

 

 

 

// Verilog HDL for "testlib", "moore" "behavioral"

 

module moore (clk, clr, insig, outsig);

input clk, clr, insig;

output outsig;

 

// define state encodings as parameters

parameter [1:0] s0 = 2'b00, s1 = 2'b01, s2 = 2'b10, s3 = 2'b11;

 

// define reg vars for state register and next_state logic

reg [1:0] state, next_state;

 

//define state register (with asynchronous active-low clear)

always @(posedge clk or negedge clr)

begin

        if (clr == 0) state = s0;

        else state = next_state;

end

 

// define combinational logic for next_state

always @(insig or state)

begin

        case (state)

                s0: if (insig) next_state = s1;

                    else next_state = s0;

                s1: if (insig) next_state = s2;

                    else next_state = s1;

                s2: if (insig) next_state = s3;

                    else next_state = s2;

                s3: if (insig) next_state = s1;

                    else next_state = s0;

        endcase

end

 

// now set the outsig. This could also be done in an always

// block... but in that case, outsig would have to be

// defined as a reg.

assign outsig = ((state == s1) || (state == s3));

 

endmodule

 

 

 

 

 

 

 

 

 

 

 
The state machine that is implemented by this code is shown below:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

This is a simple moore-style finite state machine. The syntax of the transitions shown in this diagram is actually VHDL, but this is just to show you what the state machine is doing. The translation to Verilog uses the correct syntax to get everything working. You should look at the Verilog code and make sure you understand how the state diagram is implemented by the Verilog code if you’re curious. At the least, you’ll need to understand the inputs and outputs of the state machine so that the testbench will make sense.

 

To get the transistor-level circuit to use for this example I’ve synthesized the state machine using Synopsys and targeting the UofU_Example cell library  (separate tutorial!). This is not a terrifically interesting state machine, it’s just a schematic to use to demonstrate how various simulation options work.

You can find this example as the cell named moore in the UofU_Example library. The top-level schematic that we’ll be simulating is called test_moore and includes inverters (from the UofU_Example library) on inputs and outputs, and a copy of the moore cell as the main circuit.

 

The synthesized moore circuit looks like the following when imported into cadence as a schematic view:

 

 

The moore_test schematic simply includes some buffers (not really necessary, but useful later on) and an instance of the moore cell. It looks like this:

 

 

Here’s a very simple testbench that will take the state machine through a couple states:

 

 

// Verilog stimulus file.

// Please do not create a module in this file.

 

// Default verilog stimulus.

 

initial

begin

 

   clk = 1'b0;

   clr = 1'b0;

   insig = 1'b0;

 

#10

$display("clr=%b, insig=%b, outsig=%b", clr, insig, outsig);

 

clr = 1;

#10

clk = 1'b1;

#10

$display("clr=%b, insig=%b, outsig=%b", clr, insig, outsig);

 

clk = 0;

#10

insig = 1;

#10

clk = 1;

#10

$display("clr=%b, insig=%b, outsig=%b", clr, insig, outsig);

 

end

 

When this is run on the test_moore schematic the output looks like this:

 

clr=0, insig=0, outsig=0

clr=1, insig=0, outsig=0

clr=1, insig=1, outsig=1

0 simulation events (use +profile or +listcounts option to count) + 93 accelerated events + 38 timing check events

CPU time: 0.0 secs to compile + 0.0 secs to link + 0.0 secs in simulation

End of Tool:     VERILOG-XL 05.10.004-s   Jan 20, 2005  15:36:21

 

If you want to use this cell to follow along with the tutorial, you should copy it from the UofU_Example library into a library of your own so you can edit the schematics.

 

 

Behavioral Simulation

 

One way to speed up simulation is to simulate parts of your system as behavioral Verilog code. This way you can simulate complex behavior at a high level in the Verilog code and only use the detailed switch-level simulation for parts of the circuit. If you are using a cell library with behavioral views (like UofU_Example, for example), then this is the simulation you’ll get with the standard setup. You’ll have to modify things to get switch-level simulations (as seen later).

 

One way to get timing information into a behavioral  simulation is to include timing information explicitly into your behavioral descriptions. For example, using hash notation like #10 will insert 10 units of delay into your behavioral simulation at that point in the Verilog code. This can enable a rough top-level estimate of system timing in a description that is a long ways from a real hardware implementation.

Remember, though, that #10-type timing is ignored for synthesis. Synthesis takes timing into account using the gate timing of the cells in the target library. It does not try to impose any timing that you specify in the behavioral description.

 

Example - Verilog NAND model with continuous assignment timing:

 

module NAND (out, in1, in2);
      output out;
      input in1, in2;
      assign #10 out = ~(in1 & in2);
endmodule

 

Example - Verilog NAND with procedural assignment timing:

 

module NAND (out, in1, in2);
      output out;
      reg out;
      input in1, in2;
      always @(in1 or in2)
                  begin
                              #10 out = ~(in1 & in2);
                  end
endmodule

 

Note that you can define parameters in your module descriptions, and use the parameters in the delay expressions.

 

Example – Verilog NAND with procedural assignment timing using a parameter

 

module NAND (out, in1, in2);
      output out;
      reg out;
      input in1, in2;

parameter delay = 10;
            always @(in1 or in2)
                        begin
                                    #delay out = ~(in1 & in2);
                        end
endmodule

 

If you define the delay with a parameter then you can override the parameter when you instantiate the module. For example, to instantiate a copy of the NAND gate with a delay of 5, you would instantiate it as:

 

NAND #(5) _i0 (a, b, c);

 

Which would override the first parameter (delay) to have a value of 5. Note that the instance name in this case is _i0.

 

So, here’s away to include timing, and to speed up simulation. If you add behavioral views for all your standard cells as verilog code (as in the UofU_Example library), then when you simulate using the default stop list you won’t get all the way to transistors, you’ll stop at the behavioral view instead. With the standard view list and stop list for Verilog-XL, and with behavioral views for all the standard cells (for example, the UofU_Example library has behavioral views for all cells), you would see something similar to the following in the CIW when the top-level circuit is netlisted:

 

---------- Begin Netlist Configuration Info ----------

 

CELL NAME                   VIEW NAME            NOTE            

---------                   ---------            ----            

 

nand2                       behavioral           *Stopping View* 

mux2                        behavioral           *Stopping View* 

dff_qb                      behavioral           *Stopping View* 

nor2                        behavioral           *Stopping View* 

inv                         behavioral           *Stopping View* 

moore                       schematic                            

 

---------- End Netlist Configuration Info   ----------

 

Note that in this case the moore cell is still a schematic, but all the standard cells have stopped at their behavioral views rather than expanding all the way to the nmos/pmos functional views. This means that the simulation will be simulating the behavior of the gates, not the transistors in the gates. It can be quite a bit faster to simulate behaviors instead of transistors, but of course you trade off accuracy for speed.

 

 

Structural Simulation using Built In Gate Primitives

 

Another way to get timing information into a simulation is to write structural Verilog code using Verilog built in gate-level primitives (and, or, nand, nor, xor, xnor, buf, not) and give those gate-level primitives timing information. That is, describe behavior in terms of the built-in gates instead of assignment statements. These gates are built in primitives in Verilog so they don’t need additional behavioral descriptions. They also do not correspond with any particular gates in your (or any) library. They are just abstract models of primitive gates. If you include a timing argument in the instantiation of the gate, Verilog will apply that timing to the gate’s evaluation.

Example: Verilog NAND gate using a nand primitive with timing:

module nand2 (Y, A, B);

output Y;

input A;

input B;

 

nand #(5) _i0 (Y, A, B);

endmodule

 

This module instantiates a single nand2 primitive gate. This instance is named “_i0”, and is given a delay of 5 units.

 

If delay is given as a single number, then that delay is used for all transitions of the output node of the primitive gate. If you give a delay two numbers #(5,6) then the first number is used for rising transitions and the second for falling transitions.  If each number is actually a set of three numbers separated by colons then that delay is being specified for min:typ:max timing that can be set elsewhere. That is, #((4.8:5.0:5.2),(5.8:6.0:6.2)) would define a similar rising/falling set of delays, but the overall simulation could choose which number to use depending on whether you specify the timing as min, typ, or max for this simulation. We usually don’t bother with this level of detail.

 

This is fine for putting gate-level timing information in your module descriptions, but it’s only really effective if the gate-level implementation in the Verilog matches the way you’ve built things! You might be using the gate-level primitives to describe the behavior, but building your circuit quite differently. For that you need the next method.

 

Behavioral Verilog with Specify Blocks

 

Behavioral Verilog code can include timing in a “specify” block instead of in each assignment statement. A specify block allows you to define “path delays” from input pins to output pins of a module. Path delays are assigned in Verilog between specify and endspecify keywords. Statements between these keywords constitute a specify block. A specify block appears at the top level of the module, not within any other initial or always block. Path delays define timing between inputs and outputs of the module without saying anything about the actual circuit implementation of the module. They are simply overall timings applied at the I/O interface of the module.  This is the timing model used by UofU_Example so that the SDF timings from Synopsys can be used as shown in this section.

 

Example: Verilog NAND with specify block:

 

module nand2 (Y, A, B);

output Y;

input A;

input B;

 

nand _i0 (Y, A, B);

 

specify

(A => Y) = (1.5, 1.0);

(B => Y) = (1.7, 1.2);

endspecify

 

endmodule

 

In this module the overall delay between a change on A and a change on Y is specified in the first path delay. Note that the rising transition is slightly longer than the falling transition.

 

In a specify block you can also specify parameters to use within that specify block. These are called specparams. The ides here, like any parameterization, is that you can change a single number and update multiple places (clearly this is more use in a more complex module with more path delays than in this example).

 

Example: Verilog NAND with specify block and specparam statements:

 

module nand2 (Y, A, B);

output Y;

input A;

input B;

 

nand _i0 (Y, A, B);

 

specify

specparam a_to_y_r = 1.5;

specparam a_to_y_f = 1.0;
  

(A => Y) = (a_to_y_r, a_to_y_f);

(B => Y) = (1.7, 1.2);

endspecify

 

endmodule

 

There are two main reasons to use a specify block to describe timing

  1. So that you can describe path timing between inputs and outputs of complex modules without specifying detailed timing of the specific circuits used to implement the module

  2. So that you can back-annotate circuits that use this cell with timing information from a tool like Synopsys.

 

Synopsys can produce a timing information file as output from the synthesis process in SDF format (standard delay format). An SDF file will have extracted timings for all the gates in the synthesized circuit. Synopsys gets these timings from the .lib file and from an estimate of wiring delays so they’re pretty accurate. They also assume that every cell in the library has a specify block that specifies the delay from each input to each output!

 

If you have an sdf file, you can annotate your verilog file with this sdf information. This will override all the default values in the specify blocks with the estimated values from the sdf file. For example, a snippet of an sdf file for a circuit that uses a nand2 gate looks like:

 

(CELL

(CELLTYPE "nand2")

(INSTANCE U21)

(DELAY

(ABSOLUTE

(IOPATH A Y (0.385:0.423:0.423) (0.240:0.251:0.251))

(IOPATH B Y (0.397:0.397:0.397) (0.243:0.243:0.243))

)

)

)

 

Notice the matching of the timing paths in the specify bock to the IOPATH statements in the sdf file, and the the timings are specified in min:typ:max form for both rising and falling transitions. Each instance of a nand2 in the circuit would have its own CELL block in the sdf file and thus get its own timing based on the extracted timing done by synopsys during synthesis. Remember, though, that this is just estimated timing. You could get better timing if you generated an sdf file after placement and routing.

 

To generate sdf files from Synopsys start by synthesizing your circuit in the standard way (analyze, elaborate, set constraints, optimize, output as structural verilog). When you’re finished with synthesis and you have a circuit, then choose the File->SaveInfo->DesignTiming option in Synopsys. You’ll get a dialog box like this:

 

 

Make sure that SDF is the Format, and change the output file name to whatever makes sense to you. This sdf file is now generated in your ~IC_CAD/synopsys directory.

 

If you’re using dc_shell instead of design_analuzer, the command line version is:

 

write_sdf –version 1.0 filename.sdf

 

Now you can read the structural verilog in to icfb using the verilog-in form and the instructions in Tutorial 4. You should now have a schematic that you can simulate in Verilog-XL. You can simulate the library cells as behavioral views with the deafly timings in the specify blocks, or you can take “behavioral” out of the netlist search path and simulate at the switch-level with the 0.1ns of delay on each transistor.

 

If you want to use the sdf information, make sure you’re netlisting to the behavioral views. These are the views with the specify blocks so they are the views that the sdf file can annotate.

 

In Verilog-XL, select the Setup->Envornment menu choice, and the “SDF Delay Annotation” button. You should get a dialog box like the following. Fill in the name of your sdf file, and click the “Use Delay File at Time Zero” button. The sdf2sdf File field will be filled in automatically.

 

Now when you enter interactive mode and re-netlist the circuit, you should get an $sdf_annotate command showing up in the Verilog-XL window. You’ll probably get some warnings/errors about being unable to find source ports test.xxxx. You can safely ignore them. It’s complaining that the way that Verilog-XL has set up the testbench it hasn’t exported the ports of the cell under test. That’s all right. The internal test will use the sdf timings which you can verify on the waveform output display.

 

Note that if you’re using a different Verilog simulator (like ncverilog or modelsim for example), you can put the $sdf_annotate() statement in your top-level Verilog file (not in the testbench, in your Verilog file) before that tool reads in the file and get the same effect. It would look something like this:

 

      module moore ( clk, clr, insig, outsig );

input  clk, clr, insig;

output outsig;

wire state_1, next_state_0, next_state_1, n6, n7, n8, n9, n10, n11, n12;

   initial

      begin

          $sdf_annotate(“pathname/filename.sdf”);

       end

    inv U3 ( .A(insig), .Y(n7) );

    nand2 U4 ( .A(n8), .B(n9), .Y(next_state_0) );

    nor2 U5 ( .A(n6), .B(n7), .Y(n10) );

    mux2 U6 ( .A(n10), .B(n6), .S(state_1), .Y(next_state_1) );

    nor2 U7 ( .A(n6), .B(state_1), .Y(n11) );

    nor2 U8 ( .A(n7), .B(n11), .Y(n12) );

    nand2 U9 ( .A(n11), .B(n7), .Y(n8) );

    inv U10 ( .A(n12), .Y(n9) );

    dff_qb state_reg_0 ( .D(next_state_0), .G(clk), .CLR(clr), .Q(outsig), .QB(n6) );

    dff_qb state_reg_1 ( .D(next_state_1), .G(clk), .CLR(clr), .Q(state_1) );

endmodule

 


Structural Simulation using Transistor Models

 

If the gates in your library are constructed using the transistors from the NSCU_Analog_Parts library (which they certainly are if you’re following along with the class), then you get some sort of timing for free when you simulate structural circuits. Once you have a structural circuit, either from Synopsys synthesis, or just from putting library cells together in Composer, you can simulate the structural circuit with Verilog-XL.

 

If your cells don’t have behavioral views, this is what you’ll get by default. But, if you are using a library like UofU_Example that has behavioral views, and you’d rather do a switch-level simulation all the way to the transistors, go to the Setup->Netlist option in the Verilog-XL gui and remove “behavioral” from the “Netlist these views” list. Then when you start up the simulation and you re-netlist the circuit, you’ll skip the behavioral views and expand down to the transistor functional views (with the 0.1ns delay on each transistor.

 

 

If you’ve removed “behavioral” from the view list, then the netlister will continue to expand “schematic” views and only stop when you get to a “functional” view. Because you haven’t added any functional views to your library, and there are no functional views in the UofU_Example library cells, this means that the netlister will continue to expand schematics until it hits the first functional view, and the first functional view it will hit is the functional view of the nmos and pmos cells from the NCSU library.  That’s what the following stuff means that shows up in the CIW when you start up a Verilog-XL simulation. It means that it’s expanding the schematic views until it finds a “stopping view.” The functional views of the nmos, pmos, and r_nmos (weak nmos) cells have functional views, and therefore the netlister stops expanding when it finds them.

 


---------- Begin Netlist Configuration Info ----------

                (incremental data only)

 

CELL NAME                   VIEW NAME            NOTE            

---------                   ---------            ----            

 

pmos                        functional           *Stopping View* 

nmos                        functional           *Stopping View* 

r_pmos                      functional           *Stopping View* 

moore                       schematic                             

inv                         schematic                            

nor2                        schematic                            

dff_qb                      schematic                            

mux2                        schematic                             

nand2                       schematic                            

 

---------- End Netlist Configuration Info   ----------

 

With the netlist generated in this way, the simulation that is run is a simulation where every component being simulated is a transistor. In our version of the NCSU_Analog_Parts library, I’ve added 0.1ns of delay to every transistor. This means that every transistor in the pullup or pulldown path takes 0.1ns before the signal passes through it. This is a pretty rough estimate, but it does add enough delay so that the simulation of your structural schematics has some delay.

 

The lists of views to traverse during netlisting, and the views to stop at during netlisting are set in the .simrc file in the ncsu system directory. They are currently set to the following:

 

verilogSimViewList = '("behavioral" "functional" "schematic" "symbol" “cmos_sch")

verilogSimStopList = '("behavioral" "functional" “symbol”)

 

This means that the netlister will look at all the views in the View list, but stop when it finds a view in the Stop list. I’m not sure why “symbol” is in the stop list, and why the netlister doesn’t stop at the first symbol view, but that’s the way things are set up now and they seem to work.

 

 

 

SpectreS and Analog Simulation

 

The ultimate in timed simulation is, of course, analog simulation using SpectreS. This very detailed simulation of every transistor in your design gives you timing results that are within a few percent of the fabricated chip. Of course, it’s also VERY slow, especially for large chips. It’s also difficult to use the vpulse and vpwl components to generate complex data streams for digital circuits. However, if you really want good timing information about your chip, there’s no substitute for analog simulation of the whole chip!

 

Mixed Mode Analog/Digital Simulation

 

Luckily, there is a compromise between full analog simulation and purely functional simulation. Cadence is designed to do mixed mode simulation where part of your design is simulated using Verilog-XL and part is simulated using SpectreS. You can use this capability for a variety of simulation tasks.

 

  1. You can simulate circuits that are actually mixed mode circuits. That is, systems that have both analog and digital components like a successive approximation ADC.

  2. You can simulate large digital systems by simulating most of the circuit using Verilog-XL, but specify that certain critical parts are simulated using the analog simulator for more accuracy.

  3. You can simulate the entire system with the analog simulator, but have a small set of digital components in your testbench file so that you can write the testbench in Verilog instead of using vpulse and vpwl components.

Cadence does through the config view that defines how each part of the system should be treated. Essentially you have a view of your top-level schematic that lets you specify, for each subpart of the system, whether that part should be simulated digitally (i.e. with Verilog-XL as either behavior or at a switch level), or as an analog circuit (with SpectreS).  It also automatically installs “interface elements” between the digital and analog portions of the design (they’re called a2d and d2a), and automatically interfaces the two simulators. A config view is an extra view that binds parts of the schematic to certain views and other parts to other views.


The first thing we need to do is create a new schematic that will be the one that is simulated as an analog or mixed mode circuits. The main difference between the schematic that we’ve been using and one that involves the analog simulator is that you need to add the Vdc component between Vdd and Gnd symbols to define the power supply. The moore_test_mixed schematic looks like this:

 

 

If this were a purely analog schematic you would need to include Vpulse or Vpwl components on the inputs to drive the analog inputs of the moore cell. For mixed mode simulation we will use Verilog-XL to provide the inputs through the clk, clr, and insig signals.

 

The first thing we need to do is create a config view of the schematic. To create a config view, go to the Library Manager and create a new cell view. The cell view tool should be set to Hierarchy-Editor, the View Name should be config, and the Cell Name should be moore_test_mixed (or whatever your cell is called).

 

 

 

When you get to the “New Configuration” dialog box, use a template to set things up. To set up for mixed mode simulation use the “SepctreSVerilog” template. Also, change the View: at the top of the New Configuration dialog box to be schematic.

 

 

Now you should be looking at the config view in the Cadence Hierarchy Editor. I find it easier to deal with if I immediately go to the View menu and change to the tree view. What you should see (you may need to open the schematic view in the top line of the Hierarchy Editor to see this) is the following:

 

 

Now you have a config view that describes each instance in the schematic and what view to use to simulate it. At the moment they are all default views (in this case the default is behavioral because that view exists in the UofU_Example library). The trick to mixed mode simulation is to specify a view for some cells that results in analog simulation, and a view for other cells that results in digital (Verilog) simulation for those cells. Note that you’re making this choice for a tree of cells. If you make a choice for a cell, all cells under that cell inherit that choice unless you descend into the hierarchy and override that decision.

 

In the first new configuration you’ll see that all the cells have chosen behavioral views. This is because I used the UofU_Example library where all the cells have behavioral views. If we simulate in mixed-mode with this configuration all the cells will be simulated using Verilog-XL because behavioral is a digital view.

 

If you open the config view along with the schematic view, then you can see how to make the partition. In the schematic pane, select Tools->MixedSignalOps. This will add a couple menu choices to your Composer window that deal with mixed-mode simulation. Click on Mixed-Signal->PartitioningOptions and you’ll see a dialog box that shows you two different stop-view lists: one for analog simulation and one for digital simulation. These lists tell you which views will be simulated with which simulator.

 

 

The important ones from our point of view are the specterS view in the analog list, and the behavioral and functional views in the digital list. All the basic transistors in the NCSU_Analog_Parts library have spectreS and functional views. Cells in your library (or at least in my library) have behavioral views. This gives us choices in how the mixed simulator simulates each circuit piece.

 

Now select Mixed-Signal->DisplayPartition->Interactive. This will bring up a dialog box that shows you how it’s going to color each type of partition. The default is that the analot parts will be red and the digital parts will be orange. Anything that is mixed (because you’ve split things further down in the hierarchy) will be blue. I find that red and orange look pretty similar, so I like to change one of those. In this example I’ll change red to green. In any case, when you click on OK it will highlight all the circuits in your circuit and tell you how they’re being simulated At this point they’re all being simulated digitally because they all find their behavioral views and stop. So, they’ll all be orange (except for the Vdc which is green (analog)).  You can also see the view names in white if you squint hard enough. The inverters are simulated using behavioral views, and the moore block, while still digital, is a schematic view.

 

 

 

 

 

 

 

 

 

This indicates that the inverters and the moore machine are all currently headed for the digital simulator (Verilog-XL) and the vds is headed to the analog simulator (spectreS).

 

Before we change the partitioning of the circuit, we have to make sure that the mixed-mode simulator can find the interface elements that we want it to put between the digital and analog portions of the circuit. Select the Mixed-Signal->InterfaceElements->DefaultOptions menu choice to get the dialog box. In this box, update the Default IE Library Name to be NCSU_Analog_Parts.

 

 

Now you can select Mixed-Signal->InterfaceElements->Library to change the default characteristics of the interface elements. For example, the “output” d2a devices have rising and falling slopes, and high and low voltages defined so that they know how to take digital signals and generate analog versions.

 

 

For the “input” devices you can set at what analog voltage the a2d thinks the value is a logic 0 or a logic 1, and the max amount of time an a2d can remain between a logic 1 and logic 0 before it reports an X to the digital simulator.

 

 

Once you have things set up, you can change the partitioning by changing how the config view looks at each circuit. In this case I’ll change the inverters closest to the moore state machine to use analog simulation, and choose analog simulation for the whole moore machine. I’ll be able to apply inputs to the test circuit using Verilog to drive the clk, clr, and insig signals, and see the output outsig as an analog waveform.

 

In my schematic, inverters I2, I4, and I7 are the ones closest to then moore machine. I’ll change their views to cmos_sch so that the netlister sill expand them (do this by selecting the instance in the Hierarchy Viewer and right-clicking to get the set-instance-view menu choice), and change their inherited view list to be spectreS so that the netlister will stop only when it finds that view (which is an analog view according to the Analog Stop List). To set the Inherited View List, select that word in the Hierarchy Editor and just type in what you want the view list to Just for fun, I’ll take inverter I4 which is the inverter connected to the clk input, and change its view to schematic, but change its stop list to be functional. This means that it will be expanded to transistors, but we’ll get a Verilog-XL simulation of the transistor’s functional views instead of an analog simulation of the spectreS view. For the moore block, I’ll keep it a schematic view, and change the inherited viewlist to  “schematic cmos_sch spectreS” so that it’s also simulated with spectreS. I need schematic, cmos_sch, and spectreS in the inherited view list is so that the netlister will continue to expand the schematic and cmos_sch  views until it finally gets to a spectreS stopping view. Now update the config view using View->Update. The config now look like this:

 

 

And if I look at the partition in the schematic, it’s a little hard to see, but it now shows that moore and two of the three inverters driving moore are analog, and the three inverters to the left, and the i4 inverter  are digital. Everything that is in the digital partition will be simulated with Verilog-XL, and everything in the analog partition will be simulated with SpectreS.

 

 

Now I can open the analog environment to start up the simulation (Tools->AnalogEnvironment) in the schematic). Make sure that you’re simulating the config view. 

 

 

Now, in the Setup->Simulator dialog box select spectreSVerilog as the simulator.

 

 

 

Make sure that your model path includes /uusoc/facility/cad_common/NSCU/CDK1.3/local/models/spectre/nom. You may have to add this by hand until I figure out how to get the default set. Type it into the New Directory box and add it.

 

 

In your Setup-Environment dialog box, make sure your Include Foramt is spectre, and that you’re using Hierarchical Netlist Mode.

 

 

And, in the Verilog Netlist Option part of that form, make sure that you’re using Verimix as your Generate Test Fixture Template, and that Drop Port Range is selected.

 

Whew! Now you can Setup->Stimulus->EditDigital to make your Verilog testbench driver program. Here’s my example for the moore state machine(same as before!)

 

 

 

 

// Vermix stimulus file.

// Default verimix stimulus.

 

initial

begin

 

   clk = 1'b0;

   clr = 1'b0;

   insig = 1'b0;

 

#10

$display("clr=%b, insig=%b, outsig=%b", clr, insig, outsig);

 

clr = 1;

#10

clk = 1'b1;

#10

$display("clr=%b, insig=%b, outsig=%b", clr, insig, outsig);

 

clk = 0;

#10

insig = 1;

#10

clk = 1;

#10

$display("clr=%b, insig=%b, outsig=%b", clr, insig, outsig);

 

 

end

 

Note that this simulation file has delays in it that last for 60ns. So, my transient analysis had better be at least this long! I’ll choose a transient analysis of 200n just to be safe.  Now I’ll select the nodes to be plotted like usual for an analog simulation, but for fun I’ll choose some digital signals (like the inputs being driven by the testbench), and some analog (like the inputs to the moore block and outsig). Then I’ll tell the simulation to start up.

 

Sometimes I can’t get SpectreS to find the transistor models until I go to Setup->ModelCorner and choose a corner. I’m not sure why this is…

 

In any case, once the simulation has run, this is what you might see:

 

 

 

 

Note that the digital signals look like digital waveforms, and the analog results are all overlapped. This confuses the “switch axis mode” button, so you have to separate the waveforms by hand using the Curves->Edit option to assign each curve to its own strip on the display (hint – click “change” after each assignment of a curve to a strip)(another hint, after you have some strips, you can click and drag waveforms to different strips). If you do that, it looks like this:

 

 

If I rearrange things again, I can overlap digital and analog signals on the same strip to see the differences. Here I’ve overlapped the digital signals at the inputs with the analog signals at the output of the second inverter so you can see both the delay, and the analog waveform of the second (analog) inverter. You can also see the outsig rising after the clock signal where insig is high.

 

 

Note that outsig is an analog waveform, but you could put it back into a digital portion of the system and Cadence would add the appropriate a2d to convert back to logical 1 and 0.

For example, I could add a couple of digital inver