223 lines
8.6 KiB
Python
223 lines
8.6 KiB
Python
#!/usr/bin/python3
|
|
|
|
# A2O Test - build with core.py
|
|
# a2o.py --csr-csv csr.csv --no-compile-software --build [--sys-clk-freq 50e6]
|
|
#
|
|
|
|
import os
|
|
import argparse
|
|
|
|
from migen import *
|
|
|
|
# wtf - use local platform
|
|
from platforms import cmod7
|
|
|
|
# wtf - use local core (not built into litex)
|
|
# help python find package
|
|
import sys
|
|
binPath = os.path.dirname(os.path.realpath(__file__))
|
|
sys.path.append(os.path.join(binPath, 'a2p')) # dir with core package; core.py defines core source location
|
|
# get core def
|
|
from a2o import A2O
|
|
# add to litex dict
|
|
from litex.soc.cores import cpu
|
|
cpu.CPUS['a2o'] = A2O
|
|
|
|
from litex.soc.cores.clock import *
|
|
from litex.soc.integration.soc import SoCRegion
|
|
from litex.soc.integration.soc_core import *
|
|
from litex.soc.integration.builder import *
|
|
|
|
from litex.soc.cores.led import LedChaser
|
|
from litex.soc.cores import dna, xadc
|
|
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.cores import uart
|
|
from litex.soc.cores.uart import UART
|
|
from litex.soc.cores.uart import UARTPHY
|
|
from litex.soc.cores.uart import UARTWishboneBridge
|
|
from litescope import LiteScopeAnalyzer
|
|
|
|
# CRG ----------------------------------------------------------------------------------------------
|
|
|
|
class _CRG(Module):
|
|
def __init__(self, platform, sys_clk_freq):
|
|
self.rst = Signal()
|
|
self.clock_domains.cd_sys = ClockDomain()
|
|
self.clock_domains.cd_sys2x = ClockDomain(reset_less=True)
|
|
self.clock_domains.cd_idelay = ClockDomain()
|
|
|
|
self.submodules.pll = pll = S7MMCM(speedgrade=-1)
|
|
#wtf if you do this it crashes later..request() takes the pin off 'available' list i think; so can't put to csr reg
|
|
#no idea how to modify the reset signal later
|
|
#maybe have to change this class to take a signal you create first?
|
|
#x = platform.request('user_btn',0)
|
|
self.comb += pll.reset.eq(self.rst)
|
|
#self.comb += pll.reset.eq(self.rst)
|
|
pll.register_clkin(platform.request('clk12'), 12e6)
|
|
pll.create_clkout(self.cd_sys, sys_clk_freq)
|
|
pll.create_clkout(self.cd_sys2x, 2*sys_clk_freq)
|
|
pll.create_clkout(self.cd_idelay, 200e6)
|
|
platform.add_false_path_constraints(self.cd_sys.clk, pll.clkin) # Ignore sys_clk to pll.clkin path created by SoC's rst.
|
|
|
|
self.submodules.idelayctrl = S7IDELAYCTRL(self.cd_idelay)
|
|
|
|
def _to_signal(obj):
|
|
return obj.raw_bits() if isinstance(obj, Record) else obj
|
|
|
|
class BaseSoC(SoCCore):
|
|
|
|
def __init__(self, sys_clk_freq=int(50e6),
|
|
with_analyzer=False,
|
|
uart_baudrate=115200,
|
|
**kwargs):
|
|
|
|
coreUART = True
|
|
|
|
# try build using different fpga's
|
|
#platform = cmod7.Platform()
|
|
#platform = cmod7.Platform(fpga='xc7a200t-SBG484-1') # arty-200
|
|
#platform = cmod7.Platform(fpga='xc7k325t-ffv676-1 ) #
|
|
platform = cmod7.Platform(fpga='xc7k410t-ffv676-1') #
|
|
|
|
SoCCore.__init__(self, platform, sys_clk_freq, csr_data_width=32,
|
|
with_uart=coreUART, integrated_sram_size=0, integrated_rom_size=0,
|
|
ident='A2O Test', ident_version=True, uart_baudrate=uart_baudrate,
|
|
cpu_type='a2o')
|
|
|
|
print(f'Building variant={self.cpu.variant}.')
|
|
|
|
# no irq yet? should be able to connect
|
|
#self.add_constant('UART_POLLING')
|
|
|
|
#!!!!!!!!!!!!!!!!!!
|
|
# any hints here on using uarts (to get the gpio one working)?
|
|
# cult-soft.de/2920/05/24/litex-uart-hub
|
|
# played a little below but didnt try if it works
|
|
#!!!!!!!!!!!!!!!!!!
|
|
|
|
# this appears to be how to set up fixed csr order but not sure it works this way. https://github.com/litex-hub/linux-on-litex-vexriscv/blob/master/soc_linux.py
|
|
#SoCCore.csr_map
|
|
#self.csr_map = {**SoCCore.csr_map, **{
|
|
#self.csr_map = {
|
|
# 'ctrl': 0,
|
|
# 'dna' : 1,
|
|
# 'uart': 2,
|
|
# 'i2c': 3,
|
|
# 'leds': 4
|
|
#}}
|
|
#interrupt_map = {**soc_cls.interrupt_map, **{
|
|
# 'uart': 0,
|
|
# 'timer0': 1,
|
|
#}}
|
|
|
|
self.mem_map = {
|
|
'csr': 0xFFF00000,
|
|
'main_ram': 0x00100000,
|
|
'rom': 0x00000000,
|
|
'ram': 0x00010000,
|
|
}
|
|
|
|
# CRG --------------------------------------------------------------------------------------
|
|
self.submodules.crg = _CRG(platform, sys_clk_freq)
|
|
|
|
if not coreUART:
|
|
self.submodules.serial_bridge = UARTWishboneBridge(platform.request('serial'), sys_clk_freq)
|
|
self.add_wb_master(self.serial_bridge.wishbone)
|
|
|
|
self.add_csr('node_ctl')
|
|
self.add_csr('node_config')
|
|
self.add_csr('node_status')
|
|
|
|
# ON-BOARD MEM ------------------------------------------------------------------------------
|
|
|
|
with open('rom.init', 'r') as file:
|
|
hexdata = file.read().replace('\n', '')
|
|
|
|
#a2o how will this work for a2o? should allow 32BE or 64LE to load kernel+bios
|
|
# 1. core resets to 32BE
|
|
# 2. probably want to link kernel+bios in same mode, so have kernel deal with possible mode switch
|
|
# 3. load mem here in proper mode based on variant (A2O_32BE or A2O64_LE)
|
|
|
|
outFile = open('mem_init', 'w') # write data immediately so available even if not building (sim)
|
|
# this seems to work (specified in BE in rom.init, instructions are decoded properly)
|
|
# BUT, vivado wants each line to be 4B to match width (at least for sim)
|
|
bytedata = []
|
|
for i in range(0, len(hexdata), 8):
|
|
data = int(hexdata[i+6:i+8] + hexdata[i+4:i+6] + hexdata[i+2:i+4] + hexdata[i:i+2], 16) # BE->LE
|
|
bytedata.append(data)
|
|
outFile.write(hexdata[i+6:i+8] + hexdata[i+4:i+6] + hexdata[i+2:i+4] + hexdata[i:i+2] + '\n')
|
|
#bytedata.append(int(hexdata[i:i+2] + hexdata[i+2:i+4] + hexdata[i+4:i+6] + hexdata[i+6:i+8], 16))
|
|
romdata = bytedata
|
|
print('Read ' + str(len(romdata)) + ' bytes for ROM data.')
|
|
outFile.close()
|
|
print('Wrote mem.init')
|
|
|
|
self.add_rom('rom', origin=self.mem_map['rom'], size=0x10000, contents=romdata) # name, origin, size, contents=[], mode='r'
|
|
# make this sram to match what linker expects
|
|
self.add_ram('sram', origin=self.mem_map['ram'], size=0x10000) # name, origin, size, contents=[], mode='rw'
|
|
|
|
# Leds -------------------------------------------------------------------------------------
|
|
self.submodules.leds = LedChaser(
|
|
pads = platform.request_all('user_led'),
|
|
sys_clk_freq = sys_clk_freq
|
|
)
|
|
self.add_csr('leds')
|
|
|
|
# Buttons
|
|
self.submodules.buttons = GPIOIn(
|
|
pads = platform.request_all('user_btn')
|
|
)
|
|
self.add_csr('buttons')
|
|
|
|
# SRAM -------------------------------------------------------------------------------------
|
|
self.add_ram('main_ram', origin=self.mem_map['main_ram'], size=0x100)
|
|
|
|
# Analyzer ---------------------------------------------------------------------------------
|
|
if with_analyzer:
|
|
analyzer_signals = [
|
|
self.cpu.dbus.stb,
|
|
self.cpu.dbus.cyc,
|
|
self.cpu.dbus.adr,
|
|
self.cpu.dbus.we,
|
|
self.cpu.dbus.ack,
|
|
self.cpu.dbus.sel,
|
|
self.cpu.dbus.dat_w,
|
|
self.cpu.dbus.dat_r,
|
|
]
|
|
self.submodules.analyzer = LiteScopeAnalyzer(analyzer_signals,
|
|
depth = 512,
|
|
clock_domain = 'sys',
|
|
csr_csv = 'analyzer.csv')
|
|
self.add_csr('analyzer')
|
|
|
|
|
|
|
|
# Build --------------------------------------------------------------------------------------------
|
|
|
|
def main():
|
|
|
|
parser = argparse.ArgumentParser(description='A2O Test')
|
|
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=100e6, help='System clock frequency (default: 100MHz)')
|
|
parser.add_argument('--with-analyzer', action='store_true', help='Include analyzer')
|
|
|
|
builder_args(parser)
|
|
args = parser.parse_args()
|
|
|
|
soc = BaseSoC(
|
|
sys_clk_freq = int(float(args.sys_clk_freq)),
|
|
with_analyzer = args.with_analyzer,
|
|
)
|
|
|
|
builder = Builder(soc, **builder_argdict(args))
|
|
builder.build(run=args.build)
|
|
|
|
if __name__ == '__main__':
|
|
main()
|