• 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. Functional Verification
  3. Capacitor model SystemVerilog

Stats

  • Locked Locked
  • Replies 8
  • Subscribers 68
  • Views 22895
  • 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

Capacitor model SystemVerilog

NE555
NE555 over 9 years ago

Hi to everyone, 

I'm working on systemverilog code for my mixed signal IC, to improve the velocity of the simulation. For the resistor and capacitor connected to ground i use the model from cadence, but now i need the model for a capacitor without a pin connected to ground.

to made it i fuse the code of resistor (with P and N terminal) and the code of capacitor connected to ground. the code work and the behavior of component is ok, but not the tension and current value. the code is this:

`timescale 1ns/1ps
import EE_pkg::*;

module  Cap(
inout EEnet P,
inout EEnet N,
input real cval
);


parameter real vtol=1e-6;    // voltage tolerance for iterations.
parameter real rmin=1e-4;    // minimum differential resistance.
parameter real rmax=1e2;    // "off" resistance for Z
parameter real itermax=20;   // max iterations at one timepoint.
parameter real rs=1;        // voltage tolerance for iterations.

real Rval;                        // limited versions of rs inputs
real VPin,RPin,VNin,RNin;              // inputs with small changes ignored
real VPeff,RPeff,VNeff,RNeff;          // effective external V & R values
real VPdrv,RPdrv,VNdrv,RNdrv;          // voltage & resistance output drives
real TPdrv=0,TNdrv=0;                  // time of most recent driver updates
integer iterP=0,iterN=0;               // number iterations at this timepoint


parameter real ic=0;       // initial capacitor voltage at time zero
parameter real tinc=1e-10;  // timestep for computing voltage update (sec)
parameter real itol=1e-7;  // minimum current

real Vcap=ic,Tcap=0,Icap=0; // voltage on capacitor @ time, and current value
real Inew;                  // recomputed current at end of interval
real tinct = tinc*1s;       // tinc converted to timescale units
real Vout,Tout;             // voltage value to output pin (limited update)
reg ck=0;
always #(tinct) ck=!ck;   // toggle clock at defined rate

real Vcapn=ic,Tcapn=0,Icapn=0; // voltage on capacitor @ time, and current value
real Inewn;                  // recomputed current at end of interval


initial begin   // block starts in "off" mode, effective values are as measured:
  VPdrv=0;
  RPdrv=rmax;
  VNdrv=0;
  RNdrv=rmax;
  VPeff=P.V;
  RPeff=P.R;
  VNeff=N.V;
  RNeff=N.R;
end

// update VPin,RPin,VNin,RNin but skip LSB type changes:
always @(P.V,P.R) begin
  if ((abs(P.V-VPin)<1e-14)==1'b0)       VPin=P.V;
  if ((abs(P.R-RPin)<=RPin*1e-14)==1'b0) RPin=P.R;
end
always @(N.V,N.R) begin
  if ((abs(N.V-VNin)<1e-14)==1'b0)       VNin=N.V;
  if ((abs(N.R-RNin)<=RNin*1e-14)==1'b0) RNin=N.R;
end

// update Rval whenever rs change, filtering special cases:
always begin
  if (rs<rmin)       Rval=rmin;      // min resistance
  else if (rs>rmax)  Rval=rmax;      // max resistance
  else                 Rval=rs;      // normal resistance
  @(rs);
end

always begin
  if ($realtime>TPdrv) begin        // new timepoint
    TPdrv=$realtime;                // save time value
    iterP=0;                        // start counter
  end
  else begin
    iterP+=1;                       // else increment counter
    if (iterP==itermax) $display(
     "<EE> ERROR: instance %M node P unconverged at T=%.0fns", $realtime);
  end
  if (iterP<=itermax) begin

          RPeff = RPin*RPdrv/(RPdrv-RPin);
 RNeff = RNin*RNdrv/(RNdrv-RNin);



  Inew = (rs==0)? P.I : (P.V-VPeff)/rs;   // compute new current
  Vcap += (Inew+Icap)/2*($realtime-Tcap)/(cval*1s);  // update voltage by I*dT
  Tcap = $realtime;                      // save time of cap computation
  Icap = Inew;
  if (abs(VPeff-Vcap)>vtol) begin  // if enough dV&dT
    VPeff <= Vcap;                        //  update output voltage
    VNeff <= P.V - Vcap;
  end

        end

    @(P.V, P.R, N.V, N.R, cval, ck);
end


assign P = '{VPeff,0,RPdrv};                        // drive output pins
assign N = '{VNeff,0,RNdrv};

endmodule

someone can help me to find the problem?

tanks

  • Cancel
  • NE555
    NE555 over 9 years ago
    i made a new code that work. there is only1 problem... if I send a square waveform, on the rising edge the model work, on the falling edge doesn't work a voltage on the N pin. this is the code: `timescale 1ns/1ps
    import EE_pkg::*;

    module Cap(
    inout EEnet P,
    inout EEnet N,
    input real cval
    );

    parameter real rval=1; // voltage tolerance for iterations.
    parameter real vtol=1e-7; // voltage tolerance for iterations.
    parameter real rmin=1e-4; // minimum differential resistance.
    parameter real rmax=1e10; // "off" resistance for Z
    parameter real itermax=20; // max iterations at one timepoint.
    parameter real rs=1; // voltage tolerance for iterations.

    real Rval; // limited versions of rs inputs

    real v1, v2;

    real VPin,RPin,VNin,RNin; // inputs with small changes ignored
    real VPeff,RPeff,VNeff,RNeff; // effective external V & R values
    real VPdrv,RPdrv,VNdrv,RNdrv; // voltage & resistance output drives
    real TPdrv=0,TNdrv=0; // time of most recent driver updates
    integer iterP=0,iterN=0; // number iterations at this timepoint


    parameter real ic=0; // initial capacitor voltage at time zero
    parameter real tinc=1e-11; // timestep for computing voltage update (sec)
    parameter real itol=1e-7; // minimum current

    real Vcap=ic,Tcap=0,Icap=0; // voltage on capacitor @ time, and current value
    real Inew; // recomputed current at end of interval
    real tinct = tinc*1s; // tinc converted to timescale units
    real Vout,Tout; // voltage value to output pin (limited update)
    reg ck=0;
    always #(tinct) ck=!ck; // toggle clock at defined rate

    real VNeff1; // voltage on capacitor @ time, and current value
    real Inewn; // recomputed current at end of interval


    initial begin // block starts in "off" mode, effective values are
    as measured:
    VPdrv=0;
    RPdrv=rmax;
    VNdrv=0;
    RNdrv=rmax;
    VPeff=P.V;
    RPeff=P.R;
    VNeff1=N.V;
    VNeff1 = ((VNin*RNdrv-RNin*VNdrv)/(RNdrv-RNin));
    VNeff = VNeff1 -Vcap;
    end
    else begin
    VNeff1 = VNin; // previously ways highZ
    RNeff = RNin;
    end
    end
    else begin // external open
    VNeff = VNin;
    RNeff = `Z;
    end
    if ((abs(VNeff-VPdrv)<vtol)==1'b0) VPdrv <= VNeff;
    RPdrv <= (RNeff+Rval<rmax)? RNeff+Rval : `Z;
    end
    else begin // no internal drive
    VNeff = VNin;
    RNeff = RNin;
    VPdrv <= VNin;
    RPdrv <= `Z; // R>1e12 uses Z
    end
    end
    @(VNin,RNin,Rval, Vcap);
    end


    always begin

    Inew = (rs==0)? P.I : ((-VNeff-VPeff)-Vcap)/rs; // compute new current
    Vcap += (((Inew+Icap))*($realtime-Tcap))/(cval*1s); // update


    voltage by I*dT
    Tcap = $realtime; // save time of cap computation
    Icap = Inew;
    if (abs(VPeff-Vcap)>vtol) begin // if enough dV&dT
    end


    @(P.V, P.R, N.V, N.R, cval, ck, VPdrv, VNdrv);
    end


    assign P = '{VPdrv,0,RPdrv}; // drive output pins
    assign N = '{VNdrv,0,RNdrv};

    endmodule
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • tpylant
    tpylant over 9 years ago

    There is some missing code in your initial block. Can you repost the code?

    Tim

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • NE555
    NE555 over 9 years ago

    Hi Tim. this is the code of my capacitor:

    `timescale 1ns/1ps
    import EE_pkg::*;

      module  Cap(
      inout EEnet P,
      inout EEnet N,
      input real cval
      );

      parameter real rval=1;         // Equivalent Series Resistor
      parameter real vtol=1e-7;      // voltage tolerance for iterations.
      parameter real rmin=1e-4;      // minimum differential resistance.
      parameter real rmax=1e10;      // "off" resistance for Z
      parameter real itermax=20;     // max iterations at one timepoint.

      real Rval;                     // limited versions of rval inputs

      real VPin,RPin,VNin,RNin;              // inputs with small changes ignored
      real VPeff,RPeff,VNeff,RNeff;          // effective external V & R values
      real VPdrv,RPdrv,VNdrv,RNdrv;          // voltage & resistance output drives
      real TPdrv=0,TNdrv=0;                  // time of most recent driver updates
      integer iterP=0,iterN=0;               // number iterations at this timepoint


      parameter real ic=0;                  // initial capacitor voltageand current at time zero
      parameter real tinc=1e-11;            // timestep for computingvoltage update (sec)
      parameter real itol=1e-7;             // minimum current tollerance

      real Vcap=ic,Tcap=0,Icap=0;           // voltage on capacitor @time, and current value
      real Inew;                            // recomputed current at end of interval
      real tinct = tinc*1s;                 // tinc converted to timescale units
      real Vout,Tout;                       // voltage value to output pin (limited update)

      reg ck=0;
      always #(tinct) ck=!ck;               // toggle clock at defined rate


     initial begin                          // block starts in "off" mode,effective values are as measured:
       VPdrv=0;
       RPdrv=rmax;
       VNdrv=0;
       RNdrv=rmax;
       VPeff=P.V;
       RPeff=P.R;
       VNeff=N.V;
       RNeff=N.R;
     end


     // update VPin,RPin,VNin,RNin but skip LSB type changes:
     always @(P.V,P.R) begin
       if ((abs(P.V-VPin)<1e-14)==1'b0)       VPin=P.V;
       if ((abs(P.R-RPin)<=RPin*1e-14)==1'b0) RPin=P.R;
     end
     always @(N.V,N.R) begin
       if ((abs(N.V-VNin)<1e-14)==1'b0)       VNin=N.V;
       if ((abs(N.R-RNin)<=RNin*1e-14)==1'b0) RNin=N.R;
     end



     // update Rval whenever rval change, filtering special cases:
     always begin
       if (rval<rmin)       Rval=rmin;          // min resistance
       else if (rval>rmax)  Rval=rmax;      // max resistance
       else                 Rval=rval;              // normal resistance
       @(rval);
     end



     always begin
       if ($realtime>TPdrv) begin                         // new timepoint
         TPdrv=$realtime;                                 // save time value
         iterP=0;                                         // start counter
       end
       else begin
         iterP+=1;                                         // else increment counter
         if (iterP==itermax) $display(
          "<EE> ERROR: instance %M node P unconverged at T=%.0fns", $realtime);
       end
       if (iterP<=itermax) begin
         if (Rval<rmax) begin                // if connected
           if (RPin<rmax && (RPdrv==`Z || RPin!=RPdrv)) begin  // normal case
             if (RPdrv<rmax) begin                            // compute effective vals

              RPeff = RPin*RPdrv/(RPdrv-RPin);            //compute new resistence
              VPeff = ((VPin*RPdrv-RPin*VPdrv)/(RPdrv-RPin)) + Vcap;   //compute mnew tension

             end

             else begin
               VPeff = VPin;        // was undriven
               RPeff = RPin;
             end
           end
           else begin    // external open
             VPeff = VPin;
             RPeff = `Z;
           end
           if ((abs(VPeff-VNdrv)<vtol)==1'b0)  VNdrv <= VPeff;
           RNdrv <= (RPeff+Rval<rmax)? RPeff+Rval : `Z;
         end
         else begin                                                     //no drive (also used for unknown drive)
           VPeff = VPin;
           RPeff = RPin;
           VNdrv <= VPin;
           RNdrv <= `Z;
         end
       end
       @(VPin,RPin,Rval, Vcap);
     end

     always begin
       if ($realtime>TNdrv) begin                                       //new timepoint
         TNdrv=$realtime;                                               //save time value
         iterN=0;                                                       //start counter
       end
       else begin
         iterN+=1;                                                     //else increment counter
         if (iterN==itermax) $display(
          "<EE> ERROR: instance %M node N unconverged at T=%.0fns", $realtime);
       end
       if (iterN<=itermax) begin
         if (Rval<rmax) begin                                           //if connected
           if (RNin<rmax && (RNdrv==`Z || RNin!=RNdrv)) begin // normal case
             if (RNdrv<rmax) begin                                     //compute effective vals


             RNeff = RNin*RNdrv/(RNdrv-RNin);               //new value of resistence
             VNeff = ((VNin*RNdrv-RNin*VNdrv)/(RNdrv-RNin))-Vcap;  //new value of tension

             end
             else begin
               VNeff = VNin;                                           //previously ways highZ
               RNeff = RNin;
             end
           end
           else begin                                                   //external open
             VNeff = VNin;
             RNeff = `Z;
           end
           if ((abs(VNeff-VPdrv)<vtol)==1'b0)  VPdrv <= VNeff;
           RPdrv <= (RNeff+Rval<rmax)? RNeff+Rval : `Z;
         end
         else begin                                                    //no internal drive
           VNeff = VNin;
           RNeff = RNin;
           VPdrv <= VNin;
           RPdrv <= `Z;                                                 //R>1e12 uses Z
         end
       end
       @(VNin,RNin,Rval, Vcap);
     end


      always begin          //Capacitance

        Inew = (Rval==0)? P.I : ((-VNeff-VPeff)-Vcap)/abs(RPdrv);       //compute new current
        Vcap += (((Inew+Icap))*($realtime-Tcap))/(cval*1s);           //update voltage by I*dT
        Tcap = $realtime;                                             //save time of cap computation
        Icap = Inew;

          @(P.V, P.R, N.V, N.R, cval, ck, VPdrv);
      end


      assign P = '{VPdrv,0 ,RPdrv};                        // drive output pins
      assign N = '{VNdrv,0 ,RNdrv};

      endmodule

    this is the code of tb:

    `timescale 1ns/1ps
    import EE_pkg::*;


    module dcdc_ana_tb ();

    EEnet V_in, v1,V_out, vgnd;
    real pvval;

    initial begin
    pvval = 3.6;
    #(300)
    pvval = 0;
    #(300)
    pvval = 3.6;
    #(300)
    pvval = 0;
    end

    assign V_in = '{pvval,0, 0};
    assign vgnd = '{0,0, 0};

    EEnet vcom;

      res              res1(.P(V_in), .N(v1), .rval(1e3));
      res              res2(.P(V_out), .N(vgnd), .rval(1e3));
      Cap              Cap1(.P(v1), .N(V_out), .cval(10e-11));

    endmodule

     

     


    the code of the resistor is the following:

    `timescale 1ns/1ps
    import EE_pkg::*;

    // Shorthand for standard real constants:
    `define Z `wrealZState
    `define X `wrealXState

    module  res(P,N,rval);
    inout EEnet P,N;
    input real rval;

    parameter real vtol=1e-6;    // voltage tolerance for iterations.
    parameter real rmin=1e-4;    // minimum differential resistance.
    parameter real rmax=1e15;    // "off" resistance for Z
    parameter real itermax=20;   // max iterations at one timepoint.

    real Rval, current;                        // limited versions of rval inputs
    real VPin,RPin,VNin,RNin;              // inputs with small changes ignored
    real VPeff,RPeff,VNeff,RNeff;          // effective external V & R values
    real VPdrv,RPdrv,VNdrv,RNdrv;          // voltage & resistance output drives
    real TPdrv=0,TNdrv=0;                  // time of most recent driver updates
    integer iterP=0,iterN=0;               // number iterations at this timepoint

    initial begin   // block starts in "off" mode, effective values are as measured:
      VPdrv=0;
      RPdrv=rmax;
      VNdrv=0;
      RNdrv=rmax;
      VPeff=P.V;
      RPeff=P.R;
      VNeff=N.V;
      RNeff=N.R;
    end

    // update VPin,RPin,VNin,RNin but skip LSB type changes:
    always @(P.V,P.R) begin
      if ((abs(P.V-VPin)<1e-14)==1'b0)       VPin=P.V;
      if ((abs(P.R-RPin)<=RPin*1e-14)==1'b0) RPin=P.R;
    end
    always @(N.V,N.R) begin
      if ((abs(N.V-VNin)<1e-14)==1'b0)       VNin=N.V;
      if ((abs(N.R-RNin)<=RNin*1e-14)==1'b0) RNin=N.R;
    end

    // update Rval whenever rval change, filtering special cases:
    always begin
      if (rval<rmin)       Rval=rmin;      // min resistance
      else if (rval>rmax)  Rval=rmax;      // max resistance
      else                 Rval=rval;      // normal resistance
      @(rval);
    end

    always begin
      if ($realtime>TPdrv) begin        // new timepoint
        TPdrv=$realtime;                // save time value
        iterP=0;                        // start counter
      end
      else begin
        iterP+=1;                       // else increment counter
        if (iterP==itermax) $display(
         "<EE> ERROR: instance %M node P unconverged at T=%.0fns", $realtime);
      end
      if (iterP<=itermax) begin
        if (Rval<rmax) begin                            // if connected
          if (RPin<rmax && (RPdrv==`Z || RPin!=RPdrv)) begin // normal case
            if (RPdrv<rmax) begin                       // compute effective vals
              RPeff = RPin*RPdrv/(RPdrv-RPin);

           /* if (RPeff<=rmin) VPeff = VPin;            // ignore equiv if tiny R
              else */          VPeff = (VPin*RPdrv-RPin*VPdrv)/(RPdrv-RPin);
            end
            else begin
              VPeff = VPin;                             // was undriven
              RPeff = RPin;
            end
          end
          else begin                                    // external open
            VPeff = VPin;
            RPeff = `Z;
          end
          if ((abs(VPeff-VNdrv)<vtol)==1'b0)  VNdrv <= VPeff;
          RNdrv <= (RPeff+Rval<rmax)? RPeff+Rval : `Z;
        end
        else begin            // no drive (also used for unknown drive)
          VPeff = VPin;
          RPeff = RPin;
          VNdrv <= VPin;
          RNdrv <= `Z;
        end
      end
      @(VPin,RPin,Rval);
    end

    always begin
      if ($realtime>TNdrv) begin        // new timepoint
        TNdrv=$realtime;                // save time value
        iterN=0;                        // start counter
      end
      else begin
        iterN+=1;                       // else increment counter
        if (iterN==itermax) $display(
         "<EE> ERROR: instance %M node N unconverged at T=%.0fns", $realtime);
      end
      if (iterN<=itermax) begin
        if (Rval<rmax) begin                            // if connected
          if (RNin<rmax && (RNdrv==`Z || RNin!=RNdrv)) begin // normal case
            if (RNdrv<rmax) begin                      // compute effective vals
              RNeff = RNin*RNdrv/(RNdrv-RNin);
          /*  if (RNeff<=rmin) VNeff = VNin;            // ignore equiv if tiny R
              else */          VNeff = (VNin*RNdrv-RNin*VNdrv)/(RNdrv-RNin);
            end
            else begin
              VNeff = VNin;                             // previously ways highZ
              RNeff = RNin;
            end
          end
          else begin                                    // external open
            VNeff = VNin;
            RNeff = `Z;
          end
          if ((abs(VNeff-VPdrv)<vtol)==1'b0)  VPdrv <= VNeff;
          RPdrv <= (RNeff+Rval<rmax)? RNeff+Rval : `Z;
        end
        else begin                                      // no internal drive
          VNeff = VNin;
          RNeff = RNin;
          VPdrv <= VNin;
          RPdrv <= `Z;                                  // R>1e12 uses Z
        end
      end
      @(VNin,RNin,Rval);
    end


    assign P = '{VPdrv,0,RPdrv};                        // drive output pins

    assign N = '{VNdrv,0 ,RNdrv};

    endmodule


    the model of the resistor is the model made by cadence.

    The simulation circuit is very simple: a pulse generator with period 600nS, a resistor, capacitor and another resistor. the circuit and the correct resoult are the following ( sorry if I use multisim as simulator :)..... )

    the image is on my website, the first is of the correct result:

    the result with my code in system Verilog is the following:

    on the firs part, on the rising edge all both pin signal is right. on the falling edge the signal V1 is right, the signal Vout go down only for 0.1V, there is something that block the negative peak. I try to solve this but nothing.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • vlella
    vlella over 9 years ago
    Hi Luigi,
    I am interested in your work and model you have written. I would like to know if you were able to solve the problem on the negative edge as you described. If you did could you please share it.
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • NE555
    NE555 over 9 years ago
    Unfortunately, after 1 week of work without a good result I post my problem here but no one help me, so, I stop to search a solution too....

    Why you don't try to search a solution ? :) :) :)
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Raj Mitra
    Raj Mitra over 9 years ago

    Hi,

    I would like to suggest a slightly different approach using a method called State Space Solver. I have attached it

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Raj Mitra
    Raj Mitra over 9 years ago

    Continued -

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • ronvogelsong
    ronvogelsong over 9 years ago

    That problem has nothing to do with your model at all!  The model is working fine.  It is the EE_pkg itself that is imposing the limitation.  If you'll look inside the resolution function in EE_pkg, you'll see that it has limits specified for the max high and low range for resolved output voltage.  Currently they default to VHI=5.1, VLO=-0.1.  You'll need to edit those to be wider so that negative voltages will pass through without being bounded.  These limits were included in the model so that current drive into open-circuited pins would be limited to some reasonable high and low values rather than being unbounded, but the default values are obviously overly restrictive for general purpose systems.  So if you change them to for example VHI=999, VLO=-999, you'll get the operation that you expect.

    • 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