Writing Verilog-A for an Inverter
First, start the Cadence tools by typing "icfb &" from your cadence directory in a shell window. In the Library Manager window, after highlighting your library, select File -> New -> Cell View ... Enter "adc" or something similar in the "Cell Name" field. In the "Cell View" field, enter "veriloga". That tool should automatically change to the Verilog-A Editor.
After selecting OK, the Invoke Modelwriter window will appear. Select OK.
Then, the Cadence Modelwriter window will appear and you can select a variety of components. Feel free to see what is available. For this tutorial, select the "Analog to Digital Converter" device in the "Interface" folder. Then, select Next>.
The next window includes all of the parameters of the analog to digital converter. Change the "Number of Bits" to 4 and the "Max. Input Voltage" and the "Min. Input Voltage" to 5 V and 0 V, respectively. Leave everything else as is. Select Next>.
The window below contains the verilog-a code generated by the wizard. Scroll through the code and try to understand the functions used. Select Save Generated Code at the bottom right corner of the screen. Then, select Finished! Exit in the same place.
You will be prompted about creating a symbol. Select Yes.
The Symbol Generation Options window will appear. All of the default settings should be fine. Therefore, go ahead and select OK.
The symbol for the ADC will appear in the Virtuoso Symbol Editing window. Make any changes desired to the shape to the symbol shape. Move "[@instanceName]" so that it is above the symbol and change the name of "[@partName]" to something like "ADC". After all changes have been made, select Design -> Check and Save or select F8 and then close the Virtuoso Symbol Editing window.
To test out the ADC, the first simulation should be a ramp. With using a ramp, the output of the ADC can be checked to see if it corresponds to the correct input voltage. Place the ADC symbol you created in the middle of the Virtuoso Schematic Editing window. Next, connect a "vpwl" voltage source to the "vin" pin and a "vpulse" voltage source to the "clk" pin of the ADC. Make an output bus (type 'W') from the "dout<3:0>" output of the ADC. Make four smaller wires (type 'w') attached to the bus and connect pins to them, named "dout<3>", "dout<2>", "dout<1>", and "dout<0>". Name the bus "dout<3:0>" and the small wires the same names that you gave their respective pins.
Next, the parameters need to be changed for the voltage sources. You do not want the voltage sources to operate at the same frequency because then, you will always clock in the same data to the ADC. Therefore, change the following parameters:
When your test schematic is complete, it should look something like the picture below.
Check and save your schematic by typing the "F8" key and select Tools -> Analog Environment. The Cadence Analog Design Environment window will appear. Verify that the simulator is "spectreS". If it is not, then you can change the simulator by selecting Setup -> Simulator/Directory/Host ... To test the ADC, we will run a transient simulation.
To properly set up the transient simulation, select Analyses -> Choose ... Select the "tran" Analysis and enter a Stop Time of 5ms. Select OK.
Select Outputs -> To Be Plotted -> Select On Schematic and then select the two inputs and the output bus in the Virtuoso Schematic Editing window.
Run the simulation by selecting the green traffic light icon in the Cadence Analog Design Environment window. The waveforms of the simulation should appear in the Waveform Window. Select the Switch Axis Mode icon (second icon from bottom) in the Waveform Window.
Pick a few points on vin and verify that the 4-bit ADC is accurate (determine the 4-bit binary value at this point by viewing the dout pins to see if they are high or low). Verify that the output is changing on the rising edge of the clock. To change the ADC so the output changes on the falling edge, go to the Library Manager window and select the veriloga cell view of the adc. Find the following line of code:
Change the '1' to a '-1'. This argument determines whether or not the ADC will change on the rising or falling edge of the clock. Save your file and then rerun the simulation from the Cadence Analog Design Environment window. In the Waveform Window, verify that the output is different from the previous simulation, with the output changing on the falling edge of the clock. Also, verify that the digital output is consistent with the analog input.
To begin, create a new cell called "inverter2" with a "veriloga" cell view. When the Invoke Modelwriter window appears, select Cancel to manually type up your own Verilog-A code.
Your default text editor should open after selecting cancel. Depending on how you set it up, your text editor is probably Emacs or VI.
The file that opens will appear with the following text.
// VerilogA for ECEn445, inverter2, veriloga
`include "constants.h"
`include "discipline.h"
module inverter2;
endmodule
The line at the top beginning with "//" is a comment line. Any time you
want to add comments (text that won't effect your code), just add "//" at the
beginning of the line or before wherever you want to comment. All of your code
will go between the module and endmodule commands. "module inverter2" indicates
that inverter2 is the name of the module. This line is like a function header.
We would like to have 2 arguments for our inverter: an input and an output. Let
us call them "vin" and "vout". The arguments of the module can be indicated by
placing them inside parenthesis next to "inverter2". module inverter2(vin, vout);The next part of the code that we will define is all of the initializations. In other words, we need to define what vin, vout, and any other arguments are. To define inputs and outputs, use the commands input and output, respectively.
input vin;
output vin;
We also need to define these pins as electrical ports. electrical vin, vout;We want the inverter to change as the input crosses a certain threshold. We will define this parameter as "vtrans". We also want to define delay, rise, and fall time characteristics of the inverter. These parameters will be called "tdelay", "trise", and "tfall". To incorporate these factors of an inverter, we will use the transition filter for the output. The transition filter will be explained later in this tutorial. For now though, let us define these parameters using the "parameter real" statement. Also, each of these statements need to have a time period where their value holds true. In other words, following the definition, the statement "from (0:inf)" (from 0 to infinity) needs to be included in order to define the specific value from 0 to infinity seconds.
parameter real vtrans = 1.4;
parameter real tdelay = 0 from [0:inf);
parameter real trise = 2n from (0:inf);
parameter real tfall = 2n from (0:inf);
The last parameter we need to define is the output value that we want the
output of the inverter to transition to using the parameters above.
real vout_val;
Now that we have defined everything, we need to set up the main equations
(the meat of the code). This part of the code needs to lie within the analog
block. Since we will need more than one line to write the main equations, a
begin and end statement are needed.
analog begin
// Main equations here
end
A function that we should use to define the transition of the inverter is
the "cross" function. This function takes a minimum of two arguments. The first
argument required is the threshold point of the input that indicates when the
output should change, and the second is the edge where this threshold point is
located. A '1' is indicated for a rising edge and a '-1' for a falling egde. A
'0' indicates any crossing, rising or falling. In this case, we want to set up
two cross statements; one for the rising of the input and one for the falling.
When we detect a rising edge of the input, we want the output to fall to 0
volts. When we detect a falling edge of the input to 0 volts, we want the output
to rise to 5 volts. The cross event is expressed by "@ cross()", followed by a
statement that should result from the cross event occuring. Think of it like a
if-then statement. "If the waveform crosses at these certain conditions, then
the following will occur".
@ (cross(V(vin) - vtrans, 1)) vout_val = 0;
@ (cross(V(vin) - vtrans, -1)) vout_val = 5;
The last thing we need to do is use the transition filter. "With the
transition filter, you can control transitions between discrete signal levels by
setting the rise time and fall time of signal transitions" (Ref. Manual,
Transition Filter). We will use the branch contribution statement (<+) to
define the voltage of the output.
V(vout) <+ transition(vout_val, tdelay, trise, tfall);
The transition filter will help make the inverter seem more realistic,
without instantaneous rises and falls. All of the major parts have been covered,
so the Verilog-A code is complete.
// VerilogA for ECEn445, inverter2, veriloga
`include "constants.h"
`include "discipline.h"
module inverter2(vin, vout);
input vin;
output vout;
electrical vin, vout;
parameter real vtrans = 1.4;
parameter real tdelay = 0 from [0:inf);
parameter real trise = 2n from (0:inf);
parameter real tfall = 2n from (0:inf);
real vout_val;
analog begin
@ (cross(V(vin) - vtrans, 1)) vout_val = 0;
@ (cross(V(vin) - vtrans, -1)) vout_val = 5;
V(vout) <+ transition( vout_val, tdelay, trise, tfall);
end
endmodule
Save your text file and close it. You will be prompted to create a symbol.
Select Yes.
All of the default settings should be fine, so select OK in the Symbol Generation Options window.
The Virtuoso Symbol Editing window will appear. Make any necessary changes to the shape of the symbol. Name the inverter by selecting "Property" (type 'q') and then selecting "[@partName]". Refer to Analog Tutorial 2: Simulating an Inverter for instructions on executing a transient simulation of the inverter. If there are any errors in your Verilog-A code, the simulation will not work.