Hello,
I am trying to model a more accurate op-amp with a current limiting function (different sinking and sourcing currents) and some intuitive parameters for tuning the op-amp characteristics. So I used a transfer function, H(s), to model the ideal op-amp. And then tried to add the current limiting function which is in vain. Could someone give some suggestions? Thanks in advance.
p.s. I am aware of the convergence issue about the numerical difficulties. However, I cannot say I am 100% understand the issue. And I found it some what confusing and causing some difficulties to make two limitations.
Here's my code... I marked out some lines I tried before. So you might have to tweak the code a little bit.
Code:`include "disciplines.vams"
`include "constants.vams"
`define dB2dec(x) pow(10,x/20)
module opamp(vinp,vinm,vdd,vss,voutp);
inout vinp,vinm,vdd,vss;
inout voutp;
electrical vinp,vinm,vdd,vss,voutp;
electrical n1,n2;
parameter real gain = 90 from (0:inf), // open loop gain in dB
three_dB_freq = 100 from (0:inf), // 3dB frequency
rin = 10M from (0:inf), // input resistance
cin = 1p from [0:inf), // input capacitance
ioutp_max = 20u from (0:inf), // max. classAB PMOS output current
ioutn_max = 10u from (0:inf), // max. classAB NMOS output current
rout = 1k from (0:inf), // output resistance
cout = 1p from (0:inf), // output capacitance
vout_offset = 0,
volc = 1;
real vin,vout,vout0;
real voutmax,voutmin;
real iout;
real qin = 0;
real qout = 0;
real cond1, cond2;
analog begin
vin = V(vinp,vinm);
vout = V(voutp,vss);
voutmax = V(vdd);
voutmin = V(vss);
qin = cin * vin;
I(vinp,vinm) <+ vin / rin + ddt(qin);
vout0 = laplace_nd(vin*`dB2dec(gain),{1,0},{1,1/(`M_TWO_PI*three_dB_freq)}) + vout_offset;
iout = (vout0 - vout) / rout;
/* try
//cond1 = (vout0-voutmax)/voutmax - (iout-ioutp_max)/ioutp_max;
//cond2 = (vout0-voutmin) - (iout-(-ioutn_max));
//@(cross(cond1,0))
//;
//@(cross(cond2,0))
//;
//if(cond1*cond2<0) begin
// if(cond1>0)
// vout0 = voutmax;
// else
// vout0 = voutmin;
//end
//else begin
// if(cond1<0)
// iout = ioutp_max;
// else if (cond2>0)
// iout = -ioutn_max;
//end
end of try*/
/* another try
// output current limitation
//case (1)
// iout > ioutp_max : iout = ioutp_max;
// iout < -ioutn_max : iout = -ioutn_max;
//endcase
// output voltage limitation
//if (vout >= vout_offset)
// iout = iout*tanh(volc*(voutmax-vout));
//else
// iout = iout*tanh(volc*abs(voutmin-vout));
//iout = slew(iout,ioutp_max*three_dB_freq,-ioutn_max*three_dB_freq);
//I(voutp,vss) <+ -iout;
end of another try*/
// Here just some codes to let this can be run like an ideal model.
I(n1,n2) <+ iout;
V(n2,vss) <+ idt(iout) / cout;
V(voutp,vss) <+ V(n2,vss);
end
endmodule
Here's a testbench. (using HSPICE)
Code:.options post=1
$.options method = gear2only
.param VH = 5
.param VL = 1
Vin in 0 pwl(5u VL 5.1u VH 25u VH 25.1u VL)
Vdd Vdd 0 6
Vss Vss 0 0
Vfb Vfb VOUT DC=0
Xopamp1 in Vfb Vdd Vss VOUT opamp
.param RP=3k
.param CP=30p
R1 VOUT V1 'RP/3'
R2 V1 V2 'RP/3'
R3 V2 V3 'RP/3'
C1 V1 0 'CP/3'
C2 V2 0 'CP/3'
C3 V3 0 'CP/3'
.tran 1n 30u
.probe tran v(*) i(*)
.end