cores/cpu: Add intitial gowin_ae350 support.
This commit is contained in:
parent
e689aab18a
commit
8aa5958fb7
|
@ -10,6 +10,8 @@
|
||||||
- build/openfpgaloader : Added kwargs support to flash for specific/less common cases.
|
- build/openfpgaloader : Added kwargs support to flash for specific/less common cases.
|
||||||
- cpu/gowin_emcu : Improved/Cleaned-up.
|
- cpu/gowin_emcu : Improved/Cleaned-up.
|
||||||
- interconnect/ahb : Added data_width/address_width parameters.
|
- interconnect/ahb : Added data_width/address_width parameters.
|
||||||
|
- interconnect/ahb : Added proper byte/sel support to AHB2Wishbone.
|
||||||
|
- cpu/gowin_ae350 : Added initial support.
|
||||||
|
|
||||||
[> Changed
|
[> Changed
|
||||||
----------
|
----------
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
from litex.soc.cores.cpu.gowin_ae350.core import GowinAE350
|
|
@ -0,0 +1,4 @@
|
||||||
|
.section .text, "ax", @progbits
|
||||||
|
.global boot_helper
|
||||||
|
boot_helper:
|
||||||
|
jr x13
|
|
@ -0,0 +1,308 @@
|
||||||
|
#
|
||||||
|
# This file is part of LiteX.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2024 Gwenhael Goavec-Merou <gwenhael@enjoy-digital.fr>
|
||||||
|
# Copyright (c) 2024 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||||
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from migen import *
|
||||||
|
|
||||||
|
from litex.gen import *
|
||||||
|
|
||||||
|
from litex.soc.interconnect import wishbone, ahb
|
||||||
|
from litex.soc.interconnect.csr import *
|
||||||
|
from litex.soc.cores.cpu import CPU, CPU_GCC_TRIPLE_RISCV32
|
||||||
|
|
||||||
|
# Gowin AE350 Constants ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
APB_CE_APB = (1 << 0)
|
||||||
|
APB_CE_UART1 = (1 << 1)
|
||||||
|
APB_CE_UART2 = (1 << 2)
|
||||||
|
APB_CE_SPI = (1 << 3)
|
||||||
|
APB_CE_GPIO = (1 << 4)
|
||||||
|
APB_CE_PIT = (1 << 5)
|
||||||
|
APB_CE_I2C = (1 << 6)
|
||||||
|
APB_CE_WDT = (1 << 7)
|
||||||
|
|
||||||
|
# Gowin AE350 --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class GowinAE350(CPU):
|
||||||
|
variants = ["standard"]
|
||||||
|
category = "hardcore"
|
||||||
|
family = "riscv"
|
||||||
|
name = "gowin_ae350"
|
||||||
|
human_name = "Gowin AE350"
|
||||||
|
data_width = 32
|
||||||
|
endianness = "little"
|
||||||
|
reset_address = 0x8000_0000
|
||||||
|
gcc_triple = CPU_GCC_TRIPLE_RISCV32
|
||||||
|
linker_output_format = "elf32-littleriscv"
|
||||||
|
nop = "nop"
|
||||||
|
io_regions = {
|
||||||
|
# Origin, Length.
|
||||||
|
0xe800_0000: 0x6000_0000
|
||||||
|
}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mem_map(self):
|
||||||
|
return {
|
||||||
|
"rom" : 0x80000000,
|
||||||
|
"sram" : 0x00000000,
|
||||||
|
"peripherals" : 0xf0000000,
|
||||||
|
"csr" : 0xe8000000,
|
||||||
|
}
|
||||||
|
|
||||||
|
# GCC Flags.
|
||||||
|
@property
|
||||||
|
def gcc_flags(self):
|
||||||
|
flags = f" -mabi=ilp32 -march=rv32imafdc"
|
||||||
|
flags += f" -D__AE350__"
|
||||||
|
return flags
|
||||||
|
|
||||||
|
def __init__(self, platform, variant, *args, **kwargs):
|
||||||
|
self.platform = platform
|
||||||
|
self.reset = Signal()
|
||||||
|
self.ibus = ibus = wishbone.Interface(data_width=32, address_width=32, addressing="byte")
|
||||||
|
self.dbus = dbus = wishbone.Interface(data_width=64, address_width=32, addressing="word")
|
||||||
|
self.pbus = pbus = wishbone.Interface(data_width=32, address_width=32, addressing="byte")
|
||||||
|
self.periph_buses = [ibus, dbus, pbus] # Peripheral buses (Connected to main SoC's bus).
|
||||||
|
self.memory_buses = [] # Memory buses (Connected directly to LiteDRAM).
|
||||||
|
|
||||||
|
|
||||||
|
# AHBLite Buses.
|
||||||
|
# --------------
|
||||||
|
self.ahb_rom = ahb_rom = ahb.AHBInterface(data_width=32, address_width=32)
|
||||||
|
self.ahb_ram = ahb_ram = ahb.AHBInterface(data_width=64, address_width=32)
|
||||||
|
self.ahb_exts = ahb_exts = ahb.AHBInterface(data_width=32, address_width=32)
|
||||||
|
self.comb += [
|
||||||
|
# Set AHBLite ROM static signals.
|
||||||
|
ahb_rom.sel.eq(1),
|
||||||
|
ahb_rom.size.eq(0b010),
|
||||||
|
ahb_rom.burst.eq(0),
|
||||||
|
# Set AHBLite RAM static signals.
|
||||||
|
ahb_ram.sel.eq(1),
|
||||||
|
]
|
||||||
|
|
||||||
|
# CPU Instance.
|
||||||
|
# -------------
|
||||||
|
self.cpu_params = dict(
|
||||||
|
# Clk/Rst.
|
||||||
|
i_CORE_CLK = ClockSignal("cpu"),
|
||||||
|
i_DDR_CLK = ClockSignal("sys"),
|
||||||
|
i_AHB_CLK = ClockSignal("sys"),
|
||||||
|
i_APB_CLK = ClockSignal("sys"),
|
||||||
|
i_POR_N = 1,
|
||||||
|
i_HW_RSTN = ~(ResetSignal("sys") | self.reset),
|
||||||
|
o_PRESETN = Open(),
|
||||||
|
o_HRESETN = Open(),
|
||||||
|
o_DDR_RSTN = Open(),
|
||||||
|
|
||||||
|
# Features/Peripherals Enable.
|
||||||
|
i_CORE_CE = 1,
|
||||||
|
i_AXI_CE = 1,
|
||||||
|
i_DDR_CE = 1,
|
||||||
|
i_AHB_CE = 1,
|
||||||
|
i_APB_CE = Constant(APB_CE_APB, 8),
|
||||||
|
i_APB2AHB_CE = 1,
|
||||||
|
|
||||||
|
# WFI.
|
||||||
|
o_CORE0_WFI_MODE = Open(),
|
||||||
|
i_WAKEUP_IN = 0,
|
||||||
|
|
||||||
|
# RTC.
|
||||||
|
i_RTC_CLK = ClockSignal("sys"),
|
||||||
|
o_RTC_WAKEUP = Open(),
|
||||||
|
|
||||||
|
# Interrupts.
|
||||||
|
i_GP_INT = Constant(0, 16),
|
||||||
|
|
||||||
|
# DMA.
|
||||||
|
i_DMA_REQ = Constant(0, 8),
|
||||||
|
o_DMA_ACK = Open(8),
|
||||||
|
|
||||||
|
# AHBLite ROM interface.
|
||||||
|
i_ROM_HRDATA = ahb_rom.rdata,
|
||||||
|
i_ROM_HREADY = ahb_rom.readyout,
|
||||||
|
i_ROM_HRESP = ahb_rom.resp,
|
||||||
|
o_ROM_HADDR = ahb_rom.addr,
|
||||||
|
o_ROM_HTRANS = ahb_rom.trans,
|
||||||
|
o_ROM_HWRITE = ahb_rom.write,
|
||||||
|
|
||||||
|
# APBLite Fabric interface (Slave).
|
||||||
|
o_APB_PADDR = Open(32),
|
||||||
|
o_APB_PENABLE = Open(),
|
||||||
|
i_APB_PRDATA = Constant(0, 32),
|
||||||
|
i_APB_PREADY = 0,
|
||||||
|
o_APB_PSEL = Open(),
|
||||||
|
o_APB_PWDATA = Open(32),
|
||||||
|
o_APB_PWRITE = Open(),
|
||||||
|
i_APB_PSLVERR = 0,
|
||||||
|
o_APB_PPROT = Open(3),
|
||||||
|
o_APB_PSTRB = Open(4),
|
||||||
|
|
||||||
|
# AHBLite Peripheral interface (Master).
|
||||||
|
i_EXTS_HRDATA = ahb_exts.rdata,
|
||||||
|
i_EXTS_HREADYIN = ahb_exts.readyout,
|
||||||
|
i_EXTS_HRESP = ahb_exts.resp,
|
||||||
|
o_EXTS_HADDR = ahb_exts.addr,
|
||||||
|
o_EXTS_HBURST = ahb_exts.burst,
|
||||||
|
o_EXTS_HPROT = ahb_exts.prot,
|
||||||
|
o_EXTS_HSEL = ahb_exts.sel,
|
||||||
|
o_EXTS_HSIZE = ahb_exts.size,
|
||||||
|
o_EXTS_HTRANS = ahb_exts.trans,
|
||||||
|
o_EXTS_HWDATA = ahb_exts.wdata,
|
||||||
|
o_EXTS_HWRITE = ahb_exts.write,
|
||||||
|
|
||||||
|
# AHBLite Peripheral interface (Slave).
|
||||||
|
i_EXTM_HADDR = Constant(0, 32),
|
||||||
|
i_EXTM_HBURST = Constant(0, 3),
|
||||||
|
i_EXTM_HPROT = Constant(0, 4),
|
||||||
|
o_EXTM_HRDATA = Open(64),
|
||||||
|
i_EXTM_HREADY = 0,
|
||||||
|
o_EXTM_HREADYOUT = Open(),
|
||||||
|
o_EXTM_HRESP = Open(),
|
||||||
|
i_EXTM_HSEL = 0,
|
||||||
|
i_EXTM_HSIZE = Constant(0, 3),
|
||||||
|
i_EXTM_HTRANS = Constant(0, 2),
|
||||||
|
i_EXTM_HWDATA = Constant(0, 64),
|
||||||
|
i_EXTM_HWRITE = 0,
|
||||||
|
|
||||||
|
# AHBLite RAM interface (Slave).
|
||||||
|
i_DDR_HRDATA = ahb_ram.rdata,
|
||||||
|
i_DDR_HREADY = ahb_ram.readyout,
|
||||||
|
i_DDR_HRESP = ahb_ram.resp,
|
||||||
|
o_DDR_HADDR = ahb_ram.addr,
|
||||||
|
o_DDR_HBURST = ahb_ram.burst,
|
||||||
|
o_DDR_HPROT = ahb_ram.prot,
|
||||||
|
o_DDR_HSIZE = ahb_ram.size,
|
||||||
|
o_DDR_HTRANS = ahb_ram.trans,
|
||||||
|
o_DDR_HWDATA = ahb_ram.wdata,
|
||||||
|
o_DDR_HWRITE = ahb_ram.write,
|
||||||
|
|
||||||
|
# GPIOs.
|
||||||
|
i_GPIO_IN = Constant(0, 32),
|
||||||
|
o_GPIO_OUT = Open(32),
|
||||||
|
o_GPIO_OE = Open(32),
|
||||||
|
|
||||||
|
# SCAN.
|
||||||
|
i_SCAN_EN = 0,
|
||||||
|
i_SCAN_TEST = 0,
|
||||||
|
i_SCAN_IN = Constant(0xfffff, 20),
|
||||||
|
o_SCAN_OUT = Open(20),
|
||||||
|
|
||||||
|
# Integrated JTAG.
|
||||||
|
i_INTEG_TCK = 1,
|
||||||
|
i_INTEG_TDI = 1,
|
||||||
|
i_INTEG_TMS = 1,
|
||||||
|
i_INTEG_TRST = 1,
|
||||||
|
o_INTEG_TDO = Open(),
|
||||||
|
|
||||||
|
# SRAM (FIXME : Cleanup).
|
||||||
|
i_PGEN_CHAIN_I = 1,
|
||||||
|
o_PRDYN_CHAIN_O = Open(),
|
||||||
|
i_EMA = Constant(0b011, 3),
|
||||||
|
i_EMAW = Constant(0b01, 2),
|
||||||
|
i_EMAS = 0,
|
||||||
|
i_RET1N = 1,
|
||||||
|
i_RET2N = 1,
|
||||||
|
|
||||||
|
# SPI.
|
||||||
|
i_SPI2_HOLDN_IN = 0,
|
||||||
|
i_SPI2_WPN_IN = 0,
|
||||||
|
i_SPI2_CLK_IN = 0,
|
||||||
|
i_SPI2_CSN_IN = 0,
|
||||||
|
i_SPI2_MISO_IN = 0,
|
||||||
|
i_SPI2_MOSI_IN = 0,
|
||||||
|
o_SPI2_HOLDN_OUT = Open(),
|
||||||
|
o_SPI2_HOLDN_OE = Open(),
|
||||||
|
o_SPI2_WPN_OUT = Open(),
|
||||||
|
o_SPI2_WPN_OE = Open(),
|
||||||
|
o_SPI2_CLK_OUT = Open(),
|
||||||
|
o_SPI2_CLK_OE = Open(),
|
||||||
|
o_SPI2_CSN_OUT = Open(),
|
||||||
|
o_SPI2_CSN_OE = Open(),
|
||||||
|
o_SPI2_MISO_OUT = Open(),
|
||||||
|
o_SPI2_MISO_OE = Open(),
|
||||||
|
o_SPI2_MOSI_OUT = Open(),
|
||||||
|
o_SPI2_MOSI_OE = Open(),
|
||||||
|
|
||||||
|
# I2C.
|
||||||
|
i_I2C_SCL_IN = 0,
|
||||||
|
i_I2C_SDA_IN = 0,
|
||||||
|
o_I2C_SCL = Open(),
|
||||||
|
o_I2C_SDA = Open(),
|
||||||
|
|
||||||
|
# PIT/PWM.
|
||||||
|
o_CH0_PWM = Open(),
|
||||||
|
o_CH0_PWMOE = Open(),
|
||||||
|
o_CH1_PWM = Open(),
|
||||||
|
o_CH1_PWMOE = Open(),
|
||||||
|
o_CH2_PWM = Open(),
|
||||||
|
o_CH2_PWMOE = Open(),
|
||||||
|
o_CH3_PWM = Open(),
|
||||||
|
o_CH3_PWMOE = Open(),
|
||||||
|
|
||||||
|
# UART1.
|
||||||
|
o_UART1_TXD = Open(),
|
||||||
|
o_UART1_RTSN = Open(),
|
||||||
|
i_UART1_RXD = 0,
|
||||||
|
i_UART1_CTSN = 0,
|
||||||
|
i_UART1_DSRN = 0,
|
||||||
|
i_UART1_DCDN = 0,
|
||||||
|
i_UART1_RIN = 0,
|
||||||
|
o_UART1_DTRN = Open(),
|
||||||
|
o_UART1_OUT1N = Open(),
|
||||||
|
o_UART1_OUT2N = Open(),
|
||||||
|
|
||||||
|
# UART2.
|
||||||
|
o_UART2_TXD = Open(),
|
||||||
|
o_UART2_RTSN = Open(),
|
||||||
|
i_UART2_RXD = 0,
|
||||||
|
i_UART2_CTSN = 1,
|
||||||
|
i_UART2_DCDN = 1,
|
||||||
|
i_UART2_DSRN = 1,
|
||||||
|
i_UART2_RIN = 1,
|
||||||
|
o_UART2_DTRN = Open(),
|
||||||
|
o_UART2_OUT1N = Open(),
|
||||||
|
o_UART2_OUT2N = Open(),
|
||||||
|
|
||||||
|
# JTAG.
|
||||||
|
i_DBG_TCK = 1,
|
||||||
|
i_TMS_IN = 1,
|
||||||
|
i_TRST_IN = 1,
|
||||||
|
i_TDI_IN = 0,
|
||||||
|
o_TDO_OUT = Open(),
|
||||||
|
o_TDO_OE = Open(),
|
||||||
|
|
||||||
|
# Test.
|
||||||
|
i_TEST_CLK = 0,
|
||||||
|
i_TEST_MODE = 0,
|
||||||
|
i_TEST_RSTN = 1,
|
||||||
|
)
|
||||||
|
|
||||||
|
# AHBLite ROM Interface.
|
||||||
|
# ----------------------
|
||||||
|
self.submodules += ahb.AHB2Wishbone(ahb_rom, self.ibus)
|
||||||
|
|
||||||
|
# AHBLite RAM Interface.
|
||||||
|
# ----------------------
|
||||||
|
self.submodules += ahb.AHB2Wishbone(ahb_ram, self.dbus)
|
||||||
|
|
||||||
|
# AHBLite Peripheral Interface.
|
||||||
|
# -----------------------------
|
||||||
|
self.submodules += ahb.AHB2Wishbone(ahb_exts, self.pbus)
|
||||||
|
|
||||||
|
def connect_jtag(self, pads):
|
||||||
|
self.cpu_params.update(
|
||||||
|
i_DBG_TCK = pads.tck,
|
||||||
|
i_TMS_IN = pads.tms,
|
||||||
|
i_TRST_IN = pads.trst,
|
||||||
|
i_TDI_IN = pads.tdi,
|
||||||
|
o_TDO_OUT = pads.tdo,
|
||||||
|
o_TDO_OE = Open(),
|
||||||
|
)
|
||||||
|
|
||||||
|
def do_finalize(self):
|
||||||
|
self.specials += Instance("AE350_SOC", **self.cpu_params)
|
|
@ -0,0 +1,75 @@
|
||||||
|
#define MIE_MEIE 0x800
|
||||||
|
|
||||||
|
.global _start
|
||||||
|
_start:
|
||||||
|
j reset_vector
|
||||||
|
|
||||||
|
reset_vector:
|
||||||
|
la sp, _fstack
|
||||||
|
la t0, trap_vector
|
||||||
|
csrw mtvec, t0
|
||||||
|
|
||||||
|
// initialize .data
|
||||||
|
la t0, _fdata
|
||||||
|
la t1, _edata
|
||||||
|
la t2, _fdata_rom
|
||||||
|
1: beq t0, t1, 2f
|
||||||
|
lw t3, 0(t2)
|
||||||
|
sw t3, 0(t0)
|
||||||
|
addi t0, t0, 4
|
||||||
|
addi t2, t2, 4
|
||||||
|
j 1b
|
||||||
|
2:
|
||||||
|
|
||||||
|
// initialize .bss
|
||||||
|
la t0, _fbss
|
||||||
|
la t1, _ebss
|
||||||
|
1: beq t0, t1, 3f
|
||||||
|
sw zero, 0(t0)
|
||||||
|
addi t0, t0, 4
|
||||||
|
j 1b
|
||||||
|
3:
|
||||||
|
// enable external interrupts
|
||||||
|
li t0, MIE_MEIE
|
||||||
|
csrs mie, t0
|
||||||
|
|
||||||
|
call main
|
||||||
|
1: j 1b
|
||||||
|
|
||||||
|
trap_vector:
|
||||||
|
addi sp, sp, -16*4
|
||||||
|
sw ra, 0*4(sp)
|
||||||
|
sw t0, 1*4(sp)
|
||||||
|
sw t1, 2*4(sp)
|
||||||
|
sw t2, 3*4(sp)
|
||||||
|
sw a0, 4*4(sp)
|
||||||
|
sw a1, 5*4(sp)
|
||||||
|
sw a2, 6*4(sp)
|
||||||
|
sw a3, 7*4(sp)
|
||||||
|
sw a4, 8*4(sp)
|
||||||
|
sw a5, 9*4(sp)
|
||||||
|
sw a6, 10*4(sp)
|
||||||
|
sw a7, 11*4(sp)
|
||||||
|
sw t3, 12*4(sp)
|
||||||
|
sw t4, 13*4(sp)
|
||||||
|
sw t5, 14*4(sp)
|
||||||
|
sw t6, 15*4(sp)
|
||||||
|
call isr
|
||||||
|
lw ra, 0*4(sp)
|
||||||
|
lw t0, 1*4(sp)
|
||||||
|
lw t1, 2*4(sp)
|
||||||
|
lw t2, 3*4(sp)
|
||||||
|
lw a0, 4*4(sp)
|
||||||
|
lw a1, 5*4(sp)
|
||||||
|
lw a2, 6*4(sp)
|
||||||
|
lw a3, 7*4(sp)
|
||||||
|
lw a4, 8*4(sp)
|
||||||
|
lw a5, 9*4(sp)
|
||||||
|
lw a6, 10*4(sp)
|
||||||
|
lw a7, 11*4(sp)
|
||||||
|
lw t3, 12*4(sp)
|
||||||
|
lw t4, 13*4(sp)
|
||||||
|
lw t5, 14*4(sp)
|
||||||
|
lw t6, 15*4(sp)
|
||||||
|
addi sp, sp, 16*4
|
||||||
|
mret
|
|
@ -0,0 +1,4 @@
|
||||||
|
#ifndef __IRQ_H
|
||||||
|
#define __IRQ_H
|
||||||
|
|
||||||
|
#endif /* __IRQ_H */
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef __SYSTEM_H
|
||||||
|
#define __SYSTEM_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__attribute__((unused)) static void flush_cpu_icache(void){}; /* FIXME */
|
||||||
|
__attribute__((unused)) static void flush_cpu_dcache(void){}; /* FIXME */
|
||||||
|
void flush_l2_cache(void);
|
||||||
|
|
||||||
|
void busy_wait(unsigned int ms);
|
||||||
|
void busy_wait_us(unsigned int us);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __SYSTEM_H */
|
|
@ -125,7 +125,11 @@ __attribute__((__used__)) int main(int i, char **c)
|
||||||
printf("--=============== \e[1mSoC\e[0m ==================--\n");
|
printf("--=============== \e[1mSoC\e[0m ==================--\n");
|
||||||
printf("\e[1mCPU\e[0m:\t\t%s @ %dMHz\n",
|
printf("\e[1mCPU\e[0m:\t\t%s @ %dMHz\n",
|
||||||
CONFIG_CPU_HUMAN_NAME,
|
CONFIG_CPU_HUMAN_NAME,
|
||||||
|
#ifdef CONFIG_CPU_CLK_FREQ
|
||||||
|
CONFIG_CPU_CLK_FREQ/1000000);
|
||||||
|
#else
|
||||||
CONFIG_CLOCK_FREQUENCY/1000000);
|
CONFIG_CLOCK_FREQUENCY/1000000);
|
||||||
|
#endif
|
||||||
printf("\e[1mBUS\e[0m:\t\t%s %d-bit @ %dGiB\n",
|
printf("\e[1mBUS\e[0m:\t\t%s %d-bit @ %dGiB\n",
|
||||||
CONFIG_BUS_STANDARD,
|
CONFIG_BUS_STANDARD,
|
||||||
CONFIG_BUS_DATA_WIDTH,
|
CONFIG_BUS_DATA_WIDTH,
|
||||||
|
|
Loading…
Reference in New Issue