Commit e680f7fb authored by Raptor Engineering Development Team's avatar Raptor Engineering Development Team
Browse files

Split Tercel SPI off of Kestrel litex-boards repository at GIT hash e1d7618

parents
#!/usr/bin/env python3
from setuptools import setup
from setuptools import find_packages
setup(
name="tercelspi",
description="Full featured single/quad SPI master with Wishbone interface",
author="Raptor Engineering, LLC",
author_email="support@raptorengineering.com",
url="https://www.raptorengineering.com",
download_url="https://gitlab.raptorengineering.com/kestrel-collaboration/kestrel-litex/tercelspi",
test_suite="test",
license="GPLv3",
python_requires="~=3.6",
packages=find_packages(exclude=("test*", "sim*", "doc*", "examples*")),
include_package_data=True,
)
#!/usr/bin/env python3
# This file is Copyright (c) 2018-2019 Florent Kermarrec <florent@enjoy-digital.fr>
# This file is Copyright (c) 2018-2019 David Shah <dave@ds0.me>
# This file is Copyright (c) 2020-2021 Raptor Engineering, LLC
# License: BSD
import os
import argparse
import subprocess
import tempfile
from migen import *
from litex import get_data_mod
from litex.soc.interconnect import wishbone, stream
from litex.soc.interconnect.csr import *
from litex.gen.common import reverse_bytes
from litex.build.io import SDRTristate
kB = 1024
mB = 1024*kB
# SPI interface ------------------------------------------------------------------------------------
class TercelSPI(Module, AutoCSR):
def __init__(self, platform, pads, clk_freq, endianness="big", adr_offset=0x0, debug_signals=None):
self.bus = bus = wishbone.Interface(data_width=32, adr_width=30)
self.cfg_bus = cfg_bus = wishbone.Interface(data_width=32, adr_width=30)
self.cs_n = cs_n = Signal()
# Bus endianness handlers
self.dat_w = Signal(32)
self.dat_r = Signal(32)
self.comb += self.dat_w.eq(bus.dat_w if endianness == "big" else reverse_bytes(bus.dat_w))
self.comb += bus.dat_r.eq(self.dat_r if endianness == "big" else reverse_bytes(self.dat_r))
self.cfg_dat_w = Signal(32)
self.cfg_dat_r = Signal(32)
self.comb += self.cfg_dat_w.eq(cfg_bus.dat_w if endianness == "big" else reverse_bytes(cfg_bus.dat_w))
self.comb += cfg_bus.dat_r.eq(self.cfg_dat_r if endianness == "big" else reverse_bytes(self.cfg_dat_r))
# Calculate SPI flash address
spi_bus_adr = Signal(30)
self.comb += spi_bus_adr.eq(bus.adr - (adr_offset >> 2)) # wb address is in words, offset is in bytes
# SPI bus signals
self.spi_clock = Signal()
self.spi_d0_out = Signal()
self.spi_d0_direction = Signal()
self.spi_d0_in = Signal()
self.spi_d1_out = Signal()
self.spi_d1_direction = Signal()
self.spi_d1_in = Signal()
self.spi_d2_out = Signal()
self.spi_d2_direction = Signal()
self.spi_d2_in = Signal()
self.spi_d3_out = Signal()
self.spi_d3_direction = Signal()
self.spi_d3_in = Signal()
self.spi_ss_n = Signal()
# Debug signals
self.debug_port = Signal(8)
self.specials += Instance("tercel_spi_master_wishbone",
# Configuration data
i_sys_clk_freq = clk_freq,
# Wishbone signals
i_wb_cyc = bus.cyc,
i_wb_stb = bus.stb,
i_wb_we = bus.we,
i_wb_addr = spi_bus_adr, # The final SPI address is created inside the shim module from both wb_addr and wb_sel
i_wb_dat_w = self.dat_w,
o_wb_dat_r = self.dat_r,
i_wb_sel = bus.sel,
o_wb_ack = bus.ack,
o_wb_err = bus.err,
# Wishbone cfg port signals
i_cfg_wb_cyc = cfg_bus.cyc,
i_cfg_wb_stb = cfg_bus.stb,
i_cfg_wb_we = cfg_bus.we,
i_cfg_wb_addr = cfg_bus.adr,
i_cfg_wb_dat_w = self.cfg_dat_w,
o_cfg_wb_dat_r = self.cfg_dat_r,
i_cfg_wb_sel = cfg_bus.sel,
o_cfg_wb_ack = cfg_bus.ack,
o_cfg_wb_err = cfg_bus.err,
# Clock and reset
# Put the peripheral on the both main system clock and reset domains
i_peripheral_reset = ResetSignal('sys'),
i_peripheral_clock = ClockSignal('sys'),
# Debug port
o_debug_port = self.debug_port,
# SPI interface
o_spi_clock = self.spi_clock,
o_spi_d0_out = self.spi_d0_out,
o_spi_d0_direction = self.spi_d0_direction,
i_spi_d0_in = self.spi_d0_in,
o_spi_d1_out = self.spi_d1_out,
o_spi_d1_direction = self.spi_d1_direction,
i_spi_d1_in = self.spi_d1_in,
o_spi_d2_out = self.spi_d2_out,
o_spi_d2_direction = self.spi_d2_direction,
i_spi_d2_in = self.spi_d2_in,
o_spi_d3_out = self.spi_d3_out,
o_spi_d3_direction = self.spi_d3_direction,
i_spi_d3_in = self.spi_d3_in,
o_spi_ss_n = self.spi_ss_n
)
# Add Verilog source files
self.add_sources(platform)
# I/O drivers
self.specials += SDRTristate(
io = pads.dq[0],
o = self.spi_d0_out,
oe = self.spi_d0_direction,
i = self.spi_d0_in,
)
self.specials += SDRTristate(
io = pads.dq[1],
o = self.spi_d1_out,
oe = self.spi_d1_direction,
i = self.spi_d1_in,
)
self.specials += SDRTristate(
io = pads.dq[2],
o = self.spi_d2_out,
oe = self.spi_d2_direction,
i = self.spi_d2_in,
)
self.specials += SDRTristate(
io = pads.dq[3],
o = self.spi_d3_out,
oe = self.spi_d3_direction,
i = self.spi_d3_in,
)
self.comb += pads.cs_n.eq(self.spi_ss_n)
self.comb += pads.clk.eq(self.spi_clock)
if debug_signals is not None:
self.comb += debug_signals[0].eq(self.spi_d0_in)
self.comb += debug_signals[1].eq(self.spi_d1_in)
self.comb += debug_signals[2].eq(self.spi_d2_in)
self.comb += debug_signals[3].eq(self.spi_d3_in)
#self.comb += debug_signals[2].eq(self.debug_port[0])
#self.comb += debug_signals[3].eq(self.debug_port[1])
#self.comb += debug_signals[4].eq(self.debug_port[2])
#self.comb += debug_signals[5].eq(self.debug_port[3])
@staticmethod
def add_sources(platform):
vdir = get_data_mod("peripheral", "tercelspi").data_location
platform.add_source(os.path.join(vdir, "spi_master.v"))
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment