diff --git a/litex/soc/cores/cpu/gowin_emcu/core.py b/litex/soc/cores/cpu/gowin_emcu/core.py index c8551b21c..dddf86e23 100644 --- a/litex/soc/cores/cpu/gowin_emcu/core.py +++ b/litex/soc/cores/cpu/gowin_emcu/core.py @@ -2,6 +2,7 @@ # This file is part of LiteX. # # Copyright (c) 2021 Ilia Sergachev +# Copyright (c) 2024 Florent Kermarrec # SPDX-License-Identifier: BSD-2-Clause from migen import * @@ -11,42 +12,6 @@ from litex.gen import * from litex.soc.interconnect import wishbone, ahb from litex.soc.cores.cpu import CPU -# AHB Flash ---------------------------------------------------------------------------------------- - -class AHBFlash(LiteXModule): - def __init__(self, bus): - addr = Signal(13) - read = Signal() - self.comb += bus.resp.eq(0) - - self.fsm = fsm = FSM() - fsm.act("IDLE", - bus.readyout.eq(1), - If(bus.sel & bus.trans[1], - NextValue(addr, bus.addr[2:]), - NextState("READ"), - ) - ) - fsm.act("READ", - read.eq(1), - NextState("WAIT"), - ) - fsm.act("WAIT", - NextState("IDLE") - ) - self.specials += Instance("FLASH256K", - o_DOUT = bus.rdata, - i_DIN = Signal(32), - i_XADR = addr[6:], - i_YADR = addr[:6], - i_XE = ~ResetSignal("sys"), - i_YE = ~ResetSignal("sys"), - i_SE = read, - i_PROG = 0, - i_ERASE = 0, - i_NVSTR = 0 - ) - # Gowin EMCU --------------------------------------------------------------------------------------- class GowinEMCU(CPU): @@ -64,7 +29,7 @@ class GowinEMCU(CPU): io_regions = { # Origin, Length. 0x4000_0000: 0x2000_0000, - 0xA000_0000: 0x6000_0000 + 0xa000_0000: 0x6000_0000 } @property @@ -78,45 +43,50 @@ class GowinEMCU(CPU): def __init__(self, platform, variant, *args, **kwargs): super().__init__(*args, **kwargs) - - self.reset = Signal() - self.bus_reset = Signal() - bus_reset_n = Signal() - self.comb += self.bus_reset.eq(~bus_reset_n) + self.reset = Signal() self.interrupt = Signal(5) self.reset_address = self.mem_map["rom"] + 0 + self.periph_buses = [] - self.gpio_in = Signal(16) - self.gpio_out = Signal(16) - self.gpio_out_en = Signal(16) + # CPU Instance. + # ------------- + bus_reset_n = Signal() self.cpu_params = dict() self.cpu_params.update( - i_MTXREMAP = Signal(4, reset=0b1111), - o_MTXHRESETN = bus_reset_n, - - i_FLASHERR = Signal(), - i_FLASHINT = Signal(), - + # Clk/Rst. i_FCLK = ClockSignal("sys"), i_PORESETN = ~self.reset, i_SYSRESETN = ~self.reset, - i_RTCSRCCLK = Signal(), # TODO - RTC clk in + i_MTXREMAP = Signal(4, reset=0b1111), + o_MTXHRESETN = bus_reset_n, - i_IOEXPINPUTI = self.gpio_in, - o_IOEXPOUTPUTO = self.gpio_out, - o_IOEXPOUTPUTENO = self.gpio_out_en, + # RTC. + i_RTCSRCCLK = Signal(), # TODO: RTC Clk In. + # GPIOs. + i_IOEXPINPUTI = Signal(), # TODO: GPIO Input (16-bit). + o_IOEXPOUTPUTO = Signal(), # TODO: GPIO Output (16-bit). + o_IOEXPOUTPUTENO = Signal(), # TODO: GPIO Output Enable (16-bit). + + # Interrupts. i_GPINT = self.interrupt, o_INTMONITOR = Signal(), + + # Flash. + i_FLASHERR = Signal(), + i_FLASHINT = Signal(), ) - # 32b CPU SRAM split between 8 SRAMs x 4 bit each + # SRAM (32-bit RAM split between 8 SRAMs x 4 bit each). + # ----------------------------------------------------- + # Parameters. sram_dw = 32 single_sram_dw = 4 - n_srams = sram_dw // single_sram_dw + nsrams = sram_dw // single_sram_dw + # CPU SRAM Interface. sram0_addr = Signal(13) sram0_rdata = Signal(sram_dw) sram0_wdata = Signal(sram_dw) @@ -130,7 +100,8 @@ class GowinEMCU(CPU): o_SRAM0CS = sram0_cs, ) - for i in range(n_srams): + # SRAMS Instances. + for i in range(nsrams): self.specials += Instance("SDPB", p_READ_MODE = 0, p_BIT_WIDTH_0 = single_sram_dw, @@ -144,16 +115,51 @@ class GowinEMCU(CPU): i_ADB = Cat(Signal(2), sram0_addr[:-1]), i_CEA = sram0_wren[i // 2], i_CEB = ~sram0_wren[i // 2], - i_CLKA = ClockSignal(), - i_CLKB = ClockSignal(), + i_CLKA = ClockSignal("sys"), + i_CLKB = ClockSignal("sys"), i_RESETA = 0, - i_RESETB = self.bus_reset, + i_RESETB = ~bus_reset_n, i_OCE = 1, i_BLKSELA = Cat(sram0_cs, sram0_cs, sram0_cs), i_BLKSELB = Cat(sram0_cs, sram0_cs, sram0_cs), ) - # Boot Flash memory connected via AHB + # Flash (Boot Flash memory connected via AHB). + # -------------------------------------------- + + class AHBFlash(LiteXModule): + def __init__(self, bus): + addr = Signal(13) + read = Signal() + self.comb += bus.resp.eq(0) + + self.fsm = fsm = FSM() + fsm.act("IDLE", + bus.readyout.eq(1), + If(bus.sel & bus.trans[1], + NextValue(addr, bus.addr[2:]), + NextState("READ"), + ) + ) + fsm.act("READ", + read.eq(1), + NextState("WAIT"), + ) + fsm.act("WAIT", + NextState("IDLE") + ) + self.specials += Instance("FLASH256K", + o_DOUT = bus.rdata, + i_DIN = Signal(32), + i_XADR = addr[6:], + i_YADR = addr[:6], + i_XE = ~ResetSignal("sys"), + i_YE = ~ResetSignal("sys"), + i_SE = read, + i_PROG = 0, + i_ERASE = 0, + i_NVSTR = 0 + ) ahb_flash = ahb.Interface() for s, _ in ahb_flash.master_signals: @@ -163,26 +169,28 @@ class GowinEMCU(CPU): for s, _ in ahb_flash.slave_signals: self.cpu_params[f"i_TARGFLASH0H{s.upper()}"] = getattr(ahb_flash, s) flash = ResetInserter()(AHBFlash(ahb_flash)) - self.comb += flash.reset.eq(self.bus_reset) + self.comb += flash.reset.eq(~bus_reset_n) self.submodules += flash - # Extension AHB -> Wishbone CSR via bridge + + # Peripheral Bus (AHB -> Wishbone). + # --------------------------------- self.pbus = wishbone.Interface(data_width=32, adr_width=30, addressing="word") - self.periph_buses = [self.pbus] ahb_targexp0 = ahb.Interface() for s, _ in ahb_targexp0.master_signals: self.cpu_params[f"o_TARGEXP0H{s.upper()}"] = getattr(ahb_targexp0, s) for s, _ in ahb_targexp0.slave_signals: self.cpu_params[f"i_TARGEXP0H{s.upper()}"] = getattr(ahb_targexp0, s) self.submodules += ahb.AHB2Wishbone(ahb_targexp0, self.pbus) + self.periph_buses.append(self.pbus) def connect_uart(self, pads, n=0): assert n in (0, 1), "this CPU has 2 built-in UARTs, 0 and 1" self.cpu_params.update({ - f"i_UART{n}RXDI": pads.rx, - f"o_UART{n}TXDO": pads.tx, - f"o_UART{n}BAUDTICK": Signal() + f"i_UART{n}RXDI" : pads.rx, + f"o_UART{n}TXDO" : pads.tx, + f"o_UART{n}BAUDTICK" : Signal() }) def connect_jtag(self, pads):