1 # nmigen: UnusedElaboratable=no
3 from nmigen
.hdl
import *
4 from nmigen
.sim
import *
5 from nmigen
.lib
.cdc
import *
10 class FFSynchronizerTestCase(FHDLTestCase
):
11 def test_stages_wrong(self
):
12 with self
.assertRaisesRegex(TypeError,
13 r
"^Synchronization stage count must be a positive integer, not 0$"):
14 FFSynchronizer(Signal(), Signal(), stages
=0)
15 with self
.assertRaisesRegex(ValueError,
16 r
"^Synchronization stage count may not safely be less than 2$"):
17 FFSynchronizer(Signal(), Signal(), stages
=1)
22 frag
= FFSynchronizer(i
, o
)
27 self
.assertEqual((yield o
), 0)
30 self
.assertEqual((yield o
), 0)
32 self
.assertEqual((yield o
), 0)
34 self
.assertEqual((yield o
), 1)
35 sim
.add_process(process
)
38 def test_reset_value(self
):
41 frag
= FFSynchronizer(i
, o
, reset
=1)
46 self
.assertEqual((yield o
), 1)
49 self
.assertEqual((yield o
), 1)
51 self
.assertEqual((yield o
), 1)
53 self
.assertEqual((yield o
), 0)
54 sim
.add_process(process
)
58 class AsyncFFSynchronizerTestCase(FHDLTestCase
):
59 def test_stages_wrong(self
):
60 with self
.assertRaisesRegex(TypeError,
61 r
"^Synchronization stage count must be a positive integer, not 0$"):
62 ResetSynchronizer(Signal(), stages
=0)
63 with self
.assertRaisesRegex(ValueError,
64 r
"^Synchronization stage count may not safely be less than 2$"):
65 ResetSynchronizer(Signal(), stages
=1)
67 def test_edge_wrong(self
):
68 with self
.assertRaisesRegex(ValueError,
69 r
"^AsyncFFSynchronizer async edge must be one of 'pos' or 'neg', not 'xxx'$"):
70 AsyncFFSynchronizer(Signal(), Signal(), o_domain
="sync", async_edge
="xxx")
72 def test_pos_edge(self
):
76 m
.domains
+= ClockDomain("sync")
77 m
.submodules
+= AsyncFFSynchronizer(i
, o
)
83 self
.assertEqual((yield i
), 0)
84 self
.assertEqual((yield o
), 1)
85 yield Tick(); yield Delay(1e-8)
86 self
.assertEqual((yield o
), 1)
87 yield Tick(); yield Delay(1e-8)
88 self
.assertEqual((yield o
), 0)
89 yield Tick(); yield Delay(1e-8)
90 self
.assertEqual((yield o
), 0)
91 yield Tick(); yield Delay(1e-8)
95 self
.assertEqual((yield o
), 1)
96 yield Tick(); yield Delay(1e-8)
97 self
.assertEqual((yield o
), 1)
99 yield Tick(); yield Delay(1e-8)
100 self
.assertEqual((yield o
), 1)
101 yield Tick(); yield Delay(1e-8)
102 self
.assertEqual((yield o
), 0)
103 yield Tick(); yield Delay(1e-8)
104 self
.assertEqual((yield o
), 0)
105 yield Tick(); yield Delay(1e-8)
106 sim
.add_process(process
)
107 with sim
.write_vcd("test.vcd"):
110 def test_neg_edge(self
):
114 m
.domains
+= ClockDomain("sync")
115 m
.submodules
+= AsyncFFSynchronizer(i
, o
, async_edge
="neg")
121 self
.assertEqual((yield i
), 1)
122 self
.assertEqual((yield o
), 1)
123 yield Tick(); yield Delay(1e-8)
124 self
.assertEqual((yield o
), 1)
125 yield Tick(); yield Delay(1e-8)
126 self
.assertEqual((yield o
), 0)
127 yield Tick(); yield Delay(1e-8)
128 self
.assertEqual((yield o
), 0)
129 yield Tick(); yield Delay(1e-8)
133 self
.assertEqual((yield o
), 1)
134 yield Tick(); yield Delay(1e-8)
135 self
.assertEqual((yield o
), 1)
137 yield Tick(); yield Delay(1e-8)
138 self
.assertEqual((yield o
), 1)
139 yield Tick(); yield Delay(1e-8)
140 self
.assertEqual((yield o
), 0)
141 yield Tick(); yield Delay(1e-8)
142 self
.assertEqual((yield o
), 0)
143 yield Tick(); yield Delay(1e-8)
144 sim
.add_process(process
)
145 with sim
.write_vcd("test.vcd"):
149 class ResetSynchronizerTestCase(FHDLTestCase
):
150 def test_stages_wrong(self
):
151 with self
.assertRaisesRegex(TypeError,
152 r
"^Synchronization stage count must be a positive integer, not 0$"):
153 ResetSynchronizer(Signal(), stages
=0)
154 with self
.assertRaisesRegex(ValueError,
155 r
"^Synchronization stage count may not safely be less than 2$"):
156 ResetSynchronizer(Signal(), stages
=1)
158 def test_basic(self
):
161 m
.domains
+= ClockDomain("sync")
162 m
.submodules
+= ResetSynchronizer(arst
)
170 self
.assertEqual((yield s
), 1)
171 yield Tick(); yield Delay(1e-8)
172 self
.assertEqual((yield s
), 1)
173 yield Tick(); yield Delay(1e-8)
174 self
.assertEqual((yield s
), 1)
175 yield Tick(); yield Delay(1e-8)
176 self
.assertEqual((yield s
), 0)
177 yield Tick(); yield Delay(1e-8)
181 self
.assertEqual((yield s
), 0)
182 yield Tick(); yield Delay(1e-8)
183 self
.assertEqual((yield s
), 1)
185 yield Tick(); yield Delay(1e-8)
186 self
.assertEqual((yield s
), 1)
187 yield Tick(); yield Delay(1e-8)
188 self
.assertEqual((yield s
), 1)
189 yield Tick(); yield Delay(1e-8)
190 self
.assertEqual((yield s
), 0)
191 yield Tick(); yield Delay(1e-8)
192 sim
.add_process(process
)
193 with sim
.write_vcd("test.vcd"):
197 # TODO: test with distinct clocks
198 class PulseSynchronizerTestCase(FHDLTestCase
):
199 def test_stages_wrong(self
):
200 with self
.assertRaisesRegex(TypeError,
201 r
"^Synchronization stage count must be a positive integer, not 0$"):
202 PulseSynchronizer("w", "r", stages
=0)
203 with self
.assertRaisesRegex(ValueError,
204 r
"^Synchronization stage count may not safely be less than 2$"):
205 PulseSynchronizer("w", "r", stages
=1)
207 def test_smoke(self
):
209 m
.domains
+= ClockDomain("sync")
210 ps
= m
.submodules
.dut
= PulseSynchronizer("sync", "sync")
216 # TODO: think about reset
219 # Make sure no pulses are generated in quiescent state
222 self
.assertEqual((yield ps
.o
), 0)
223 # Check conservation of pulses
226 yield ps
.i
.eq(1 if n
< 4 else 0)
229 self
.assertEqual(accum
, 4)
230 sim
.add_process(process
)