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