Fix CRG, revert to resetful sync domain
[gram.git] / gram / simulation / simsoc.py
1 # This file is Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
2
3 from nmigen import *
4 from nmigen.lib.cdc import ResetSynchronizer
5 from nmigen_soc import wishbone, memory
6
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
14
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
19
20 from icarusecpix5platform import IcarusECPIX5Platform
21 from uartbridge import UARTBridge
22
23 class PLL(Elaboratable):
24 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):
25 self.clkin = clkin
26 self.clkout1 = clkout1
27 self.clkout2 = clkout2
28 self.clkout3 = clkout3
29 self.clkout4 = clkout4
30 self.clksel = clksel
31 self.lock = lock
32 self.CLKI_DIV = CLKI_DIV
33 self.CLKFB_DIV = CLKFB_DIV
34 self.CLKOP_DIV = CLK1_DIV
35 self.CLKOS_DIV = CLK2_DIV
36 self.CLKOS2_DIV = CLK3_DIV
37 self.CLKOS3_DIV = CLK4_DIV
38 self.ports = [
39 self.clkin,
40 self.clkout1,
41 self.clkout2,
42 self.clkout3,
43 self.clkout4,
44 self.clksel,
45 self.lock,
46 ]
47
48 def elaborate(self, platform):
49 clkfb = Signal()
50 pll = Instance("EHXPLLL",
51 p_CLKOP_FPHASE=0,
52 p_CLKOP_CPHASE=1,
53 p_OUTDIVIDER_MUXA='DIVA',
54 p_CLKOP_ENABLE='ENABLED',
55 p_CLKOP_DIV=self.CLKOP_DIV,
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,
60 p_CLKI_DIV=self.CLKI_DIV,
61 p_FEEDBK_PATH='INT_OP',
62 #p_FREQUENCY_PIN_CLKOP='200',
63 i_CLKI=self.clkin,
64 i_CLKFB=clkfb,
65 i_RST=0,
66 i_STDBY=0,
67 i_PHASESEL0=1,
68 i_PHASESEL1=1,
69 i_PHASEDIR=0,
70 i_PHASESTEP=0,
71 i_PLLWAKESYNC=0,
72 i_ENCLKOP=1,
73 i_ENCLKOS=1,
74 i_ENCLKOS2=0,
75 i_ENCLKOS3=0,
76 o_CLKOP=self.clkout1,
77 o_CLKOS=self.clkout2,
78 o_CLKOS2=self.clkout3,
79 o_CLKOS3=self.clkout4,
80 o_LOCK=self.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
95 class ECPIX5CRG(Elaboratable):
96 def __init__(self):
97 ...
98
99 def elaborate(self, platform):
100 m = Module()
101
102 # Get 100Mhz from oscillator
103 clk100 = platform.request("clk100")
104 cd_rawclk = ClockDomain("rawclk", local=True, reset_less=True)
105 m.d.comb += cd_rawclk.clk.eq(clk100)
106 m.domains += cd_rawclk
107
108 # Reset
109 reset = platform.request(platform.default_rst).i
110 gsr0 = Signal()
111 gsr1 = Signal()
112
113 m.submodules += [
114 Instance("FD1S3AX", p_GSR="DISABLED", i_CK=ClockSignal("rawclk"), i_D=~reset, o_Q=gsr0),
115 Instance("FD1S3AX", p_GSR="DISABLED", i_CK=ClockSignal("rawclk"), i_D=gsr0, o_Q=gsr1),
116 Instance("SGSR", i_CLK=ClockSignal("rawclk"), i_GSR=gsr1),
117 ]
118
119 # Power-on delay (655us)
120 podcnt = Signal(16, reset=2**16-1)
121 pod_done = Signal()
122 with m.If(podcnt != 0):
123 m.d.rawclk += podcnt.eq(podcnt-1)
124 m.d.comb += pod_done.eq(podcnt == 0)
125
126 # Generating sync2x (200Mhz) and init (25Mhz) from clk100
127 cd_sync2x = ClockDomain("sync2x", local=False)
128 cd_sync2x_unbuf = ClockDomain("sync2x_unbuf", local=True, reset_less=True)
129 cd_init = ClockDomain("init", local=False)
130 cd_sync = ClockDomain("sync", local=False)
131 cd_dramsync = ClockDomain("dramsync", local=False)
132 m.submodules.pll = pll = PLL(ClockSignal("rawclk"), CLKI_DIV=1, CLKFB_DIV=2, CLK1_DIV=2, CLK2_DIV=16, CLK3_DIV=4,
133 clkout1=ClockSignal("sync2x_unbuf"), clkout2=ClockSignal("init"))
134 m.submodules += Instance("ECLKSYNCB",
135 i_ECLKI = ClockSignal("sync2x_unbuf"),
136 i_STOP = 0,
137 o_ECLKO = ClockSignal("sync2x"))
138 m.domains += cd_sync2x_unbuf
139 m.domains += cd_sync2x
140 m.domains += cd_init
141 m.domains += cd_sync
142 m.domains += cd_dramsync
143 m.d.comb += ResetSignal("init").eq(~pll.lock|~pod_done)
144 m.d.comb += ResetSignal("sync").eq(~pll.lock|~pod_done)
145 m.d.comb += ResetSignal("dramsync").eq(~pll.lock|~pod_done)
146
147 rgb_led = platform.request("rgb_led", 2)
148 cnt = Signal(25)
149 m.d.sync += cnt.eq(cnt+1)
150 m.d.comb += rgb_led.r.eq(cnt[24])
151 m.d.comb += rgb_led.g.eq(~pod_done)
152 m.d.comb += rgb_led.b.eq(~pll.lock)
153
154 # Generating sync (100Mhz) from sync2x
155
156 m.submodules += Instance("CLKDIVF",
157 p_DIV="2.0",
158 i_ALIGNWD=0,
159 i_CLKI=ClockSignal("sync2x"),
160 i_RST=0,
161 o_CDIVX=ClockSignal("sync"))
162 m.d.comb += ClockSignal("dramsync").eq(ClockSignal("sync"))
163
164 return m
165
166 class OldCRG(Elaboratable):
167 def elaborate(self, platform):
168 m = Module()
169
170 m.submodules.pll = pll = PLL(ClockSignal(
171 "sync"), CLKI_DIV=1, CLKFB_DIV=2, CLK1_DIV=2, CLK2_DIV=16)
172 cd_sync2x = ClockDomain("sync2x", local=False)
173 m.d.comb += cd_sync2x.clk.eq(pll.clkout1)
174 m.domains += cd_sync2x
175
176 cd_init = ClockDomain("init", local=False)
177 m.d.comb += cd_init.clk.eq(pll.clkout2)
178 m.domains += cd_init
179
180 return m
181
182 class ThinCRG(Elaboratable):
183 """
184 Sync (clk100, resetless) => PLL => sync2x_unbuf (200Mhz) => ECLKSYNC => sync2x => CLKDIVF => dramsync
185 """
186
187 def __init__(self):
188 ...
189
190 def elaborate(self, platform):
191 m = Module()
192
193 # Power-on delay (655us)
194 podcnt = Signal(16, reset=2**16-1)
195 pod_done = Signal()
196 with m.If(podcnt != 0):
197 m.d.sync += podcnt.eq(podcnt-1)
198 m.d.comb += pod_done.eq(podcnt == 0)
199
200 # Generating sync2x (200Mhz) and init (25Mhz) from clk100
201 cd_sync2x = ClockDomain("sync2x", local=False)
202 cd_sync2x_unbuf = ClockDomain("sync2x_unbuf", local=True, reset_less=True)
203 cd_init = ClockDomain("init", local=False)
204 cd_dramsync = ClockDomain("dramsync", local=False)
205 m.submodules.pll = pll = PLL(ClockSignal("sync"), CLKI_DIV=1, CLKFB_DIV=2, CLK1_DIV=2, CLK2_DIV=16, CLK3_DIV=4,
206 clkout1=ClockSignal("sync2x_unbuf"), clkout2=ClockSignal("init"))
207 m.submodules += Instance("ECLKSYNCB",
208 i_ECLKI = ClockSignal("sync2x_unbuf"),
209 i_STOP = 0,
210 o_ECLKO = ClockSignal("sync2x"))
211 m.domains += cd_sync2x_unbuf
212 m.domains += cd_sync2x
213 m.domains += cd_init
214 m.domains += cd_dramsync
215 m.d.comb += ResetSignal("init").eq(~pll.lock|~pod_done)
216 m.d.comb += ResetSignal("dramsync").eq(~pll.lock|~pod_done)
217
218 # Generating sync (100Mhz) from sync2x
219 m.submodules += Instance("CLKDIVF",
220 p_DIV="2.0",
221 i_ALIGNWD=0,
222 i_CLKI=ClockSignal("sync2x"),
223 i_RST=0,
224 o_CDIVX=ClockSignal("dramsync"))
225
226 return m
227
228
229 class DDR3SoC(SoC, Elaboratable):
230 def __init__(self, *, clk_freq,
231 ddrphy_addr, dramcore_addr,
232 ddr_addr):
233 self._arbiter = wishbone.Arbiter(addr_width=30, data_width=32, granularity=8,
234 features={"cti", "bte"})
235 self._decoder = wishbone.Decoder(addr_width=30, data_width=32, granularity=8,
236 features={"cti", "bte"})
237
238 self.crg = ECPIX5CRG()
239
240 self.ub = UARTBridge(divisor=868, pins=platform.request("uart", 0))
241 self._arbiter.add(self.ub.bus)
242
243 self.ddrphy = DomainRenamer("dramsync")(ECP5DDRPHY(platform.request("ddr3", 0, dir={"dq":"-", "dqs":"-"})))
244 self._decoder.add(self.ddrphy.bus, addr=ddrphy_addr)
245
246 ddrmodule = MT41K256M16(clk_freq, "1:4")
247
248 self.dramcore = DomainRenamer("dramsync")(gramCore(
249 phy=self.ddrphy,
250 geom_settings=ddrmodule.geom_settings,
251 timing_settings=ddrmodule.timing_settings,
252 clk_freq=clk_freq))
253 self._decoder.add(self.dramcore.bus, addr=dramcore_addr)
254
255 self.drambone = DomainRenamer("dramsync")(gramWishbone(self.dramcore))
256 self._decoder.add(self.drambone.bus, addr=ddr_addr)
257
258 self.memory_map = self._decoder.bus.memory_map
259
260 self.clk_freq = clk_freq
261
262 def elaborate(self, platform):
263 m = Module()
264
265 m.submodules.sysclk = self.crg
266
267 m.submodules.arbiter = self._arbiter
268 m.submodules.ub = self.ub
269
270 m.submodules.decoder = self._decoder
271 m.submodules.ddrphy = self.ddrphy
272 m.submodules.dramcore = self.dramcore
273 m.submodules.drambone = self.drambone
274
275 m.d.comb += [
276 self._arbiter.bus.connect(self._decoder.bus),
277 ]
278
279 return m
280
281
282 if __name__ == "__main__":
283 platform = IcarusECPIX5Platform()
284
285 soc = DDR3SoC(clk_freq=int(platform.default_clk_frequency),
286 ddrphy_addr=0x00008000, dramcore_addr=0x00009000,
287 ddr_addr=0x10000000)
288
289 soc.build(do_build=True)
290 platform.build(soc)