Power stage 2: LM61460-Q1 15V->+5v 5A sync buck (SPICE-verified 5.02V)

Second power stage. U_BUCK5 = LM61460-Q1 (6A, 42V abs-max synchronous).
No KiCad symbol existed, so built one from the TI datasheet (SNVSB70F:
14-pin HTSSOP-1EP + EP, VREF=1.0V) and added it to the project library
carrier/CM5IO.kicad_sym as CM5IO:LM61460-Q1.

- FB divider R_FBT5 40.2k / R_FBB5 10.0k -> 5.02V (SPICE-confirmed
  vfb=1.0V=VREF at 5.02V); L5 4.7uH, Cout 2x47u/16V, Cin 2x10u/50V,
  Cboot 100n+Rboot, RT 31.6k (~400kHz), BIAS->+5v, EN->VIN_PROT
- +5v pre-exists in the carrier as a hierarchical net -> exposed via a
  hierarchical label + a +5v sheet pin on the Power symbol, tied into the
  root +5v net (a global label would trip same_local_global_label).
  Netlist confirms the buck now sources Module1 + GPIO headers + USB.
- FB pin typed passive (high-Z sense) to clear an analyzer no_driver
- build_power.py: register_lm61460(), Device:L, HIER_NETS/emit_hlabel

Verify: ERC 133->133 (zero new); analyzer +32 added, 0 regressions;
SPICE 12/13 pass, 0 fail (1 benign warn: L5/Cboot mis-grouped as LC).

Confirm vs datasheet: RT freq, L saturation >=7A, EP=pad15, EN UVLO.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
noise
2026-07-01 18:31:26 -04:00
parent c469238dd5
commit fd627f512b
5 changed files with 11133 additions and 10221 deletions

View File

@@ -67,6 +67,42 @@ def add_from(lib_id, srctext, srcname=None):
# reuse R/C/C_Polarized/GND verbatim from the carrier (guaranteed compatible)
for lid in ["Device:R", "Device:C", "Device:C_Polarized", "power:GND"]:
add_from(lid, carrier_hs)
add_from("Device:L", open(f"{KSS}/Device.kicad_sym").read(), "L")
def register_lm61460():
"""Hand-authored lib_symbol for LM61460-Q1 (14-pin HTSSOP-1EP + EP=15),
built from the datasheet pin table (SNVSB70F). VREF(FB)=1.0V, VIN abs-max 42V.
Pin types picked for cross-sheet ERC: VIN/PGND/AGND/BIAS/EP power_in, VCC power_out,
SW output, FB/EN input, RT/CBOOT/RBOOT passive, PGOOD open_collector."""
P = [('8','VIN1','power_in',-16.51,15.24,0), ('12','VIN2','power_in',-16.51,12.7,0),
('7','EN/SYNC','input',-16.51,5.08,0), ('1','BIAS','power_in',-16.51,0,0),
('6','RT','passive',-16.51,-7.62,0),
('10','SW','output',16.51,15.24,180), ('14','CBOOT','passive',16.51,12.7,180),
('13','RBOOT','passive',16.51,10.16,180), ('2','VCC','power_out',16.51,5.08,180),
('4','FB','passive',16.51,-2.54,180), ('5','PGOOD','open_collector',16.51,-7.62,180),
('9','PGND1','power_in',-7.62,-21.59,90), ('11','PGND2','power_in',-2.54,-21.59,90),
('3','AGND','power_in',2.54,-21.59,90), ('15','EP','power_in',7.62,-21.59,90)]
pt = ""
for num, name, ty, lx, ly, ang in P:
pt += (f'\t\t\t(pin {ty} line (at {lx} {ly} {ang}) (length 3.81)\n'
f'\t\t\t\t(name "{name}" (effects (font (size 1.27 1.27))))\n'
f'\t\t\t\t(number "{num}" (effects (font (size 1.27 1.27))))\n\t\t\t)\n')
blk = ('\t(symbol "CM5IO:LM61460-Q1"\n\t\t(pin_names (offset 1.016))\n'
'\t\t(exclude_from_sim no)\n\t\t(in_bom yes)\n\t\t(on_board yes)\n'
'\t\t(property "Reference" "U" (at 0 22.86 0) (effects (font (size 1.27 1.27))))\n'
'\t\t(property "Value" "LM61460-Q1" (at 0 -26.67 0) (effects (font (size 1.27 1.27))))\n'
'\t\t(property "Footprint" "Package_SO:Texas_HTSSOP-14-1EP_4.4x5mm_P0.65mm_EP3.4x5mm_Mask3.155x3.255mm_ThermalVias" (at 0 0 0) (effects (font (size 1.27 1.27)) (hide yes)))\n'
'\t\t(property "Datasheet" "https://www.ti.com/lit/ds/symlink/lm61460-q1.pdf" (at 0 0 0) (effects (font (size 1.27 1.27)) (hide yes)))\n'
'\t\t(symbol "LM61460-Q1_0_1"\n'
'\t\t\t(rectangle (start -12.7 20.32) (end 12.7 -20.32) (stroke (width 0.254) (type default)) (fill (type background)))\n\t\t)\n'
f'\t\t(symbol "LM61460-Q1_1_1"\n{pt}\t\t)\n\t)')
LIBS["CM5IO:LM61460-Q1"] = (blk, lib_pins(blk))
register_lm61460()
# +5v pre-exists in the carrier as a HIERARCHICAL net (local + hierarchical labels on the CM5
# sheets) -> expose it hierarchically here (a global label collides: same_local_global_label).
# +3V3_RF/+3V3_AUX are new nets introduced by this port -> global is fine.
GLOBAL_NETS = {"+3V3_RF", "+3V3_AUX"}
HIER_NETS = {"+5v"}
# from KiCad libs (renamed to full lib_id)
add_from("power:PWR_FLAG", open(f"{KSS}/power.kicad_sym").read(), "PWR_FLAG")
add_from("Power_Management:LM74700", open(f"{KSS}/Power_Management.kicad_sym").read(), "LM74700")
@@ -82,6 +118,9 @@ def emit_label(net, x, y, ang=0):
def emit_glabel(net, x, y, ang=0):
body.append(f'\t(global_label "{net}"\n\t\t(shape input)\n\t\t(at {x} {y} {ang})\n'
f'\t\t(effects (font (size 1.27 1.27)) (justify left))\n\t\t(uuid "{U("gl-"+net+f"-{x}-{y}")}")\n\t)\n')
def emit_hlabel(net, x, y, ang=0):
body.append(f'\t(hierarchical_label "{net}"\n\t\t(shape passive)\n\t\t(at {x} {y} {ang})\n'
f'\t\t(effects (font (size 1.27 1.27)) (justify left))\n\t\t(uuid "{U("hl-"+net+f"-{x}-{y}")}")\n\t)\n')
def emit_gnd(x, y, tag):
body.append(f'\t(symbol\n\t\t(lib_id "power:GND")\n\t\t(at {x} {y} 0)\n\t\t(unit 1)\n'
f'\t\t(exclude_from_sim no) (in_bom yes) (on_board yes) (dnp no)\n\t\t(uuid "{U("gnd-"+tag)}")\n'
@@ -121,6 +160,8 @@ def place(lib_id, ref, value, footprint, ox, oy, pin_nets):
lx, ly, _ = pins[num]; px, py = round(ox + lx, 2), round(oy - ly, 2)
if net == ('gnd',): emit_gnd(px, py, ref + num)
elif isinstance(net, tuple) and net[0] == 'global': emit_glabel(net[1], px, py)
elif net in GLOBAL_NETS: emit_glabel(net, px, py)
elif net in HIER_NETS: emit_hlabel(net, px, py)
else: emit_label(net, px, py)
return ox, oy
@@ -144,6 +185,28 @@ def pin_abs(origin, lib_id, num):
fx, fy = pin_abs(drev, "Power_Management:LM74700", "6"); emit_flag(fx, fy, "15IN")
vx, vy = pin_abs(tvs, "Device:D_TVS", "1"); emit_flag(vx, vy, "VINP")
# ---- STAGE 2: U_BUCK5 15V -> +5v 5A (LM61460-Q1, sync, 42V absmax) --------------
# FB divider: Vout = VREF*(1+Rfbt/Rfbb), VREF=1.0V -> Rfbt/Rfbb=4 -> 40.2k/10.0k = 5.02V.
# fsw ~= 400kHz (RT 31.6k); L=4.7uH; Cout 2x47u/16V; Cin 2x10u/50V; Cboot 100n; BIAS->+5v.
place("CM5IO:LM61460-Q1", "U_BUCK5", "LM61460-Q1", "Package_SO:Texas_HTSSOP-14-1EP_4.4x5mm_P0.65mm_EP3.4x5mm_Mask3.155x3.255mm_ThermalVias",
110, 150, {'8': 'VIN_PROT', '12': 'VIN_PROT', '7': 'VIN_PROT', '1': '+5v', '2': 'VCC5',
'6': 'RT5', '5': 'PG5', '4': 'FB5', '10': 'SW5', '14': 'BOOT5', '13': 'RBOOT5',
'9': GND, '11': GND, '3': GND, '15': GND})
l5 = place("Device:L", "L5", "4.7uH/7A", "Inductor_SMD:L_Bourns_SRP1245A", 150, 138, {'1': 'SW5', '2': '+5v'})
place("Device:C", "C_BOOT5", "100n", "Capacitor_SMD:C_0402_1005Metric", 140, 132, {'1': 'SW5', '2': 'BOOT5'})
place("Device:R", "R_BOOT5", "4.7", "Resistor_SMD:R_0402_1005Metric", 145, 128, {'1': 'RBOOT5', '2': 'BOOT5'})
place("Device:R", "R_RT5", "31.6k", "Resistor_SMD:R_0402_1005Metric", 90, 158, {'1': 'RT5', '2': GND})
place("Device:R", "R_PG5", "100k", "Resistor_SMD:R_0402_1005Metric", 135, 143, {'1': 'PG5', '2': '+5v'})
place("Device:R", "R_FBT5", "40.2k", "Resistor_SMD:R_0402_1005Metric", 165, 150, {'1': '+5v', '2': 'FB5'})
place("Device:R", "R_FBB5", "10.0k", "Resistor_SMD:R_0402_1005Metric", 165, 158, {'1': 'FB5', '2': GND})
place("Device:C", "C_VCC5", "1u", "Capacitor_SMD:C_0402_1005Metric", 100, 158, {'1': 'VCC5', '2': GND})
place("Device:C", "C_IN5a", "10u/50V", "Capacitor_SMD:C_1210_3225Metric", 95, 145, {'1': 'VIN_PROT', '2': GND})
place("Device:C", "C_IN5b", "10u/50V", "Capacitor_SMD:C_1210_3225Metric", 100, 145, {'1': 'VIN_PROT', '2': GND})
place("Device:C", "C_OUT5a", "47u/16V", "Capacitor_SMD:C_1210_3225Metric", 175, 138, {'1': '+5v', '2': GND})
place("Device:C", "C_OUT5b", "47u/16V", "Capacitor_SMD:C_1210_3225Metric", 180, 138, {'1': '+5v', '2': GND})
# +5v is now sourced by this buck -> PWR_FLAG co-located on L5 pin2 (+5v)
p5x, p5y = pin_abs(l5, "Device:L", "2"); emit_flag(p5x, p5y, "P5V")
# ---- file scaffold ----------------------------------------------------------------
libsyms = "\n".join(blk for blk, _ in LIBS.values())
sheet = ('(kicad_sch\n\t(version 20231120)\n\t(generator "eeschema")\n\t(generator_version "8.0")\n'