1 # This file is Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
4 from nmigen_soc
import wishbone
, memory
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
14 from gram
.core
import gramCore
15 from gram
.phy
.ecp5ddrphy
import ECP5DDRPHY
16 from gram
.modules
import MT41K256M16
17 from gram
.frontend
.wishbone
import gramWishbone
19 from customecpix5
import ECPIX5Platform
22 class PLL(Elaboratable
):
23 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
.clkout1
= clkout1
26 self
.clkout2
= clkout2
27 self
.clkout3
= clkout3
28 self
.clkout4
= clkout4
31 self
.CLKI_DIV
= CLKI_DIV
32 self
.CLKFB_DIV
= CLKFB_DIV
33 self
.CLKOP_DIV
= CLK1_DIV
34 self
.CLKOS_DIV
= CLK2_DIV
35 self
.CLKOS2_DIV
= CLK3_DIV
36 self
.CLKOS3_DIV
= CLK4_DIV
47 def elaborate(self
, platform
):
49 pll
= Instance("EHXPLLL",
50 p_PLLRST_ENA
='DISABLED',
51 p_INTFB_WAKE
='DISABLED',
52 p_STDBY_ENABLE
='DISABLED',
55 p_OUTDIVIDER_MUXA
='DIVA',
56 p_CLKOP_ENABLE
='ENABLED',
57 # 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
58 p_CLKOP_DIV
=self
.CLKOP_DIV
,
59 p_CLKOS_DIV
=self
.CLKOS_DIV
,
60 p_CLKOS2_DIV
=self
.CLKOS2_DIV
,
61 p_CLKOS3_DIV
=self
.CLKOS3_DIV
,
62 p_CLKFB_DIV
=self
.CLKFB_DIV
, # 25
63 p_CLKI_DIV
=self
.CLKI_DIV
, # 6
64 p_FEEDBK_PATH
='USERCLOCK',
80 o_CLKOS2
=self
.clkout3
,
81 o_CLKOS3
=self
.clkout4
,
87 with m
.If(self
.clksel
== 0):
88 m
.d
.comb
+= clkfb
.eq(self
.clkout1
)
89 with m
.Elif(self
.clksel
== 1):
90 m
.d
.comb
+= clkfb
.eq(self
.clkout2
)
91 with m
.Elif(self
.clksel
== 2):
92 m
.d
.comb
+= clkfb
.eq(self
.clkout3
)
94 m
.d
.comb
+= clkfb
.eq(self
.clkout4
)
98 class SysClocker(Elaboratable
):
99 def elaborate(self
, platform
):
102 m
.submodules
.pll
= pll
= PLL(ClockSignal(
103 "sync"), CLKI_DIV
=1, CLKFB_DIV
=2, CLK1_DIV
=2, CLK2_DIV
=16)
104 cd_sys2x
= ClockDomain("sys2x", local
=False)
105 m
.d
.comb
+= cd_sys2x
.clk
.eq(pll
.clkout1
)
106 m
.domains
+= cd_sys2x
108 cd_init
= ClockDomain("init", local
=False)
109 m
.d
.comb
+= cd_init
.clk
.eq(pll
.clkout2
)
115 class DDR3SoC(CPUSoC
, Elaboratable
):
116 def __init__(self
, *, reset_addr
, clk_freq
,
118 rom2_addr
, rom2_size
,
120 uart_addr
, uart_divisor
, uart_pins
,
121 timer_addr
, timer_width
,
122 ddrphy_addr
, dramcore_addr
,
124 self
._arbiter
= wishbone
.Arbiter(addr_width
=30, data_width
=32, granularity
=8,
125 features
={"cti", "bte"})
126 self
._decoder
= wishbone
.Decoder(addr_width
=30, data_width
=32, granularity
=8,
127 features
={"cti", "bte"})
129 self
.cpu
= MinervaCPU(reset_address
=reset_addr
)
130 self
._arbiter
.add(self
.cpu
.ibus
)
131 self
._arbiter
.add(self
.cpu
.dbus
)
133 self
.rom
= SRAMPeripheral(size
=rom_size
, writable
=False)
134 self
._decoder
.add(self
.rom
.bus
, addr
=rom_addr
)
136 self
.rom2
= SRAMPeripheral(size
=rom2_size
)
137 self
._decoder
.add(self
.rom2
.bus
, addr
=rom2_addr
)
139 self
.ram
= SRAMPeripheral(size
=ram_size
)
140 self
._decoder
.add(self
.ram
.bus
, addr
=ram_addr
)
142 self
.uart
= AsyncSerialPeripheral(divisor
=uart_divisor
, pins
=uart_pins
)
143 self
._decoder
.add(self
.uart
.bus
, addr
=uart_addr
)
145 self
.timer
= TimerPeripheral(width
=timer_width
)
146 self
._decoder
.add(self
.timer
.bus
, addr
=timer_addr
)
148 self
.intc
= GenericInterruptController(width
=len(self
.cpu
.ip
))
149 self
.intc
.add_irq(self
.timer
.irq
, 0)
150 self
.intc
.add_irq(self
.uart
.irq
, 1)
152 self
.ddrphy
= ECP5DDRPHY(platform
.request("ddr3", 0))
153 self
._decoder
.add(self
.ddrphy
.bus
, addr
=ddrphy_addr
)
155 ddrmodule
= MT41K256M16(clk_freq
, "1:4")
157 self
.dramcore
= gramCore(
159 geom_settings
=ddrmodule
.geom_settings
,
160 timing_settings
=ddrmodule
.timing_settings
,
162 self
._decoder
.add(self
.dramcore
.bus
, addr
=dramcore_addr
)
164 self
.drambone
= gramWishbone(self
.dramcore
)
165 self
._decoder
.add(self
.drambone
.bus
, addr
=ddr_addr
)
167 self
.memory_map
= self
._decoder
.bus
.memory_map
169 self
.clk_freq
= clk_freq
171 def elaborate(self
, platform
):
174 m
.submodules
.arbiter
= self
._arbiter
175 m
.submodules
.cpu
= self
.cpu
177 m
.submodules
.decoder
= self
._decoder
178 m
.submodules
.rom
= self
.rom
179 m
.submodules
.ram
= self
.ram
180 m
.submodules
.uart
= self
.uart
181 m
.submodules
.timer
= self
.timer
182 m
.submodules
.intc
= self
.intc
183 m
.submodules
.ddrphy
= self
.ddrphy
184 m
.submodules
.dramcore
= self
.dramcore
185 m
.submodules
.drambone
= self
.drambone
187 m
.submodules
.sysclk
= SysClocker()
190 self
._arbiter
.bus
.connect(self
._decoder
.bus
),
191 self
.cpu
.ip
.eq(self
.intc
.ip
),
197 if __name__
== "__main__":
198 platform
= ECPIX5Platform()
200 uart_divisor
= int(platform
.default_clk_frequency
// 115200)
201 uart_pins
= platform
.request("uart", 0)
204 reset_addr
=0x00000000, clk_freq
=int(platform
.default_clk_frequency
),
205 rom_addr
=0x00000000, rom_size
=0x4000,
206 rom2_addr
=0x7000, rom2_size
=0x1000,
207 ram_addr
=0x00004000, ram_size
=0x1000,
208 uart_addr
=0x00005000, uart_divisor
=uart_divisor
, uart_pins
=uart_pins
,
209 timer_addr
=0x00006000, timer_width
=32,
210 ddrphy_addr
=0x00008000, dramcore_addr
=0x00009000,
214 soc
.build(do_build
=True, do_init
=True)
215 platform
.build(soc
, do_program
=True)