Skip to content

Commit f64d8d7

Browse files
committed
serial: fix RX logic on continuous bytes; fix reversed data in RX tests
1 parent bdd32d7 commit f64d8d7

2 files changed

Lines changed: 33 additions & 38 deletions

File tree

nmigen_stdio/serial.py

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def __init__(self, *, divisor, divisor_bits=None, data_bits=8, parity="none", pi
6363

6464
self.timer = Signal.like(self.divisor)
6565
self.shreg = Record(_wire_layout(len(self.data), self._parity))
66-
self.bits_left = Signal(range(len(self.shreg) + 1))
66+
self.bits_left = Signal(range(len(self.shreg)))
6767
self.done = Signal()
6868

6969
def elaborate(self, platform):
@@ -81,26 +81,26 @@ def elaborate(self, platform):
8181
with m.State("IDLE"):
8282
with m.If(~self.i):
8383
m.d.sync += [
84-
bits_left.eq(len(shreg)),
84+
bits_left.eq(len(shreg) - 1),
8585
timer.eq(self.divisor >> 1)
8686
]
8787
m.next = "BUSY"
8888

8989
with m.State("BUSY"):
9090
with m.If(timer != 0):
9191
m.d.sync += timer.eq(timer - 1)
92-
with m.If(((timer == 0) & (bits_left != 1)) | ((timer == 1) & (bits_left == 1))):
92+
with m.Else():
9393
m.d.sync += [
9494
shreg.eq(Cat(shreg[1:], self.i)),
95-
bits_left.eq(bits_left - 1)
95+
bits_left.eq(bits_left - 1),
96+
timer.eq(self.divisor)
9697
]
97-
with m.If(bits_left != 1):
98-
m.d.sync += timer.eq(self.divisor)
99-
with m.Else():
98+
with m.If(((self.divisor != 0) & (bits_left == 0)) |
99+
((self.divisor == 0) & (bits_left == 1))):
100100
m.next = "DONE"
101101

102102
with m.State("DONE"):
103-
with m.If(~done & (timer == 0)):
103+
with m.If(timer == self.divisor):
104104
with m.If(self.ack):
105105
m.d.sync += [
106106
self.data.eq(shreg.data),
@@ -109,34 +109,27 @@ def elaborate(self, platform):
109109
_compute_parity_bit(shreg.data, self._parity)))
110110
]
111111
m.d.sync += [
112-
self.err.overflow.eq(~self.ack)
113-
]
114-
# At second clock edge for DONE,
115-
# timer is set as divisor
116-
m.d.sync += [
117-
timer.eq(self.divisor),
118-
done.eq(1)
112+
self.err.overflow.eq(~self.ack),
113+
self.r_rdy.eq(1)
119114
]
120-
# Continue the timer to receive one more bit
121-
# Set back to IDLE if it is still stop bit
122115
with m.If(timer != 0):
123116
m.d.sync += timer.eq(timer - 1)
124-
with m.Elif(done):
125-
m.d.sync += done.eq(0)
117+
with m.Else():
118+
# Check if this next bit is start bit
119+
# (useful for divisor == 0)
126120
with m.If(~self.i):
127121
m.d.sync += [
128122
shreg.eq(Cat(shreg[1:], self.i)),
129-
bits_left.eq(len(shreg)),
123+
bits_left.eq(len(shreg) - 2),
130124
timer.eq(self.divisor)
131125
]
132126
m.next = "BUSY"
133127
with m.Else():
134128
m.next = "IDLE"
135129

136-
m.d.comb += [
137-
self.r_rdy.eq(fsm.ongoing("DONE") & done),
138-
self.busy.eq(fsm.ongoing("BUSY"))
139-
]
130+
m.d.comb += self.busy.eq(fsm.ongoing("BUSY"))
131+
with m.If(self.r_rdy):
132+
m.d.sync += self.r_rdy.eq(0)
140133

141134
return m
142135

nmigen_stdio/test/test_serial.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ def simulation_test(dut, process):
1717
sim.run()
1818

1919

20+
# TODO: Add test cases for continuous RX
2021
class AsyncSerialRXTestCase(unittest.TestCase):
2122
def tx_period(self):
2223
for _ in range((yield self.dut.divisor) + 1):
@@ -29,10 +30,10 @@ def tx_bits(self, bits):
2930

3031
def rx_test(self, bits, *, data=None, errors=None):
3132
def process():
32-
self.assertFalse((yield self.dut.rdy))
33+
self.assertFalse((yield self.dut.r_rdy))
3334
yield self.dut.ack.eq(1)
3435
yield from self.tx_bits(bits)
35-
while not (yield self.dut.rdy):
36+
while not (yield self.dut.r_rdy):
3637
yield
3738
if data is not None:
3839
self.assertFalse((yield self.dut.err))
@@ -45,35 +46,35 @@ def process():
4546

4647
def test_8n1(self):
4748
self.dut = AsyncSerialRX(divisor=7, data_bits=8, parity="none")
48-
self.rx_test([0, 1,0,1,0,1,1,1,0, 1], data=0b10101110)
49+
self.rx_test([0, 1,0,1,0,1,1,1,0, 1], data=0b01110101)
4950

5051
def test_16n1(self):
5152
self.dut = AsyncSerialRX(divisor=7, data_bits=16, parity="none")
5253
self.rx_test([0, 1,0,1,0,1,1,1,0,1,1,1,1,0,0,0,0, 1],
53-
data=0b1010111011110000)
54+
data=0b0000111101110101)
5455

5556
def test_8m1(self):
5657
self.dut = AsyncSerialRX(divisor=7, data_bits=8, parity="mark")
57-
self.rx_test([0, 1,0,1,0,1,1,1,0, 1, 1], data=0b10101110)
58-
self.rx_test([0, 1,0,1,0,1,1,0,0, 1, 1], data=0b10101100)
58+
self.rx_test([0, 1,0,1,0,1,1,1,0, 1, 1], data=0b01110101)
59+
self.rx_test([0, 1,0,1,0,1,1,0,0, 1, 1], data=0b00110101)
5960
self.rx_test([0, 1,0,1,0,1,1,1,0, 0, 1], errors={"parity"})
6061

6162
def test_8s1(self):
6263
self.dut = AsyncSerialRX(divisor=7, data_bits=8, parity="space")
63-
self.rx_test([0, 1,0,1,0,1,1,1,0, 0, 1], data=0b10101110)
64-
self.rx_test([0, 1,0,1,0,1,1,0,0, 0, 1], data=0b10101100)
64+
self.rx_test([0, 1,0,1,0,1,1,1,0, 0, 1], data=0b01110101)
65+
self.rx_test([0, 1,0,1,0,1,1,0,0, 0, 1], data=0b00110101)
6566
self.rx_test([0, 1,0,1,0,1,1,1,0, 1, 1], errors={"parity"})
6667

6768
def test_8e1(self):
6869
self.dut = AsyncSerialRX(divisor=7, data_bits=8, parity="even")
69-
self.rx_test([0, 1,0,1,0,1,1,1,0, 1, 1], data=0b10101110)
70-
self.rx_test([0, 1,0,1,0,1,1,0,0, 0, 1], data=0b10101100)
70+
self.rx_test([0, 1,0,1,0,1,1,1,0, 1, 1], data=0b01110101)
71+
self.rx_test([0, 1,0,1,0,1,1,0,0, 0, 1], data=0b00110101)
7172
self.rx_test([0, 1,0,1,0,1,1,1,0, 0, 1], errors={"parity"})
7273

7374
def test_8o1(self):
7475
self.dut = AsyncSerialRX(divisor=7, data_bits=8, parity="odd")
75-
self.rx_test([0, 1,0,1,0,1,1,1,0, 0, 1], data=0b10101110)
76-
self.rx_test([0, 1,0,1,0,1,1,0,0, 1, 1], data=0b10101100)
76+
self.rx_test([0, 1,0,1,0,1,1,1,0, 0, 1], data=0b01110101)
77+
self.rx_test([0, 1,0,1,0,1,1,0,0, 1, 1], data=0b00110101)
7778
self.rx_test([0, 1,0,1,0,1,1,1,0, 1, 1], errors={"parity"})
7879

7980
def test_err_frame(self):
@@ -84,15 +85,16 @@ def test_err_overflow(self):
8485
self.dut = AsyncSerialRX(divisor=7)
8586

8687
def process():
87-
self.assertFalse((yield self.dut.rdy))
88+
self.assertFalse((yield self.dut.r_rdy))
8889
yield from self.tx_bits([0, 0,0,0,0,0,0,0,0, 1])
8990
yield from self.tx_period()
90-
self.assertFalse((yield self.dut.rdy))
91+
self.assertFalse((yield self.dut.r_rdy))
9192
self.assertTrue((yield self.dut.err.overflow))
9293

9394
simulation_test(self.dut, process)
9495

9596

97+
# TODO: Add test cases for continuous TX
9698
class AsyncSerialTXTestCase(unittest.TestCase):
9799
def tx_period(self):
98100
for _ in range((yield self.dut.divisor) + 1):

0 commit comments

Comments
 (0)