c8afa89a19f18e44e55f1eb6795078e7f37ca88b
[lambdasoc.git] / examples / sdram_soc.py
1 import argparse
2
3 from nmigen import *
4 from nmigen.build import *
5 from nmigen_soc import wishbone
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.sdram import SDRAMPeripheral
13 from lambdasoc.soc.cpu import CPUSoC
14
15 from lambdasoc.cores import litedram
16
17
18 __all__ = ["SDRAMSoC"]
19
20
21 class SDRAMSoC(CPUSoC, Elaboratable):
22 def __init__(self, *, reset_addr, clk_freq,
23 rom_addr, rom_size,
24 ram_addr, ram_size,
25 uart_addr, uart_divisor, uart_pins,
26 timer_addr, timer_width,
27 sdram_addr, sdram_core, sdram_cache_size):
28 self._arbiter = wishbone.Arbiter(addr_width=30, data_width=32, granularity=8,
29 features={"cti", "bte"})
30 self._decoder = wishbone.Decoder(addr_width=30, data_width=32, granularity=8,
31 features={"cti", "bte"})
32
33 self.cpu = MinervaCPU(
34 reset_address=reset_addr,
35 with_icache=True, icache_nlines=128, icache_nwords=4, icache_nways=1,
36 icache_base=sdram_addr, icache_limit=sdram_addr + sdram_core.size,
37 with_dcache=True, dcache_nlines=128, dcache_nwords=4, dcache_nways=1,
38 dcache_base=sdram_addr, dcache_limit=sdram_addr + sdram_core.size,
39 with_muldiv=True,
40 )
41 self._arbiter.add(self.cpu.ibus)
42 self._arbiter.add(self.cpu.dbus)
43
44 self.rom = SRAMPeripheral(size=rom_size, writable=False)
45 self._decoder.add(self.rom.bus, addr=rom_addr)
46
47 self.ram = SRAMPeripheral(size=ram_size)
48 self._decoder.add(self.ram.bus, addr=ram_addr)
49
50 self.sdram = SDRAMPeripheral(core=sdram_core, cache_size=sdram_cache_size)
51 self._decoder.add(self.sdram.bus, addr=sdram_addr)
52
53 self.uart = AsyncSerialPeripheral(divisor=uart_divisor, pins=uart_pins)
54 self._decoder.add(self.uart.bus, addr=uart_addr)
55
56 self.timer = TimerPeripheral(width=timer_width)
57 self._decoder.add(self.timer.bus, addr=timer_addr)
58
59 self.intc = GenericInterruptController(width=len(self.cpu.ip))
60 self.intc.add_irq(self.timer.irq, 0)
61 self.intc.add_irq(self.uart .irq, 1)
62
63 self.memory_map = self._decoder.bus.memory_map
64
65 self.clk_freq = clk_freq
66
67 def elaborate(self, platform):
68 m = Module()
69
70 m.domains += [
71 ClockDomain("litedram_input"),
72 ClockDomain("litedram_user"),
73 ClockDomain("sync"),
74 ]
75
76 m.d.comb += [
77 ClockSignal("litedram_input").eq(platform.request("clk100", 0).i),
78
79 ClockSignal("sync").eq(ClockSignal("litedram_user")),
80 ResetSignal("sync").eq(ResetSignal("litedram_user")),
81 ]
82
83 m.submodules.arbiter = self._arbiter
84 m.submodules.cpu = self.cpu
85
86 m.submodules.decoder = self._decoder
87 m.submodules.rom = self.rom
88 m.submodules.ram = self.ram
89 m.submodules.sdram = self.sdram
90 m.submodules.uart = self.uart
91 m.submodules.timer = self.timer
92 m.submodules.intc = self.intc
93
94 m.d.comb += [
95 self._arbiter.bus.connect(self._decoder.bus),
96 self.cpu.ip.eq(self.intc.ip),
97 ]
98
99 return m
100
101
102 if __name__ == "__main__":
103 parser = argparse.ArgumentParser()
104 parser.add_argument("--platform", type=str,
105 choices=("arty_a7", "ecpix5_85"),
106 help="target platform")
107 parser.add_argument("--baudrate", type=int,
108 default=9600,
109 help="UART baudrate (default: 9600)")
110 args = parser.parse_args()
111
112 if args.platform == "arty_a7":
113 from nmigen_boards.arty_a7 import ArtyA7_35Platform
114 platform = ArtyA7_35Platform()
115 litedram_cfg = litedram.Artix7Config(
116 memtype = "DDR3",
117 speedgrade = "-1",
118 cmd_latency = 0,
119 module_name = "MT41K128M16",
120 module_bytes = 2,
121 module_ranks = 1,
122 rtt_nom = 60,
123 rtt_wr = 60,
124 ron = 34,
125 input_clk_freq = int(100e6),
126 user_clk_freq = int(100e6),
127 iodelay_clk_freq = int(200e6),
128 )
129 elif args.platform == "ecpix5_85":
130 from nmigen_boards.ecpix5 import ECPIX585Platform
131 platform = ECPIX585Platform()
132 litedram_cfg = litedram.ECP5Config(
133 memtype = "DDR3",
134 module_name = "MT41K256M16",
135 module_bytes = 2,
136 module_ranks = 1,
137 input_clk_freq = int(100e6),
138 user_clk_freq = int(70e6),
139 init_clk_freq = int(25e6),
140 )
141 else:
142 assert False
143
144 litedram_pins = litedram_cfg.request_pins(platform, "ddr3", 0)
145 litedram_core = litedram.Core(litedram_cfg, pins=litedram_pins)
146
147 litedram_builder = litedram.Builder()
148 litedram_products = litedram_core.build(litedram_builder, do_build=True)
149
150 litedram_core_v = f"{litedram_core.name}/{litedram_core.name}.v"
151 platform.add_file(litedram_core_v, litedram_products.get(litedram_core_v, mode="t"))
152
153 soc = SDRAMSoC(
154 reset_addr=0x30000000, clk_freq=litedram_cfg.user_clk_freq,
155 uart_addr=0x00005000, uart_divisor=int(litedram_cfg.user_clk_freq // args.baudrate),
156 uart_pins=platform.request("uart", 0),
157 timer_addr=0x00006000, timer_width=32,
158
159 rom_addr=0x30000000, rom_size=0x8000,
160 ram_addr=0x30008000, ram_size=0x1000,
161 sdram_addr=0x40000000, sdram_core=litedram_core, sdram_cache_size=8192,
162 )
163 soc.build(do_build=True, do_init=True)
164
165 platform.build(soc, do_program=True)