The Designer's Guide Community Forum
https://designers-guide.org/forum/YaBB.pl
Design Languages >> Verilog-AMS >> is possible to write model for piecewise linear source
https://designers-guide.org/forum/YaBB.pl?num=1270820173

Message started by seefree on Apr 9th, 2010, 6:36am

Title: is possible to write model for piecewise linear source
Post by seefree on Apr 9th, 2010, 6:36am

Hi there,

Is it possible to write a pwl voltage source model in veriloga? I want to use a pwl voltage source with an enable signal, whenever the enable is high, the pwl source starts to work. The problem is, I don't know how to define the number of pairs for the model for different simulations.

Thanks,

Title: Re: is possible to write model for piecewise linear source
Post by Boris Troyanovsky on Apr 9th, 2010, 10:32am

Here's a Verilog-A pwl implementation using arrays for time/voltage input. It doesn't have the enable feature (not sure what the goal there would be), but you should be able to add that in.


Code:
`include "disciplines.vams"

module pwl(out);
output out;
electrical out;

parameter integer N = 1 from [2:inf);parameter real t[1:N] = {N{0}};
parameter real y[1:N] = {N{0}};

analog begin : blk
integer nxt_i;
real yp, tp, slope;
integer err;

       @(initial_step) begin
               nxt_i = 1;
               yp = y[1];
               tp = 0.0;
       end

       @(timer(t[nxt_i])) begin
               yp = y[nxt_i];
               tp = t[nxt_i];

               if(nxt_i < N) begin
                       nxt_i = nxt_i + 1;
                       if(t[nxt_i] - tp <= 0) begin
                               err = 1;
                               $debug("Non monotonic time sequence: t[%d] == %e, t[%d] == %e", nxt_i-1, tp, nxt_i, t[nxt_i]);
                               $finish;
                       end
                       if(!err)
                               slope = (y[nxt_i] - yp)/(t[nxt_i] - tp);
               end
       end

       if(!err)
               V(out) <+ yp + slope*($realtime - tp);

end

endmodule

Title: Re: is possible to write model for piecewise linear source
Post by Boris Troyanovsky on Apr 9th, 2010, 10:40am

... and here's one if you prefer string input for the pwl (e.g., pwl="0.0, 0.0, 0.5, 1.1, 1.0, -1.1,..."). It does use the non-standard string .len() operator from System-Verilog, and so may not be suitable for your application.


Code:
module strpwl(p, n);
  electrical p, n;
  inout p, n;

  parameter string pwl = "";
  parameter        dcval = 0.0;
 

  analog function real scanval;
     input s;
     inout pos;
     string s;
     integer pos;
     integer ipos;
     string  valstr;
           
     begin
        ipos = pos;
        while(pos < s.len() && s.substr(pos, pos) != ",")
          pos = pos+1;

        valstr = s.substr(ipos, pos-1);
        if(1 == $sscanf(valstr, "%g", scanval))
          pos = pos+1;
        else
          pos = -1;  // Error indicator
     end
  endfunction

  integer pos = 0;
  real    tnext, vnext;
  real    tprev = 0.0;
  real    vprev = dcval;
  real    slope;
 
  integer err;
 
  analog initial begin : blk
     real retVal;

     tprev = 0.0;
     vprev = dcval;
     
     tnext = scanval(pwl, pos);
     vnext = scanval(pwl, pos);
     if (tnext-tprev != 0.0)
         slope = (vnext - vprev)/(tnext - tprev);
     $strobe(tnext, vnext);
  end

  analog begin
     @(timer(tnext)) begin
        tprev = tnext;
        vprev = vnext;
       
        tnext = scanval(pwl, pos);
        vnext = scanval(pwl, pos);

        if(pos > 0)
          begin
             if(tnext - tprev <= 0) begin
                err = 1;
                $debug("Non monotonic time sequence.");
                $finish;
             end
             if(!err)
               slope = (vnext - vprev)/(tnext - tprev);
          end
     end

     if(!err)
       V(p, n) <+ vprev + slope*($abstime - tprev);

  end

endmodule

Title: Re: is possible to write model for piecewise linear source
Post by seefree on Apr 9th, 2010, 10:51am

I will add the enable pin and try the models.

Appreciate your help

Title: Re: is possible to write model for piecewise linear source
Post by seefree on Apr 14th, 2010, 11:25am

This model works in spectre. However, if I run it in ams, I got the ncvlog error message complaining phrase:
   parameter real t[1:N] = {0,1};
It says "In Affirma-AMS, parameter array declaration is not supported"

How can I solve this problem?

Thanks,





Boris Troyanovsky wrote on Apr 9th, 2010, 10:32am:
Here's a Verilog-A pwl implementation using arrays for time/voltage input. It doesn't have the enable feature (not sure what the goal there would be), but you should be able to add that in.


Code:
`include "disciplines.vams"

module pwl(out);
output out;
electrical out;

parameter integer N = 1 from [2:inf);parameter real t[1:N] = {N{0}};
parameter real y[1:N] = {N{0}};

analog begin : blk
integer nxt_i;
real yp, tp, slope;
integer err;

       @(initial_step) begin
               nxt_i = 1;
               yp = y[1];
               tp = 0.0;
       end

       @(timer(t[nxt_i])) begin
               yp = y[nxt_i];
               tp = t[nxt_i];

               if(nxt_i < N) begin
                       nxt_i = nxt_i + 1;
                       if(t[nxt_i] - tp <= 0) begin
                               err = 1;
                               $debug("Non monotonic time sequence: t[%d] == %e, t[%d] == %e", nxt_i-1, tp, nxt_i, t[nxt_i]);
                               $finish;
                       end
                       if(!err)
                               slope = (y[nxt_i] - yp)/(t[nxt_i] - tp);
               end
       end

       if(!err)
               V(out) <+ yp + slope*($realtime - tp);

end

endmodule


Title: Re: is possible to write model for piecewise linear source
Post by patrick on Apr 14th, 2010, 1:42pm

I'm not sure if this would work for you but you could put the pwl breakpoints into a file and use $table_model in the module body to read them in.

Patrick

Title: Re: is possible to write model for piecewise linear source
Post by Marq Kole on May 17th, 2010, 4:11am

Another approach is to create an array variable and assign it a value in an initial step:


Code:
`include "disciplines.vams"

module test (a, b);

 parameter integer npairs = 4;

 inout a, b;
 electrical a, b;

 real times[0:npairs-1], values[0:npairs-1];
 integer i;

 analog begin

   @(initial_step) begin
     times[0] = 0;    values[0] = 0;
     times[1] = 1n;   values[1] = 0.25;
     times[2] = 2n;   values[2] = 0.5;
     times[3] = 5n;   values[3] = 0.75;
   end

   if (times[i+1] < $abstime) begin
     i = i + 1;
     $discontinuity(1);
   end
   V(a, b) <+ (values[i+1] - values[i]) * ($abstime - times[i])/(times[i+1] - times[i]) + values[i];

 end
 
endmodule // test


But first try to use Patrick's suggestion: it is much simpler and more flexible.

Cheers,
Marq

The Designer's Guide Community Forum » Powered by YaBB 2.2.2!
YaBB © 2000-2008. All Rights Reserved.