diff --git a/CHANGES.md b/CHANGES.md index d431772ec..9efb5d1ee 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,8 @@ - build/openfpgaloader : Added kwargs support to flash for specific/less common cases. - cpu/gowin_emcu : Improved/Cleaned-up. - interconnect/ahb : Added data_width/address_width parameters. + - interconnect/ahb : Added proper byte/sel support to AHB2Wishbone. + - cpu/gowin_ae350 : Added initial support. [> Changed ---------- diff --git a/litex/soc/cores/cpu/gowin_ae350/__init__.py b/litex/soc/cores/cpu/gowin_ae350/__init__.py new file mode 100644 index 000000000..55596975c --- /dev/null +++ b/litex/soc/cores/cpu/gowin_ae350/__init__.py @@ -0,0 +1 @@ +from litex.soc.cores.cpu.gowin_ae350.core import GowinAE350 diff --git a/litex/soc/cores/cpu/gowin_ae350/boot-helper.S b/litex/soc/cores/cpu/gowin_ae350/boot-helper.S new file mode 100644 index 000000000..e8bd5c760 --- /dev/null +++ b/litex/soc/cores/cpu/gowin_ae350/boot-helper.S @@ -0,0 +1,4 @@ + .section .text, "ax", @progbits + .global boot_helper +boot_helper: + jr x13 diff --git a/litex/soc/cores/cpu/gowin_ae350/core.py b/litex/soc/cores/cpu/gowin_ae350/core.py new file mode 100644 index 000000000..6d7a8271e --- /dev/null +++ b/litex/soc/cores/cpu/gowin_ae350/core.py @@ -0,0 +1,308 @@ +# +# This file is part of LiteX. +# +# Copyright (c) 2024 Gwenhael Goavec-Merou +# Copyright (c) 2024 Florent Kermarrec +# 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) diff --git a/litex/soc/cores/cpu/gowin_ae350/crt0.S b/litex/soc/cores/cpu/gowin_ae350/crt0.S new file mode 100644 index 000000000..13bfc48e9 --- /dev/null +++ b/litex/soc/cores/cpu/gowin_ae350/crt0.S @@ -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 diff --git a/litex/soc/cores/cpu/gowin_ae350/irq.h b/litex/soc/cores/cpu/gowin_ae350/irq.h new file mode 100644 index 000000000..7374cf506 --- /dev/null +++ b/litex/soc/cores/cpu/gowin_ae350/irq.h @@ -0,0 +1,4 @@ +#ifndef __IRQ_H +#define __IRQ_H + +#endif /* __IRQ_H */ diff --git a/litex/soc/cores/cpu/gowin_ae350/system.h b/litex/soc/cores/cpu/gowin_ae350/system.h new file mode 100644 index 000000000..c27fc4da8 --- /dev/null +++ b/litex/soc/cores/cpu/gowin_ae350/system.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 */ diff --git a/litex/soc/software/bios/main.c b/litex/soc/software/bios/main.c index a39caafd3..67ca3d590 100644 --- a/litex/soc/software/bios/main.c +++ b/litex/soc/software/bios/main.c @@ -125,7 +125,11 @@ __attribute__((__used__)) int main(int i, char **c) printf("--=============== \e[1mSoC\e[0m ==================--\n"); printf("\e[1mCPU\e[0m:\t\t%s @ %dMHz\n", CONFIG_CPU_HUMAN_NAME, +#ifdef CONFIG_CPU_CLK_FREQ + CONFIG_CPU_CLK_FREQ/1000000); +#else CONFIG_CLOCK_FREQUENCY/1000000); +#endif printf("\e[1mBUS\e[0m:\t\t%s %d-bit @ %dGiB\n", CONFIG_BUS_STANDARD, CONFIG_BUS_DATA_WIDTH,