2be6bfcae47ce4dff66dd585a7eedcddfa72b250
[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("--baudrate", type=int,
105 default=9600,
106 help="UART baudrate (default: 9600)")
107 args = parser.parse_args()
108
109 # from nmigen_boards.arty_a7 import ArtyA7_35Platform
110 # platform = ArtyA7_35Platform()
111 # litedram_cfg = litedram.Artix7Config(
112 # memtype = "DDR3",
113 # speedgrade = "-1",
114 # cmd_latency = 0,
115 # module_name = "MT41K128M16",
116 # module_bytes = 2,
117 # module_ranks = 1,
118 # rtt_nom = 60,
119 # rtt_wr = 60,
120 # ron = 34,
121 # input_clk_freq = int(100e6),
122 # user_clk_freq = int(100e6),
123 # iodelay_clk_freq = int(200e6),
124 # )
125
126 from nmigen_boards.ecpix5 import ECPIX585Platform
127 platform = ECPIX585Platform()
128 litedram_cfg = litedram.ECP5Config(
129 memtype = "DDR3",
130 module_name = "MT41K256M16",
131 module_bytes = 2,
132 module_ranks = 1,
133 input_clk_freq = int(100e6),
134 user_clk_freq = int(70e6),
135 init_clk_freq = int(25e6),
136 )
137
138 litedram_core = litedram.Core(
139 litedram_cfg,
140 pins = litedram_cfg.request_pins(platform, "ddr3", 0),
141 )
142
143 litedram_products = litedram_core.build(do_build=True)
144 with litedram_products.extract(f"{litedram_core.name}/{litedram_core.name}.v") as litedram_v:
145 with open(litedram_v, "r") as litedram_v_contents:
146 platform.add_file(litedram_v, litedram_v_contents)
147
148 soc = SDRAMSoC(
149 reset_addr=0x30000000, clk_freq=litedram_cfg.user_clk_freq,
150 uart_addr=0x00005000, uart_divisor=int(litedram_cfg.user_clk_freq // args.baudrate),
151 uart_pins=platform.request("uart", 0),
152 timer_addr=0x00006000, timer_width=32,
153
154 rom_addr=0x30000000, rom_size=0x8000,
155 ram_addr=0x30008000, ram_size=0x1000,
156 sdram_addr=0x40000000, sdram_core=litedram_core, sdram_cache_size=8192,
157 )
158 soc.build(do_build=True, do_init=True)
159
160 platform.build(soc, do_program=True)