Skip to content

Instantly share code, notes, and snippets.

@enjoy-digital
Created April 30, 2021 17:09
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save enjoy-digital/74f2d8cf0f7a1966428e930602f6705d to your computer and use it in GitHub Desktop.
Save enjoy-digital/74f2d8cf0f7a1966428e930602f6705d to your computer and use it in GitHub Desktop.
Raspberry Pi Pico <> LiteX SoC (on GoWin FPGA) proof of concept.
#!/usr/bin/env python3
# Raspberry Pi Pico <> LiteX SoC (on GoWin FPGA) proof of concept.
#
# Copyright (c) 2021 Florent Kermarrec <florent@enjoy-digital.fr>
# SPDX-License-Identifier: BSD-2-Clause
import os
import argparse
from migen import *
from litex.build.generic_platform import *
from litex.soc.cores.clock.gowin_gw1n import GW1NPLL
from litex.soc.integration.soc_core import *
from litex.soc.integration.builder import *
from litex.soc.cores.led import LedChaser
from litex_boards.platforms import tec0117
# IOs ----------------------------------------------------------------------------------------------
_pico_spi_ios = [
("pico_spi", 0,
Subsignal("clk", Pins("29")), # SPI SCK.
Subsignal("cs_n", Pins("31")), # SPI CSn.
Subsignal("mosi", Pins("28")), # SPI TX.
Subsignal("miso", Pins("32")), # SPI RX.
IOStandard("LVCMOS33"),
)
]
# CRG ----------------------------------------------------------------------------------------------
class _CRG(Module):
def __init__(self, platform, sys_clk_freq):
self.clock_domains.cd_sys = ClockDomain()
# # #
# Clk / Rst
clk100 = platform.request("clk100")
# PLL
self.submodules.pll = pll = GW1NPLL(device="GW1N9K")
pll.register_clkin(clk100, 100e6)
pll.create_clkout(self.cd_sys, sys_clk_freq)
# BaseSoC ------------------------------------------------------------------------------------------
class BaseSoC(SoCCore):
def __init__(self, sys_clk_freq=int(50e6)):
platform = tec0117.Platform()
platform.add_extension(_pico_spi_ios)
# CRG --------------------------------------------------------------------------------------
self.submodules.crg = _CRG(platform, sys_clk_freq)
# SoCMini ----------------------------------------------------------------------------------
SoCMini.__init__(self, platform, sys_clk_freq,
ident = "Raspberry Pi Pico <> LiteX SoC proof of concept.",
ident_version = True)
# SPI --------------------------------------------------------------------------------------
if not os.path.exists("spibone.py"):
os.system("wget https://raw.githubusercontent.com/xobs/spibone/master/spibone.py")
import spibone
self.submodules.spibone = spibone.SpiWishboneBridge(platform.request("pico_spi"))
self.add_wb_master(self.spibone.wishbone)
# Leds -------------------------------------------------------------------------------------
self.submodules.leds = LedChaser(
pads = platform.request_all("user_led"),
sys_clk_freq = sys_clk_freq)
# Build --------------------------------------------------------------------------------------------
def main():
parser = argparse.ArgumentParser(description="Raspberry Pi Pico <> LiteX SoC proof of concept.")
parser.add_argument("--build", action="store_true", help="Build bitstream")
parser.add_argument("--load", action="store_true", help="Load bitstream")
parser.add_argument("--sys-clk-freq", default=50e6, help="System clock frequency (default: 50MHz)")
args = parser.parse_args()
soc = BaseSoC(sys_clk_freq=int(float(args.sys_clk_freq)))
builder = Builder(soc, csr_csv="csv.csv")
builder.build(run=args.build)
if args.load:
prog = soc.platform.create_programmer()
prog.load_bitstream(os.path.join(builder.gateware_dir, "impl", "pnr", "project.fs"))
if __name__ == "__main__":
main()
#!/usr/bin/env python3
# Raspberry Pi Pico <> LiteX SoC (on GoWin FPGA) proof of concept.
#
# Copyright (c) 2021 Florent Kermarrec <florent@enjoy-digital.fr>
# SPDX-License-Identifier: BSD-2-Clause
import time
from machine import Pin, SPI
# Registers ----------------------------------------------------------------------------------------
CSR_LEDS = 0x00001000
CSR_BTNS = 0x00001000
CSR_IDENTIFIER = 0x00000800
# SPI Bone -----------------------------------------------------------------------------------------
class SPIBone:
def __init__(self, pins={"sck": 18, "csn": 17, "mosi": 19, "miso": 16}, clk_freq=1e6):
self.csn = Pin(pins["csn"], Pin.OUT, value=1)
self.spi = SPI(0, baudrate=int(clk_freq), polarity=0, phase=0,
sck = Pin(pins["sck"]),
mosi = Pin(pins["mosi"]),
miso = Pin(pins["miso"])
)
def write(self, address, value):
self.csn.low()
self.spi.write(int(0x0).to_bytes(1, "big"))
self.spi.write( address.to_bytes(4, "big"))
self.spi.write( value.to_bytes(4, "big"))
self.spi.read(1)
self.csn.high()
def read(self, address):
self.csn.low()
self.spi.write(int(0x1).to_bytes(1, "big"))
self.spi.write( address.to_bytes(4, "big"))
self.spi.read(1)
value = int.from_bytes(self.spi.read(4), 4, "big")
self.csn.high()
return value
bus = SPIBone()
# Demo ---------------------------------------------------------------------------------------------
def identifier_demo():
print("Identifier:")
identifier = ""
for i in range(256):
c = chr(bus.read(CSR_IDENTIFIER + 4*i) & 0xff)
identifier += c
if c == "\0":
break
print(identifier)
def led_demo():
print("Led Demo:")
print("Counter mode...")
for i in range(16):
bus.write(CSR_LEDS, i)
time.sleep(0.1)
print("Shift mode...")
for i in range(8):
bus.write(CSR_LEDS, 1<<i)
time.sleep(0.1)
for i in reversed(range(8)):
bus.write(CSR_LEDS, 1<<i)
time.sleep(0.1)
print("Dance mode...\n");
for i in range(4):
bus.write(CSR_LEDS, 0x55)
time.sleep(0.2)
bus.write(CSR_LEDS, 0xaa)
time.sleep(0.2)
identifier_demo()
led_demo()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment