Verilog-A pwl implementation using arrays for time/voltage input
`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
System-Verilog pwl implementation
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