Connect dramcore to SoC bus in ECPIX-5 example
[gram.git] / examples / ecpix5.py
1 # This file is Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
2
3 from nmigen import *
4 from nmigen_soc import wishbone, memory
5
6 from lambdasoc.cpu.minerva import MinervaCPU
7 from lambdasoc.periph.intc import GenericInterruptController
8 from lambdasoc.periph.serial import AsyncSerialPeripheral
9 from lambdasoc.periph.sram import SRAMPeripheral
10 from lambdasoc.periph.timer import TimerPeripheral
11 from lambdasoc.periph import Peripheral
12 from lambdasoc.soc.cpu import CPUSoC
13
14 from gram.core import gramCore
15 from gram.phy.ecp5ddrphy import ECP5DDRPHY
16 from gram.modules import MT41K256M16
17
18 from customecpix5 import ECPIX5Platform
19
20 class PLL(Elaboratable):
21 def __init__(self, clkin, clksel=Signal(shape=2, reset=2), clkout1=Signal(), clkout2=Signal(), clkout3=Signal(), clkout4=Signal(), lock=Signal(), CLKI_DIV=1, CLKFB_DIV=1, CLK1_DIV=3, CLK2_DIV=4, CLK3_DIV=5, CLK4_DIV=6):
22 self.clkin = clkin
23 self.clkout1 = clkout1
24 self.clkout2 = clkout2
25 self.clkout3 = clkout3
26 self.clkout4 = clkout4
27 self.clksel = clksel
28 self.lock = lock
29 self.CLKI_DIV = CLKI_DIV
30 self.CLKFB_DIV = CLKFB_DIV
31 self.CLKOP_DIV = CLK1_DIV
32 self.CLKOS_DIV = CLK2_DIV
33 self.CLKOS2_DIV = CLK3_DIV
34 self.CLKOS3_DIV = CLK4_DIV
35 self.ports = [
36 self.clkin,
37 self.clkout1,
38 self.clkout2,
39 self.clkout3,
40 self.clkout4,
41 self.clksel,
42 self.lock,
43 ]
44
45 def elaborate(self, platform):
46 clkfb = Signal()
47 pll = Instance("EHXPLLL",
48 p_PLLRST_ENA='DISABLED',
49 p_INTFB_WAKE='DISABLED',
50 p_STDBY_ENABLE='DISABLED',
51 p_CLKOP_FPHASE=0,
52 p_CLKOP_CPHASE=11,
53 p_OUTDIVIDER_MUXA='DIVA',
54 p_CLKOP_ENABLE='ENABLED',
55 p_CLKOP_DIV=self.CLKOP_DIV, #Max 948 MHz at OP=79 FB=1 I=1 F_in=12 MHz, Min 30 MHz (28 MHz locks sometimes, lock LED blinks) Hmm... /3*82/25
56 p_CLKOS_DIV=self.CLKOS_DIV,
57 p_CLKOS2_DIV=self.CLKOS2_DIV,
58 p_CLKOS3_DIV=self.CLKOS3_DIV,
59 p_CLKFB_DIV=self.CLKFB_DIV, #25
60 p_CLKI_DIV=self.CLKI_DIV, #6
61 p_FEEDBK_PATH='USERCLOCK',
62 i_CLKI=self.clkin,
63 i_CLKFB=clkfb,
64 i_RST=0,
65 i_STDBY=0,
66 i_PHASESEL0=0,
67 i_PHASESEL1=0,
68 i_PHASEDIR=0,
69 i_PHASESTEP=0,
70 i_PLLWAKESYNC=0,
71 i_ENCLKOP=0,
72 i_ENCLKOS=0,
73 i_ENCLKOS2=0,
74 i_ENCLKOS3=0,
75 o_CLKOP=self.clkout1,
76 o_CLKOS=self.clkout2,
77 o_CLKOS2=self.clkout3,
78 o_CLKOS3=self.clkout4,
79 o_LOCK=self.lock,
80 #o_LOCK=pll_lock
81 )
82 m = Module()
83 m.submodules += pll
84 with m.If(self.clksel == 0):
85 m.d.comb += clkfb.eq(self.clkout1)
86 with m.Elif(self.clksel == 1):
87 m.d.comb += clkfb.eq(self.clkout2)
88 with m.Elif(self.clksel == 2):
89 m.d.comb += clkfb.eq(self.clkout3)
90 with m.Else():
91 m.d.comb += clkfb.eq(self.clkout4)
92 return m
93
94 class SysClocker(Elaboratable):
95 def elaborate(self, platform):
96 m = Module()
97
98 m.submodules.pll = pll = PLL(ClockSignal("sync"), CLKI_DIV=1, CLKFB_DIV=2, CLK1_DIV=2, CLK2_DIV=16)
99 cd_sys2x = ClockDomain("sys2x", local=False)
100 m.d.comb += cd_sys2x.clk.eq(pll.clkout1)
101 m.domains += cd_sys2x
102
103 cd_init = ClockDomain("init", local=False)
104 m.d.comb += cd_init.clk.eq(pll.clkout2)
105 m.domains += cd_init
106
107 return m
108
109 class DDR3SoC(CPUSoC, Elaboratable):
110 def __init__(self, *, reset_addr, clk_freq,
111 rom_addr, rom_size,
112 rom2_addr, rom2_size,
113 ram_addr, ram_size,
114 uart_addr, uart_divisor, uart_pins,
115 timer_addr, timer_width,
116 ddrphy_addr, dramcore_addr):
117 self._arbiter = wishbone.Arbiter(addr_width=30, data_width=32, granularity=8,
118 features={"cti", "bte"})
119 self._decoder = wishbone.Decoder(addr_width=30, data_width=32, granularity=8,
120 features={"cti", "bte"})
121
122 self.cpu = MinervaCPU(reset_address=reset_addr)
123 self._arbiter.add(self.cpu.ibus)
124 self._arbiter.add(self.cpu.dbus)
125
126 self.rom = SRAMPeripheral(size=rom_size, writable=False)
127 self._decoder.add(self.rom.bus, addr=rom_addr)
128
129 self.rom2 = SRAMPeripheral(size=rom2_size)
130 self._decoder.add(self.rom2.bus, addr=rom2_addr)
131
132 self.ram = SRAMPeripheral(size=ram_size)
133 self._decoder.add(self.ram.bus, addr=ram_addr)
134
135 self.uart = AsyncSerialPeripheral(divisor=uart_divisor, pins=uart_pins)
136 self._decoder.add(self.uart.bus, addr=uart_addr)
137
138 self.timer = TimerPeripheral(width=timer_width)
139 self._decoder.add(self.timer.bus, addr=timer_addr)
140
141 self.intc = GenericInterruptController(width=len(self.cpu.ip))
142 self.intc.add_irq(self.timer.irq, 0)
143 self.intc.add_irq(self.uart .irq, 1)
144
145 self.ddrphy = ECP5DDRPHY(platform.request("ddr3", 0))
146 self._decoder.add(self.ddrphy.bus, addr=ddrphy_addr)
147
148 ddrmodule = MT41K256M16(clk_freq, "1:4")
149
150 self.dramcore = gramCore(
151 phy = self.ddrphy,
152 geom_settings = ddrmodule.geom_settings,
153 timing_settings = ddrmodule.timing_settings,
154 clk_freq = clk_freq)
155 self._decoder.add(self.dramcore.bus, addr=dramcore_addr)
156
157 self.dramport = self.dramcore.crossbar.get_port()
158
159 self.memory_map = self._decoder.bus.memory_map
160
161 self.clk_freq = clk_freq
162
163 def elaborate(self, platform):
164 m = Module()
165
166 m.submodules.arbiter = self._arbiter
167 m.submodules.cpu = self.cpu
168
169 m.submodules.decoder = self._decoder
170 m.submodules.rom = self.rom
171 m.submodules.ram = self.ram
172 m.submodules.uart = self.uart
173 m.submodules.timer = self.timer
174 m.submodules.intc = self.intc
175 m.submodules.ddrphy = self.ddrphy
176 m.submodules.dramcore = self.dramcore
177
178 m.submodules.sysclk = SysClocker()
179
180 m.d.comb += [
181 self._arbiter.bus.connect(self._decoder.bus),
182 self.cpu.ip.eq(self.intc.ip),
183 ]
184
185 return m
186
187
188 if __name__ == "__main__":
189 platform = ECPIX5Platform()
190
191 uart_divisor = int(platform.default_clk_frequency // 115200)
192 uart_pins = platform.request("uart", 0)
193
194 soc = DDR3SoC(
195 reset_addr=0x00000000, clk_freq=int(platform.default_clk_frequency),
196 rom_addr=0x00000000, rom_size=0x4000,
197 rom2_addr=0x7000, rom2_size=0x1000,
198 ram_addr=0x00004000, ram_size=0x1000,
199 uart_addr=0x00005000, uart_divisor=uart_divisor, uart_pins=uart_pins,
200 timer_addr=0x00006000, timer_width=32,
201 ddrphy_addr=0x00008000, dramcore_addr=0x00009000
202 )
203
204 soc.build(do_build=True, do_init=True)
205 platform.build(soc, do_program=True)