core/cpu: integrate Zynq as a classical CPU (Zynq7000), deprecate SoCZynq.
This is the logical continuation of the recent change to avoid specific SoC classes. A Zynq FPGA can be used with or without the PS7. When used without the PS7, a softcore CPU can be used as with others FPGAs. When using the PS7, the softcore is replaced with the PS7 and connected to the SoC through one of the AXI GP interface. An example is available on litex-boards.
This commit is contained in:
parent
8bdf6941a3
commit
041c7527ce
|
@ -1,5 +1,5 @@
|
||||||
|
# This file is Copyright (c) 2015-2020 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||||
# This file is Copyright (c) 2017-2018 Tim 'mithro' Ansell <me@mith.ro>
|
# This file is Copyright (c) 2017-2018 Tim 'mithro' Ansell <me@mith.ro>
|
||||||
# This file is Copyright (c) 2015-2019 Florent Kermarrec <florent@enjoy-digital.fr>
|
|
||||||
# License: BSD
|
# License: BSD
|
||||||
|
|
||||||
from migen import *
|
from migen import *
|
||||||
|
@ -56,16 +56,29 @@ CPU_GCC_TRIPLE_RISCV64 = (
|
||||||
|
|
||||||
# CPUS ---------------------------------------------------------------------------------------------
|
# CPUS ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# LM32
|
||||||
from litex.soc.cores.cpu.lm32 import LM32
|
from litex.soc.cores.cpu.lm32 import LM32
|
||||||
|
|
||||||
|
# OpenRisc
|
||||||
from litex.soc.cores.cpu.mor1kx import MOR1KX
|
from litex.soc.cores.cpu.mor1kx import MOR1KX
|
||||||
|
|
||||||
|
# OpenPower
|
||||||
from litex.soc.cores.cpu.microwatt import Microwatt
|
from litex.soc.cores.cpu.microwatt import Microwatt
|
||||||
|
|
||||||
|
# RISC-V (32-bit)
|
||||||
from litex.soc.cores.cpu.serv import SERV
|
from litex.soc.cores.cpu.serv import SERV
|
||||||
from litex.soc.cores.cpu.picorv32 import PicoRV32
|
from litex.soc.cores.cpu.picorv32 import PicoRV32
|
||||||
from litex.soc.cores.cpu.minerva import Minerva
|
from litex.soc.cores.cpu.minerva import Minerva
|
||||||
from litex.soc.cores.cpu.vexriscv import VexRiscv
|
from litex.soc.cores.cpu.vexriscv import VexRiscv
|
||||||
|
from litex.soc.cores.cpu.cv32e40p import CV32E40P
|
||||||
|
|
||||||
|
# RISC-V (64-bit)
|
||||||
from litex.soc.cores.cpu.rocket import RocketRV64
|
from litex.soc.cores.cpu.rocket import RocketRV64
|
||||||
from litex.soc.cores.cpu.blackparrot import BlackParrotRV64
|
from litex.soc.cores.cpu.blackparrot import BlackParrotRV64
|
||||||
from litex.soc.cores.cpu.cv32e40p import CV32E40P
|
|
||||||
|
# Zynq
|
||||||
|
from litex.soc.cores.cpu.zynq7000 import Zynq7000
|
||||||
|
|
||||||
|
|
||||||
CPUS = {
|
CPUS = {
|
||||||
# None
|
# None
|
||||||
|
@ -77,17 +90,20 @@ CPUS = {
|
||||||
# OpenRisc
|
# OpenRisc
|
||||||
"mor1kx" : MOR1KX,
|
"mor1kx" : MOR1KX,
|
||||||
|
|
||||||
# Open Power
|
# OpenPower
|
||||||
"microwatt" : Microwatt,
|
"microwatt" : Microwatt,
|
||||||
|
|
||||||
# RISC-V 32-bit
|
# RISC-V (32-bit)
|
||||||
"serv" : SERV,
|
"serv" : SERV,
|
||||||
"picorv32" : PicoRV32,
|
"picorv32" : PicoRV32,
|
||||||
"minerva" : Minerva,
|
"minerva" : Minerva,
|
||||||
"vexriscv" : VexRiscv,
|
"vexriscv" : VexRiscv,
|
||||||
"cv32e40p" : CV32E40P,
|
"cv32e40p" : CV32E40P,
|
||||||
|
|
||||||
# RISC-V 64-bit
|
# RISC-V (64-bit)
|
||||||
"rocket" : RocketRV64,
|
"rocket" : RocketRV64,
|
||||||
"blackparrot" : BlackParrotRV64,
|
"blackparrot" : BlackParrotRV64,
|
||||||
|
|
||||||
|
# Zynq
|
||||||
|
"zynq7000" : Zynq7000,
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
from litex.soc.cores.cpu.zynq7000.core import Zynq7000
|
|
@ -0,0 +1,225 @@
|
||||||
|
# This file is Copyright (c) 2019-2020 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||||
|
# License: BSD
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from migen import *
|
||||||
|
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||||
|
|
||||||
|
from litex.soc.interconnect import wishbone
|
||||||
|
from litex.soc.interconnect import axi
|
||||||
|
|
||||||
|
from litex.soc.cores.cpu import CPU
|
||||||
|
|
||||||
|
|
||||||
|
class Zynq7000(CPU):
|
||||||
|
variants = ["standard"]
|
||||||
|
name = "zynq7000"
|
||||||
|
human_name = "Zynq7000"
|
||||||
|
data_width = 32
|
||||||
|
endianness = "little"
|
||||||
|
reset_address = 0x00000000
|
||||||
|
gcc_triple = "arm-xilinx-eabi"
|
||||||
|
linker_output_format = "elf32-littlearm"
|
||||||
|
nop = "nop"
|
||||||
|
io_regions = {0x00000000: 0x100000000} # origin, length
|
||||||
|
|
||||||
|
def __init__(self, platform, variant):
|
||||||
|
self.platform = platform
|
||||||
|
self.reset = Signal()
|
||||||
|
self.periph_buses = []
|
||||||
|
self.memory_buses = []
|
||||||
|
|
||||||
|
self.axi_gp_masters = []
|
||||||
|
self.axi_gp_slaves = []
|
||||||
|
self.axi_hp_slaves = []
|
||||||
|
|
||||||
|
# # #
|
||||||
|
|
||||||
|
self.clock_domains.cd_ps7 = ClockDomain()
|
||||||
|
|
||||||
|
# PS7 (Minimal) ----------------------------------------------------------------------------
|
||||||
|
ps7_rst_n = Signal()
|
||||||
|
ps7_ddram_pads = platform.request("ps7_ddram")
|
||||||
|
self.cpu_params = dict(
|
||||||
|
# Clk/Rst
|
||||||
|
io_PS_CLK = platform.request("ps7_clk"),
|
||||||
|
io_PS_PORB = platform.request("ps7_porb"),
|
||||||
|
io_PS_SRSTB = platform.request("ps7_srstb"),
|
||||||
|
|
||||||
|
# MIO
|
||||||
|
io_MIO = platform.request("ps7_mio"),
|
||||||
|
|
||||||
|
# DDRAM
|
||||||
|
io_DDR_Addr = ps7_ddram_pads.addr,
|
||||||
|
io_DDR_BankAddr = ps7_ddram_pads.ba,
|
||||||
|
io_DDR_CAS_n = ps7_ddram_pads.cas_n,
|
||||||
|
io_DDR_Clk_n = ps7_ddram_pads.ck_n,
|
||||||
|
io_DDR_Clk = ps7_ddram_pads.ck_p,
|
||||||
|
io_DDR_CKE = ps7_ddram_pads.cke,
|
||||||
|
io_DDR_CS_n = ps7_ddram_pads.cs_n,
|
||||||
|
io_DDR_DM = ps7_ddram_pads.dm,
|
||||||
|
io_DDR_DQ = ps7_ddram_pads.dq,
|
||||||
|
io_DDR_DQS_n = ps7_ddram_pads.dqs_n,
|
||||||
|
io_DDR_DQS = ps7_ddram_pads.dqs_p,
|
||||||
|
io_DDR_ODT = ps7_ddram_pads.odt,
|
||||||
|
io_DDR_RAS_n = ps7_ddram_pads.ras_n,
|
||||||
|
io_DDR_DRSTB = ps7_ddram_pads.reset_n,
|
||||||
|
io_DDR_WEB = ps7_ddram_pads.we_n,
|
||||||
|
io_DDR_VRN = ps7_ddram_pads.vrn,
|
||||||
|
io_DDR_VRP = ps7_ddram_pads.vrp,
|
||||||
|
|
||||||
|
# Ethernet
|
||||||
|
i_ENET0_MDIO_I = 0,
|
||||||
|
|
||||||
|
# SDIO0
|
||||||
|
i_SDIO0_WP = 0,
|
||||||
|
|
||||||
|
# USB0
|
||||||
|
i_USB0_VBUS_PWRFAULT = 0,
|
||||||
|
|
||||||
|
# Fabric Clk/Rst
|
||||||
|
o_FCLK_CLK0 = ClockSignal("ps7"),
|
||||||
|
o_FCLK_RESET0_N = ps7_rst_n
|
||||||
|
)
|
||||||
|
self.specials += AsyncResetSynchronizer(self.cd_ps7, ~ps7_rst_n)
|
||||||
|
|
||||||
|
def set_ps7_xci(self, ps7_xci):
|
||||||
|
self.ps7_xci = ps7_xci
|
||||||
|
self.platform.add_ip(ps7_xci)
|
||||||
|
|
||||||
|
# AXI GP Master --------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def add_axi_gp_master(self):
|
||||||
|
assert len(self.axi_gp_masters) < 2
|
||||||
|
n = len(self.axi_gp_masters)
|
||||||
|
axi_gpn = axi.AXIInterface(data_width=32, address_width=32, id_width=12)
|
||||||
|
self.axi_gp_masters.append(axi_gpn)
|
||||||
|
self.cpu_params.update({
|
||||||
|
# AXI GP clk
|
||||||
|
f"i_M_AXI_GP{n}_ACLK" : ClockSignal("ps7"),
|
||||||
|
|
||||||
|
# AXI GP aw
|
||||||
|
f"o_M_AXI_GP{n}_AWVALID" : axi_gpn.aw.valid,
|
||||||
|
f"i_M_AXI_GP{n}_AWREADY" : axi_gpn.aw.ready,
|
||||||
|
f"o_M_AXI_GP{n}_AWADDR" : axi_gpn.aw.addr,
|
||||||
|
f"o_M_AXI_GP{n}_AWBURST" : axi_gpn.aw.burst,
|
||||||
|
f"o_M_AXI_GP{n}_AWLEN" : axi_gpn.aw.len,
|
||||||
|
f"o_M_AXI_GP{n}_AWSIZE" : axi_gpn.aw.size,
|
||||||
|
f"o_M_AXI_GP{n}_AWID" : axi_gpn.aw.id,
|
||||||
|
f"o_M_AXI_GP{n}_AWLOCK" : axi_gpn.aw.lock,
|
||||||
|
f"o_M_AXI_GP{n}_AWPROT" : axi_gpn.aw.prot,
|
||||||
|
f"o_M_AXI_GP{n}_AWCACHE" : axi_gpn.aw.cache,
|
||||||
|
f"o_M_AXI_GP{n}_AWQOS" : axi_gpn.aw.qos,
|
||||||
|
|
||||||
|
# AXI GP w
|
||||||
|
f"o_M_AXI_GP{n}_WVALID" : axi_gpn.w.valid,
|
||||||
|
f"o_M_AXI_GP{n}_WLAST" : axi_gpn.w.last,
|
||||||
|
f"i_M_AXI_GP{n}_WREADY" : axi_gpn.w.ready,
|
||||||
|
f"o_M_AXI_GP{n}_WID" : axi_gpn.w.id,
|
||||||
|
f"o_M_AXI_GP{n}_WDATA" : axi_gpn.w.data,
|
||||||
|
f"o_M_AXI_GP{n}_WSTRB" : axi_gpn.w.strb,
|
||||||
|
|
||||||
|
# AXI GP b
|
||||||
|
f"i_M_AXI_GP{n}_BVALID" : axi_gpn.b.valid,
|
||||||
|
f"o_M_AXI_GP{n}_BREADY" : axi_gpn.b.ready,
|
||||||
|
f"i_M_AXI_GP{n}_BID" : axi_gpn.b.id,
|
||||||
|
f"i_M_AXI_GP{n}_BRESP" : axi_gpn.b.resp,
|
||||||
|
|
||||||
|
# AXI GP ar
|
||||||
|
f"o_M_AXI_GP{n}_ARVALID" : axi_gpn.ar.valid,
|
||||||
|
f"i_M_AXI_GP{n}_ARREADY" : axi_gpn.ar.ready,
|
||||||
|
f"o_M_AXI_GP{n}_ARADDR" : axi_gpn.ar.addr,
|
||||||
|
f"o_M_AXI_GP{n}_ARBURST" : axi_gpn.ar.burst,
|
||||||
|
f"o_M_AXI_GP{n}_ARLEN" : axi_gpn.ar.len,
|
||||||
|
f"o_M_AXI_GP{n}_ARID" : axi_gpn.ar.id,
|
||||||
|
f"o_M_AXI_GP{n}_ARLOCK" : axi_gpn.ar.lock,
|
||||||
|
f"o_M_AXI_GP{n}_ARSIZE" : axi_gpn.ar.size,
|
||||||
|
f"o_M_AXI_GP{n}_ARPROT" : axi_gpn.ar.prot,
|
||||||
|
f"o_M_AXI_GP{n}_ARCACHE" : axi_gpn.ar.cache,
|
||||||
|
f"o_M_AXI_GP{n}_ARQOS" : axi_gpn.ar.qos,
|
||||||
|
|
||||||
|
# AXI GP r
|
||||||
|
f"i_M_AXI_GP{n}_RVALID" : axi_gpn.r.valid,
|
||||||
|
f"o_M_AXI_GP{n}_RREADY" : axi_gpn.r.ready,
|
||||||
|
f"i_M_AXI_GP{n}_RLAST" : axi_gpn.r.last,
|
||||||
|
f"i_M_AXI_GP{n}_RID" : axi_gpn.r.id,
|
||||||
|
f"i_M_AXI_GP{n}_RRESP" : axi_gpn.r.resp,
|
||||||
|
f"i_M_AXI_GP{n}_RDATA" : axi_gpn.r.data,
|
||||||
|
})
|
||||||
|
return axi_gpn
|
||||||
|
|
||||||
|
# AXI GP Slave ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def add_axi_gp_slave(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
# AXI HP Slave ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def add_axi_hp_slave(self):
|
||||||
|
assert len(self.axi_hp_slaves) < 4
|
||||||
|
n = len(self.axi_hp_slaves)
|
||||||
|
axi_hpn = axi.AXIInterface(data_width=64, address_width=32, id_width=6)
|
||||||
|
self.axi_hp_masters.append(axi_hpn)
|
||||||
|
self.cpu_params.update({
|
||||||
|
# AXI HP0 clk
|
||||||
|
f"i_S_AXI_HP{n}_ACLK" : ClockSignal("ps7"),
|
||||||
|
|
||||||
|
# AXI HP0 aw
|
||||||
|
f"i_S_AXI_HP{n}_AWVALID" : axi_hpn.aw.valid,
|
||||||
|
f"o_S_AXI_HP{n}_AWREADY" : axi_hpn.aw.ready,
|
||||||
|
f"i_S_AXI_HP{n}_AWADDR" : axi_hpn.aw.addr,
|
||||||
|
f"i_S_AXI_HP{n}_AWBURST" : axi_hpn.aw.burst,
|
||||||
|
f"i_S_AXI_HP{n}_AWLEN" : axi_hpn.aw.len,
|
||||||
|
f"i_S_AXI_HP{n}_AWSIZE" : axi_hpn.aw.size,
|
||||||
|
f"i_S_AXI_HP{n}_AWID" : axi_hpn.aw.id,
|
||||||
|
f"i_S_AXI_HP{n}_AWLOCK" : axi_hpn.aw.lock,
|
||||||
|
f"i_S_AXI_HP{n}_AWPROT" : axi_hpn.aw.prot,
|
||||||
|
f"i_S_AXI_HP{n}_AWCACHE" : axi_hpn.aw.cache,
|
||||||
|
f"i_S_AXI_HP{n}_AWQOS" : axi_hpn.aw.qos,
|
||||||
|
|
||||||
|
# AXI HP0 w
|
||||||
|
f"i_S_AXI_HP{n}_WVALID" : axi_hpn.w.valid,
|
||||||
|
f"i_S_AXI_HP{n}_WLAST" : axi_hpn.w.last,
|
||||||
|
f"o_S_AXI_HP{n}_WREADY" : axi_hpn.w.ready,
|
||||||
|
f"i_S_AXI_HP{n}_WID" : axi_hpn.w.id,
|
||||||
|
f"i_S_AXI_HP{n}_WDATA" : axi_hpn.w.data,
|
||||||
|
f"i_S_AXI_HP{n}_WSTRB" : axi_hpn.w.strb,
|
||||||
|
|
||||||
|
# AXI HP0 b
|
||||||
|
f"o_S_AXI_HP{n}_BVALID" : axi_hpn.b.valid,
|
||||||
|
f"i_S_AXI_HP{n}_BREADY" : axi_hpn.b.ready,
|
||||||
|
f"o_S_AXI_HP{n}_BID" : axi_hpn.b.id,
|
||||||
|
f"o_S_AXI_HP{n}_BRESP" : axi_hpn.b.resp,
|
||||||
|
|
||||||
|
# AXI HP0 ar
|
||||||
|
f"i_S_AXI_HP{n}_ARVALID" : axi_hpn.ar.valid,
|
||||||
|
f"o_S_AXI_HP{n}_ARREADY" : axi_hpn.ar.ready,
|
||||||
|
f"i_S_AXI_HP{n}_ARADDR" : axi_hpn.ar.addr,
|
||||||
|
f"i_S_AXI_HP{n}_ARBURST" : axi_hpn.ar.burst,
|
||||||
|
f"i_S_AXI_HP{n}_ARLEN" : axi_hpn.ar.len,
|
||||||
|
f"i_S_AXI_HP{n}_ARID" : axi_hpn.ar.id,
|
||||||
|
f"i_S_AXI_HP{n}_ARLOCK" : axi_hpn.ar.lock,
|
||||||
|
f"i_S_AXI_HP{n}_ARSIZE" : axi_hpn.ar.size,
|
||||||
|
f"i_S_AXI_HP{n}_ARPROT" : axi_hpn.ar.prot,
|
||||||
|
f"i_S_AXI_HP{n}_ARCACHE" : axi_hpn.ar.cache,
|
||||||
|
f"i_S_AXI_HP{n}_ARQOS" : axi_hpn.ar.qos,
|
||||||
|
|
||||||
|
# AXI HP0 r
|
||||||
|
f"o_S_AXI_HP{n}_RVALID" : axi_hpn.r.valid,
|
||||||
|
f"i_S_AXI_HP{n}_RREADY" : axi_hpn.r.ready,
|
||||||
|
f"o_S_AXI_HP{n}_RLAST" : axi_hpn.r.last,
|
||||||
|
f"o_S_AXI_HP{n}_RID" : axi_hpn.r.id,
|
||||||
|
f"o_S_AXI_HP{n}_RRESP" : axi_hpn.r.resp,
|
||||||
|
f"o_S_AXI_HP{n}_RDATA" : axi_hpn.r.data,
|
||||||
|
})
|
||||||
|
return axi_hpn
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def add_sources(platform):
|
||||||
|
platform.add_ip(os.path.join("ip", self.ps7))
|
||||||
|
|
||||||
|
def do_finalize(self):
|
||||||
|
assert hasattr(self, "ps7_xci")
|
||||||
|
ps7_name = os.path.splitext(os.path.basename(self.ps7_xci))[0]
|
||||||
|
self.specials += Instance(ps7_name, **self.cpu_params)
|
|
@ -17,9 +17,15 @@ import shutil
|
||||||
from litex import get_data_mod
|
from litex import get_data_mod
|
||||||
from litex.build.tools import write_to_file
|
from litex.build.tools import write_to_file
|
||||||
from litex.soc.integration import export, soc_core
|
from litex.soc.integration import export, soc_core
|
||||||
|
from litex.soc.cores import cpu
|
||||||
|
|
||||||
__all__ = ["soc_software_packages", "soc_directory",
|
__all__ = [
|
||||||
"Builder", "builder_args", "builder_argdict"]
|
"soc_software_packages",
|
||||||
|
"soc_directory",
|
||||||
|
"Builder",
|
||||||
|
"builder_args",
|
||||||
|
"builder_argdict"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
soc_software_packages = [
|
soc_software_packages = [
|
||||||
|
@ -84,7 +90,7 @@ class Builder:
|
||||||
os.makedirs(self.include_dir, exist_ok=True)
|
os.makedirs(self.include_dir, exist_ok=True)
|
||||||
os.makedirs(self.generated_dir, exist_ok=True)
|
os.makedirs(self.generated_dir, exist_ok=True)
|
||||||
|
|
||||||
if self.soc.cpu_type is not None:
|
if self.soc.cpu_type not in [None, "zynq7000"]:
|
||||||
variables_contents = []
|
variables_contents = []
|
||||||
def define(k, v):
|
def define(k, v):
|
||||||
variables_contents.append("{}={}\n".format(k, _makefile_escape(v)))
|
variables_contents.append("{}={}\n".format(k, _makefile_escape(v)))
|
||||||
|
|
|
@ -825,7 +825,7 @@ class SoC(Module):
|
||||||
self.bus.add_region("io{}".format(n), SoCIORegion(origin=origin, size=size, cached=False))
|
self.bus.add_region("io{}".format(n), SoCIORegion(origin=origin, size=size, cached=False))
|
||||||
self.mem_map.update(self.cpu.mem_map) # FIXME
|
self.mem_map.update(self.cpu.mem_map) # FIXME
|
||||||
# Add Bus Masters/CSR/IRQs
|
# Add Bus Masters/CSR/IRQs
|
||||||
if not isinstance(self.cpu, cpu.CPUNone):
|
if not isinstance(self.cpu, (cpu.CPUNone, cpu.Zynq7000)):
|
||||||
if reset_address is None:
|
if reset_address is None:
|
||||||
reset_address = self.mem_map["rom"]
|
reset_address = self.mem_map["rom"]
|
||||||
self.cpu.set_reset_address(reset_address)
|
self.cpu.set_reset_address(reset_address)
|
||||||
|
@ -972,7 +972,7 @@ class SoC(Module):
|
||||||
self.add_constant(name + "_" + constant.name, constant.value.value)
|
self.add_constant(name + "_" + constant.name, constant.value.value)
|
||||||
|
|
||||||
# SoC CPU Check ----------------------------------------------------------------------------
|
# SoC CPU Check ----------------------------------------------------------------------------
|
||||||
if not isinstance(self.cpu, cpu.CPUNone):
|
if not isinstance(self.cpu, (cpu.CPUNone, cpu.Zynq7000)):
|
||||||
if "sram" not in self.bus.regions.keys():
|
if "sram" not in self.bus.regions.keys():
|
||||||
self.logger.error("CPU needs {} Region to be {} as Bus or Linker Region.".format(
|
self.logger.error("CPU needs {} Region to be {} as Bus or Linker Region.".format(
|
||||||
colorer("sram"),
|
colorer("sram"),
|
||||||
|
|
|
@ -131,6 +131,8 @@ class SoCCore(LiteXSoC):
|
||||||
self.cpu_variant = cpu_variant
|
self.cpu_variant = cpu_variant
|
||||||
self.cpu_cls = cpu_cls
|
self.cpu_cls = cpu_cls
|
||||||
|
|
||||||
|
if cpu_type in [None, "zynq7000"]:
|
||||||
|
integrated_rom_size = 0
|
||||||
self.integrated_rom_size = integrated_rom_size
|
self.integrated_rom_size = integrated_rom_size
|
||||||
self.integrated_rom_initialized = integrated_rom_init != []
|
self.integrated_rom_initialized = integrated_rom_init != []
|
||||||
self.integrated_sram_size = integrated_sram_size
|
self.integrated_sram_size = integrated_sram_size
|
||||||
|
|
|
@ -1,218 +0,0 @@
|
||||||
# This file is Copyright (c) 2019 Florent Kermarrec <florent@enjoy-digital.fr>
|
|
||||||
# License: BSD
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
from migen import *
|
|
||||||
|
|
||||||
from litex.build.generic_platform import tools
|
|
||||||
from litex.soc.integration.soc_core import *
|
|
||||||
from litex.soc.integration.export import get_csr_header
|
|
||||||
from litex.soc.interconnect import wishbone
|
|
||||||
from litex.soc.interconnect import axi
|
|
||||||
|
|
||||||
# Record layouts -----------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def axi_fifo_ctrl_layout():
|
|
||||||
return [
|
|
||||||
("racount", 3, DIR_M_TO_S),
|
|
||||||
("rcount", 8, DIR_M_TO_S),
|
|
||||||
("rdissuecapen", 1, DIR_S_TO_M),
|
|
||||||
("wacount", 6, DIR_M_TO_S),
|
|
||||||
("wcount", 8, DIR_M_TO_S),
|
|
||||||
("wrissuecapen", 1, DIR_S_TO_M),
|
|
||||||
]
|
|
||||||
|
|
||||||
# SoC Zynq -----------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
class SoCZynq(SoCCore):
|
|
||||||
SoCCore.mem_map["csr"] = 0x00000000
|
|
||||||
def __init__(self, platform, clk_freq, ps7_name, **kwargs):
|
|
||||||
self.ps7_name = ps7_name
|
|
||||||
SoCCore.__init__(self, platform, clk_freq, cpu_type=None, **kwargs)
|
|
||||||
|
|
||||||
# PS7 (Minimal) ----------------------------------------------------------------------------
|
|
||||||
fclk_reset0_n = Signal()
|
|
||||||
ps7_ddram_pads = platform.request("ps7_ddram")
|
|
||||||
self.ps7_params = dict(
|
|
||||||
# clk/rst
|
|
||||||
io_PS_CLK = platform.request("ps7_clk"),
|
|
||||||
io_PS_PORB = platform.request("ps7_porb"),
|
|
||||||
io_PS_SRSTB = platform.request("ps7_srstb"),
|
|
||||||
|
|
||||||
# mio
|
|
||||||
io_MIO=platform.request("ps7_mio"),
|
|
||||||
|
|
||||||
# ddram
|
|
||||||
io_DDR_Addr = ps7_ddram_pads.addr,
|
|
||||||
io_DDR_BankAddr = ps7_ddram_pads.ba,
|
|
||||||
io_DDR_CAS_n = ps7_ddram_pads.cas_n,
|
|
||||||
io_DDR_Clk_n = ps7_ddram_pads.ck_n,
|
|
||||||
io_DDR_Clk = ps7_ddram_pads.ck_p,
|
|
||||||
io_DDR_CKE = ps7_ddram_pads.cke,
|
|
||||||
io_DDR_CS_n = ps7_ddram_pads.cs_n,
|
|
||||||
io_DDR_DM = ps7_ddram_pads.dm,
|
|
||||||
io_DDR_DQ = ps7_ddram_pads.dq,
|
|
||||||
io_DDR_DQS_n = ps7_ddram_pads.dqs_n,
|
|
||||||
io_DDR_DQS = ps7_ddram_pads.dqs_p,
|
|
||||||
io_DDR_ODT = ps7_ddram_pads.odt,
|
|
||||||
io_DDR_RAS_n = ps7_ddram_pads.ras_n,
|
|
||||||
io_DDR_DRSTB = ps7_ddram_pads.reset_n,
|
|
||||||
io_DDR_WEB = ps7_ddram_pads.we_n,
|
|
||||||
io_DDR_VRN = ps7_ddram_pads.vrn,
|
|
||||||
io_DDR_VRP = ps7_ddram_pads.vrp,
|
|
||||||
|
|
||||||
# ethernet
|
|
||||||
i_ENET0_MDIO_I=0,
|
|
||||||
|
|
||||||
# sdio0
|
|
||||||
i_SDIO0_WP=0,
|
|
||||||
|
|
||||||
# usb0
|
|
||||||
i_USB0_VBUS_PWRFAULT=0,
|
|
||||||
|
|
||||||
# fabric clk/rst
|
|
||||||
o_FCLK_CLK0 = ClockSignal("sys"),
|
|
||||||
o_FCLK_RESET0_N = fclk_reset0_n
|
|
||||||
)
|
|
||||||
self.comb += ResetSignal("sys").eq(~fclk_reset0_n)
|
|
||||||
platform.add_ip(os.path.join("ip", ps7_name + ".xci"))
|
|
||||||
|
|
||||||
# GP0 ------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def add_gp0(self):
|
|
||||||
self.axi_gp0 = axi_gp0 = axi.AXIInterface(data_width=32, address_width=32, id_width=12)
|
|
||||||
self.ps7_params.update(
|
|
||||||
# axi gp0 clk
|
|
||||||
i_M_AXI_GP0_ACLK=ClockSignal("sys"),
|
|
||||||
|
|
||||||
# axi gp0 aw
|
|
||||||
o_M_AXI_GP0_AWVALID = axi_gp0.aw.valid,
|
|
||||||
i_M_AXI_GP0_AWREADY = axi_gp0.aw.ready,
|
|
||||||
o_M_AXI_GP0_AWADDR = axi_gp0.aw.addr,
|
|
||||||
o_M_AXI_GP0_AWBURST = axi_gp0.aw.burst,
|
|
||||||
o_M_AXI_GP0_AWLEN = axi_gp0.aw.len,
|
|
||||||
o_M_AXI_GP0_AWSIZE = axi_gp0.aw.size,
|
|
||||||
o_M_AXI_GP0_AWID = axi_gp0.aw.id,
|
|
||||||
o_M_AXI_GP0_AWLOCK = axi_gp0.aw.lock,
|
|
||||||
o_M_AXI_GP0_AWPROT = axi_gp0.aw.prot,
|
|
||||||
o_M_AXI_GP0_AWCACHE = axi_gp0.aw.cache,
|
|
||||||
o_M_AXI_GP0_AWQOS = axi_gp0.aw.qos,
|
|
||||||
|
|
||||||
# axi gp0 w
|
|
||||||
o_M_AXI_GP0_WVALID = axi_gp0.w.valid,
|
|
||||||
o_M_AXI_GP0_WLAST = axi_gp0.w.last,
|
|
||||||
i_M_AXI_GP0_WREADY = axi_gp0.w.ready,
|
|
||||||
o_M_AXI_GP0_WID = axi_gp0.w.id,
|
|
||||||
o_M_AXI_GP0_WDATA = axi_gp0.w.data,
|
|
||||||
o_M_AXI_GP0_WSTRB = axi_gp0.w.strb,
|
|
||||||
|
|
||||||
# axi gp0 b
|
|
||||||
i_M_AXI_GP0_BVALID = axi_gp0.b.valid,
|
|
||||||
o_M_AXI_GP0_BREADY = axi_gp0.b.ready,
|
|
||||||
i_M_AXI_GP0_BID = axi_gp0.b.id,
|
|
||||||
i_M_AXI_GP0_BRESP = axi_gp0.b.resp,
|
|
||||||
|
|
||||||
# axi gp0 ar
|
|
||||||
o_M_AXI_GP0_ARVALID = axi_gp0.ar.valid,
|
|
||||||
i_M_AXI_GP0_ARREADY = axi_gp0.ar.ready,
|
|
||||||
o_M_AXI_GP0_ARADDR = axi_gp0.ar.addr,
|
|
||||||
o_M_AXI_GP0_ARBURST = axi_gp0.ar.burst,
|
|
||||||
o_M_AXI_GP0_ARLEN = axi_gp0.ar.len,
|
|
||||||
o_M_AXI_GP0_ARID = axi_gp0.ar.id,
|
|
||||||
o_M_AXI_GP0_ARLOCK = axi_gp0.ar.lock,
|
|
||||||
o_M_AXI_GP0_ARSIZE = axi_gp0.ar.size,
|
|
||||||
o_M_AXI_GP0_ARPROT = axi_gp0.ar.prot,
|
|
||||||
o_M_AXI_GP0_ARCACHE = axi_gp0.ar.cache,
|
|
||||||
o_M_AXI_GP0_ARQOS = axi_gp0.ar.qos,
|
|
||||||
|
|
||||||
# axi gp0 r
|
|
||||||
i_M_AXI_GP0_RVALID = axi_gp0.r.valid,
|
|
||||||
o_M_AXI_GP0_RREADY = axi_gp0.r.ready,
|
|
||||||
i_M_AXI_GP0_RLAST = axi_gp0.r.last,
|
|
||||||
i_M_AXI_GP0_RID = axi_gp0.r.id,
|
|
||||||
i_M_AXI_GP0_RRESP = axi_gp0.r.resp,
|
|
||||||
i_M_AXI_GP0_RDATA = axi_gp0.r.data,
|
|
||||||
)
|
|
||||||
|
|
||||||
# HP0 ------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def add_hp0(self):
|
|
||||||
self.axi_hp0 = axi_hp0 = axi.AXIInterface(data_width=64, address_width=32, id_width=6)
|
|
||||||
self.axi_hp0_fifo_ctrl = axi_hp0_fifo_ctrl = Record(axi_fifo_ctrl_layout())
|
|
||||||
self.ps7_params.update(
|
|
||||||
# axi hp0 clk
|
|
||||||
i_S_AXI_HP0_ACLK=ClockSignal("sys"),
|
|
||||||
|
|
||||||
# axi hp0 aw
|
|
||||||
i_S_AXI_HP0_AWVALID = axi_hp0.aw.valid,
|
|
||||||
o_S_AXI_HP0_AWREADY = axi_hp0.aw.ready,
|
|
||||||
i_S_AXI_HP0_AWADDR = axi_hp0.aw.addr,
|
|
||||||
i_S_AXI_HP0_AWBURST = axi_hp0.aw.burst,
|
|
||||||
i_S_AXI_HP0_AWLEN = axi_hp0.aw.len,
|
|
||||||
i_S_AXI_HP0_AWSIZE = axi_hp0.aw.size,
|
|
||||||
i_S_AXI_HP0_AWID = axi_hp0.aw.id,
|
|
||||||
i_S_AXI_HP0_AWLOCK = axi_hp0.aw.lock,
|
|
||||||
i_S_AXI_HP0_AWPROT = axi_hp0.aw.prot,
|
|
||||||
i_S_AXI_HP0_AWCACHE = axi_hp0.aw.cache,
|
|
||||||
i_S_AXI_HP0_AWQOS = axi_hp0.aw.qos,
|
|
||||||
|
|
||||||
# axi hp0 w
|
|
||||||
i_S_AXI_HP0_WVALID = axi_hp0.w.valid,
|
|
||||||
i_S_AXI_HP0_WLAST = axi_hp0.w.last,
|
|
||||||
o_S_AXI_HP0_WREADY = axi_hp0.w.ready,
|
|
||||||
i_S_AXI_HP0_WID = axi_hp0.w.id,
|
|
||||||
i_S_AXI_HP0_WDATA = axi_hp0.w.data,
|
|
||||||
i_S_AXI_HP0_WSTRB = axi_hp0.w.strb,
|
|
||||||
|
|
||||||
# axi hp0 b
|
|
||||||
o_S_AXI_HP0_BVALID = axi_hp0.b.valid,
|
|
||||||
i_S_AXI_HP0_BREADY = axi_hp0.b.ready,
|
|
||||||
o_S_AXI_HP0_BID = axi_hp0.b.id,
|
|
||||||
o_S_AXI_HP0_BRESP = axi_hp0.b.resp,
|
|
||||||
|
|
||||||
# axi hp0 ar
|
|
||||||
i_S_AXI_HP0_ARVALID = axi_hp0.ar.valid,
|
|
||||||
o_S_AXI_HP0_ARREADY = axi_hp0.ar.ready,
|
|
||||||
i_S_AXI_HP0_ARADDR = axi_hp0.ar.addr,
|
|
||||||
i_S_AXI_HP0_ARBURST = axi_hp0.ar.burst,
|
|
||||||
i_S_AXI_HP0_ARLEN = axi_hp0.ar.len,
|
|
||||||
i_S_AXI_HP0_ARID = axi_hp0.ar.id,
|
|
||||||
i_S_AXI_HP0_ARLOCK = axi_hp0.ar.lock,
|
|
||||||
i_S_AXI_HP0_ARSIZE = axi_hp0.ar.size,
|
|
||||||
i_S_AXI_HP0_ARPROT = axi_hp0.ar.prot,
|
|
||||||
i_S_AXI_HP0_ARCACHE = axi_hp0.ar.cache,
|
|
||||||
i_S_AXI_HP0_ARQOS = axi_hp0.ar.qos,
|
|
||||||
|
|
||||||
# axi hp0 r
|
|
||||||
o_S_AXI_HP0_RVALID = axi_hp0.r.valid,
|
|
||||||
i_S_AXI_HP0_RREADY = axi_hp0.r.ready,
|
|
||||||
o_S_AXI_HP0_RLAST = axi_hp0.r.last,
|
|
||||||
o_S_AXI_HP0_RID = axi_hp0.r.id,
|
|
||||||
o_S_AXI_HP0_RRESP = axi_hp0.r.resp,
|
|
||||||
o_S_AXI_HP0_RDATA = axi_hp0.r.data,
|
|
||||||
|
|
||||||
# axi hp0 fifo ctrl
|
|
||||||
o_S_AXI_HP0_RACOUNT = axi_hp0_fifo_ctrl.racount,
|
|
||||||
o_S_AXI_HP0_RCOUNT = axi_hp0_fifo_ctrl.rcount,
|
|
||||||
i_S_AXI_HP0_RDISSUECAP1_EN = axi_hp0_fifo_ctrl.rdissuecapen,
|
|
||||||
o_S_AXI_HP0_WACOUNT = axi_hp0_fifo_ctrl.wacount,
|
|
||||||
o_S_AXI_HP0_WCOUNT = axi_hp0_fifo_ctrl.wcount,
|
|
||||||
i_S_AXI_HP0_WRISSUECAP1_EN = axi_hp0_fifo_ctrl.wrissuecapen
|
|
||||||
)
|
|
||||||
|
|
||||||
def add_axi_to_wishbone(self, axi_port, base_address=0x43c00000):
|
|
||||||
wb = wishbone.Interface()
|
|
||||||
axi2wishbone = axi.AXI2Wishbone(axi_port, wb, base_address)
|
|
||||||
self.submodules += axi2wishbone
|
|
||||||
self.add_wb_master(wb)
|
|
||||||
|
|
||||||
def do_finalize(self):
|
|
||||||
SoCCore.do_finalize(self)
|
|
||||||
self.specials += Instance(self.ps7_name, **self.ps7_params)
|
|
||||||
|
|
||||||
def generate_software_header(self, filename):
|
|
||||||
csr_header = get_csr_header(self.csr_regions,
|
|
||||||
self.constants,
|
|
||||||
with_access_functions=False)
|
|
||||||
tools.write_to_file(filename, csr_header)
|
|
Loading…
Reference in New Issue