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
18 from customecpix5
import ECPIX5Platform
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):
23 self
.clkout1
= clkout1
24 self
.clkout2
= clkout2
25 self
.clkout3
= clkout3
26 self
.clkout4
= clkout4
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
45 def elaborate(self
, platform
):
47 pll
= Instance("EHXPLLL",
48 p_PLLRST_ENA
='DISABLED',
49 p_INTFB_WAKE
='DISABLED',
50 p_STDBY_ENABLE
='DISABLED',
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',
77 o_CLKOS2
=self
.clkout3
,
78 o_CLKOS3
=self
.clkout4
,
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
)
91 m
.d
.comb
+= clkfb
.eq(self
.clkout4
)
94 class SysClocker(Elaboratable
):
95 def elaborate(self
, platform
):
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
103 cd_init
= ClockDomain("init", local
=False)
104 m
.d
.comb
+= cd_init
.clk
.eq(pll
.clkout2
)
109 class DDR3SoC(CPUSoC
, Elaboratable
):
110 def __init__(self
, *, reset_addr
, clk_freq
,
112 rom2_addr
, rom2_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"})
122 self
.cpu
= MinervaCPU(reset_address
=reset_addr
)
123 self
._arbiter
.add(self
.cpu
.ibus
)
124 self
._arbiter
.add(self
.cpu
.dbus
)
126 self
.rom
= SRAMPeripheral(size
=rom_size
, writable
=False)
127 self
._decoder
.add(self
.rom
.bus
, addr
=rom_addr
)
129 self
.rom2
= SRAMPeripheral(size
=rom2_size
)
130 self
._decoder
.add(self
.rom2
.bus
, addr
=rom2_addr
)
132 self
.ram
= SRAMPeripheral(size
=ram_size
)
133 self
._decoder
.add(self
.ram
.bus
, addr
=ram_addr
)
135 self
.uart
= AsyncSerialPeripheral(divisor
=uart_divisor
, pins
=uart_pins
)
136 self
._decoder
.add(self
.uart
.bus
, addr
=uart_addr
)
138 self
.timer
= TimerPeripheral(width
=timer_width
)
139 self
._decoder
.add(self
.timer
.bus
, addr
=timer_addr
)
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)
145 self
.ddrphy
= ECP5DDRPHY(platform
.request("ddr3", 0))
146 self
._decoder
.add(self
.ddrphy
.bus
, addr
=ddrphy_addr
)
148 ddrmodule
= MT41K256M16(clk_freq
, "1:4")
150 self
.dramcore
= gramCore(
152 geom_settings
= ddrmodule
.geom_settings
,
153 timing_settings
= ddrmodule
.timing_settings
,
155 self
._decoder
.add(self
.dramcore
.bus
, addr
=dramcore_addr
)
157 self
.dramport
= self
.dramcore
.crossbar
.get_port()
159 self
.memory_map
= self
._decoder
.bus
.memory_map
161 self
.clk_freq
= clk_freq
163 def elaborate(self
, platform
):
166 m
.submodules
.arbiter
= self
._arbiter
167 m
.submodules
.cpu
= self
.cpu
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
178 m
.submodules
.sysclk
= SysClocker()
181 self
._arbiter
.bus
.connect(self
._decoder
.bus
),
182 self
.cpu
.ip
.eq(self
.intc
.ip
),
188 if __name__
== "__main__":
189 platform
= ECPIX5Platform()
191 uart_divisor
= int(platform
.default_clk_frequency
// 115200)
192 uart_pins
= platform
.request("uart", 0)
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
204 soc
.build(do_build
=True, do_init
=True)
205 platform
.build(soc
, do_program
=True)