示例#1
0
def characterize_casc_amp(env_list,
                          fg_list,
                          w_list,
                          db_list,
                          vbias_list,
                          vload_list,
                          vtail_list,
                          vmid_list,
                          vcm,
                          vdd,
                          vin_max,
                          cw,
                          rw,
                          fanout,
                          ton,
                          k_settle_targ,
                          verr_max,
                          scale_res=0.1,
                          scale_min=0.25,
                          scale_max=20):
    # compute DC transfer function curve and compute linearity spec
    results = solve_casc_diff_dc(env_list,
                                 db_list,
                                 w_list,
                                 fg_list,
                                 vbias_list,
                                 vload_list,
                                 vtail_list,
                                 vmid_list,
                                 vdd,
                                 vcm,
                                 vin_max,
                                 verr_max,
                                 num_points=20)

    vin_vec, vmat_list, verr_list, gain_list = results

    # compute settling ratio
    fg_in, fg_casc, fg_load = fg_list[1:]
    db_in, db_casc, db_load = db_list[1:]
    w_in, w_casc, w_load = w_list[1:]
    fzin = 1.0 / (2 * ton)
    wzin = 2 * np.pi * fzin
    tvec = np.linspace(0, ton, 200, endpoint=True)
    scale_list = []
    for env, vload, vtail, vmid in zip(env_list, vload_list, vtail_list,
                                       vmid_list):
        # step 1: construct half circuit
        in_params = db_in.query(env=env,
                                w=w_in,
                                vbs=-vtail,
                                vds=vmid - vtail,
                                vgs=vcm - vtail)
        casc_params = db_casc.query(env=env,
                                    w=w_casc,
                                    vbs=-vmid,
                                    vds=vcm - vmid,
                                    vgs=vdd - vmid)
        load_params = db_load.query(env=env,
                                    w=w_load,
                                    vbs=0,
                                    vds=vcm - vdd,
                                    vgs=vload - vdd)
        circuit = LTICircuit()
        circuit.add_transistor(in_params, 'mid', 'in', 'gnd', fg=fg_in)
        circuit.add_transistor(casc_params, 'd', 'gnd', 'mid', fg=fg_casc)
        circuit.add_transistor(load_params, 'd', 'gnd', 'gnd', fg=fg_load)
        # step 2: get input capacitance
        zin = circuit.get_impedance('in', fzin)
        cin = (1 / zin).imag / wzin
        circuit.add_cap(cin * fanout, 'out', 'gnd')
        # step 3: find scale factor to achieve k_settle
        bin_iter = BinaryIterator(scale_min,
                                  None,
                                  step=scale_res,
                                  is_float=True)
        while bin_iter.has_next():
            # add scaled wired parasitics
            cur_scale = bin_iter.get_next()
            cap_cur = cw / 2 / cur_scale
            res_cur = rw * cur_scale
            circuit.add_cap(cap_cur, 'd', 'gnd')
            circuit.add_cap(cap_cur, 'out', 'gnd')
            circuit.add_res(res_cur, 'd', 'out')
            # get settling factor
            sys = circuit.get_voltage_gain_system('in', 'out')
            dc_gain = sys.freqresp(w=np.array([0.1]))[1][0]
            sgn = 1 if dc_gain.real >= 0 else -1
            dc_gain = abs(dc_gain)
            _, yvec = scipy.signal.step(
                sys, T=tvec)  # type: Tuple[np.ndarray, np.ndarray]
            k_settle_cur = 1 - abs(yvec[-1] - sgn * dc_gain) / dc_gain
            print('scale = %.4g, k_settle = %.4g' % (cur_scale, k_settle_cur))
            # update next scale factor
            if k_settle_cur >= k_settle_targ:
                print('save scale = %.4g' % cur_scale)
                bin_iter.save()
                bin_iter.down()
            else:
                if cur_scale > scale_max:
                    raise ValueError(
                        'cannot meet settling time spec at scale = %d' %
                        cur_scale)
                bin_iter.up()
            # remove wire parasitics
            circuit.add_cap(-cap_cur, 'd', 'gnd')
            circuit.add_cap(-cap_cur, 'out', 'gnd')
            circuit.add_res(-res_cur, 'd', 'out')
        scale_list.append(bin_iter.get_last_save())

    return vmat_list, verr_list, gain_list, scale_list
示例#2
0
def characterize_casc_amp(env_list,
                          lch,
                          intent_list,
                          fg_list,
                          w_list,
                          db_list,
                          vbias_list,
                          vload_list,
                          vtail_list,
                          vmid_list,
                          vincm,
                          voutcm,
                          vdd,
                          vin_clip,
                          clip_ratio_min,
                          cw,
                          rw,
                          fanout,
                          ton,
                          k_settle_targ,
                          scale_min=0.25,
                          scale_max=20):
    # compute DC transfer function curve and compute linearity spec
    ndb, pdb = db_list[0], db_list[-1]
    results = solve_casc_diff_dc(env_list,
                                 ndb,
                                 pdb,
                                 lch,
                                 intent_list,
                                 w_list,
                                 fg_list,
                                 vbias_list,
                                 vload_list,
                                 vtail_list,
                                 vmid_list,
                                 vdd,
                                 vincm,
                                 voutcm,
                                 vin_clip,
                                 clip_ratio_min,
                                 num_points=20)
    vmat_list, ratio_list, gain_list = results
    # compute settling ratio
    fg_tail, fg_in, fg_casc, fg_load = fg_list
    db_tail, db_in, db_casc, db_load = db_list
    w_tail, w_in, w_casc, w_load = w_list
    fzin = 1.0 / (2 * ton)
    wzin = 2 * np.pi * fzin
    tvec = np.linspace(0, ton, 200, endpoint=True)
    scale_list = []
    cin_list = []
    for env, vbias, vload, vtail, vmid, vmat in zip(env_list, vbias_list,
                                                    vload_list, vtail_list,
                                                    vmid_list, vmat_list):
        # step 1: get half circuit parameters and compute input capacitance
        in_par = db_in.query(env=env,
                             w=w_in,
                             vbs=-vtail,
                             vds=vmid - vtail,
                             vgs=vincm - vtail)
        casc_par = db_casc.query(env=env,
                                 w=w_casc,
                                 vbs=-vmid,
                                 vds=voutcm - vmid,
                                 vgs=vdd - vmid)
        load_par = db_load.query(env=env,
                                 w=w_load,
                                 vbs=0,
                                 vds=voutcm - vdd,
                                 vgs=vload - vdd)
        cir = LTICircuit()
        cir.add_transistor(in_par, 'mid', 'in', 'gnd', fg=fg_in)
        cir.add_transistor(casc_par, 'out', 'gnd', 'mid', fg=fg_casc)
        cir.add_transistor(load_par, 'out', 'gnd', 'gnd', fg=fg_load)
        zin = cir.get_impedance('in', fzin)
        cin = (1 / zin).imag / wzin
        cin_list.append(cin)
        # step 3A: construct differential circuit with vin_clip / 2.
        vts, vmps, vmns, vops, vons = vmat[-1, :]
        vinp = vincm + vin_clip / 4
        vinn = vincm - vin_clip / 4
        tail_par = db_tail.query(env=env, w=w_tail, vbs=0, vds=vts, vgs=vbias)
        inp_par = db_in.query(env=env,
                              w=w_in,
                              vbs=-vts,
                              vds=vmns - vts,
                              vgs=vinp - vts)
        inn_par = db_in.query(env=env,
                              w=w_in,
                              vbs=-vts,
                              vds=vmps - vts,
                              vgs=vinn - vts)
        cascp_par = db_casc.query(env=env,
                                  w=w_casc,
                                  vbs=-vmns,
                                  vds=vons - vmns,
                                  vgs=vdd - vmns)
        cascn_par = db_casc.query(env=env,
                                  w=w_casc,
                                  vbs=-vmps,
                                  vds=vops - vmps,
                                  vgs=vdd - vmps)
        loadp_par = db_load.query(env=env,
                                  w=w_load,
                                  vbs=0,
                                  vds=vons - vdd,
                                  vgs=vload - vdd)
        loadn_par = db_load.query(env=env,
                                  w=w_load,
                                  vbs=0,
                                  vds=vops - vdd,
                                  vgs=vload - vdd)
        cir = LTICircuit()
        cir.add_transistor(tail_par, 'tail', 'gnd', 'gnd', fg=fg_tail)
        cir.add_transistor(inp_par, 'midn', 'inp', 'tail', fg=fg_in)
        cir.add_transistor(inn_par, 'midp', 'inn', 'tail', fg=fg_in)
        cir.add_transistor(cascp_par, 'dn', 'gnd', 'midn', fg=fg_casc)
        cir.add_transistor(cascn_par, 'dp', 'gnd', 'midp', fg=fg_casc)
        cir.add_transistor(loadp_par, 'dn', 'gnd', 'gnd', fg=fg_load)
        cir.add_transistor(loadn_par, 'dp', 'gnd', 'gnd', fg=fg_load)
        cir.add_vcvs(0.5, 'inp', 'gnd', 'inac', 'gnd')
        cir.add_vcvs(-0.5, 'inn', 'gnd', 'inac', 'gnd')
        # step 3B: compute DC gain
        cir.add_vcvs(1, 'dac', 'gnd', 'dp', 'dn')
        dc_tf = cir.get_transfer_function('inac', 'dac')
        _, gain_vec = dc_tf.freqresp(w=[0.1])
        dc_gain = gain_vec[0].real
        # step 3C add cap loading
        cload = fanout * cin
        cir.add_cap(cload, 'outp', 'gnd')
        cir.add_cap(cload, 'outn', 'gnd')
        cir.add_vcvs(1, 'outac', 'gnd', 'outp', 'outn')
        # step 4: find scale factor to achieve k_settle
        # noinspection PyUnresolvedReferences
        scale_swp = np.arange(scale_min, scale_max, 0.25).tolist()
        max_kset = 0
        opt_scale = 0
        for cur_scale in scale_swp:
            # add scaled wired parasitics
            cap_cur = cw / 2 / cur_scale
            res_cur = rw * cur_scale
            cir.add_cap(cap_cur, 'dp', 'gnd')
            cir.add_cap(cap_cur, 'dn', 'gnd')
            cir.add_cap(cap_cur, 'outp', 'gnd')
            cir.add_cap(cap_cur, 'outn', 'gnd')
            cir.add_res(res_cur, 'dp', 'outp')
            cir.add_res(res_cur, 'dn', 'outn')
            # get settling factor
            sys = cir.get_state_space('inac', 'outac')
            _, yvec = scipy.signal.step(
                sys, T=tvec)  # type: Tuple[np.ndarray, np.ndarray]
            k_settle_cur = yvec[-1] / dc_gain
            # print('scale = %.4g, k_settle = %.4g' % (cur_scale, k_settle_cur))
            # update next scale factor
            if k_settle_cur > max_kset:
                max_kset = k_settle_cur
                opt_scale = cur_scale
            else:
                # k_settle is decreasing, break
                break
            if max_kset >= k_settle_targ:
                break

            # remove wire parasitics
            cir.add_cap(-cap_cur, 'dp', 'gnd')
            cir.add_cap(-cap_cur, 'dn', 'gnd')
            cir.add_cap(-cap_cur, 'outp', 'gnd')
            cir.add_cap(-cap_cur, 'outn', 'gnd')
            cir.add_res(-res_cur, 'dp', 'outp')
            cir.add_res(-res_cur, 'dn', 'outn')

        if max_kset < k_settle_targ:
            raise ValueError('%s max kset = %.4g @ scale = %.4g, '
                             'cannot meet settling time spec.' %
                             (env, max_kset, opt_scale))
        scale_list.append(opt_scale)

    return vmat_list, ratio_list, gain_list, scale_list, cin_list