You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

275 lines
10 KiB
Python

#!/usr/bin/python3
# A2P Caravel Site Test
# python3 a2p_site.py
#
# 1 or 2 cores
# Manager (wb is only slave)
# Async RAM interface ** won't work - only half of io can be outputs **
# use custom serial interface ~ 8 pins, 4B/32B packets
# UARTs
# I2C
# special-purpose GPIO
# Mgmt interface
# Beer on tap
import os
import argparse
from migen import *
# wtf - use local platform
from platforms import caravel_user
# wtf - use local core
# help python find package
import sys
binPath = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(binPath, 'a2p'))
# get core def
from a2p import A2P
# add to litex dict
from litex.soc.cores import cpu
cpu.CPUS['a2p'] = A2P
# local modules
sys.path.append(os.path.join(binPath, 'modules'))
from litex.soc.integration.soc import colorer
from litex.soc.integration.soc import SoCRegion
from litex.soc.integration.soc_core import *
from litex.soc.integration.soc_sdram import *
from litex.soc.integration.builder import *
from litex.soc.cores.led import LedChaser
from litex.soc.cores.gpio import GPIOIn
from litex.soc.cores.gpio import GPIOOut
from litex.soc.cores.bitbang import I2CMaster
from litex.soc.interconnect import wishbone
from litex.soc.interconnect import csr
from litex.soc.cores.uart import UART
from litex.soc.cores.uart import RS232PHY
# possibly use octspi with a memory controller to send/rcv 32b/128b data with header and crc?
#from litespi.common import *
#from litespi.phy.generic_sdr import LiteSPISDRPHYCore
#from litespi.phy.generic_ddr import LiteSPIDDRPHYCore
# BaseSoC ------------------------------------------------------------------------------------------
from litex.soc.interconnect import wishbone
def _to_signal(obj):
return obj.raw_bits() if isinstance(obj, Record) else obj
class BaseSoC(SoCCore):
def __init__(self, sys_clk_freq=50e6, uart_baudrate=115200, **kwargs):
platform = caravel_user.Platform()
SoCCore.__init__(self, platform, 50e6, sys_clk_freq=50e6, cpu_type='a2p',
csr_data_width=32, with_uart=False, integrated_sram_size=0, integrated_rom_size=0,
ident='A2P Caravel Site Test', ident_version=True)
# no irq yet
self.add_constant('UART_POLLING')
self.mem_map = {
'csr': 0xFFF00000,
'sram': 0x00000000,
'mgmt': 0xE0000000
}
# I/O connections --------------------------------------------------------------------------
# clk is connected by platform
# make these exist even if unconnected so i/o are defined
# --- clk/rst
#self.sys_rst = Signal() #this creates sys_rst_1
#self.comb += self.int_rst.eq(platform.request('wb_rst_i')) no idea how to connect to top level sigs that are magically gen'd
# apprarently they give you a few things useful!
self.sys_rst = ResetSignal()
self.comb += self.sys_rst.eq(platform.request('wb_rst_i'))
# but gens some whack logic
# always @(*) begin
# sys_rst <= 1'd0;
# sys_rst <= wb_rst_i;
# sys_rst <= int_rst;
# end
self.user_clock2 = Signal()
self.comb += self.user_clock2.eq(platform.request('user_clock2'))
# --- wb
# options:
# * unused
# * user area is slave (config/test only)
# * user area is master/slave - not possible - NO MASTER SIGS!!!
# slave interface for mgmt macro (core controls, etc.); could hang csr off it and interface through them
# i suppose then you could let the csr be read/written by both sides, so you could do some polled mailbox messaging; probs could proxy i/o through pico
# they would have to be r/w by 2 different wb's
self.wb_mgmt = wishbone.Interface()
self.wb_io = Record([('cyc', 1), ('stb', 1), ('we', 1), ('sel', 4), ('adr', 32), ('ack', 1), ('dat_r', 32), ('dat_w', 32),
('cti', 1), ('bte', 32), ('err', 1)])
self.wb_io.cyc = platform.request('wbs_cyc_i')
self.wb_io.stb = platform.request('wbs_stb_i')
self.wb_io.we = platform.request('wbs_we_i')
self.wb_io.sel = platform.request('wbs_sel_i')
self.wb_io.adr = platform.request('wbs_adr_i')
self.wb_io.ack = platform.request('wbs_ack_o')
self.wb_io.dat_r = platform.request('wbs_dat_o')
self.wb_io.dat_w = platform.request('wbs_dat_i')
self.wb_io.cti = Signal()
self.wb_io.bte = Signal()
self.wb_io.err = Signal()
self.wb_mgmt.connect_to_pads(self.wb_io, mode='slave')
#somehow get this built and then connected to 2 wb
#self.wb_shared = wishbone.InterconnectShared(masters,slaves)
self.mailbox = csr.CSRStorage(size=16, name='mailbox')
self.add_csr('mailbox')
# --- gpio
self.in_in = Signal(19)
self.comb += self.in_in.eq(platform.request('in_in'))
self.in_out = Signal(19)
self.comb += self.in_out.eq(platform.request('in_out'))
self.in_oeb = Signal(19)
self.comb += self.in_oeb.eq(platform.request('in_oeb'))
# skip analog_in; too curvy
# allocate
uart_0_io = {
'rx': self.in_in[0],
'tx': self.in_out[0]
}
uart_1_io = {
'rx': self.in_in[1],
'tx': self.in_out[1]
}
i2c_io = {
'scl': self.in_out[2],
'sda': self.in_out[3]
}
dshot_io = self.in_out[3:6]
# toss
ram_io = {
'ce': Signal(1),
'oe': Signal(), # self.in_out[7],
'we': Signal(), # self.in_out[8],
'adr': Signal(19), # self.in_out[18:0],
'dat': Signal(8) # self.in_out[18:11]
}
# --- misc
self.user_irq = Signal(3)
self.comb += self.user_irq.eq(platform.request('user_irq'))
# --- la
self.la_data_in = Signal(128)
self.comb += self.la_data_in.eq(platform.request('la_data_in'))
self.la_data_out = Signal(128)
self.comb += self.la_data_out.eq(platform.request('la_data_out'))
self.la_oenb = Signal(128)
self.comb += self.la_oenb.eq(platform.request('la_oenb'))
# ON-BOARD MEM ------------------------------------------------------------------------------
# None, unless a small 'ROM'-like device
#self.add_rom('rom', origin=self.mem_map['rom'], size=rom_size, contents=romdata)
# MANAGER -----------------------------------------------------------------------------------
# service processor stuff controlled by the man
# External SRAM (512K) -----------------------------------------------------------------------
# GPIO-connected SRAM/FPGA
# *** doh, won't work - only half the i/o are outputs!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ***
# will have to resurrect custom serial i/o with fpga on other end
from issiram import ISSIRam
platform.add_source('./momv modules/issiram.v')
sram_bus = wishbone.Interface()
sram = ISSIRam(self, ClockSignal(), ResetSignal(), sram_bus, ram_io)
self.submodules.sram = sram
# ERROR: Output port top.issiram.mem_adr (issiram) is connected to constants: { \basesoc_in_out [17:0] 1'x }
# Command exited with non-zero status 1
# Elapsed time: 0:12.27[h:]min:sec. CPU time: user 11.77 sys 0.48 (99%). Peak memory: 1468464KB.
# make: *** [Makefile:354: results/sky130hd/a2p_litex/output/20211125085224/base/1_1_yosys.v] Error 1
self.bus.add_slave('sram', sram_bus, SoCRegion(origin=self.mem_map['sram'], size=sram.size))
#self.logger.info('SRAM {} {} {}.'.format(
# colorer('sram'),
# colorer('added', color='green'),
# self.bus.regions['sram']))
# Leds n LaserBeams -----------------------------------------------------------------------
#self.submodules.leds = LedChaser(
# pads = platform.request_all('user_led'),
# sys_clk_freq = sys_clk_freq
#)
#self.add_csr('leds')
# Buttons n KillSwitches ------------------------------------------------------------------
#self.submodules.buttons = GPIOIn(
# pads = platform.request_all('user_btn')
#)
#self.add_csr('buttons')
# GPIO I2C
#wtf must be an elegant pythonic way to do this junk
pins = Record([('scl', 1), ('sda', 1)])
pins.scl = i2c_io['scl']
pins.sda = i2c_io['sda']
#wtf needs to be 'i2c' for bios for now
self.submodules.i2c = I2CMaster(pins)
self.add_csr('i2c')
# GPIO UARTs = 2 pins per -----------------------------------------------------------------
pins = Record([('rx', 1), ('tx', 1)])
pins.rx = uart_0_io['rx']
pins.tx = uart_0_io['tx']
self.submodules.uart_0_phy = RS232PHY(pins, sys_clk_freq, with_dynamic_baudrate=True)
self.add_csr('uart_0_phy')
self.submodules.uart_0 = UART(phy=self.uart_0_phy)
self.add_csr('uart_0')
pins = Record([('rx', 1), ('tx', 1)])
pins.rx = uart_1_io['tx']
pins.tx = uart_1_io['tx']
self.submodules.uart_1_phy = RS232PHY(pins, sys_clk_freq, with_dynamic_baudrate=True)
self.add_csr('uart_1_phy')
self.submodules.uart_1 = UART(phy=self.uart_1_phy)
self.add_csr('uart_1')
# DShot M0:M3 (no telemetry) = 4 pins -----------------------------------------------------
#self.submodules.dshot = DShot(dshot_io)
#self.add_csr('dshot')
# Build -------------------------------------------------------------------------------------------
def main():
parser = argparse.ArgumentParser(description='A2P Caravel Test Site')
builder_args(parser)
soc_sdram_args(parser)
args = parser.parse_args()
soc = BaseSoC(**soc_sdram_argdict(args))
builder = Builder(soc, **builder_argdict(args))
soc.build_name = 'wtf' #wtf dont work!
builder.build_name = 'wtf' #wtf dont work!
builder.compile_software = False
builder.csr_csv = 'csr.csv'
builder.build(run=False)
if __name__ == "__main__":
main()