cpu: Add initial EOS-S3 Integration.

Initial support allowing Software control of the Leds in the eFPGA.
This commit is contained in:
Gwenhael Goavec-Merou 2021-11-09 18:53:09 +01:00 committed by Florent Kermarrec
parent f89b99eccc
commit a742731d26
7 changed files with 166 additions and 6 deletions

View file

@ -2,6 +2,7 @@
# This file is part of LiteX.
#
# Copyright (c) 2021 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2021 Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>
# SPDX-License-Identifier: BSD-2-Clause
import os
@ -40,17 +41,27 @@ def _build_makefile(platform, sources, build_dir, build_name):
# Define Paths.
makefile.append("mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))")
makefile.append("current_dir := $(patsubst %/,%,$(dir $(mkfile_path)))")
# bit -> h and bit -> bin requires TOP_F
makefile.append(f"TOP_F={build_name}")
# Create Project.
# FIXME: Only use top file for now and ignore .init files.
makefile.append("all:")
makefile.append("all: {top}_bit.h {top}.bin build/{top}.bit".format(top=build_name))
# build bit file (default)
makefile.append(f"build/{build_name}.bit:")
makefile.append("\tql_symbiflow -compile -d {device} -P {part} -v {verilog} -t {top} -p {pcf}".format(
device = platform.device,
part = {"ql-eos-s3": "pd64"}.get(platform.device),
part = {"ql-eos-s3": "PU64"}.get(platform.device),
verilog = f"{build_name}.v",
top = build_name,
pcf = f"{build_name}.pcf"
))
# build header to include in CPU firmware
makefile.append("{top}_bit.h: build/{top}.bit".format(top=build_name))
makefile.append(f"\t(cd build; TOP_F=$(TOP_F) symbiflow_write_bitheader)")
# build binary to write in dedicated FLASH area
makefile.append("{top}.bin: build/{top}.bit".format(top=build_name))
makefile.append(f"\t(cd build; TOP_F=$(TOP_F) symbiflow_write_binary)")
# Generate Makefile.
tools.write_to_file("Makefile", "\n".join(makefile))

View file

@ -89,6 +89,8 @@ from litex.soc.cores.cpu.blackparrot import BlackParrotRV64
# Zynq
from litex.soc.cores.cpu.zynq7000 import Zynq7000
# EOS-S3
from litex.soc.cores.cpu.eos_s3 import EOS_S3
CPUS = {
# None
@ -122,4 +124,7 @@ CPUS = {
# Zynq
"zynq7000" : Zynq7000,
# EOS-S3
"eos-s3" : EOS_S3,
}

View file

@ -0,0 +1 @@
from litex.soc.cores.cpu.eos_s3.core import EOS_S3

View file

@ -0,0 +1,141 @@
#
# This file is part of LiteX.
#
# Copyright (c) 2021 Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>
# SPDX-License-Identifier: BSD-2-Clause
import os
from migen import *
from migen.genlib.resetsync import AsyncResetSynchronizer
from litex.soc.interconnect import wishbone
from litex.soc.cores.cpu import CPU
# EOS-S3 -------------------------------------------------------------------------------------------
class EOS_S3(CPU):
variants = ["standard"]
family = "arm"
name = "eos-s3"
human_name = "eos-s3"
data_width = 32
endianness = "little"
reset_address = 0x00000000
gcc_triple = "gcc-arm-none-eabi"
linker_output_format = "elf32-littlearm"
nop = "nop"
io_regions = {0x00000000: 0x100000000} # Origin, Length.
# Memory Mapping.
@property
def mem_map(self):
return {"csr": 0x00000000}
def __init__(self, platform, variant):
self.platform = platform
self.reset = Signal()
self.periph_buses = [] # Peripheral buses (Connected to main SoC's bus).
self.memory_buses = [] # Memory buses (Connected directly to LiteDRAM).
self.wishbone_master = [] # General Purpose Wishbone Masters.
# # #
self.wb = wishbone.Interface(data_width=32, adr_width=17)
# EOS-S3 Clocking.
self.clock_domains.cd_Sys_Clk0 = ClockDomain()
self.clock_domains.cd_Sys_Clk1 = ClockDomain()
# EOS-S3 (Minimal) -------------------------------------------------------------------------
Sys_Clk0_Rst = Signal()
Sys_Clk1_Rst = Signal()
WB_RST = Signal()
self.cpu_params = dict(
# AHB-To-FPGA Bridge
i_WB_CLK = ClockSignal("Sys_Clk0"),
o_WB_RST = WB_RST,
o_WBs_ADR = self.wb.adr,
o_WBs_CYC = self.wb.cyc,
o_WBs_BYTE_STB = self.wb.sel,
o_WBs_WE = self.wb.we,
o_WBs_STB = self.wb.stb,
#o_WBs_RD"(), = // output | Read Enable to FPGA
o_WBs_WR_DAT = self.wb.dat_w,
i_WBs_RD_DAT = self.wb.dat_r,
i_WBs_ACK = self.wb.ack,
# SDMA Signals
#SDMA_Req(4'b0000),
#SDMA_Sreq(4'b0000),
#SDMA_Done(),
#SDMA_Active(),
# FB Interrupts
#FB_msg_out(4'b0000),
#FB_Int_Clr(8'h0),
#FB_Start(),
#FB_Busy= 0,
# FB Clocks
o_Sys_Clk0 = ClockSignal("Sys_Clk0"),
o_Sys_Clk0_Rst = Sys_Clk0_Rst,
o_Sys_Clk1 = ClockSignal("Sys_Clk1"),
o_Sys_Clk1_Rst = Sys_Clk1_Rst,
# Packet FIFO
#Sys_PKfb_Clk = 0,
#Sys_PKfb_Rst(),
#FB_PKfbData(32'h0),
#FB_PKfbPush(4'h0),
#FB_PKfbSOF = 0,
#FB_PKfbEOF = 0,
#FB_PKfbOverflow(),
# Sensor Interface
#Sensor_Int(),
#TimeStamp(),
# SPI Master APB Bus
#Sys_Pclk(),
#Sys_Pclk_Rst(),
#Sys_PSel = 0,
#SPIm_Paddr(16'h0),
#SPIm_PEnable = 0,
#SPIm_PWrite = 0,
#SPIm_PWdata(32'h0),
#SPIm_Prdata(),
#SPIm_PReady(),
#SPIm_PSlvErr(),
# Misc
i_Device_ID = 0xCAFE,
# FBIO Signals
#FBIO_In(),
#FBIO_In_En(),
#FBIO_Out(),
#FBIO_Out_En(),
# ???
#SFBIO = ,
i_Device_ID_6S = 0,
i_Device_ID_4S = 0,
i_SPIm_PWdata_26S = 0,
i_SPIm_PWdata_24S = 0,
i_SPIm_PWdata_14S = 0,
i_SPIm_PWdata_11S = 0,
i_SPIm_PWdata_0S = 0,
i_SPIm_Paddr_8S = 0,
i_SPIm_Paddr_6S = 0,
i_FB_PKfbPush_1S = 0,
i_FB_PKfbData_31S = 0,
i_FB_PKfbData_21S = 0,
i_FB_PKfbData_19S = 0,
i_FB_PKfbData_9S = 0,
i_FB_PKfbData_6S = 0,
i_Sys_PKfb_ClkS = 0,
i_FB_BusyS = 0,
i_WB_CLKS = 0,
)
self.specials += Instance("gclkbuff",
i_A = Sys_Clk0_Rst | WB_RST,
o_Z = self.cd_Sys_Clk0.rst)
def do_finalize(self):
self.specials += Instance("qlal4s3b_cell_macro", **self.cpu_params)

View file

@ -275,7 +275,7 @@ class Builder:
self.soc.platform.output_dir = self.output_dir
# Check if BIOS is used and add software package if so.
with_bios = self.soc.cpu_type not in [None, "zynq7000"]
with_bios = self.soc.cpu_type not in [None, "zynq7000", "eos-s3"]
if with_bios:
self.add_software_package("bios")

View file

@ -924,7 +924,9 @@ class SoC(Module):
self.mem_map.update(self.cpu.mem_map)
# Add Bus Masters/CSR/IRQs.
if not isinstance(self.cpu, (cpu.CPUNone, cpu.Zynq7000)):
if isinstance(self.cpu, cpu.EOS_S3):
self.bus.add_master(master=self.cpu.wb)
if not isinstance(self.cpu, (cpu.CPUNone, cpu.Zynq7000, cpu.EOS_S3)):
if reset_address is None:
reset_address = self.mem_map["rom"]
self.cpu.set_reset_address(reset_address)
@ -1082,7 +1084,7 @@ class SoC(Module):
self.add_constant(name + "_" + constant.name, constant.value.value)
# SoC CPU Check ----------------------------------------------------------------------------
if not isinstance(self.cpu, (cpu.CPUNone, cpu.Zynq7000)):
if not isinstance(self.cpu, (cpu.CPUNone, cpu.Zynq7000, cpu.EOS_S3)):
cpu_reset_address_valid = False
for name, container in self.bus.regions.items():
if self.bus.check_region_is_in(

View file

@ -158,7 +158,7 @@ class SoCCore(LiteXSoC):
integrated_rom_size = 4*len(integrated_rom_init)
# Disable ROM when no CPU/hard-CPU.
if cpu_type in [None, "zynq7000"]:
if cpu_type in [None, "zynq7000", "eos-s3"]:
integrated_rom_init = []
integrated_rom_size = 0
self.integrated_rom_size = integrated_rom_size