Skip to content

Tutorial

Litex

fjullien migen_litex_tutorials <-- Best Litex tutorial

Local migen_litex_tutorials

officail litx wiki.

Litex MIPI CSI

ICEStorm Install icestorm_install.md

getting-started-with-litex

Migen Simulation

Counter

from migen import *

class DPLL(Module):
    def __init__(self):
        self.count = Signal(4)

        self.sync += self.count.eq(self.count + 1)

def dpll_test(dut):
    for i in range(20):
         print((yield dut.count))
         yield

if __name__ == "__main__":
    dut = DPLL()
    run_simulation(dut, dpll_test(dut), vcd_name="dpll.vcd")

Migen Selection of Signal from Signal as Index

        shiftout = Array({} for i in range(REG_Number))

        for i in range(16):
            shiftout[0][i] = [self.spi_miso1.eq(Regsiters[0][i] & ~self.spi_cs)]
            shiftout[1][i] = [self.spi_miso2.eq(Regsiters[1][i] & ~self.spi_cs)]

        for i in range(REG_Number):
            self.comb += [
                Case(shift_count, shiftout[i])
            ]

Migen Case

        self.comb += Case(word_cound,{
            0: self.uart_tx.eq(start_b0),
            1: self.uart_tx.eq(start_b1),
            2: self.uart_tx.eq(timestamp_b0),
            3: self.uart_tx.eq(timestamp_b1),
            4: self.uart_tx.eq(timestamp_b2),
            5: self.uart_tx.eq(timestamp_b3),
            "default": self.uart_tx.eq(0),
        })

Migen Module

        encoder = Encoder8b10b()
        decoder = Decoder8b10b()

        self.submodules += [
            encoder, decoder
        ]

Migen Reset FSM

        fsm   = FSM(reset_state="WAIT")
        fsm   = ClockDomainsRenamer("icap")(fsm)
        fsm   = ResetInserter()(fsm)
        self.submodules += fsm
        self.comb += fsm.reset.eq(~(self.write | self.read))

IceStorm toolset for ICE40 FPGA

# Project setup
PROJ      = blinky
BUILD     = ./build
DEVICE    = 8k
FOOTPRINT = ct256

# Files
FILES = top.v

.PHONY: all clean burn timing

all $(BUILD)/$(PROJ).asc $(BUILD)/$(PROJ).bin:
    # if build folder doesn't exist, create it
    mkdir -p $(BUILD)
    # synthesize using Yosys
    yosys -p "synth_ice40 -top top -blif $(BUILD)/$(PROJ).blif -json $(BUILD)/$(PROJ).json" $(FILES)
    # Place and route using arachne
    #arachne-pnr -d $(DEVICE) -P $(FOOTPRINT) -o $(BUILD)/$(PROJ).asc -p pinmap.pcf $(BUILD)/$(PROJ).blif
    nextpnr-ice40 --hx$(DEVICE) --json build/$(PROJ).json --pcf pinmap.pcf --asc build/$(PROJ).asc
    # Convert to bitstream using IcePack
    icepack $(BUILD)/$(PROJ).asc $(BUILD)/$(PROJ).bin

burn: $(BUILD)/$(PROJ).bin
    iceprog $(BUILD)/$(PROJ).bin

timing: $(BUILD)/$(PROJ).asc
    icetime -tmd hx$(DEVICE) $(BUILD)/$(PROJ).asc

clean:
    rm build/*

Chisel FPGA開発日記

https://msyksphinz.hatenablog.com/

https://www.hatena.ne.jp/

https://hatenablog.com/

Agile Hardware Design Video 2024

Chip Alliance

Chip Alliance

Amaranth

Amaranth HDL Document

Verilog

https://verilogguide.readthedocs.io/en/latest/

https://www.chipverify.com/

The Art of FPGA Design - element14 Community

The Art of FPGA Design - element14 Community

Digital Signal Processing, from Algorithm to FPGA Bitstream - element14 Community

Digital Signal Processing, from Algorithm to FPGA Bitstream

Linux and Programming

Linux Thread

Linuxとpthreadsによる マルチスレッドプログラミング入門|サポート|秀和システム Book Link

Linux Kernel Module Programming Guide

https://sysprog21.github.io/lkmpg/

Tutorial 1 https://linux-kernel-labs.github.io/refs/heads/master/#

SSH Turnnel

ssh -f -N -L 127.0.0.1:8888:127.0.0.1:8888 -i pemKey  user@ipaddress
For Jupyter notebook

PICO

PICO Programming Tutorial

Digital Systems Design Using Microcontrollers - V. Hunter Adams

Raspberry Pi Pico Lectures 2025 YT

RP2040 + FPGA RISC-V AXIS Communication

YouTube from FPGA Zealot

PICO PIO Programming

PICO PIO Programming Youtube Video

PICO PIO Programming Youtube Video Github Code

Web Reference

PICO PIO url

A Practical Look at PIO on the Raspberry Pi Pico URL

Introduction to the PIO (Programmable Input Output) of the RP2040

programmable-io-programming @ circuitcellar URL

playing-with-the-pico

RP2040 PICO DMA

RP2040 PICO DMA

RP2040 PICO DAC DMA

Playing with the Pico Part 4 - Getting Acquainted with PIO

RP2040 LVGL

http://bbs.eeworld.com.cn/thread-1227666-1-1.html

RT-Thread and LVGL

RP2040 Arduino How to Make 2 PWM Start at the same time

#define _PWM_LOGLEVEL_        0
#include "RP2040_PWM.h"

//creates pwm instance
RP2040_PWM* PWM_Instance1;
RP2040_PWM* PWM_Instance2;

#define FREQ1  2000000
#define FREQ2  2000000

int updated = 0;

void setup() {
  Serial.begin(115200);

  PWM_Instance1 = new RP2040_PWM(10, FREQ1, 0);
  PWM_Instance1->setPWM(10, FREQ1, 0);
  turn_on_pwm1();
}

void turn_on_pwm1()
{
  rp2040.fifo.push(1);
  PWM_Instance1->setPWM(10, FREQ1, 50);  
}
void turn_on_pwm2()
{
  while(1) {
    if (rp2040.fifo.available()) {
        PWM_Instance2->setPWM(12, FREQ2, 50);
        rp2040.fifo.pop();
        return;
    }
  }
}

void setup1() {
  PWM_Instance2 = new RP2040_PWM(12, FREQ2, 0);
  PWM_Instance2->setPWM(12, FREQ2, 0);
  turn_on_pwm2();
}
void loop() {
  delay(1000);
}
void loop1() {

  delay(1000);
}

SPI Master and Slave on Pico

// Shows how to use SPISlave on a single device.
// Core0 runs as an SPI master and initiates a transmission to the slave
// Core1 runs the SPI Slave mode and provides a unique reply to messages from the master
//
// Released to the public domain 2023 by Earle F. Philhower, III <earlephilhower@yahoo.com>

#include <SPI.h>
#include <SPISlave.h>

// Wiring:
// Master RX  GP0 <-> GP11  Slave TX
// Master CS  GP1 <-> GP9   Slave CS
// Master CK  GP2 <-> GP10  Slave CK
// Master TX  GP3 <-> GP8   Slave RX

SPISettings spisettings(1000000, MSBFIRST, SPI_MODE0);

// Core 0 will be SPI master
void setup() {
  SPI.setRX(0);
  SPI.setCS(1);
  SPI.setSCK(2);
  SPI.setTX(3);
  SPI.begin(true);

  delay(5000);
}

int transmits = 0;
void loop() {
  char msg[42];
  memset(msg, 0, sizeof(msg));
  sprintf(msg, "What's up? This is transmission %d", transmits);
  Serial.printf("\n\nM-SEND: '%s'\n", msg);
  SPI.beginTransaction(spisettings);
  SPI.transfer(msg, sizeof(msg));
  SPI.endTransaction();
  Serial.printf("M-RECV: '%s'\n", msg);
  transmits++;
  delay(5000);
}

// Core 1 will be SPI slave

volatile bool recvBuffReady = false;
char recvBuff[42] = "";
int recvIdx = 0;
void recvCallback(uint8_t *data, size_t len) {
  memcpy(recvBuff + recvIdx, data, len);
  recvIdx += len;
  if (recvIdx == sizeof(recvBuff)) {
    recvBuffReady = true;
    recvIdx = 0;
  }
}

int sendcbs = 0;
// Note that the buffer needs to be long lived, the SPISlave doesn't copy it.  So no local stack variables, only globals or heap(malloc/new) allocations.
char sendBuff[42];
void sentCallback() {
  memset(sendBuff, 0, sizeof(sendBuff));
  sprintf(sendBuff, "Slave to Master Xmission %d", sendcbs++);
  SPISlave1.setData((uint8_t*)sendBuff, sizeof(sendBuff));
}

// Note that we use SPISlave1 here **not** because we're running on
// Core 1, but because SPI0 is being used already.  You can use
// SPISlave or SPISlave1 on any core.
void setup1() {
  SPISlave1.setRX(8);
  SPISlave1.setCS(9);
  SPISlave1.setSCK(10);
  SPISlave1.setTX(11);
  // Ensure we start with something to send...
  sentCallback();
  // Hook our callbacks into the slave
  SPISlave1.onDataRecv(recvCallback);
  SPISlave1.onDataSent(sentCallback);
  SPISlave1.begin(spisettings);
  delay(3000);
  Serial.println("S-INFO: SPISlave started");
}

void loop1() {
  if (recvBuffReady) {
    Serial.printf("S-RECV: '%s'\n", recvBuff);
    recvBuffReady = false;
  }
}

Python

使用 uv 管理 Python 環境

使用 uv 管理 Python 環境

UV Commands

PySerial

PySerial Example Code pyserial_sample.md

Python FTDI for SPI

Python FTDI for SPI

from pyftdi.ftdi import Ftdi
Ftdi.show_devices()
from pyftdi.spi import SpiController

spi.configure('ftdi://ftdi:2232h:1:7b/1')
slave = spi.get_port(cs=1, freq=10E6, mode=2)
write_buf = b'\x01\x02\x03'
read_buf = slave.exchange(write_buf, duplex=True)

FTDI SPI DDS AD9833

from pyftdi.spi import SpiController


############user changes these###############
user_freq = 1000

#pinout from H232 for SPI
'''
ad0 SCLK to UNO pin 13
ad1 MOSI to UNO pin     11
ad2 MISO to UNO pin 12 (not used)
ad3 CS0 to UNO pin 10
ad4 cs1 ... ad7 CS4.
'''
#WE WANT TO BE ABLE TO ENTER A FREQ TO SHOW ON SCOPE.
# Instantiate a SPI controller
# We need want to use A*BUS4 for /CS, so at least 2 /CS lines should be
# reserved for SPI, the remaining IO are available as GPIOs.


def get_dec_freq(freq):
    bignum = 2**28
    f = freq
    clock=25000000 #if your clock is different enter that here./
    dec_freq = f*bignum/clock
    return int(dec_freq)


padded_binary = 0
bits_pushed = 0
d = get_dec_freq(user_freq)

print("freq int returned is: " + str(d))

#turn into binary string.
str1 = bin(d)
#print(str1)

#get rid of first 2 chars.
str2 = str1[2:]
#print(str2)

#pad whatever we have so far to 28 bits:
longer = str2.zfill(28)
#print("here is 28 bit version of string")
#print(str(longer))
#print("here is length of that string")
#print(len(str(longer)))

lm1 = "01" + longer[:6]
lm2 = longer[6:14]
rm1 = "01" + longer[14:20]
rm2 = longer[20:]
# print(lm1 + " " + lm2  + " " + rm1 + " " + rm2)


def str_2_int(strx):
    numb = int(strx, 2)
    return numb

lm1x = str_2_int(lm1)
lm2x = str_2_int(lm2)
rm1x = str_2_int(rm1)
rm2x = str_2_int(rm2)
print(str(lm1x) + " " + str(lm2x)  + " " + str(rm1x) + " " + str(rm2x))

##########
#freq0_loadlower16 = [80,199]
#freq0_loadupper16 = [64,0]
#64 0 80 198


spi = SpiController(cs_count=2)
device = 'ftdi://ftdi:232h:0:1/1'
# Configure the first interface (IF/1) of the FTDI device as a SPI master
spi.configure(device)

# Get a port to a SPI slave w/ /CS on A*BUS4 and SPI mode 2 @ 10MHz
slave = spi.get_port(cs=1, freq=8E6, mode=2)


freq0_loadlower16 = [rm1x,rm2x]
freq0_loadupper16 = [lm1x,lm2x]

cntrl_reset = [33,0]

phase0 = [192,0]

cntrl_write = [32,0]

send2_9833 = cntrl_reset + freq0_loadlower16 + freq0_loadupper16 + phase0 + cntrl_write

print(send2_9833)

qq = bytearray(send2_9833)
# Synchronous exchange with the remote SPI slave
#write_buf = qq
#read_buf = slave.exchange(write_buf, duplex=False)
slave.exchange(out=qq, readlen=0, start=True, stop=True, duplex=False, droptail=0)
slave.flush()

Virtual Enviroment

python3 -m venv virtkv
source ./virtkv/bin/activate

Pyenv

Other Solution https://python-poetry.org/

Makefile for Python

Makefile for Python project

# 預設目標,當直接執行 make 時會執行的目標
.PHONY: all
all: install test build

# 安裝相依性
.PHONY: install
install:
    pip install -r requirements.txt

# 執行測試
.PHONY: test
test:
    python -m unittest discover tests

# 打包程式碼 (使用 setuptools)
.PHONY: build
build:
    python setup.py sdist bdist_wheel

# 清理
.PHONY: clean
clean:
    rm -rf build dist *.egg-info

Python Import Module from Parent Folder

import os
import sys

current_dir = os.path.dirname(os.path.abspath(__file__))
parent_dir = os.path.join(current_dir, '..')
sys.path.append(os.path.abspath(parent_dir))

Python for PDF

    from pypdf import PdfReader, PdfWriter

    reader = PdfReader("input.pdf")
    writer = PdfWriter()

    for page in reader.pages:
        # Define new crop box coordinates (adjust as needed)
        # Example: crop 10 units from each side
        left = page.mediabox.left + 10
        bottom = page.mediabox.bottom + 10
        right = page.mediabox.right - 10
        top = page.mediabox.top - 10

        page.mediabox.lower_left = (left, bottom)
        page.mediabox.upper_right = (right, top)
        writer.add_page(page)

    with open("output_cropped.pdf", "wb") as fp:
        writer.write(fp)

Micropython

Pyboard Sleep and Wakeup

lowpower.py

import pyb, stm
from pyb import Pin

    # wakeup callback
    wakeup = False
    def cb(exti):
        nonlocal wakeup
        wakeup = True

    # configure switch to generate interrupt on press
    sw = pyb.Switch()
    sw.callback(lambda:cb(0))

    # function to flash an LED
    def flash(led):
        led.on()
        pyb.delay(100)
        led.off()

    while True:
        # standby (need to exit by pressing RST, or wait 15s)
        if stm.mem32[stm.RTC + stm.RTC_BKP1R] == 0:
            flash(led1)
            stm.mem32[stm.RTC + stm.RTC_BKP1R] = 1
            rtc.wakeup(15000, cb)
            pyb.standby()
        else:
            stm.mem32[stm.RTC + stm.RTC_BKP1R] = 0

        # stop
        flash(led2)
        led_off()
        pyb.stop()
        led_on()

        # idle
        flash(led3)
        wakeup = False
        while not wakeup:
            pyb.wfi()

        # run
        flash(led4)
        wakeup = False
        while not wakeup:
            pass

Micropython pyBoard DAC use DMA

import math
from array import array
from pyb import DAC

# create a buffer containing a sine-wave, using half-word samples
buf = array('H', 2048 + int(2047 * math.sin(2 * math.pi * i / 128)) for i in range(128))

# output the sine-wave at 400Hz
dac = DAC(1, bits=12)
dac.write_timed(buf, 400 * len(buf), mode=DAC.CIRCULAR)

Micropython Debounce

import pyb

def wait_pin_change(pin):
    # wait for pin to change value
    # it needs to be stable for a continuous 20ms
    cur_value = pin.value()
    active = 0
    while active < 20:
        if pin.value() != cur_value:
            active += 1
        else:
            active = 0
        pyb.delay(1)

pin_x1 = pyb.Pin('X1', pyb.Pin.IN, pyb.Pin.PULL_DOWN)
while True:
    wait_pin_change(pin_x1)
    pyb.LED(4).toggle()

Micropython json

import ujson
parsed = ujson.loads("""{"name":"John"}""")
print(parsed)

Micropython USB UART Passthrough

import pyb
import select

def pass_through(usb, uart):
    usb.setinterrupt(-1)
    while True:
        select.select([usb, uart], [], [])
        if usb.any():
            uart.write(usb.read(256))
        if uart.any():
            usb.write(uart.read(256))

pass_through(pyb.USB_VCP(), pyb.UART(1, 9600, timeout=0))

Micropython GPIO IRQ

# Rui Santos & Sara Santos - Random Nerd Tutorials
# Complete project details at https://RandomNerdTutorials.com/raspberry-pi-pico-interrupts-micropython/

from machine import Pin

button = Pin(21, Pin.IN, Pin.PULL_DOWN)

def button_pressed(pin):
    print("Button Pressed!")

# Attach the interrupt to the button's rising edge
button.irq(trigger=Pin.IRQ_RISING, handler=button_pressed)

Micropython Timer IRQ

# Rui Santos & Sara Santos - Random Nerd Tutorials
# Complete project details at https://RandomNerdTutorials.com/raspberry-pi-pico-interrupts-micropython/

from machine import Pin, Timer
from time import sleep

# LED pin
led_pin = 20
led = Pin(led_pin, Pin.OUT)

# Callback function for the timer
def toggle_led(timer):
    led.value(not led.value())  # Toggle the LED state (ON/OFF)

# Create a periodic timer
blink_timer = Timer()
blink_timer.init(mode=Timer.PERIODIC, period=500, callback=toggle_led)  # Timer repeats every half second

# Main loop (optional)
while True:
    print('Main Loop is running')
    sleep(2)

Micrpython IRQ

raspberry-pi-pico-interrupts-micropython

Arduino Pico

UART to USB Passthrough as FT232

void setup() {
  // Initialize USB Serial communication (to computer)
  Serial.begin(115200); 
  while (!Serial); // Wait for Serial Monitor to open (optional)

  // Initialize hardware UART (e.g., UART0 on Pico, connected to external device)
  Serial1.begin(115200); 
}

void loop() {
  // Read from hardware UART and send to USB Serial
  if (Serial1.available()) {
    Serial.write(Serial1.read());
  }

  // Read from USB Serial and send to hardware UART
  if (Serial.available()) {
    Serial1.write(Serial.read());
  }
}

Chromebook

Install Desktop GUI in chromebook chromebookDesktop.md

DSP

Wavelet

Wavelet_101

Neuro Science

Neuroscience exploration Video

Topological Data Analysis (TDA)

VSCode

VSCode and Docker

LTSpice Tutorial

LTspice Tutorial

LTSpice Tutorial