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
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()
|