-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuart_fifo.py
More file actions
119 lines (110 loc) · 4.93 KB
/
uart_fifo.py
File metadata and controls
119 lines (110 loc) · 4.93 KB
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
118
119
from nmigen import *
from nmigen.back import pysim, verilog
from nmigen.cli import main
from nmigen.lib.fifo import *
from nmigen_boards.icebreaker import ICEBreakerPlatform
from uart_wrapper_nmigen import UART
from uart_wrapper_sim import UART_SIM
class UART_FIFO(Elaboratable):
def __init__(self, sim, sim_tx_cycle_accurate, width, depth, clk, board_uart):
self.sim = sim
self.sim_tx_cycle_accurate = sim_tx_cycle_accurate
self.tx = Signal() # output from uart_fifo to host, fed by t_fifo
self.tx_active = Signal() # high while busy transmitting data
self.tx_done = Signal() # high for one cycle, after tx completed
self.rx = Signal() # input to uart_fifo from host, feeds r_fifo
# data coming into the fifo_uart from the host
# -- TODO use r_port record in the future
self.r_fifo_readable = Signal()
self.r_fifo_re = Signal()
self.r_fifo_dout = Signal(width)
# data leaving the fifo_uart to the host
# -- TODO use w_port record in the future
self.w_fifo_writable = Signal()
self.w_fifo_we = Signal()
self.w_fifo_din = Signal(width)
# internal
if not self.sim:
self.uart = UART(clk, board_uart)
else:
self.uart = UART_SIM()
self.r_fifo = SyncFIFOBuffered(width=width, depth=depth)
self.w_fifo = SyncFIFOBuffered(width=width, depth=depth)
def elaborate(self, platform):
m = Module()
# FIXME rm if
if self.uart:
m.submodules.uart = self.uart
m.submodules.r_fifo = self.r_fifo
m.submodules.w_fifo = self.w_fifo
# FIXME rm if
if self.uart:
m.d.comb += [
self.tx.eq(self.uart.tx),
self.rx.eq(self.uart.rx)
]
m.d.comb += [
# r_fifo, rd port
self.r_fifo_readable.eq(self.r_fifo.r_rdy),
self.r_fifo_re.eq(self.r_fifo.r_en),
self.r_fifo_dout.eq(self.r_fifo.r_data),
# w_fifo, wr port
self.w_fifo_writable.eq(self.w_fifo.w_rdy),
self.w_fifo_we.eq(self.w_fifo.w_en),
self.w_fifo_din.eq(self.w_fifo.w_data)
]
# host to device loop
with m.FSM(reset='AWAIT_UART_DATA') as fsm_rd_from_host:
with m.State('AWAIT_UART_DATA'):
# TODO send backpresure to host if r_fifo is close to full:
# [Use the fifo's .level signal to gauge 'close to full'
# and pause the sender ahead of the overrun!]
# Use SW flow control (send XOFF/XON)
# See https://pyserial.readthedocs.io/en/latest/pyserial_api.html
# and https://en.wikipedia.org/wiki/Software_flow_control
with m.If(self.uart.rx_rdy & self.r_fifo.w_rdy):
m.d.comb += [
self.r_fifo.w_data.eq(self.uart.rx_data),
self.r_fifo.w_en.eq(1)
]
m.next = 'AWAIT_UART_DATA' # LOOP
# device to host loop
with m.FSM(reset='AWAIT_FIFO_DATA') as fsm_wr_to_host:
with m.State('AWAIT_FIFO_DATA'):
# checks to see if uart is ready to transmit data
with m.If(self.w_fifo.r_rdy & ~self.uart.tx_active):
m.d.comb += [
self.uart.tx_data.eq(self.w_fifo.r_data),
self.uart.tx_rdy.eq(1),
]
# not needed in sim since we're reading from
# the w_fifo ourselves in the uart.py driver_proc.
if platform:
m.d.comb += [
# rd fifo (dequeue element)
self.w_fifo.r_en.eq(1)
]
if self.sim_tx_cycle_accurate:
m.d.comb += [
# rd fifo (dequeue element)
self.w_fifo.r_en.eq(1)
]
m.next = 'AWAIT_FIFO_DATA_COMPLETE'
with m.State('AWAIT_FIFO_DATA_COMPLETE'):
# wait until uart is done transmitting data
with m.If(self.uart.tx_done):
m.next = 'AWAIT_FIFO_DATA'
return m
#
# +--------------------+
# | (rd port) | w_fifo_writable
# | fsm_wr_to_host | user (wr port) w_fifo_we
# | | | | w_fifo_din
# (host) tx <- uart(tx) <------ w_fifo <- device
# (host) rx -> uart(rx) ------> r_fifo -> device
# | | | | r_fifo_readable
# | fsm_rd_from_host | user (rd port) r_fifo_re
# | | | r_fifo_dout
# | (wr port) |
# +--------------------+
#