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_width_wrong(self
):
73 with self
.assertRaisesRegex(ValueError,
74 r
"^AsyncFFSynchronizer input width must be 1, not 2$"):
75 AsyncFFSynchronizer(Signal(2), Signal(), o_domain
="sync")
76 with self
.assertRaisesRegex(ValueError,
77 r
"^AsyncFFSynchronizer output width must be 1, not 2$"):
78 AsyncFFSynchronizer(Signal(), Signal(2), o_domain
="sync")
80 def test_pos_edge(self
):
84 m
.domains
+= ClockDomain("sync")
85 m
.submodules
+= AsyncFFSynchronizer(i
, o
)
91 self
.assertEqual((yield i
), 0)
92 self
.assertEqual((yield o
), 1)
93 yield Tick(); yield Delay(1e-8)
94 self
.assertEqual((yield o
), 1)
95 yield Tick(); yield Delay(1e-8)
96 self
.assertEqual((yield o
), 0)
97 yield Tick(); yield Delay(1e-8)
98 self
.assertEqual((yield o
), 0)
99 yield Tick(); yield Delay(1e-8)
103 self
.assertEqual((yield o
), 1)
104 yield Tick(); yield Delay(1e-8)
105 self
.assertEqual((yield o
), 1)
107 yield Tick(); yield Delay(1e-8)
108 self
.assertEqual((yield o
), 1)
109 yield Tick(); yield Delay(1e-8)
110 self
.assertEqual((yield o
), 0)
111 yield Tick(); yield Delay(1e-8)
112 self
.assertEqual((yield o
), 0)
113 yield Tick(); yield Delay(1e-8)
114 sim
.add_process(process
)
115 with sim
.write_vcd("test.vcd"):
118 def test_neg_edge(self
):
122 m
.domains
+= ClockDomain("sync")
123 m
.submodules
+= AsyncFFSynchronizer(i
, o
, async_edge
="neg")
129 self
.assertEqual((yield i
), 1)
130 self
.assertEqual((yield o
), 1)
131 yield Tick(); yield Delay(1e-8)
132 self
.assertEqual((yield o
), 1)
133 yield Tick(); yield Delay(1e-8)
134 self
.assertEqual((yield o
), 0)
135 yield Tick(); yield Delay(1e-8)
136 self
.assertEqual((yield o
), 0)
137 yield Tick(); yield Delay(1e-8)
141 self
.assertEqual((yield o
), 1)
142 yield Tick(); yield Delay(1e-8)
143 self
.assertEqual((yield o
), 1)
145 yield Tick(); yield Delay(1e-8)
146 self
.assertEqual((yield o
), 1)
147 yield Tick(); yield Delay(1e-8)
148 self
.assertEqual((yield o
), 0)
149 yield Tick(); yield Delay(1e-8)
150 self
.assertEqual((yield o
), 0)
151 yield Tick(); yield Delay(1e-8)
152 sim
.add_process(process
)
153 with sim
.write_vcd("test.vcd"):
157 class ResetSynchronizerTestCase(FHDLTestCase
):
158 def test_stages_wrong(self
):
159 with self
.assertRaisesRegex(TypeError,
160 r
"^Synchronization stage count must be a positive integer, not 0$"):
161 ResetSynchronizer(Signal(), stages
=0)
162 with self
.assertRaisesRegex(ValueError,
163 r
"^Synchronization stage count may not safely be less than 2$"):
164 ResetSynchronizer(Signal(), stages
=1)
166 def test_basic(self
):
169 m
.domains
+= ClockDomain("sync")
170 m
.submodules
+= ResetSynchronizer(arst
)
178 self
.assertEqual((yield s
), 1)
179 yield Tick(); yield Delay(1e-8)
180 self
.assertEqual((yield s
), 1)
181 yield Tick(); yield Delay(1e-8)
182 self
.assertEqual((yield s
), 1)
183 yield Tick(); yield Delay(1e-8)
184 self
.assertEqual((yield s
), 0)
185 yield Tick(); yield Delay(1e-8)
189 self
.assertEqual((yield s
), 0)
190 yield Tick(); yield Delay(1e-8)
191 self
.assertEqual((yield s
), 1)
193 yield Tick(); yield Delay(1e-8)
194 self
.assertEqual((yield s
), 1)
195 yield Tick(); yield Delay(1e-8)
196 self
.assertEqual((yield s
), 1)
197 yield Tick(); yield Delay(1e-8)
198 self
.assertEqual((yield s
), 0)
199 yield Tick(); yield Delay(1e-8)
200 sim
.add_process(process
)
201 with sim
.write_vcd("test.vcd"):
205 # TODO: test with distinct clocks
206 class PulseSynchronizerTestCase(FHDLTestCase
):
207 def test_stages_wrong(self
):
208 with self
.assertRaisesRegex(TypeError,
209 r
"^Synchronization stage count must be a positive integer, not 0$"):
210 PulseSynchronizer("w", "r", stages
=0)
211 with self
.assertRaisesRegex(ValueError,
212 r
"^Synchronization stage count may not safely be less than 2$"):
213 PulseSynchronizer("w", "r", stages
=1)
215 def test_smoke(self
):
217 m
.domains
+= ClockDomain("sync")
218 ps
= m
.submodules
.dut
= PulseSynchronizer("sync", "sync")
224 # TODO: think about reset
227 # Make sure no pulses are generated in quiescent state
230 self
.assertEqual((yield ps
.o
), 0)
231 # Check conservation of pulses
234 yield ps
.i
.eq(1 if n
< 4 else 0)
237 self
.assertEqual(accum
, 4)
238 sim
.add_process(process
)