You need to sign in or sign up before continuing.
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