• Skip to main content
  • Skip to search
  • Skip to footer
Cadence Home
  • This search text may be transcribed, used, stored, or accessed by our third-party service providers per our Cookie Policy and Privacy Policy.

  1. Community Forums
  2. Mixed-Signal Design
  3. Changing the number of input bits in a DAC and problem in...

Stats

  • Locked Locked
  • Replies 18
  • Subscribers 64
  • Views 27495
  • Members are here 0
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Changing the number of input bits in a DAC and problem in ADE simulation

vasug7
vasug7 over 7 years ago

I am trying to design a generic N-bit DAC using variable input bits. Please take a look at a simple code snippet given below.

`include "constants.vams"
`include "disciplines.vams"

module DAC_va(out, in, clk);
parameter integer bits = 4;
parameter real fullscale = 1.8;
parameter real td = 0;
parameter real tt = 0;
parameter real vdd = 1.8;
parameter real thresh = 0.9;

output out;
input clk;
input [0:bits] in;
voltage out, clk;
voltage [0:bits] in;
real aout;
integer weight;
genvar i;

analog begin
@(cross(V(clk) - thresh, 1) or initial_step) begin
aout = 0;
weight = 2;
for(i = bits - 1; i>=0; i = i-1) begin
if(V(in[i]) > thresh) begin
aout = aout + fullscale/weight;
end
weight = weight*2;
end
end
V(out) <+ transition(aout,td,tt);
end
endmodule

The problem I am facing is that I don't know how to give multiple inputs to the in<> terminal of the DAC symbol in the schematic window.

I am new to working with Verilog A. Any help will be appreciated.

Thanks.

Virtuoso version - IC6.1.7-64b.500.15

  • Cancel
  • Andrew Beckett
    Andrew Beckett over 7 years ago

    Virtuoso does not support parameterised bus pins and hence this makes doing this slightly trickier. The good news is that it's not impossible - you need to create PCells for the symbol and also the netlist.oa view within the veriloga view, and a netlist procedure so that spectre knows how to netlist the variable connectivity. I've been meaning to put together an example of how to do this for some time, so this gave me the excuse! Please find the code below (see the comments within). Note that you will need to change the VerilogA code slightly - it should be (note I reversed the bus order to be consistent with the pcell code too, as well as making the bus bits wide; previously it was bits+1 wide):

    input [bits-1:0] in;
    voltage out, clk;
    voltage [bits-1:0] in;

    Regards,

    Andrew.

    /* abGenericDAC.il
    
    Author     A.D.Beckett
    Group      Custom IC (UK), Cadence Design Systems Ltd.
    Language   SKILL
    Date       Jul 25, 2018 
    Modified   
    By         
    
    SKILL code to support a veriloga model with a variable width
    bus as input - in this case a DAC model. Works by creating
    PCells and a netlist procedure to handle the varying connectivity.
    
    First create a veriloga view with this content, and then call
    abCreateGenericDACViews() (with appropriate arguments) to create the
    symbol pcell, the pcell for the netlist.oa, and the CDF. Note that
    the pins need to match between the veriloga and the pcell code (and
    netlist procedure), and the parameters need to match the CDF in the
    creation code below.
    
    This file will also need to be loaded from the libInit.il within
    the library containing the component so that the netlist procedure is
    loaded when the library is first accessed in each session.
    
    `include "constants.vams"
    `include "disciplines.vams"
    
    module genericDAC(out, in, clk);
    parameter integer bits = 4;
    parameter real fullscale = 1.8;
    parameter real td = 0;
    parameter real tt = 0;
    parameter real vdd = 1.8;
    parameter real thresh = 0.9;
    
    output out;
    input clk;
    input [bits-1:0] in;
    voltage out, clk;
    voltage [bits-1:0] in;
    real aout;
    integer weight;
    genvar i;
    
    analog begin
        @(cross(V(clk) - thresh, 1) or initial_step) begin
            aout = 0;
            weight = 2;
            for(i = bits - 1; i>=0; i = i-1) begin
                if(V(in[i]) > thresh) begin
                    aout = aout + fullscale/weight;
                end
                weight = weight*2;
            end
        end
        V(out) <+ transition(aout,td,tt);
    end
    
    endmodule
    
    ***************************************************
    
    SCCS Info: @(#) abGenericDAC.il 07/26/18.14:25:22 1.2
    
    */
    
    /********************************************************************
    *                                                                   *
    *     abCreateGenericDACViews(library @key (cell "genericDAC"))     *
    *                                                                   *
    *  Create the symbol pcell, the veriloga shadow pcell, and the CDF  *
    *   for the genericDAC. This is to allow a variable width pin on    *
    * the genericDAC model, which normally isn't supported in Virtuoso. *
    *                                                                   *
    ********************************************************************/
    procedure(abCreateGenericDACViews(library @key (cell "genericDAC"))
     let( (pcellId (view "symbol") (viewType "schematicSymbol")
            tempFile tempPort params)
        unless(ddGetObj(library)
            error("Couldn't open library %L" library)
        )
    
        when(ddGetObj(library cell "symbol")
            ddDeleteObj(ddGetObj(library cell "symbol"))
        )
    
        ;--------------------------------------------------------------------
        ; Create the symbol pcell
        ;--------------------------------------------------------------------
        pcellId=eval(`pcDefinePCell(
            list(ddGetObj(,library) ,cell ,view ,viewType)
    
            ;----------------------------------------------------------------
            ; Formal parameters
            ;----------------------------------------------------------------
            (
                (bits 4)
            )
    
            ;----------------------------------------------------------------
            ; Code itself
            ;----------------------------------------------------------------
            let(( cv netIn netClk 
                netOut figIn figClk figOut hp ps pl bw lh
                pxc label)
    
            cv = pcCellView
    
            ;----------------------------------------------------------------
            ; Various dimensions
            ;----------------------------------------------------------------
            ; half pin size
            hp=0.025
            ; pin spacing
            ps=0.125
            ; pin length
            pl=0.250
            ; box width
            bw=1.4375
            ; label height
            lh=0.0625
            ; param label x coord
            pxc=0.5
    
            ;----------------------------------------------------------------
            ; create the shapes - first the pins
            ;----------------------------------------------------------------
            figIn = dbCreateRect(cv list("pin" "drawing") list(-hp:-hp hp:hp)) 
            dbCreateLine(cv list("device" "drawing") list(0:0 pl:0))
            figClk = dbCreateRect(cv list("pin" "drawing") list(-hp:-ps-hp hp:-ps+hp))
            dbCreateLine(cv list("device" "drawing") list(0:-ps pl:-ps))
            figOut = dbCreateRect(cv list("pin" "drawing")
                list(2*pl+bw-hp:-hp 2*pl+bw+hp:hp)
            ) ; dbCreateRect
            dbCreateLine(cv list("device" "drawing") list(pl+bw:0 2*pl+bw:0))
            ;----------------------------------------------------------------
            ; Then the boxes
            ;----------------------------------------------------------------
            dbCreateRect(cv list("device" "drawing") list(pl:-2*ps pl+bw:ps))
            dbCreateRect(cv list("instance" "drawing") list(0:-2*ps 2*pl+bw:ps))
    
            ;----------------------------------------------------------------
            ; create the nets
            ;----------------------------------------------------------------
            netIn=dbMakeNet(cv sprintf(nil "in<%d:0>" bits-1))
            netClk=dbMakeNet(cv "clk")
            netOut=dbMakeNet(cv "out")
            ;----------------------------------------------------------------
            ; create the terminals
            ;----------------------------------------------------------------
            dbCreateTerm(netIn netIn~>name "input")
            dbCreateTerm(netClk netClk~>name "input")
            dbCreateTerm(netOut netOut~>name "output")
            ;----------------------------------------------------------------
            ; create the pins
            ;----------------------------------------------------------------
            dbCreatePin(netIn figIn)
            dbCreatePin(netClk figClk)
            dbCreatePin(netOut figOut)
    
            ;----------------------------------------------------------------
            ; Put some labels for the pins
            ;----------------------------------------------------------------
            dbCreateLabel(cv list("pin" "drawing") pl+ps/2:0
                netIn~>name "centerLeft" "R0" "stick" lh)
            dbCreateLabel(cv list("pin" "drawing") pl+ps/2:-ps
                netClk~>name "centerLeft" "R0" "stick" lh)
            dbCreateLabel(cv list("pin" "drawing") bw+pl-ps/2:0
                netOut~>name "centerRight" "R0" "stick" lh)
    
            ;----------------------------------------------------------------
            ; And other symbol labels
            ;----------------------------------------------------------------
            label=dbCreateLabel(cv list("annotate" "drawing7") bw+pl-ps/2:ps*1.5
                "cdsName()" "centerRight" "R0" "stick" lh)
            label~>labelType="ILLabel"
            label=dbCreateLabel(cv list("annotate" "drawing") pxc:0
                "cdsParam(1)" "centerLeft" "R0" "stick" lh)
            label~>labelType="ILLabel"
            label=dbCreateLabel(cv list("annotate" "drawing") pxc:-ps
                "cdsParam(2)" "centerLeft" "R0" "stick" lh)
            label~>labelType="ILLabel"
    
            dbSetConnCurrent(cv)
            t
            ) ; let
        ))
        dbSave(pcellId)
        dbClose(pcellId) 
    
        ;--------------------------------------------------------------------
        ; Create the pcell in the "shadow" database (netlist.oa) in the
        ; veriloga view. This is so the terminals match in the switch view.
        ; Can't use pcDefinePCell because that creates a "master" OA
        ; database, and this needs to be done as a non-master database (the
        ; master is the veriloga.va file). So this works by creating a file
        ; with the code in, and then using dbDefineProc to associate it with
        ; the cellView (see further down).
        ;--------------------------------------------------------------------
        tempFile=makeTempFileName("/tmp/pccode")
        tempPort=outfile(tempFile)
        pprint(
            'procedure(pcGenCell(cv "d")
                let((pcParams bits)
                    pcParams=cv~>parameters
                    bits=pcParams~>bits
                    unless(fixp(bits) bits=4)
                    let((netIn netClk netOut)
                        netIn=dbMakeNet(cv sprintf(nil "in<%d:0>" bits-1))
                        netClk=dbMakeNet(cv "clk") 
                        netOut=dbMakeNet(cv "out") 
                        dbCreateTerm(netIn netIn~>name "input")
                        dbCreateTerm(netClk netClk~>name "input") 
                        dbCreateTerm(netOut netOut~>name "output") 
                        ;----------------------------------------------------
                        ; this is to stop the instance being omitted
                        ; because there's no hierarchy
                        ;----------------------------------------------------
                        dbCreateProp(cv "nlAction" "string" "stop")
                        dbSetConnCurrent(cv)
                    )
                ))
            tempPort
        )
        newline(tempPort)
        close(tempPort)
    
        ;--------------------------------------------------------------------
        ; Now create the non-master database (that's what the "wc" is for).
        ; Has to create the parameters hier prop and the pcell parameter
        ;--------------------------------------------------------------------
        pcellId=dbOpenCellViewByType(library cell "veriloga" "netlist" "wc")
        params = dbCreateHierProp(pcellId "parameters")
        dbCreateProp(params "bits" "int" 4)
        dbDefineProc(pcellId tempFile)
        dbSave(pcellId)
        dbClose(pcellId)
        deleteFile(tempFile)
    
    ;------------------------------------------------------------------------
    ; Now create the CDF
    ;------------------------------------------------------------------------
    
    let( ( cellId cdfId )
        unless( cellId = ddGetObj( library cell )
            error( "Could not get cell %s." cell )
        )
        when( cdfId = cdfGetBaseCellCDF( cellId )
            cdfDeleteCDF( cdfId )
        )
        cdfId  = cdfCreateBaseCellCDF( cellId )
    
        ;;; Parameters
        cdfCreateParam( cdfId
            ?name           "bits"
            ?prompt         "bits"
            ?defValue       4
            ?type           "int"
            ?display        "t"
        )
        cdfCreateParam( cdfId
            ?name           "fullscale"
            ?prompt         "fullscale"
            ?defValue       "1.8"
            ?type           "string"
            ?display        "t"
            ?parseAsNumber  "yes"
            ?parseAsCEL     "yes"
        )
        cdfCreateParam( cdfId
            ?name           "td"
            ?prompt         "td"
            ?defValue       "0"
            ?type           "string"
            ?display        "t"
            ?parseAsNumber  "yes"
            ?parseAsCEL     "yes"
        )
        cdfCreateParam( cdfId
            ?name           "tt"
            ?prompt         "tt"
            ?defValue       "0"
            ?type           "string"
            ?display        "t"
            ?parseAsNumber  "yes"
            ?parseAsCEL     "yes"
        )
        cdfCreateParam( cdfId
            ?name           "vdd"
            ?prompt         "vdd"
            ?defValue       "1.8"
            ?type           "string"
            ?display        "t"
            ?parseAsNumber  "yes"
            ?parseAsCEL     "yes"
        )
        cdfCreateParam( cdfId
            ?name           "thresh"
            ?prompt         "thresh"
            ?defValue       "0.9"
            ?type           "string"
            ?display        "t"
            ?parseAsNumber  "yes"
            ?parseAsCEL     "yes"
        )
    
        ;;; Properties
        cdfId->formInitProc            = ""
        cdfId->doneProc                = ""
        cdfId->buttonFieldWidth        = 340
        cdfId->fieldHeight             = 35
        cdfId->fieldWidth              = 350
        cdfId->promptWidth             = 175
        ;--------------------------------------------------------------------
        ; note that this needs a netlist proc so that it can
        ; handle the variable number of pins
        ;--------------------------------------------------------------------
        cdfId->viewInfo                = '(nil veriloga (nil  moduleName "genericDAC"
    namePrefix "ahdl" netlistProc abGenericDACNetlistProc stringParameterList
    nil parameterList (bits fullscale td tt vdd thresh))
    )
        cdfSaveCDF( cdfId )
    )
     ) ; let
    )
    
    /****************************************************************
    *                                                               *
    *                abGenericDACNetlistProc(inst)                  *
    *                                                               *
    *  Netlist procedure to netlist the instance. Mostly standard   *
    * other than the list of terminals which is constructuted based *
    *                    on the bits parameter.                     *
    *                                                               *
    ****************************************************************/
    procedure(abGenericDACNetlistProc(inst)
        let((formatter netlister termList bits)
            formatter=nlGetFormatter(inst)
            netlister=nlGetNetlister(formatter)
            nlPrintInstComments(formatter inst)
            nlPrintIndentString(netlister)
            nlPrintInstName(formatter inst)
            ;----------------------------------------------------------------
            ; Output the correct terminal list
            ;----------------------------------------------------------------
            bits=atoi(nlGetParamStringValue(inst "bits"))
            nlPrintString(netlister " ( ")
            termList=`("out" ,@dbProduceMemName(sprintf(nil "in<%d:0>" bits-1))
                "clk")
            foreach(term termList
                nlPrintString(netlister nlGetTerminalSignalName(inst term) " ")
            )
            nlPrintString(netlister ") ")
            nlPrintModelName(formatter inst)
            nlPrintInstParameters(formatter inst)
            t
        )
    )
    

    • Cancel
    • Vote Up +3 Vote Down
    • Cancel
  • vasug7
    vasug7 over 7 years ago in reply to Andrew Beckett

    Hi Andrew,

    Thanks for the solution. I am only a beginner to Cadence ecosystem and do not understand many terms used in the code that you shared.

    It would be of great help if you can tell the procedure of how to create a PCell. E.g. You say that first create a Verilog A view with the content of the code that you shared. I couldn't understand it. Like how does one even do that? Do I need to create a new library, another V-A code?

    It would be really helpful if there is a step-by-step procedure or a reference where I could look it up. I tried searching these terms in the "The designer's guide to Verilog-AMS" and  "Cadence Verilog-A Language Reference" but it was of no use.

    (No need to explain the code. Just a guide to how to implement it will do.)

    Thanks. :)

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 7 years ago in reply to vasug7

    Sorry for not making it clear. Here's the steps you need to take:

    1. Save the SKILL code above in a file somewhere (note I did just update it because I realised there was a discrepancy in the bus order between the pcell code and the VerilogA in the comments at the top)
    2. In the library that you wish to create the component (which I'll call mylib here), either paste the code into a file within that library directory on UNIX and call it "libInit.il" or create a libInit.il with: load("/path/to/theCode.il")
    3. Then in the CIW also load the code by calling load("/path/to/theCode.il") (obviously put the actual path in both cases)
    4. In the CIW use File->New->CellView and specify the lib/cell as mylib and whatever you want to call the DAC - in my case it was genericDAC. The view should be called "veriloga" and the Type is "VerilogA".
    5. Paste the code in the comments at the top of the view into the editor, replacing the template code  you get by default.
    6. If you've done this in a cell other than "genericDAC" then change the module name at the top of the file to reflect that.
    7. Then hit the "Build a database of instances, nets and pins found in the file" icon (the floppy disk/save icon with a green checkmark over it). 
    8. Then in the CIW enter:  abCreateGenericDACViews("DAC" ?cell "genericDAC") (change "genericDAC" to whatever you called the cell)

    That's it. Now you can place an instance of the symbol of your component, and the bits parameter will alter the width of the input bus pin.

    Hope that's clear!

    Regards,

    Andrew.

    • Cancel
    • Vote Up +2 Vote Down
    • Cancel
  • vasug7
    vasug7 over 7 years ago in reply to Andrew Beckett

    Thanks, Andrew. It worked!!

    For some of those who are reading the forum, another step.

    After adding the symbol to the schematic, to connect the bus, see the schematic snip given below.

    • Cancel
    • Vote Up +2 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 7 years ago in reply to vasug7

    Glad it worked. Here's how I connected up my test bench - you can specify the bus syntax slightly differently:

    Regards,

    Andrew.

    • Cancel
    • Vote Up +1 Vote Down
    • Cancel
  • vasug7
    vasug7 over 7 years ago in reply to Andrew Beckett

    Hi Andrew, inspired by your code for the genericDAC, I tried to tweak it somewhat to make a code for a genericADC.

    PFA the SKILL and Verilog - A code below, with the lines in bold where I made the changes.

    SKILL code


    /********************************************************************
    * *
    * abCreateGenericADCViews(library @key (cell "genericADC")) *
    * *
    * Create the symbol pcell, the veriloga shadow pcell, and the CDF *
    * for the genericADC. This is to allow a variable width pin on *
    * the genericADC model, which normally isn't supported in Virtuoso. *
    * *
    ********************************************************************/
    procedure(abCreateGenericADCViews(library @key (cell "genericADC"))
    let( (pcellId (view "symbol") (viewType "schematicSymbol")
    tempFile tempPort params)
    unless(ddGetObj(library)
    error("Couldn't open library %L" library)
    )

    when(ddGetObj(library cell "symbol")
    ddDeleteObj(ddGetObj(library cell "symbol"))
    )

    ;--------------------------------------------------------------------
    ; Create the symbol pcell
    ;--------------------------------------------------------------------
    pcellId=eval(`pcDefinePCell(
    list(ddGetObj(,library) ,cell ,view ,viewType)

    ;----------------------------------------------------------------
    ; Formal parameters
    ;----------------------------------------------------------------
    (
    (bits 4)
    )

    ;----------------------------------------------------------------
    ; Code itself
    ;----------------------------------------------------------------
    let(( cv netIn netClk 
    netOut figIn figClk figOut hp ps pl bw lh
    pxc label)

    cv = pcCellView

    ;----------------------------------------------------------------
    ; Various dimensions
    ;----------------------------------------------------------------
    ; half pin size
    hp=0.025
    ; pin spacing
    ps=0.125
    ; pin length
    pl=0.250
    ; box width
    bw=1.4375
    ; label height
    lh=0.0625
    ; param label x coord
    pxc=0.5

    ;----------------------------------------------------------------
    ; create the shapes - first the pins
    ;----------------------------------------------------------------
    figIn = dbCreateRect(cv list("pin" "drawing") list(-hp:-hp hp:hp)) 
    dbCreateLine(cv list("device" "drawing") list(0:0 pl:0))
    figClk = dbCreateRect(cv list("pin" "drawing") list(-hp:-ps-hp hp:-ps+hp))
    dbCreateLine(cv list("device" "drawing") list(0:-ps pl:-ps))
    figOut = dbCreateRect(cv list("pin" "drawing")
    list(2*pl+bw-hp:-hp 2*pl+bw+hp:hp)
    ) ; dbCreateRect
    dbCreateLine(cv list("device" "drawing") list(pl+bw:0 2*pl+bw:0))
    ;----------------------------------------------------------------
    ; Then the boxes
    ;----------------------------------------------------------------
    dbCreateRect(cv list("device" "drawing") list(pl:-2*ps pl+bw:ps))
    dbCreateRect(cv list("instance" "drawing") list(0:-2*ps 2*pl+bw:ps))

    ;----------------------------------------------------------------
    ; create the nets
    ;----------------------------------------------------------------
    netIn=dbMakeNet(cv "in")
    netClk=dbMakeNet(cv "clk")
    netOut=dbMakeNet(cv sprintf(nil "out<%d:0>" bits-1))
    ;----------------------------------------------------------------
    ; create the terminals
    ;----------------------------------------------------------------
    dbCreateTerm(netIn netIn~>name "input")
    dbCreateTerm(netClk netClk~>name "input")
    dbCreateTerm(netOut netOut~>name "output")
    ;----------------------------------------------------------------
    ; create the pins
    ;----------------------------------------------------------------
    dbCreatePin(netIn figIn)
    dbCreatePin(netClk figClk)
    dbCreatePin(netOut figOut)

    ;----------------------------------------------------------------
    ; Put some labels for the pins
    ;----------------------------------------------------------------
    dbCreateLabel(cv list("pin" "drawing") pl+ps/2:0
    netIn~>name "centerLeft" "R0" "stick" lh)
    dbCreateLabel(cv list("pin" "drawing") pl+ps/2:-ps
    netClk~>name "centerLeft" "R0" "stick" lh)
    dbCreateLabel(cv list("pin" "drawing") bw+pl-ps/2:0
    netOut~>name "centerRight" "R0" "stick" lh)

    ;----------------------------------------------------------------
    ; And other symbol labels
    ;----------------------------------------------------------------
    label=dbCreateLabel(cv list("annotate" "drawing7") bw+pl-ps/2:ps*1.5
    "cdsName()" "centerRight" "R0" "stick" lh)
    label~>labelType="ILLabel"
    label=dbCreateLabel(cv list("annotate" "drawing") pxc:0
    "cdsParam(1)" "centerLeft" "R0" "stick" lh)
    label~>labelType="ILLabel"
    label=dbCreateLabel(cv list("annotate" "drawing") pxc:-ps
    "cdsParam(2)" "centerLeft" "R0" "stick" lh)
    label~>labelType="ILLabel"

    dbSetConnCurrent(cv)
    t
    ) ; let
    ))
    dbSave(pcellId)
    dbClose(pcellId)

    ;--------------------------------------------------------------------
    ; Create the pcell in the "shadow" database (netlist.oa) in the
    ; veriloga view. This is so the terminals match in the switch view.
    ; Can't use pcDefinePCell because that creates a "master" OA
    ; database, and this needs to be done as a non-master database (the
    ; master is the veriloga.va file). So this works by creating a file
    ; with the code in, and then using dbDefineProc to associate it with
    ; the cellView (see further down).
    ;--------------------------------------------------------------------
    tempFile=makeTempFileName("/tmp/pccode")
    tempPort=outfile(tempFile)
    pprint(
    'procedure(pcGenCell(cv "d")
    let((pcParams bits)
    pcParams=cv~>parameters
    bits=pcParams~>bits
    unless(fixp(bits) bits=4)
    let((netIn netClk netOut)
    netIn=dbMakeNet(cv "in")
    netClk=dbMakeNet(cv "clk") 
    netOut=dbMakeNet(cv sprintf(nil "out<%d:0>" bits-1)) 
    dbCreateTerm(netIn netIn~>name "input")
    dbCreateTerm(netClk netClk~>name "input") 
    dbCreateTerm(netOut netOut~>name "output") 
    ;----------------------------------------------------
    ; this is to stop the instance being omitted
    ; because there's no hierarchy
    ;----------------------------------------------------
    dbCreateProp(cv "nlAction" "string" "stop")
    dbSetConnCurrent(cv)
    )
    ))
    tempPort
    )
    newline(tempPort)
    close(tempPort)

    ;--------------------------------------------------------------------
    ; Now create the non-master database (that's what the "wc" is for).
    ; Has to create the parameters hier prop and the pcell parameter
    ;--------------------------------------------------------------------
    pcellId=dbOpenCellViewByType(library cell "veriloga" "netlist" "wc")
    params = dbCreateHierProp(pcellId "parameters")
    dbCreateProp(params "bits" "int" 4)
    dbDefineProc(pcellId tempFile)
    dbSave(pcellId)
    dbClose(pcellId)
    deleteFile(tempFile)

    ;------------------------------------------------------------------------
    ; Now create the CDF
    ;------------------------------------------------------------------------

    let( ( cellId cdfId )
    unless( cellId = ddGetObj( library cell )
    error( "Could not get cell %s." cell )
    )
    when( cdfId = cdfGetBaseCellCDF( cellId )
    cdfDeleteCDF( cdfId )
    )
    cdfId = cdfCreateBaseCellCDF( cellId )

    ;;; Parameters
    cdfCreateParam( cdfId
    ?name "bits"
    ?prompt "bits"
    ?defValue 4
    ?type "int"
    ?display "t"
    )
    cdfCreateParam( cdfId
    ?name "fullscale"
    ?prompt "fullscale"
    ?defValue "1.8"
    ?type "string"
    ?display "t"
    ?parseAsNumber "yes"
    ?parseAsCEL "yes"
    )
    cdfCreateParam( cdfId
    ?name "td"
    ?prompt "td"
    ?defValue "0"
    ?type "string"
    ?display "t"
    ?parseAsNumber "yes"
    ?parseAsCEL "yes"
    )
    cdfCreateParam( cdfId
    ?name "tt"
    ?prompt "tt"
    ?defValue "0"
    ?type "string"
    ?display "t"
    ?parseAsNumber "yes"
    ?parseAsCEL "yes"
    )
    cdfCreateParam( cdfId
    ?name "vdd"
    ?prompt "vdd"
    ?defValue "1.8"
    ?type "string"
    ?display "t"
    ?parseAsNumber "yes"
    ?parseAsCEL "yes"
    )
    cdfCreateParam( cdfId
    ?name "thresh"
    ?prompt "thresh"
    ?defValue "0.9"
    ?type "string"
    ?display "t"
    ?parseAsNumber "yes"
    ?parseAsCEL "yes"
    )

    ;;; Properties
    cdfId->formInitProc = ""
    cdfId->doneProc = ""
    cdfId->buttonFieldWidth = 340
    cdfId->fieldHeight = 35
    cdfId->fieldWidth = 350
    cdfId->promptWidth = 175
    ;--------------------------------------------------------------------
    ; note that this needs a netlist proc so that it can
    ; handle the variable number of pins
    ;--------------------------------------------------------------------
    cdfId->viewInfo = '(nil veriloga (nil moduleName "genericADC"
    namePrefix "ahdl" netlistProc abGenericADCNetlistProc stringParameterList
    nil parameterList (bits fullscale td tt vdd thresh))
    )
    cdfSaveCDF( cdfId )
    )
    ) ; let
    )

    /****************************************************************
    * *
    * abGenericADCNetlistProc(inst) *
    * *
    * Netlist procedure to netlist the instance. Mostly standard *
    * other than the list of terminals which is constructuted based *
    * on the bits parameter. *
    * *
    ****************************************************************/
    procedure(abGenericADCNetlistProc(inst)
    let((formatter netlister termList bits)
    formatter=nlGetFormatter(inst)
    netlister=nlGetNetlister(formatter)
    nlPrintInstComments(formatter inst)
    nlPrintIndentString(netlister)
    nlPrintInstName(formatter inst)
    ;----------------------------------------------------------------
    ; Output the correct terminal list
    ;----------------------------------------------------------------
    bits=atoi(nlGetParamStringValue(inst "bits"))
    nlPrintString(netlister " ( ")
    termList=`(@dbProduceMemName(sprintf(nil "out<%d:0>" bits-1)), "in"
    "clk")
    foreach(term termList
    nlPrintString(netlister nlGetTerminalSignalName(inst term) " ")
    )
    nlPrintString(netlister ") ")
    nlPrintModelName(formatter inst)
    nlPrintInstParameters(formatter inst)
    t
    )
    )


    Verilog - A code for the ADC

    `include "constants.vams"
    `include "disciplines.vams"

    module genericADC(out, in, clk);
    parameter integer bits = 4;
    parameter real fullscale = 1.8;
    parameter real td = 0;
    parameter real tt = 0;
    parameter real vdd = 1.8;
    parameter real thresh = 0.9;

    output [0:bits-1] out;
    input clk;
    input in;
    voltage [0:bits-1] out;
    voltage clk;
    voltage in;
    real sample, midpoint;
    integer result[0:bits-1];
    genvar i;

    analog begin
    @(cross(V(clk) - thresh, 1) or initial_step) begin
    sample = V(in);
    midpoint = fullscale/2.0;
    for(i = bits - 1; i>=0; i = i-1) begin
    if(sample > midpoint) begin
    result[i] = vdd;
    sample = sample - midpoint;
    end else begin
    result[i] = 0.0;
    end
    sample = 2.0*sample;
    end
    end
    for(i=0; i< bits; i = i + 1) begin
    V(out[i]) <+ transition(result[i], td, tt);
    end
    end
    endmodule


    The symbol generates perfectly fine. But when I try to simulate my test_bench using Virtuoso, I get the following error.

    Error in the CIW - 

    *Error* get_string: argument #1 should be either a string or a symbol (type template = "S") at line 270 of file "/users/vasug/cadence/Project/work_libs/vasug/cds/genericADC/libInit.il" - (\@dbProduceMemName sprintf(nil "out<%d:0>" (bits - 1)))
    End netlisting Jul 27 19:20:40 2018
    ERROR (OSSHNL-514): Netlist generation failed because of the errors reported above. The netlist might not have been generated at all, or the generated netlist could be corrupt. Fix the reported errors and regenerate the netlist.

    Any hint what is going wrong. I am not familiar with SKILL. I tried looking up the SKILL language user-guide made available with my distribution but to no avail.

    Thanks.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 7 years ago in reply to vasug7

    The main problem (without trying it) is the line with dbProduceMenName. I've corrected it below. The comma is not a separator between the arguments, but it's a way of specifying a quoted list (note the quote is a backquote rather than the usual forward quote) and then anything followed by , is evaluated rather than quoted. The ,@ is a way of splicing in a list.

    termList=`(,@dbProduceMemName(sprintf(nil "out<%d:0>" bits-1)) "in"
    "clk")

    The other issue that I noticed is that you have a bus reversal between the pcell code and the VerilogA. I'd define the bus in the verilogA as:

    output [bits-1:0] out;
    voltage [bits-1:0] out;

    Regards,

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • vasug7
    vasug7 over 7 years ago in reply to Andrew Beckett

    Added a comma (:|) and it worked like magic!!

    Thanks again.

    I'll be jumping to complex circuits now, any suggestions where one can learn the basics of SKILL and other language resources that you used in your code?

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 7 years ago in reply to vasug7

    The best way to start is to read the SKILL Language User Guide. I suggest you use the Help menu in Virtuoso and type in the box at the top "SKILL Language User Guide" and this should take you to the documentation. This is written as a book on programming. Once you've mastered the basics, you could then look at some of the various application SKILL reference manuals to see how to use various functions - although I would say the quickest way to start is to attend a Cadence SKILL Programming class (look at Services->Training at the top of this web page). That covers the language plus some application stuff.

    The example here is maybe not the simplest, as it involves several pieces, and particularly getting the pcell for the veriloga view itself is mildly tricky if you don't know how to approach it (it's actually the first time I've tried doing this for a veriloga model)

    Regards,

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Anusha Kumar
    Anusha Kumar over 4 years ago in reply to Andrew Beckett

    Hi Andrew,

    Actually I'm just beginner in Verilog A.

    Thq for solution,I tired your code and with steps you mentioned it was easy and i was successful.

    I just tired to implement this DAC module with my design but I'm not able to change the parameters such threshold.

    The parameters much be changed both in Verilog A code and Skill code is that right ?

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
>

Community Guidelines

The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.

© 2025 Cadence Design Systems, Inc. All Rights Reserved.

  • Terms of Use
  • Privacy
  • Cookie Policy
  • US Trademarks
  • Do Not Sell or Share My Personal Information