546 nanoPIO

546 : nanoPIO

Design render

nanoPIO — how it works

Instruction word (13 bits, 16-word program store)

[12:10] opcode
[9:7]   delay    (0-7 extra stall cycles applied after the instruction's effect)
[6:0]   operand  (meaning depends on opcode)
opcode (3b) mnemonic operand layout effect
000 JMP [6:5]=cond [3:0]=addr PC <= addr if cond true, else PC+1
001 WAIT [6]=pol [2:0]=pin idx stall (no PC advance) until ui_in[idx] == pol
010 IN unused X <= ui_in
011 OUT [6]=dest (0=uo_out,1=uio_out) dest <= X
100 SET [6:0]=imm7 X <= {1'b0, imm7}
101/110/111 reserved NOP (PC+1)
JMP conditions
cond (2b) name taken when
00 ALWAYS always
01 X==0 (XZ) X == 0
10 X!=0 (XNZ) X != 0
11 DEC X != 0 (checked before decrement); X is then decremented regardless of branch direction

DEC is the classic PIO loop primitive: SET X, N then a body ending in JMP DEC, body_start counts down N times without a separate compare instruction.

Delay field

Every instruction (except WAIT while its condition is unmet) can attach 0-7 extra stall cycles after it executes. This lets protocol timing — a UART bit period, an SPI/I2C clock half-period — be encoded directly into the program instead of burning instruction words on busy-loops. This mirrors how RP2040 PIO folds [delay] into every instruction rather than giving it its own opcode, which matters a lot when the whole program store is only 16 words.

Registers

  • PC — 4 bits, indexes the 16-word instruction memory
  • X — 8-bit scratch/loop-counter register. No separate ISR/OSR shift registers like real PIO has: IN writes straight into X, OUT drives straight out of X. This is the single biggest area saving relative to RP2040 PIO, and it's a reasonable trade since TT's ui_in/uo_out are already 8 bits wide — there's no 32-bit-wide autopush/autopull to emulate.

There is no second (Y) counter in v0.1; nested loops (e.g. an outer bit-count loop and an inner sample-delay loop) have to share X or be restructured using the delay field instead of an inner loop.

Pinout

Pin Role while running Role while LOAD_EN (ui_in[7]) is high
ui_in[4:0] WAIT/IN pin sources ignored
ui_in[5] LOAD_DATA
ui_in[6] LOAD_CLK
ui_in[7] LOAD_EN
uo_out[7:0] OUT PINS target
uio[7:0] OUT UIO target (output-only in v1)

Reprogramming (bit-bang loader)

The instruction memory is built from per-word latches gated by a shared write-address decoder (not flip-flops, and not a synthesized ROM), so it can be rewritten after fabrication. Latches roughly halve the per-bit storage cost vs. flip-flops on this PDK, which is what lets the 16-word store fit in a 1x1 tile. To load a program:

  1. Hold ui_in[7] (LOAD_EN) high. This halts the core (PC forced to 0, X cleared) so it can't execute half-written instructions.
  2. For each instruction word, shift a 17-bit frame MSB-first into ui_in[5] (LOAD_DATA), toggling ui_in[6] (LOAD_CLK) once per bit (rising-edge sampled, internally double-flopped for metastability):
    • bits [16:13] — 4-bit address
    • bits [12:0] — 13-bit instruction
  3. Frames can be sent in any order and re-sent to patch a single word; LOAD_EN can stay high across many frames.
  4. Drop LOAD_EN low. The core resumes execution from address 0.

tools/nanopio_asm.py --frames prints the exact bit pattern for each frame of an assembled program, in the order described above.

What's simplified vs. real RP2040 PIO (and why)

  • 8-bit X instead of 32-bit ISR/OSR — TT's pin buses are 8 bits wide, so a wider shift register would mostly be padding.
  • One scratch register, no Y — halves the register file; loop nesting falls back to the per-instruction delay field where possible.
  • No autopush/autopull, no FIFO to the "system" side — there's no CPU on the other end of this chip; IN/OUT talk directly to pins.
  • uio is output-only in v1 — avoids the extra pin-direction control logic and instruction bits a bidirectional uio would need; revisit if area allows.

IO

#InputOutputBidirectional
0PIO in[0] / WAIT PIN 0 sourcePIO out[0]PIO out[8] (uio, output only)
1PIO in[1] / WAIT PIN 1 sourcePIO out[1]PIO out[9] (uio, output only)
2PIO in[2] / WAIT PIN 2 sourcePIO out[2]PIO out[10] (uio, output only)
3PIO in[3] / WAIT PIN 3 sourcePIO out[3]PIO out[11] (uio, output only)
4PIO in[4] / WAIT PIN 4 sourcePIO out[4]PIO out[12] (uio, output only)
5LOAD_DATA (reprogramming serial data in)PIO out[5]PIO out[13] (uio, output only)
6LOAD_CLK (reprogramming bit clock)PIO out[6]PIO out[14] (uio, output only)
7LOAD_EN (1 = reprogramming mode, core halted)PIO out[7]PIO out[15] (uio, output only)

Chip location

Controller Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Analog Mux Mux Mux Mux Mux Mux Mux Mux tt_um_chip_rom (Chip ROM) tt_um_factory_test (Tiny Tapeout Factory Test) tt_um_ieee_LDO (LDO) tt_um_chip_ieee_analog (IEEE Bandgap Reference) tt_um_snn_voice_calculator_mauro_ciccone (snn-voice-calculator) tt_um_hx2003_delay (4 Channel - 32 Tap Programmable Delay with Delay Locked Loop Calibration) tt_um_adxl362_test (tt_um_adxl362_test) tt_um_larsnit_cfar (1D CA/GO/SO CFAR radar detector) tt_um_abeccari_swsynth (Sine Wave Synthesizer) tt_um_dpi_adexp (AdExp DPI Neuron ) tt_um_140oo041_fpu130 (FPU-130) tt_um_blonghi_uart (uart) tt_um_directsgg_mini_proceo_8bit (Mini 8-bit Processor) tt_um_umaece1982_lfsr (Low-Power LFSR-Based Test Pattern Generator) tt_um_deploy_timer (launch deployment timer) tt_um_urish_simon (Simon Says memory game) tt_um_nimelli_kinematic_wave_engine (Kinematic Wave Engine) tt_um_multi_seg_monitor (Multi Segment Monitor) tt_um_UART_TX (project) tt_um_crc8_lfsr (CRC-8 Serial LFSR) tt_um_tinynpu4 (TinyNPU4) tt_um_alu_bns (6-bit multi function ALU ( eldawly_V2) ) tt_um_echoworld424_tpv (Timing-Prediction Test Vehicle) tt_um_gyro_lockin (Laser Gyro Lock-in Readout Core) tt_um_josue_olivos_sar_adc (4-Bit Charge-Redistribution SAR ADC Controller) tt_um_flower (VGA Flower) tt_um_vperumal_l1_fabric (Scalable Banked L1 Memory Fabric for Edge AI) tt_um_preinception_top (Preinception: Simple Compute Accelerator) tt_um_italu (iTALU: Interactive Testable Arithmetic Logic Unit) tt_um_neuron (4-Input Signed Neuron / Perceptron) tt_um_4tap_mac (4-Tap Signed MAC Unit) tt_um_mac_engine (DSP MAC Engine) tt_um_crypto_led_demo (QAMER CryptoUART: Encrypted UART with LED Status) tt_um_layernorm (LayerNorm) tt_um_ez130_8t_mystery (EZ130 8T Mystery Circuit) tt_um_sent2spi (SENT Receiver with SPI Interface) tt_um_llr_hepiarisc (Hepiarisc with SPI flash) tt_um_rebeccargb_vga_pride (VGA Pride) tt_um_hasi_ising (Oscillator Ising Machine) tt_um_c061618g2 (Circuitli C061618G2) tt_um_tiny_dram_pim (Tiny Dual-Channel DRAM-PIM Controller + PU) tt_um_Tbilisi_CORDIC_Engine (Tbilisi CORDIC Engine) tt_um_rahulmascarenhas_folded_nn (Frozen ternary backbone + loadable head) tt_um_miniMAC (miniMAC_IHP26b) tt_um_rumcajs (IEEE DOORSH) tt_um_sg13g2_mystery (SG13G2 Mystery Circuit) tt_um_ULSR88 (ULSR demo) tt_um_ez130_7t_mystery (EZ130 7T Mystery Circuit) tt_um_tinyopt4 (ieee_tt_tinyopt4) tt_um_vga_example (IEEE VGA Animated Beach) tt_um_hyphen133_drone_detection (IEEE Acoustic Drone Detector) tt_um_nuatlabs_fifo_pwm (Async FIFO with CDC + PWM Peripheral) tt_um_nuatlabs_uart (8N1 UART Transceiver) tt_um_eeg_threshold_detector (IEEE Digital EEG Threshold Event Detector) tt_um_smart_traffic (Smart Traffic Light Controller) tt_um_94442024_mini_cpu (Mini 8-bit Accumulator CPU) tt_um_wokwi_475369131246576641 (IEEE_UPB_TT_1) tt_um_aion (AION) tt_um_rebeccargb_hardware_utf8 (Hardware UTF Encoder/Decoder) tt_um_rebeccargb_universal_decoder (Universal Binary to Segment Decoder) tt_um_rebeccargb_intercal_alu (INTERCAL ALU) tt_um_flappy_bird (IEEE Flappy Bird VGA Game) tt_um_oryan01_alu (ALU CASS PUCV) tt_um_S4xU4 (S4xU4) tt_um_vga_ca (Space CA) tt_um_llr_simplenpu (simple SPI flash streaming NPU) tt_um_pucv_pspwm (3LFCC PS-PWM Modulator) tt_um_yuri_fpga (Tiny FPGA) tt_um_mikailgedik_inverted_inverters (Inverted inverters) tt_um_esauqch_hamming74 (Hamming(7,4) encoder/decoder (IEEE)) tt_um_hackin7_analog_experiments (TinyAnalogExperiments) tt_um_snake (snake game) tt_um_mini_kraken (Kraken IO Subprocessor) tt_um_fabien_pio (AstraPIO) tt_um_chiplab (ChipLab) tt_um_wokwi_475490677474407425 (Tiny_Divider) tt_um_c061618g2tr (Circuitli C061618G2TR) tt_um_catalinlazar_nanopio (nanoPIO) tt_um_catalinlazar_uart_spi_i2c_bridge (UART-SPI-I2C Bridge) tt_um_enzonappi_sent_i2c (SENT to I2C bridge) tt_um_kush1434_proof (Proof) tt_um_schwallsunk_signal_discriminator (Highspeed voltage discriminator) tt_um_tiarinix_ttihp_verilog_template (8-bit educational SAP-style CPU) tt_um_vga_glyph_mode (BOOTCAMP) tt_um_GiulioGirelli_packet_processor (Configurable Low-Latency Match-Action Packet Processor) tt_um_vga_tictactoe (Tic Tac Toe) tt_um_vga_dvd_player (DVD player) tt_um_clea_katseye_rain (KATSEYE) tt_um_romd_uart_hello (UART Hello World) tt_um_vga_snake (CDM PYTHON GAME) tt_um_vga_slot_machine (tt_um_vga_slot_machine) tt_um_jet_seq8b (SEQ8 Programmable Sequencer) tt_um_kibo_leak_inspect (KIBO Leak-Inspection Target Controller (VGA)) tt_um_endless_runner (Endless Runner) tt_um_omega_infinity_kaoru (OMEGA INFINITY KAORU 3D Metal Grid Processor) tt_um_nikleberg_mixer (Mixer) tt_um_lahnb_sgdma (TinyDMA: A Descriptor-Based Dual-PSRAM Memory Mover) tt_um_gstj_lockin (Digital IQ Lock-in (IEEE)) tt_um_benpayne_ps2_decoder (PS/2 Keyboard Decoder for 68k) tt_um_cass_s_ui_neuron_lif (Neurona LIF con Aprendizaje STDP Dinamico (IEEE)) tt_um_vga_glyph_mode_CDM_Matrix (CDM Matrix) tt_um_qd39l_xor_stream (Fixed-ROM XOR Stream Engine) tt_um_conv3x3 (3x3 Clock Rate Streaming Input Convolution Engine) tt_um_mc14500b_soc_extended (MC14500B Extended 1-bit Microcontroller SoC) tt_um_vga_hypno_spiral (tt_um_vga_hypno_spiral) tt_um_mattizen_morse_tree (Morse Tree LED Decoder) tt_um_CDM (Colegio de Muntinlupa DVD-like Display) tt_um_romd_uart_loader (UART SPI RAM Loader) tt_um_TscherterJunior_stapel_geraet (stapel gerät) tt_um_das2225_dna_accel (DNA_Accel) tt_um_tinysoc (TinySoC) tt_um_barrel_shifter (Barrel Shifter) tt_um_approx_mac_coprocessor (Approximate DSP: Time-Multiplexed MAC Coprocessor) tt_um_joesagents_market_split_oracle (Market-split oracle) tt_um_mgpauly1458_ringmeter (Ring oscillator frequency meter) tt_um_pettit_prism_lite (PRISM with Risc-V (TinyQV) SoC) tt_um_workshop_cpu (IEEE Workshop Simple CPU) tt_um_algofoogle_analog_junk (Simple comparator + 2 DACs analog layout in a 1x1 tile) tt_um_lkhanh_cordic (TinyQV SoC (Dual Memory Backend)) tt_um_4x4npu (4x4NPU: Dual-Lane INT4 Neural Accelerator) tt_um_abiaselli_izh_bridge_3x2 (Izhikevich event bridge (4 contexts)) tt_um_fabulous_ihp_26b (Tiny FABulous FPGA) tt_um_zanderivo_voronoi (Four-Metric VGA Nearest-Prototype Visualizer)