from nmigen_boards.resources.memory import HyperRAMResource
from lambdasoc.periph.hyperram import HyperRAM, HyperRAMPads, HyperRAMPHY
+from lambdasoc.periph.event import IRQLine
from lambdasoc.periph.intc import GenericInterruptController
from lambdasoc.periph.sram import SRAMPeripheral
from lambdasoc.periph.timer import TimerPeripheral
from soc.bus.external_core import ExternalCore # external libresoc/microwatt
from soc.bus.wb_downconvert import WishboneDownConvert
from soc.bus.syscon import MicrowattSYSCON
+from soc.interrupts.xics import XICS_ICP, XICS_ICS
# DDR3
from gram.common import (PhySettings, get_cl_cw, get_sys_latency,
ddr_pins, ddrphy_addr, dramcore_addr, ddr_addr,
fw_addr=0x0000_0000,
firmware=None,
+ uart_addr=None, uart_irqno,
spi0_addr, spi0_cfg_addr,
eth0_cfg_addr, eth0_irqno,
hyperram_addr=None,
hyperram_pins=None,
+ xics_icp_addr=None, xics_ics_addr=None,
clk_freq=50e6,
add_cpu=True):
if fpga in ['versa_ecp5', 'versa_ecp5_85', 'isim', 'ulx3s']:
if fpga in ['isim']:
pod_bits = 6
- self.crg = ECP5CRG(clk_freq, pod_bits)
+ self.crg = ECP5CRG(clk_freq, dram_clk_freq=None, pod_bits=pod_bits)
if fpga in ['arty_a7']:
self.crg = ArtyA7CRG(clk_freq)
self.cvtibus = cvtibus
self.cvtdbus = cvtdbus
- # CPU interrupt controller
+ # CPU interrupt controller, needs stall to be added, also
+ # compat with wishbone.Interface
self.intc = GenericInterruptController(width=len(self.cpu.irq))
+ self.xics_icp = icp = XICS_ICP()
+ self.xics_ics = ics = XICS_ICS()
+ self.int_level_i = self.xics_ics.int_level_i
+
+ self.pbus = pbus = wishbone.Interface(name="xics_icp_bus",
+ addr_width=10, data_width=32,
+ granularity=8, features={'stall'})
+ self.sbus = sbus = wishbone.Interface(name="xics_ics_bus",
+ addr_width=10, data_width=32,
+ granularity=8, features={'stall'})
+ pmap = MemoryMap(addr_width=12, data_width=8, name="icp_map")
+ pbus.memory_map = pmap
+ self._decoder.add(pbus, addr=xics_icp_addr) # ICP addr
+
+ smap = MemoryMap(addr_width=12, data_width=8, name="ics_map")
+ sbus.memory_map = smap
+ self._decoder.add(sbus, addr=xics_ics_addr) # ICP addr
+
# SRAM (but actually a ROM, for firmware)
if fw_addr is not None:
# UART at 0xC000_2000, convert 32-bit bus down to 8-bit in an odd way
if uart_pins is not None:
# sigh actual UART in microwatt is 8-bit
+ self.uart_irq = IRQLine()
self.uart = UART16550(data_width=8, pins=uart_pins,
- features={'stall'})
+ features={'stall'},
+ irq=self.uart_irq)
# but (see soc.vhdl) 8-bit regs are addressed at 32-bit locations
+ # strictly speaking this is a nmigen-soc "sparse" arrangement
+ # which should be handled by MemoryMap, but needs investigation
cvtuartbus = wishbone.Interface(addr_width=5, data_width=32,
granularity=8,
features={'stall'})
umap = MemoryMap(addr_width=7, data_width=8, name="uart_map")
cvtuartbus.memory_map = umap
- self._decoder.add(cvtuartbus, addr=0xc0002000) # 16550 UART addr
+ self._decoder.add(cvtuartbus, addr=uart_addr) # 16550 UART addr
self.cvtuartbus = cvtuartbus
+ self.intc.add_irq(self.uart.irq, index=uart_irqno)
# SDRAM module using opencores sdr_ctrl
"""
if ethmac_0_pins is not None and fpga in ['versa_ecp5',
'versa_ecp5_85',
'isim']:
+ self.eth_irq = IRQLine()
# The OpenCores Ethernet MAC contains two independent Wishbone
# interfaces, a slave (configuration) interface and a master (DMA)
# interface.
- self.eth0 = EthMAC(pins=ethmac_0_pins)
+ self.eth0 = EthMAC(pins=ethmac_0_pins, irq=self.eth_irq)
self._arbiter.add(self.eth0.master_bus)
self._decoder.add(self.eth0.slave_bus, addr=eth0_cfg_addr)
self.intc.add_irq(self.eth0.irq, index=eth0_irqno)
comb += self.uart.ri_i.eq(0)
comb += self.uart.dcd_i.eq(1)
# sigh connect up the wishbone bus manually to deal with
- # the mis-match on the data
+ # the mis-match on the data. nmigen-soc "sparse" MemoryMap
+ # should be able to deal with this. TODO, investigate
uartbus = self.uart.bus
comb += uartbus.adr.eq(self.cvtuartbus.adr)
comb += uartbus.stb.eq(self.cvtuartbus.stb)
comb += self._arbiter.bus.connect(self._decoder.bus)
if hasattr(self, "cpu"):
- # wire up the CPU interrupts
- comb += self.cpu.irq.eq(self.intc.ip)
+ m.submodules.xics_icp = icp = self.xics_icp
+ m.submodules.xics_ics = ics = self.xics_ics
+ comb += icp.ics_i.eq(ics.icp_o) # connect ICS to ICP
+ comb += self.cpu.irq.eq(icp.core_irq_o) # connect ICP to core
+
+ # wire up the CPU interrupts from the GenericInterrupt
+ comb += self.int_level_i.eq(self.intc.ip)
+
+ # grrr
+ comb += self.pbus.stall.eq(self.pbus.cyc & ~self.pbus.ack)
+ comb += self.sbus.stall.eq(self.sbus.cyc & ~self.sbus.ack)
+
+ # and also wire up make_wb_layout() to wishbone.Interface.
+ # really, XICS_ICS and XICS_ICP both need to be converted
+ # to use wishbone.Interface and this all goes
+ comb += icp.bus.adr.eq(self.pbus.adr)
+ comb += icp.bus.dat_w.eq(self.pbus.dat_w)
+ comb += icp.bus.cyc.eq(self.pbus.cyc)
+ comb += icp.bus.stb.eq(self.pbus.stb)
+ comb += icp.bus.we.eq(self.pbus.we)
+ comb += self.pbus.ack.eq(icp.bus.ack)
+ comb += self.pbus.dat_r.eq(icp.bus.dat_r)
+ comb += ics.bus.adr.eq(self.sbus.adr)
+ comb += ics.bus.dat_w.eq(self.sbus.dat_w)
+ comb += ics.bus.cyc.eq(self.sbus.cyc)
+ comb += ics.bus.stb.eq(self.sbus.stb)
+ comb += ics.bus.we.eq(self.sbus.we)
+ comb += self.sbus.ack.eq(ics.bus.ack)
+ comb += self.sbus.dat_r.eq(ics.bus.dat_r)
if platform is None:
return m
ddr_addr=0x00000000, # DRAM_BASE
spi0_addr=0xf0000000, # SPI0_BASE
spi0_cfg_addr=0xc0006000, # SPI0_CTRL_BASE
- eth0_cfg_addr=0xc0004000, # ETH0_CTRL_BASE (4k)
- eth0_irqno=0, # ETH0_IRQ number
+ eth0_cfg_addr=0xc000c000, # ETH0_CTRL_BASE (4k)
+ eth0_irqno=1, # ETH0_IRQ number (match microwatt)
hyperram_addr=0xa0000000, # HYPERRAM_BASE
fw_addr=fw_addr,
#fw_addr=None,
ddr_pins=ddr_pins,
uart_pins=uart_pins,
+ uart_irqno=0, # UART_IRQ number (match microwatt)
+ uart_addr=0xc0002000, # UART0_ADDR
spi_0_pins=spi_0_pins,
ethmac_0_pins=ethmac_0_pins,
hyperram_pins=hyperram_pins,
firmware=firmware,
+ xics_icp_addr=0xc000_4000, # XICS_ICP_BASE
+ xics_ics_addr=0xc000_5000, # XICS_ICS_BASE
clk_freq=clk_freq,
add_cpu=True)