-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
counter.py
119 lines (97 loc) · 3.03 KB
/
counter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
from amaranth import *
from amaranth.sim import *
from amaranth.lib import wiring
from amaranth.lib.wiring import In, Out
from edge_detect import EdgeDetector
class Counter(wiring.Component):
input: In(1)
latch: In(1)
enable: In(1)
def __init__(self, bits=16, rising=True, falling=False):
self.rising = rising
self.falling = falling
self.bits = bits
self.count = Signal(unsigned(bits))
self.count_latched = Signal(unsigned(bits))
super().__init__()
def elaborate(self, platform):
m = Module()
m.submodules.ed = ed = EdgeDetector()
m.d.comb += ed.i.eq(self.input)
with m.If(self.enable == 1):
if self.rising == True:
with m.If(ed.rose == 1):
m.d.sync += self.count.eq(self.count + 1)
if self.falling == True:
with m.If(ed.fell == 1):
m.d.sync += self.count.eq(self.count + 1)
with m.If(self.latch == 1):
m.d.sync += self.count_latched.eq(self.count)
return m
class CounterSync(Elaboratable):
def __init__(self, name, bits):
self.bits = bits
self.counter = Counter(bits=self.bits)
self.counter_s = Signal.like(self.counter.count)
self.counter_ffs = FFSynchronizer(self.counter.count, self.counter_s,
o_domain="sync")
def connect(self, _input, latch, enable, output, latched_output):
return [
self.counter.input.eq(_input),
self.counter.enable.eq(_enable),
counter.latch.eq(latch),
output.eq(counter_s),
latched_output.eq(counter.count_latched),
]
def elaborate(self, platform):
m = Module()
m.submodules["counter_"+name] = self.counter
m.submodules["counter_ffs_"+name] = self.counter_ffs
return m
if __name__ == '__main__':
dut = Counter()
sim = Simulator(dut)
def strobe():
yield dut.input.eq(1)
yield
yield dut.input.eq(0)
yield
def proc():
assert((yield dut.count) == 0)
yield
yield
yield
yield dut.input.eq(1)
yield
yield
assert((yield dut.count) == 0)
yield dut.input.eq(0)
yield
yield
assert((yield dut.count) == 0)
yield
yield dut.enable.eq(1)
yield
yield
yield
yield dut.input.eq(1)
yield
yield
assert((yield dut.count) == 1)
yield dut.input.eq(0)
yield
yield
assert((yield dut.count) == 1)
for i in range(10 * 2):
yield from strobe()
assert((yield dut.count) == 21)
assert((yield dut.count_latched) == 0)
yield dut.latch.eq(1)
yield
yield dut.latch.eq(0)
yield
assert((yield dut.count_latched) == 21)
sim.add_clock(1/12e6)
sim.add_sync_process(proc)
with sim.write_vcd('counter.vcd', 'counter.gtkw'):
sim.run()