-
Notifications
You must be signed in to change notification settings - Fork 0
/
uart_wrapper_sim.py
84 lines (78 loc) · 2.68 KB
/
uart_wrapper_sim.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
from nmigen import *
class Counter(Elaboratable):
def __init__(self, rr):
ndigits,_ = rr.shape()
self.rr = rr
self.start = Signal()
self.inc = Signal()
self.v = Signal(ndigits)
self.o = Signal()
self.done = Signal()
def elaborate(self, platform):
m = Module()
with m.If(self.start):
m.d.sync += self.v.eq(0)
with m.Else():
with m.If(self.v == self.rr):
m.d.comb += [
self.o.eq(1),
self.done.eq(1)
]
m.d.sync += [
self.v.eq(0)
]
with m.Else():
m.d.sync += self.v.eq(self.v + 1)
return m
class UART_SIM(Elaboratable):
def __init__(self):
self.tx = Signal()
self.tx_active = Signal()
self.tx_done = Signal()
self.tx_data = Signal(8)
self.tx_rdy = Signal() # was nandland tx_dv
self.rx = Signal()
self.rx_data = Signal(8)
self.rx_rdy = Signal() # was nandland rx_dv
# FIXME: make 104 configurable
self.cnt = Counter(Const(104)) # floor(12MHz / 115200) = 104
def elaborate(self, platform):
m = Module()
m.submodules.cnt = self.cnt
# simulate tx somewhat realistically in term of
# active and done signals, which are needed
# for proper flow control with sending
# elements.
# Note: to precisely mimic NANDLANDs uart_tx, we
# lower tx_active and only then stobe tx_done.
#
# after tx_rdy, assert active for N cycles, and
# strobe done for 1 cycle thereafter.
#
with m.FSM(reset='TX_AWAIT_START') as fsm:
with m.State('TX_AWAIT_START'):
with m.If(self.tx_rdy):
m.d.comb += [
self.cnt.start.eq(1)
]
m.d.sync += [
self.tx_active.eq(1) # assert tx_active
]
m.next = 'TX_SEND_ACTIVE'
with m.State('TX_SEND_ACTIVE'):
with m.If(~self.cnt.done):
m.d.comb += [
self.cnt.inc.eq(1),
]
m.next = 'TX_SEND_ACTIVE'
with m.Else():
m.d.sync += [
self.tx_active.eq(0)
]
m.next = 'TX_DONE'
with m.State('TX_DONE'):
m.d.comb += [
self.tx_done.eq(1) # strobe
]
m.next = 'TX_AWAIT_START'
return m