1 # This file is Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
4 from nmigen
.lib
.cdc
import ResetSynchronizer
5 from nmigen_soc
import wishbone
, memory
7 from lambdasoc
.cpu
.minerva
import MinervaCPU
8 from lambdasoc
.periph
.intc
import GenericInterruptController
9 from lambdasoc
.periph
.serial
import AsyncSerialPeripheral
10 from lambdasoc
.periph
.sram
import SRAMPeripheral
11 from lambdasoc
.periph
.timer
import TimerPeripheral
12 from lambdasoc
.periph
import Peripheral
13 from lambdasoc
.soc
.base
import SoC
15 from gram
.core
import gramCore
16 from gram
.phy
.ecp5ddrphy
import ECP5DDRPHY
17 from gram
.modules
import MT41K256M16
18 from gram
.frontend
.wishbone
import gramWishbone
20 from nmigen_boards
.ecpix5
import *
21 from uartbridge
import UARTBridge
24 class DDR3SoC(SoC
, Elaboratable
):
27 ddrphy_addr
, dramcore_addr
,
29 self
._arbiter
= wishbone
.Arbiter(addr_width
=30, data_width
=32, granularity
=8,
30 features
={"cti", "bte"})
31 self
._decoder
= wishbone
.Decoder(addr_width
=30, data_width
=32, granularity
=8,
32 features
={"cti", "bte"})
36 self
.crg
= ECPIX5CRG()
38 self
.cpu
= MinervaCPU(reset_address
=0)
39 self
._arbiter
.add(self
.cpu
.ibus
)
40 self
._arbiter
.add(self
.cpu
.dbus
)
41 self
.intc
= GenericInterruptController(width
=len(self
.cpu
.ip
))
43 self
.rom
= SRAMPeripheral(size
=4096, writable
=False)
44 with
open("firmware/main.bin", "rb") as f
:
45 words
= iter(lambda: f
.read(self
.cpu
.data_width
// 8), b
'')
46 bios
= [int.from_bytes(w
, self
.cpu
.byteorder
) for w
in words
]
48 self
._decoder
.add(self
.rom
.bus
, addr
=0)
50 self
.ram
= SRAMPeripheral(size
=4096)
51 self
._decoder
.add(self
.ram
.bus
, addr
=0x1000)
53 self
.uart
= AsyncSerialPeripheral(divisor
=int(freq
//115200), pins
=uart_pins
)
54 self
._decoder
.add(self
.uart
.bus
, addr
=0x2000)
57 self
.ddrphy
= DomainRenamer("dramsync")(ECP5DDRPHY(ddr_pins
))
58 self
._decoder
.add(self
.ddrphy
.bus
, addr
=ddrphy_addr
)
60 ddrmodule
= MT41K256M16(freq
, "1:2")
62 self
.dramcore
= DomainRenamer("dramsync")(gramCore(
64 geom_settings
=ddrmodule
.geom_settings
,
65 timing_settings
=ddrmodule
.timing_settings
,
67 self
._decoder
.add(self
.dramcore
.bus
, addr
=dramcore_addr
)
69 self
.drambone
= DomainRenamer("dramsync")(gramWishbone(self
.dramcore
))
70 self
._decoder
.add(self
.drambone
.bus
, addr
=ddr_addr
)
72 self
.memory_map
= self
._decoder
.bus
.memory_map
76 def elaborate(self
, platform
):
79 m
.submodules
.sysclk
= self
.crg
81 m
.submodules
.rom
= self
.rom
82 m
.submodules
.ram
= self
.ram
83 m
.submodules
.uart
= self
.uart
84 m
.submodules
.intc
= self
.intc
85 m
.submodules
.cpu
= self
.cpu
86 m
.submodules
.arbiter
= self
._arbiter
87 m
.submodules
.decoder
= self
._decoder
88 m
.submodules
.ddrphy
= self
.ddrphy
89 m
.submodules
.dramcore
= self
.dramcore
90 m
.submodules
.drambone
= self
.drambone
93 self
._arbiter
.bus
.connect(self
._decoder
.bus
),
94 self
.cpu
.ip
.eq(self
.intc
.ip
),
100 if __name__
== "__main__":
101 platform
= ECPIX585Platform()
103 ddr_pins
= platform
.request("ddr3", 0, dir={"dq":"-", "dqs":"-"},
104 xdr
={"clk":4, "a":4, "ba":4, "clk_en":4, "odt":4, "ras":4, "cas":4, "we":4})
105 uart_pins
= platform
.request("uart", 0)
107 soc
= DDR3SoC(ddrphy_addr
=0x00008000, dramcore_addr
=0x00009000,
108 ddr_addr
=0x10000000, ddr_pins
=ddr_pins
, uart_pins
=uart_pins
)
110 platform
.build(soc
, do_program
=True)