Skip to content

Tutorial: Build circuits with code

Before starting this tutorial

You should have already installed JITX and created your first design.

This document contains the code examples and product actions from Quickstart 2, in a format that’s easy to follow alongside the video. Use it as a companion while you watch.


Resources


Development Tips

  • Restart (“kill”) the terminal after modifying slm.toml so new libraries can be fetched.
  • Press Ctrl+Enter to run the current file.
  • Press L in Board or Schematic views to toggle net labels on/off.
  • Press e to examine a selected component’s metadata.
  • Use “multi-cursor rename” (often Ctrl+D in many editors) to quickly rename repeated identifiers in your code.
  • Verify package names and imports match your project structure.
View Design Explorer

From the terminal or command interface, run:

view-design-explorer()
This opens a tree view that shows your entire design hierarchy (modules, parts, pins). It’s a very handy way to see which pins to connect in your net() statements.


1. Project Setup

Update Main Module

First, rename the default module in main.stanza

pcb-module my-design:

...

set-main-module(my-design)
pcb-module top-level:

...

set-main-module(top-level)
Fast rename

In many code editors, you can use multi-cursor or “select next occurrence” to rename text quickly (often Ctrl+D).

View set-main-module Reference


2. Creating the Communications Core 1:26

A. Initial Module Setup

Create a communications-core module in main.stanza:

pcb-module communications-core :
  ; Components will be added here

B. Add a Zener Diode from the Database

  1. Open “Find Components” in the JITX sidebar
  2. Enter MMSZ4689T1G
  3. Click arrow → open detail
  4. Click “Copy to clipboard” for the part creation code

Then in main.stanza:

pcb-module communications-core :
  inst zener : create-part(mpn = "MMSZ4689T1G", manufacturer = "ON Semiconductor")
About create-part(...)

create-part(...) fetches a fully modeled part from the online JITX database. If you need to customize it (e.g., adjusting a symbol or landpattern), press the “Create Component” button instead.

C. Instantiate in the Top-Level

Remove old code in top-level and add an instance of communications-core:

pcb-module top-level :
  inst core : communications-core

Now the diode appears in the BOM Visualizer and in the Board view.

Use e to examine a component

Select a part in Board view and press e to see its instance name, other details like MPN. This is useful for verifying net connections.

Read more on BOM Visualizer


3. USB Interface Integration 3:42

A. Add Connectors Library Dependency

Add Connectors library in slm.toml:

connectors = { git = "JITx-Inc/connectors", version = "0.4.1" }
Whenever slm.toml changes

Kill the terminal so that Ctrl+Enter can reload dependencies.

B. Add USB Connector

Copy the USB 2.0 High-Speed code to communications-core:

inst usb-if : connectors/components/USB/USBTypeC/USBC-HighSpeed-Iface()

C. Connect zener to USB Power

The USB 2.0 High-Speed Interface docs show two ports:
- USB (type usb-data)
- VDD-USB (type power)

Where are power and usb-data defined?

power and usb-data are standard bundles in JSL. For instance, power has two pins: V+ and V- as shown in the Reference.

Use net (...) to connect the Zener pins A and K to usb-if.VDD-USB.V- and usb-if.VDD-USB.V+ respectively:

net (zener.A usb-if.VDD-USB.V-)
net (zener.K usb-if.VDD-USB.V+)

Check Board or schematic to confirm the connections.


4. Controller Module Development 7:41

A. Create the Controller Component

Create src/controller.stanza and add the lines:

#use-added-syntax(jitx)
defpackage ethernet-io/controller :
  import core
  import jitx
  import jitx/commands
  import jitx/parts
  import helpers
  import jsl

public pcb-module controller :
  name = "MCU"

B. Add to Project Configuration

In stanza.proj, link all packages in src/:

packages ethernet-io/* defined-in "src/"

C. Import & Instantiate

Add an import in main.stanza:

import ethernet-io/controller

Then instantiate inside your top-level (or communications-core):

inst ctl : controller

5. FTDI Integration 9:47

A. Add the FTDI Library

# In slm.toml
FTDI = { git = "JITx-Inc/FTDI", version = "0.3.3" }

Kill and restart the terminal afterward.

B. Add the “Application Circuit” for FT2232HL

Inside controller:

public pcb-module controller :
  name = "MCU"
  inst debug-if : FTDI/DebugIF/circuit(
    FTDI/components/FT2232HL/FT2232H-MPSSE,
    FTDI/components/FT2232HL/FT2232H-RS232
  )

6. Debug Interface Connections10:51

A. Add Ports to the Controller, Make Internal Connections

public pcb-module controller :
  name = "MCU"
  inst debug-if : FTDI/DebugIF/circuit(
    FTDI/components/FT2232HL/FT2232H-MPSSE,
    FTDI/components/FT2232HL/FT2232H-RS232
  )
public pcb-module controller :
  name = "MCU"
  port rail-3v3 : power
  port USB : usb-data
  port VDD-USB : power

  inst debug-if : FTDI/DebugIF/circuit(
    FTDI/components/FT2232HL/FT2232H-MPSSE,
    FTDI/components/FT2232HL/FT2232H-RS232
  )

  net (rail-3v3 debug-if.VDD-3v3)
  net (VDD-USB debug-if.VDD-USB)
  net (USB debug-if.USB)

B. In communications-core, connect ports to usb-if

inst ctl : controller
net (ctl.USB usb-if.USB)
net (ctl.VDD-USB usb-if.VDD-USB)

7. EEPROM Component Creation 13:10

  1. Create the component via Create Component wizard in the JITX sidebar, naming it MC-93LC46CT.
    This generates src/components/MC-93LC46CT.stanza with a template and auto-adds a line in stanza.proj.
AI Assistance

You can paste the datasheet’s pin table into ChatGPT (or another LLM) to generate the pin-properties : [...] section for you. And there are several projects offering more complete automated modeling from PDFs. Always double-check for correctness.

Final MC-93LC46CT model
public pcb-component component :
  description = "1K Serial EEPROM with 8-bit/16-bit Organization"
  mpn = "93LC46CT-I/SN"
  manufacturer = "Microchip Technology"
  datasheet = "https://ww1.microchip.com/downloads/en/DeviceDoc/20001749K.pdf"
  reference-prefix = "U"

  pin-properties :
    [pin:Ref    | pads:Int ... | side:Dir ]
    [CS         | 1        | Left ] ; Chip Select
    [CLK        | 2        | Left ] ; Serial Clock
    [DI         | 3        | Left ] ; Data Input
    [DO         | 4        | Left ] ; Data Output
    [VSS        | 5        | Left ] ; Ground
    [ORG        | 6        | Right] ; Organization Select
    [NC         | 7        | Right] ; No Connection
    [VCC        | 8        | Right] ; Power Supply

  val box = BoxSymbol(self)
  val symb = create-symbol(box)
  assign-symbol(symb)

  val pkg = SOIC-N(
    num-leads = 8,
    lead-span = min-max(5.8, 6.2),
    package-length = min-max(4.8, 5.0)
    density-level = DensityLevelC
  )
  val lp = create-landpattern(pkg)
  assign-landpattern(lp)

8. Create the EEPROM Module 17:56

In MC-93LC46CT.stanza, add:

public pcb-module module :
  port VDD-3v3 : power
  port cfg : microwire-4()

  inst EEPROM : components/MC-93LC46CT/component
  net (EEPROM.CS cfg.cs)
  net (EEPROM.CLK cfg.clk)
  net (EEPROM.DO cfg.do)
  net (EEPROM.DI cfg.di)
  net (EEPROM.VCC VDD-3v3.V+)
  net (EEPROM.VSS VDD-3v3.V-)
Where is microwire-4?

microwire-4 is another bundle in JSL (see Bundles Reference).


9. Add Parametric Parts 19:57

A. Dependency for jitx/parts to main.stanza

import jitx/parts

B. Insert Resistor & Capacitor

; Add a pull-up resistor
insert-resistor(
  EEPROM.ORG EEPROM.VCC
  helpers/R-query
  resistance = 10.e3
)

; Add a bypass capacitor
insert-capacitor(
  EEPROM.VCC EEPROM.VSS
  helpers/C-query
  capacitance = 2.2e-6
  short-trace? = true
)
Parametric part selection

Both insert-resistor(...) and insert-capacitor(...) automate supply chain choices (e.g. multiple MPNs, different tolerances) so you don’t have to manually pick every resistor or capacitor. JITX solves for possible footprints to ensure they’re widely available.


10. Integrating EEPROM

A. Instantiate in controller Module

inst EEPROM : components/MC-93LC46CT/module
net (EEPROM.VDD-3v3 rail-3v3)
net (EEPROM.cfg debug-if.CFG)

Key Concepts Learned

  1. Component Management

    • Pulling from the database with create-part(...)
    • Creating custom components from scratch
    • Using library code from Awesome JITX
  2. Circuit Organization

    • Module hierarchy & file structure
    • inst for adding components/modules
    • Packaging sub-circuits with ports and bundles
  3. Connectivity

    • Using net(...) statements
    • Defining and importing bundles (power, usb-data, microwire-4)
  4. Library Usage & Parametric

    • Adding dependencies in slm.toml
    • Parametric resistors/caps (insert-resistor, insert-capacitor) ensure standard footprints, automating the supply chain

For reference, the final JITX Project (Quickstart 2 Files) is available on GitHub.

Continue to the next tutorial:
Tutorial: Organizing a schematic


Final Notes

  • Keep verifying each step in Board/Schematic views. Press L to see net labels.
  • If a net or part does not appear as expected, re-check your import statements and project files.
  • Re-run with Ctrl+Enter to ensure all changes compile correctly.
  • Press e on a selected part to see pin names and confirm your connections.
  • Make use of the “View Design Explorer” to quickly locate pins, nets, and instance paths.