Branch data Line data Source code
1 : : /*
2 : : * bondwire.cpp - bondwire class implementation
3 : : *
4 : : * Copyright (C) 2006 Bastien Roucaries <roucaries.bastien@gmail.com>
5 : : * Copyright (C) 2007, 2008 Stefan Jahn <stefan@lkcc.org>
6 : : *
7 : : * This is free software; you can redistribute it and/or modify
8 : : * it under the terms of the GNU General Public License as published by
9 : : * the Free Software Foundation; either version 2, or (at your option)
10 : : * any later version.
11 : : *
12 : : * This software is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : : * GNU General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU General Public License
18 : : * along with this package; see the file COPYING. If not, write to
19 : : * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20 : : * Boston, MA 02110-1301, USA.
21 : : *
22 : : * $Id$
23 : : *
24 : : */
25 : :
26 : : /*!\file bondwire.cpp
27 : : \brief Implement a bondwire model
28 : :
29 : : Bibliography:
30 : :
31 : : [1] Microwave Solid State Circuit Design,
32 : : Inder Bahl and Prakash Barthia -- 2nd edition
33 : : 2003 - Wiley interscience
34 : : ISBN 9-471-20755-1
35 : :
36 : : [2] Wikibook Electronics/Inductors
37 : : http://en.wikibooks.org/w/index.php?title=Electronics/Inductors&oldid=497883
38 : : online 2006/11/02
39 : :
40 : : [3] Physical and electrical modeling of bonding wires up to 110 GHz,
41 : : Descharles, C. Algani, C. Mercier, B. Alquie, G.
42 : : Microwave Conference, 2003. 33rd European
43 : : Volume: 2, On page(s): 639- 642 vol.2
44 : : ISBN: 1-58053-834-7
45 : : INSPEC Accession Number: 1262971
46 : : */
47 : :
48 : :
49 : : #if HAVE_CONFIG_H
50 : : # include <config.h>
51 : : #endif
52 : :
53 : : #include "component.h"
54 : : #include "substrate.h"
55 : : #include "bondwire.h"
56 : :
57 : : using namespace qucs;
58 : :
59 : 0 : bondwire::bondwire () : circuit (2) {
60 : 0 : type = CIR_BONDWIRE;
61 : 0 : }
62 : :
63 : :
64 : : /*! create a matching table between model number and string */
65 : : #define TABLE(x) { #x, x }
66 : : /*! array size */
67 : : #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
68 : :
69 : : /*! bondwire model number */
70 : : enum bondwiremodel {
71 : : FREESPACE, /*!< fresspace model */
72 : : MIRROR, /*!< mirror plane model */
73 : : DESCHARLES /*!< Descharles Algani Mercier Alquie model */
74 : : };
75 : :
76 : : /*! model number to string matching table definition */
77 : : struct modeltable_t {
78 : : const char * name;
79 : : int model;
80 : : };
81 : :
82 : : /*! model number to string matching table implementation */
83 : : static const modeltable_t modeltable[] = {
84 : : TABLE(FREESPACE),
85 : : TABLE(MIRROR),
86 : : };
87 : :
88 : :
89 : : /*!\brief Get properties from model.
90 : : * Get properties and fill the class.
91 : : *
92 : : * \todo check values
93 : : */
94 : 0 : void bondwire::getProperties (void) {
95 : : unsigned int i;
96 : :
97 : 0 : R = 0;
98 : 0 : l = getPropertyDouble ("L");
99 : 0 : d = getPropertyDouble ("D");
100 : 0 : h = getPropertyDouble ("H");
101 : 0 : rho = getPropertyDouble ("rho");
102 : 0 : mur = getPropertyDouble ("mur");
103 : :
104 : : /* model used */
105 : 0 : const char * Model = getPropertyString ("Model");
106 [ # # ]: 0 : if (Model == NULL) {
107 : 0 : model = FREESPACE;
108 : 0 : logprint (LOG_STATUS, "Model is not specified force FREESPACE\n");
109 : : } else {
110 : 0 : model = (enum bondwiremodel) -1;
111 [ # # ]: 0 : for (i = 0 ; i < ARRAY_SIZE (modeltable); i++) {
112 [ # # ]: 0 : if (!strcasecmp (modeltable[i].name, Model))
113 : 0 : model = modeltable[i].model;
114 : : }
115 : :
116 [ # # ]: 0 : if (model == -1)
117 : : /* XXXX: how to abort ? */
118 : 0 : logprint (LOG_ERROR, "Model %s not defined\n", Model);
119 : : }
120 : :
121 : : /* For noise */
122 : 0 : temp = getPropertyDouble ("Temp");
123 : :
124 : : /* how to get properties of the substrate, e.g. Er, H */
125 : 0 : substrate * subst = getSubstrate ();
126 : 0 : nr_double_t er = subst->getPropertyDouble ("er");
127 : 0 : nr_double_t h = subst->getPropertyDouble ("h");
128 : 0 : nr_double_t t = subst->getPropertyDouble ("t");
129 : :
130 : : /* Not yet used */
131 : : (void) er;
132 : : (void) h;
133 : : (void) t;
134 : 0 : }
135 : :
136 : : /*! Compute skin depth.
137 : : * \todo Factorize the compution of skin depth in a header file.
138 : : *
139 : : * \param f frequency
140 : : * \param rho bond wire resistivity
141 : : * \param mur relative magnetic permeabillity
142 : : */
143 : 0 : static nr_double_t skindepth (const nr_double_t f,
144 : : const nr_double_t rho, const nr_double_t mur) {
145 : 0 : return std::sqrt (rho / (M_PI * f * MU0 * mur));
146 : : }
147 : :
148 : : /*! Compute resitance of the wire.
149 : : * Resitance of the wire is computed using classical
150 : : * tube model enhanced for case where tube is greater
151 : : * than conductor (i.e. low frequency case).
152 : : *
153 : : * \todo Offer other resistance model for
154 : : * instance exponential decay and bessel function exact
155 : : * computation. But I do not know it is worth the effort.
156 : : *
157 : : * \todo Factorise the resistance model.
158 : : */
159 : 0 : nr_double_t bondwire::resistance (const nr_double_t f) const {
160 : : nr_double_t delta, rout, rin;
161 : 0 : rout = d / 2;
162 [ # # ]: 0 : if (f > 0.0) {
163 : 0 : delta = skindepth (f, rho, mur);
164 : 0 : rin = rout - delta;
165 [ # # ]: 0 : if (rin < 0.0)
166 : 0 : rin = 0.0;
167 : : }
168 : : else
169 : 0 : rin = 0.0;
170 : :
171 : 0 : return (rho * M_1_PI * l) / (rout * rout - rin * rin);
172 : : }
173 : :
174 : :
175 : : /*! Compute correction factor.
176 : : * According to [1] pp63 (2.30a-b) correction factor
177 : : * is such as:
178 : : * \f[
179 : : * C = 0.25 \tanh \frac{4\delta}{d}
180 : : * \f]
181 : : * where \f$\delta\f$ is the well known skin depth.
182 : : *
183 : : * \param f frequency
184 : : * \param d bond wire diameter
185 : : * \param rho bond wire resistivity
186 : : * \param mur relative magnetic permeabillity
187 : : *
188 : : * However according to [2] it seems that the author of [1] do the
189 : : * assumption of \f$\mu_r=1\f$ therefore rewrite the equation such as:
190 : : *
191 : : * \f[
192 : : * C = \frac{\mu_r}{4} \tanh \frac{4\delta}{d}
193 : : * \f]
194 : : *
195 : : * \return mur/4 if rho is zero, otherwise C
196 : : * \todo Check domain validity for round C factor.
197 : : */
198 : 0 : static nr_double_t correctionfactor (const nr_double_t f,
199 : : const nr_double_t d,
200 : : const nr_double_t rho,
201 : : const nr_double_t mur) {
202 : : /* skin depth */
203 : : nr_double_t delta;
204 : :
205 [ # # ][ # # ]: 0 : if (f > 0.0 && rho > 0.0) {
206 : 0 : delta = skindepth (f, rho, mur);
207 [ # # ]: 0 : if (delta / d < 1e-2)
208 : 0 : return delta / d;
209 : : else
210 : 0 : return (mur / 4) * std::tanh ((4 * delta) / d);
211 : : }
212 : 0 : return mur / 4;
213 : : }
214 : :
215 : : /*! Compute free space inductance.
216 : : According to [1] pp63 (2.29) free space inductance (in nH)
217 : : is such as (\f$l\f$ in micrometers):
218 : :
219 : : \f[
220 : : L = 2\times10^{-4} l \left[
221 : : \ln\left\{ \frac{2l}{d}
222 : : + \sqrt{1 + \left(\frac{2l}{d}\right)^2} \right\}
223 : : + \frac{d}{2l} - \sqrt{1+\left(\frac{d}{2l}\right)^2}
224 : : + C \right]
225 : :
226 : : \f]
227 : :
228 : : According to [2] self inductance is (in H with l in m):
229 : : \f[
230 : : L = \frac{\mu_0}{2\pi} l\left[
231 : : \ln\left\{ \frac{2l}{d}
232 : : + \sqrt{1 + \left(\frac{2l}{d}\right)^2} \right\}
233 : : + \frac{d}{2l} - \sqrt{1+\left(\frac{d}{2l}\right)^2}
234 : : + \frac{\mu_r}{4} \right]
235 : :
236 : : \f]
237 : :
238 : : Finally we will use (in H with l in m):
239 : : \f[
240 : : L = \frac{\mu_0}{2\pi} l\left[
241 : : \ln\left\{ \frac{2l}{d}
242 : : + \sqrt{1 + \left(\frac{2l}{d}\right)^2} \right\}
243 : : + \frac{d}{2l} - \sqrt{1+\left(\frac{d}{2l}\right)^2}
244 : : + C \right]
245 : :
246 : : \f]
247 : :
248 : : \param f frequency
249 : : \param d bond wire diameter
250 : : \param l bond wire length (in meters)
251 : : \param rho bond wire resistivity
252 : : \param mur relative magnetic permeabillity
253 : : */
254 : 0 : nr_double_t bondwire::Lfreespace (const nr_double_t f) const {
255 : 0 : nr_double_t _2ld = (2.0 * l) / d;
256 : 0 : nr_double_t d2l = d / (2.0 * l);
257 : : nr_double_t tmp;
258 : :
259 : 0 : tmp = std::log (_2ld + std::sqrt (1 + _2ld * _2ld));
260 : 0 : tmp += d2l - std::sqrt (1 + d2l * d2l);
261 : 0 : tmp += correctionfactor (f, d, rho, mur);
262 : :
263 : 0 : return MU0 * (M_1_PI / 2) * l * tmp;
264 : : }
265 : :
266 : :
267 : : /*! Compute inductance modeling ground plane effect.
268 : : According to [1] pp64 (2.32) inductance (in nH)
269 : : is such as (\f$l\f$ in micrometers):
270 : :
271 : : \f[
272 : : L = 2\times10^{-4} l \left[
273 : : \ln \frac{4h}{d}
274 : : + \ln \frac{l+\sqrt{l^2+d^2/4}}{l+\sqrt{l^2+4h^2}}
275 : : + \sqrt{1+\frac{4h^2}{l^2}} - \sqrt{1+\frac{d^2}{4l^2}}
276 : : - 2 \frac{h}{l} + \frac{d}{2l}
277 : : \right]
278 : :
279 : : \f]
280 : :
281 : : Finally we will use (in H with l in m):
282 : : \f[
283 : : L = \frac{\mu_0}{2\pi} l \left[
284 : : \ln \frac{4h}{d}
285 : : + \ln \frac{l+\sqrt{l^2+d^2/4}}{l+\sqrt{l^2+4h^2}}
286 : : + \sqrt{1+\frac{4h^2}{l^2}} - \sqrt{1+\frac{d^2}{4l^2}}
287 : : - 2 \frac{h}{l} + \frac{d}{2l}
288 : : \right]
289 : : \f]
290 : :
291 : : \note Mirror is a strange model that is frequency independent.
292 : : Whereas computations are valid, hypothesis are arguable.
293 : : Indeed, they did the assumption that the ground plane is
294 : : perfect that is really a zero order model in the high
295 : : frequency domain.
296 : : */
297 : 0 : nr_double_t bondwire::Lmirror (void) const {
298 : : nr_double_t tmp;
299 : :
300 : : /* compute \$\ln \frac{l+\sqrt{l^2+d^2/4}}{l+\sqrt{l^2+4h^2}}\$ */
301 : 0 : tmp = std::log ((l + std::sqrt (l * l + d * d / 4)) / (l + std::sqrt (l * l + 4 * h * h)));
302 : 0 : tmp += std::log (4 * h / d);
303 : 0 : tmp += std::sqrt (1 + 4 * h * h / (l * l));
304 : 0 : tmp -= std::sqrt (1 + d * d / (4 * l * l));
305 : 0 : tmp -= 2 * h / l;
306 : 0 : tmp += d / (2 * l);
307 : :
308 : 0 : return MU0 * (M_1_PI / 2) * l * tmp;
309 : : }
310 : :
311 : :
312 : : /*! Compute Y matrix of bond wire.
313 : : */
314 : 0 : matrix bondwire::calcMatrixY (const nr_double_t f) {
315 : : nr_double_t Lw;
316 : 0 : L = 0;
317 : :
318 [ # # # ]: 0 : switch (model) {
319 : : case MIRROR:
320 : 0 : L = Lmirror ();
321 : 0 : R = resistance (f);
322 : 0 : break;
323 : : case FREESPACE:
324 : 0 : L = Lfreespace (f);
325 : 0 : R = resistance (f);
326 : 0 : break;
327 : : default:
328 : 0 : break;
329 : : }
330 : :
331 : 0 : Lw = L * 2 * M_PI * f;
332 : :
333 : : /* build Y-parameter matrix */
334 [ # # ]: 0 : nr_complex_t yL = 1.0 / nr_complex_t (R, Lw);
335 : :
336 [ # # ]: 0 : matrix Y (2);
337 [ # # ]: 0 : Y.set (NODE_1, NODE_1, +yL);
338 [ # # ]: 0 : Y.set (NODE_1, NODE_2, -yL);
339 [ # # ]: 0 : Y.set (NODE_2, NODE_1, -yL);
340 [ # # ]: 0 : Y.set (NODE_2, NODE_2, +yL);
341 : 0 : return Y;
342 : : }
343 : :
344 : : /*! Initialize S parameter simulation. */
345 : 0 : void bondwire::initSP (void) {
346 : 0 : allocMatrixS ();
347 : 0 : getProperties ();
348 : 0 : }
349 : :
350 : : /*! Compute S parameters.
351 : : *! Reuse computed Y matrix.
352 : : */
353 : 0 : void bondwire::calcSP (const nr_double_t frequency) {
354 [ # # ][ # # ]: 0 : setMatrixS (ytos (calcMatrixY (frequency)));
[ # # ][ # # ]
[ # # ]
355 : 0 : }
356 : :
357 : : /*! Save self-inductance and resistance. */
358 : 0 : void bondwire::saveCharacteristics (nr_double_t) {
359 : 0 : setCharacteristic ("L", L);
360 : 0 : setCharacteristic ("R", R);
361 : 0 : }
362 : :
363 : : /*! DC model initialization.
364 : : *! DC model of a bondwire is a resistance.
365 : : */
366 : 0 : void bondwire::initDC (void) {
367 : : nr_double_t g;
368 : :
369 : 0 : getProperties ();
370 : :
371 : : /* for non-zero resistances usual MNA entries */
372 [ # # ]: 0 : if (rho != 0.0) {
373 : 0 : g = 1.0 / resistance (0);
374 : 0 : setVoltageSources (0);
375 : 0 : allocMatrixMNA ();
376 [ # # ][ # # ]: 0 : setY (NODE_1, NODE_1, +g); setY (NODE_2, NODE_2, +g);
377 [ # # ][ # # ]: 0 : setY (NODE_1, NODE_2, -g); setY (NODE_2, NODE_1, -g);
378 : : }
379 : : /* for zero resistances create a zero voltage source */
380 : : else {
381 : 0 : setVoltageSources (1);
382 : 0 : setInternalVoltageSource (1);
383 : 0 : allocMatrixMNA ();
384 : 0 : clearY ();
385 : 0 : voltageSource (VSRC_1, NODE_1, NODE_2);
386 : : }
387 : 0 : }
388 : :
389 : : /*! Initialize AC simulation. */
390 : 0 : void bondwire::initAC (void) {
391 : 0 : getProperties ();
392 : 0 : setVoltageSources (0);
393 : 0 : allocMatrixMNA ();
394 : 0 : }
395 : :
396 : : /*! Compute AC model.
397 : : *! Use serial LR model (Y matrix).
398 : : */
399 : 0 : void bondwire::calcAC (const nr_double_t frequency) {
400 [ # # ]: 0 : setMatrixY (calcMatrixY (frequency));
401 : 0 : }
402 : :
403 : 0 : void bondwire::calcNoiseSP (nr_double_t) {
404 : : // calculate noise correlation matrix
405 : 0 : nr_double_t T = getPropertyDouble ("Temp");
406 : 0 : nr_double_t f = kelvin (T) * 4.0 * R * z0 / norm (4.0 * z0 + R) / T0;
407 [ # # ][ # # ]: 0 : setN (NODE_1, NODE_1, +f); setN (NODE_2, NODE_2, +f);
408 [ # # ][ # # ]: 0 : setN (NODE_1, NODE_2, -f); setN (NODE_2, NODE_1, -f);
409 : 0 : }
410 : :
411 : 0 : void bondwire::calcNoiseAC (nr_double_t) {
412 : : // calculate noise current correlation matrix
413 : 0 : nr_double_t y = 1 / R;
414 : 0 : nr_double_t T = getPropertyDouble ("Temp");
415 : 0 : nr_double_t f = kelvin (T) / T0 * 4.0 * y;
416 [ # # ][ # # ]: 0 : setN (NODE_1, NODE_1, +f); setN (NODE_2, NODE_2, +f);
417 [ # # ][ # # ]: 0 : setN (NODE_1, NODE_2, -f); setN (NODE_2, NODE_1, -f);
418 : 0 : }
419 : :
420 : : // properties
421 : : PROP_REQ [] = {
422 : : { "D", PROP_REAL, { 25e-6, PROP_NO_STR }, PROP_POS_RANGE },
423 : : { "L", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE },
424 : : { "H", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE },
425 : : { "mur", PROP_REAL, { 1, PROP_NO_STR }, PROP_RNGII (1, 100) },
426 : : { "rho", PROP_REAL, { 0.022e-6, PROP_NO_STR }, PROP_POS_RANGE },
427 : : { "Model", PROP_STR, { PROP_NO_VAL, "FREESPACE" },
428 : : PROP_RNG_STR3 ("FREESPACE", "MIRROR", "DESCHARLES") },
429 : : { "Subst", PROP_STR, { PROP_NO_VAL, "Subst1" }, PROP_NO_RANGE },
430 : : PROP_NO_PROP };
431 : : PROP_OPT [] = {
432 : : { "Temp", PROP_REAL, { 26.85, PROP_NO_STR }, PROP_MIN_VAL (K) },
433 : : PROP_NO_PROP };
434 : : struct define_t bondwire::cirdef =
435 : : { "BOND", 2, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_LINEAR, PROP_DEF };
|