1 # This file is Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
6 from nmigen
.asserts
import Assert
, Assume
7 from nmigen_soc
import wishbone
, memory
8 from nmigen
.lib
.cdc
import ResetSynchronizer
10 from lambdasoc
.periph
import Peripheral
11 from lambdasoc
.soc
.base
import SoC
13 from gram
.common
import *
14 from gram
.core
import gramCore
15 from gram
.phy
.fakephy
import FakePHY
, SDRAM_VERBOSE_STD
, SDRAM_VERBOSE_DBG
16 from gram
.modules
import MT41K256M16
17 from gram
.frontend
.wishbone
import gramWishbone
19 from gram
.core
.multiplexer
import _AntiStarvation
22 class DDR3SoC(SoC
, Elaboratable
):
23 def __init__(self
, *, clk_freq
, dramcore_addr
,
25 self
._decoder
= wishbone
.Decoder(addr_width
=30, data_width
=32, granularity
=8,
26 features
={"cti", "bte"})
28 self
.bus
= wishbone
.Interface(addr_width
=30, data_width
=32, granularity
=32)
36 cl
, cwl
= get_cl_cw("DDR3", tck
)
37 cl_sys_latency
= get_sys_latency(nphases
, cl
)
38 cwl_sys_latency
= get_sys_latency(nphases
, cwl
)
39 rdcmdphase
, rdphase
= get_sys_phases(nphases
, cl_sys_latency
, cl
)
40 wrcmdphase
, wrphase
= get_sys_phases(nphases
, cwl_sys_latency
, cwl
)
41 physettings
= PhySettings(
45 dfi_databits
=4*databits
,
50 rdcmdphase
=rdcmdphase
,
51 wrcmdphase
=wrcmdphase
,
54 read_latency
=2 + cl_sys_latency
+ 2 + log2_int(4//nphases
) + 4,
55 write_latency
=cwl_sys_latency
58 ddrmodule
= MT41K256M16(clk_freq
, "1:2")
59 self
.ddrphy
= FakePHY(module
=ddrmodule
,
61 verbosity
=SDRAM_VERBOSE_DBG
)
63 self
.dramcore
= gramCore(
65 geom_settings
=ddrmodule
.geom_settings
,
66 timing_settings
=ddrmodule
.timing_settings
,
68 self
._decoder
.add(self
.dramcore
.bus
, addr
=dramcore_addr
)
70 self
.drambone
= gramWishbone(self
.dramcore
)
71 self
._decoder
.add(self
.drambone
.bus
, addr
=ddr_addr
)
73 self
.memory_map
= self
._decoder
.bus
.memory_map
75 self
.clk_freq
= clk_freq
77 def elaborate(self
, platform
):
80 m
.submodules
.decoder
= self
._decoder
81 m
.submodules
.ddrphy
= self
.ddrphy
82 m
.submodules
.dramcore
= self
.dramcore
83 m
.submodules
.drambone
= self
.drambone
86 self
.bus
.connect(self
._decoder
.bus
),
91 class SocTestCase(FHDLTestCase
):
93 yield from wb_write(bus
, 0x0, 0xE, 0xF) # DFII_CONTROL_ODT|DFII_CONTROL_RESET_N|DFI_CONTROL_CKE
94 yield from wb_write(bus
, 0xC >> 2, 0x0, 0xF)
95 yield from wb_write(bus
, 0x10 >> 2, 0x0, 0xF)
96 yield from wb_write(bus
, 0x0, 0xC, 0xF)
97 yield from wb_write(bus
, 0x0, 0xE, 0xF)
100 yield from wb_write(bus
, 0xC >> 2, 0x200, 0xF)
101 yield from wb_write(bus
, 0x10 >> 2, 0x2, 0xF)
102 yield from wb_write(bus
, 0x4 >> 2, 0xF, 0xF)
103 yield from wb_write(bus
, 0x8 >> 2, 0x1, 0xF)
106 yield from wb_write(bus
, 0xC >> 2, 0x0, 0xF)
107 yield from wb_write(bus
, 0x10 >> 2, 0x3, 0xF)
108 yield from wb_write(bus
, 0x4 >> 2, 0xF, 0xF)
109 yield from wb_write(bus
, 0x8 >> 2, 0x1, 0xF)
112 yield from wb_write(bus
, 0xC >> 2, 0x6, 0xF)
113 yield from wb_write(bus
, 0x10 >> 2, 0x1, 0xF)
114 yield from wb_write(bus
, 0x4 >> 2, 0xF, 0xF)
115 yield from wb_write(bus
, 0x8 >> 2, 0x1, 0xF)
118 yield from wb_write(bus
, 0xC >> 2, 0x320, 0xF)
119 yield from wb_write(bus
, 0x10 >> 2, 0x0, 0xF)
120 yield from wb_write(bus
, 0x4 >> 2, 0xF, 0xF)
121 yield from wb_write(bus
, 0x8 >> 2, 0x1, 0xF)
126 yield from wb_write(bus
, 0xC >> 2, 0x400, 0xF)
127 yield from wb_write(bus
, 0x10 >> 2, 0x0, 0xF)
128 yield from wb_write(bus
, 0x4 >> 2, 0x3, 0xF)
129 yield from wb_write(bus
, 0x8 >> 2, 0x1, 0xF)
133 yield from wb_write(bus
, 0, 0x1, 0xF)
134 for i
in range(2000):
137 def test_multiple_reads(self
):
139 soc
= DDR3SoC(clk_freq
=100e6
,
140 dramcore_addr
=0x00000000,
145 yield from SocTestCase
.init_seq(soc
.bus
)
147 yield from wb_write(soc
.bus
, 0x10000000 >> 2, 0xACAB2020, 0xF, 128)
150 # Check for data persistence
152 res
= yield from wb_read(soc
.bus
, 0x10000000 >> 2, 0xF, 128)
154 self
.assertEqual(res
, 0xACAB2020)
156 runSimulation(m
, process
, "test_soc_multiple_reads.vcd")
158 def test_interleaved_read_write(self
):
160 soc
= DDR3SoC(clk_freq
=100e6
,
161 dramcore_addr
=0x00000000,
166 yield from SocTestCase
.init_seq(soc
.bus
)
168 yield from wb_write(soc
.bus
, 0x10000000 >> 2, 0xF00DFACE, 0xF, 128)
169 yield from wb_write(soc
.bus
, 0x10000004 >> 2, 0x12345678, 0xF, 128)
170 yield from wb_write(soc
.bus
, 0x10000008 >> 2, 0x00BA0BAB, 0xF, 128)
172 res
= yield from wb_read(soc
.bus
, 0x10000000 >> 2, 0xF, 128)
173 self
.assertEqual(res
, 0xF00DFACE)
175 yield from wb_write(soc
.bus
, 0x10000008 >> 2, 0xCAFE1000, 0xF, 128)
177 res
= yield from wb_read(soc
.bus
, 0x10000004 >> 2, 0xF, 128)
178 self
.assertEqual(res
, 0x12345678)
180 res
= yield from wb_read(soc
.bus
, 0x10000008 >> 2, 0xF, 128)
181 self
.assertEqual(res
, 0xCAFE1000)
183 runSimulation(m
, process
, "test_soc_interleaved_read_write.vcd")
185 def test_sequential_reads(self
):
187 soc
= DDR3SoC(clk_freq
=100e6
,
188 dramcore_addr
=0x00000000,
193 yield from SocTestCase
.init_seq(soc
.bus
)
195 # Should read from same row/col/bank
196 yield from wb_read(soc
.bus
, 0x10000000 >> 2, 0xF, 128)
197 yield from wb_read(soc
.bus
, 0x10000004 >> 2, 0xF, 128)
198 yield from wb_read(soc
.bus
, 0x10000008 >> 2, 0xF, 128)
199 yield from wb_read(soc
.bus
, 0x1000000C >> 2, 0xF, 128)
201 # Should read from a different row
202 yield from wb_read(soc
.bus
, 0x10000010 >> 2, 0xF, 128)
203 yield from wb_read(soc
.bus
, 0x10000014 >> 2, 0xF, 128)
204 yield from wb_read(soc
.bus
, 0x10000018 >> 2, 0xF, 128)
205 yield from wb_read(soc
.bus
, 0x1000001C >> 2, 0xF, 128)
207 runSimulation(m
, process
, "test_soc_sequential_reads.vcd")
209 def test_random_memtest(self
):
211 soc
= DDR3SoC(clk_freq
=100e6
,
212 dramcore_addr
=0x00000000,
217 yield from SocTestCase
.init_seq(soc
.bus
)
223 memtest_values
.append(random
.randint(0, 0xFFFFFFFF))
227 yield from wb_write(soc
.bus
, (0x10000000 >> 2) + i
, memtest_values
[i
], 0xF, 256)
231 self
.assertEqual(memtest_values
[i
], (yield from wb_read(soc
.bus
, (0x10000000 >> 2) + i
, 0xF, 256)))
233 runSimulation(m
, process
, "test_soc_random_memtest.vcd")
235 def test_continuous_memtest(self
):
237 soc
= DDR3SoC(clk_freq
=100e6
,
238 dramcore_addr
=0x00000000,
243 yield from SocTestCase
.init_seq(soc
.bus
)
249 yield from wb_write(soc
.bus
, (0x10000000 >> 2) + i
, 0xFACE0000 | i
, 0xF, 256)
253 self
.assertEqual(0xFACE0000 | i
, (yield from wb_read(soc
.bus
, (0x10000000 >> 2) + i
, 0xF, 256)))
255 runSimulation(m
, process
, "test_soc_continuous_memtest.vcd")