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
.rom2
= self
.rom2
180 m
.submodules
.ram
= self
.ram
181 m
.submodules
.uart
= self
.uart
182 m
.submodules
.timer
= self
.timer
183 m
.submodules
.intc
= self
.intc
184 m
.submodules
.ddrphy
= self
.ddrphy
185 m
.submodules
.dramcore
= self
.dramcore
186 m
.submodules
.drambone
= self
.drambone
188 m
.submodules
.sysclk
= SysClocker()
191 self
._arbiter
.bus
.connect(self
._decoder
.bus
),
192 self
.cpu
.ip
.eq(self
.intc
.ip
),
198 if __name__
== "__main__":
199 platform
= ECPIX5Platform()
201 uart_divisor
= int(platform
.default_clk_frequency
// 115200)
202 uart_pins
= platform
.request("uart", 0)
205 reset_addr
=0x00000000, clk_freq
=int(platform
.default_clk_frequency
),
206 rom_addr
=0x00000000, rom_size
=0x4000,
207 rom2_addr
=0x7000, rom2_size
=0x1000,
208 ram_addr
=0x00004000, ram_size
=0x1000,
209 uart_addr
=0x00005000, uart_divisor
=uart_divisor
, uart_pins
=uart_pins
,
210 timer_addr
=0x00006000, timer_width
=32,
211 ddrphy_addr
=0x00008000, dramcore_addr
=0x00009000,
215 soc
.build(do_build
=True, do_init
=True)
216 platform
.build(soc
, do_program
=True)