Skip to content

Commit cdd22c0

Browse files
committed
updated tests
1 parent bbe219f commit cdd22c0

File tree

1 file changed

+123
-27
lines changed

1 file changed

+123
-27
lines changed

test/test_uart.py

Lines changed: 123 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
from cocotb.clock import Clock
66
import random
77

8+
NUM_TESTS = 100
9+
BAUD_MAX_PERCENT = 2
810

911
@cocotb.test(timeout_time=50, timeout_unit='ms')
1012
async def transmit(dut):
@@ -16,12 +18,12 @@ async def transmit(dut):
1618
await check_tx_reset(dut)
1719

1820
# carry out 100 transmissions
19-
for count in range(100):
21+
for count in range(NUM_TESTS):
2022
# randomized payload
2123
TEST_BYTE = random.randint(0,255)
2224

2325
# randomized baud multiplier (+/- 2%)
24-
baud_mult = 1.0 + (random.random() - 0.5) / 50 * 2
26+
baud_mult = 1.0 + (random.random() - 0.5) / 50 * BAUD_MAX_PERCENT
2527

2628
await check_tx(dut, TEST_BYTE, 115200, baud_mult)
2729

@@ -30,7 +32,7 @@ async def transmit(dut):
3032
await Timer(random.randint(1,2000), units='ns')
3133

3234

33-
@cocotb.test(timeout_time=50, timeout_unit='ms')
35+
@cocotb.test(timeout_time=10, timeout_unit='ms')
3436
async def receive1(dut):
3537
"""RX with randomized payload / clock frequency shift / inter-TX delay."""
3638

@@ -41,34 +43,34 @@ async def receive1(dut):
4143
await check_rx_reset(dut)
4244

4345
# run 100 randomized tests
44-
for count in range(100):
46+
for count in range(NUM_TESTS):
4547
# randomized payload
4648
TEST_BYTE = random.randint(0,255)
4749

4850
# randomized baud multiplier (+/- 2%)
49-
baud_mult = 1.0 + (random.random() - 0.5) / 50 * 2
51+
baud_mult = 1.0 + (random.random() - 0.5) / 50 * BAUD_MAX_PERCENT
5052

5153
await check_rx(dut, TEST_BYTE, 115200, baud_mult)
5254

5355
# randomized delay
5456
await Timer(random.randint(500,2000), units='ns')
5557

5658

57-
@cocotb.test(timeout_time=50, timeout_unit='ms')
59+
#@cocotb.test(timeout_time=50, timeout_unit='ms')
5860
async def receive2(dut):
5961
"""Continuous RX with randomized payload."""
6062

6163
# 50 Mhz clock
6264
cocotb.start_soon(Clock(dut.clk, 20, units='ns').start())
6365

6466
# reset
65-
await check_tx_reset(dut)
67+
await check_rx_reset(dut)
6668

6769
# run 100 randomized tests
68-
for count in range(100):
70+
for count in range(NUM_TESTS):
6971
# randomized payload
7072
TEST_BYTE = random.randint(0,255)
71-
await check_rx(dut, TEST_BYTE, 115200, 1.0)
73+
await check_rx_concurrent(dut, TEST_BYTE, 115200, 1.0)
7274

7375

7476
@cocotb.test(timeout_time=50, timeout_unit='ms')
@@ -79,28 +81,97 @@ async def receive3(dut):
7981
cocotb.start_soon(Clock(dut.clk, 20, units='ns').start())
8082

8183
# reset
82-
await check_tx_reset(dut)
84+
await check_rx_reset(dut)
8385

8486
# run 100 randomized tests
85-
for count in range(100):
87+
for count in range(NUM_TESTS):
8688
# randomized payload
8789
TEST_BYTE = random.randint(0,255)
8890

8991
# randomized baud multiplier (+/- 2%)
90-
baud_mult = 1.0 + (random.random() - 0.5) / 50 * 2
92+
baud_mult = 1.0 + (random.random() - 0.5) / 50 * BAUD_MAX_PERCENT
9193

92-
await check_rx(dut, TEST_BYTE, 115200, baud_mult)
94+
await check_rx_concurrent(dut, TEST_BYTE, 115200, baud_mult)
9395

9496

9597
@cocotb.test(timeout_time=50, timeout_unit='ms')
9698
async def receive4(dut):
97-
"""RX overrun."""
99+
"""RX frame error (start bit)."""
98100

99101
# 50 Mhz clock
100102
cocotb.start_soon(Clock(dut.clk, 20, units='ns').start())
101103

102104
# reset
103-
await check_tx_reset(dut)
105+
await check_rx_reset(dut)
106+
107+
# keep RX ready high
108+
dut.rx_ready.value = 1
109+
110+
# run 100 randomized tests
111+
for count in range(NUM_TESTS):
112+
# prepare random test data
113+
TEST_BYTE = random.randint(0,255)
114+
TEST_BITS_LSB = [(TEST_BYTE >> s) & 1 for s in range(8)]
115+
116+
# malformed (short) start bit
117+
dut.uart_rx.value = 0
118+
await Timer(int(1 / 115200. / 16 * 4 * 1e12), units="ps")
119+
dut.uart_rx.value = 1
120+
await Timer(int(1 / 115200. / 16 * 12 * 1e12), units="ps")
121+
122+
# send start bit (0), 8 data bits, no stop bit
123+
for tx_bit in TEST_BITS_LSB + [1]:
124+
dut.uart_rx.value = tx_bit
125+
await Timer(int(1 / 115200. * 1e12), units="ps")
126+
127+
# set RX to 0 (instead of the stop bit)
128+
dut.uart_rx.value = 0
129+
130+
await Edge(dut.rx_error)
131+
assert dut.rx_error.value == 1
132+
assert dut.rx_valid.value == 0
133+
134+
135+
@cocotb.test(timeout_time=50, timeout_unit='ms')
136+
async def receive5(dut):
137+
"""RX frame error (stop bit)."""
138+
139+
# 50 Mhz clock
140+
cocotb.start_soon(Clock(dut.clk, 20, units='ns').start())
141+
142+
# reset
143+
await check_rx_reset(dut)
144+
145+
# keep RX ready high
146+
dut.rx_ready.value = 1
147+
148+
# run 100 randomized tests
149+
for count in range(NUM_TESTS):
150+
# prepare random test data
151+
TEST_BYTE = random.randint(0,255)
152+
TEST_BITS_LSB = [(TEST_BYTE >> s) & 1 for s in range(8)]
153+
154+
# send start bit (0), 8 data bits, no stop bit
155+
for tx_bit in [0] + TEST_BITS_LSB:
156+
dut.uart_rx.value = tx_bit
157+
await Timer(int(1 / 115200. * 1e12), units="ps")
158+
159+
# set RX to 0 (instead of the stop bit)
160+
dut.uart_rx.value = 0
161+
162+
await Edge(dut.rx_error)
163+
assert dut.rx_error.value == 1
164+
assert dut.rx_valid.value == 0
165+
166+
@cocotb.test(timeout_time=50, timeout_unit='ms')
167+
async def receive6(dut):
168+
"""RX overrun error."""
169+
170+
# 50 Mhz clock
171+
cocotb.start_soon(Clock(dut.clk, 20, units='ns').start())
172+
173+
# reset
174+
await check_rx_reset(dut)
104175

105176
# set RX ready low, and keep it low...
106177
dut.rx_ready.value = 0
@@ -128,15 +199,14 @@ async def receive4(dut):
128199
assert dut.rx_overrun.value == 1
129200

130201

131-
132202
# --- HELPER FUNCTIONS ---
133203

134204
async def check_tx_reset(dut):
135205
# reset
136206
dut.tx_reset.value = 1
137-
await Timer(1, units="ms")
207+
await Timer(10, units="us")
138208
dut.tx_reset.value = 0
139-
await Timer(1, units="ms")
209+
await Timer(10, units="us")
140210

141211
assert dut.tx_ready.value == 1
142212

@@ -145,11 +215,14 @@ async def check_rx_reset(dut):
145215
# drive input high
146216
dut.uart_rx.value = 1
147217

218+
# drive RX ready low
219+
dut.rx_ready.value = 0
220+
148221
# reset
149222
dut.rx_reset.value = 1
150-
await Timer(1, units="ms")
223+
await Timer(10, units="us")
151224
dut.rx_reset.value = 0
152-
await Timer(1, units="ms")
225+
await Timer(10, units="us")
153226

154227
assert dut.rx_valid.value == 0
155228
assert dut.rx_error.value == 0
@@ -166,7 +239,7 @@ async def check_tx(dut, data, baud, baud_mult):
166239

167240
# set data value and then start TX
168241
dut.tx_data.value = data
169-
await Timer(random.randint(100, 500), units="ns")
242+
#await Timer(random.randint(100, 500), units="ns")
170243
dut.tx_valid.value = 1
171244

172245
# wait for TX->0 transition, check TX=0 and ready=0
@@ -190,9 +263,6 @@ async def check_tx(dut, data, baud, baud_mult):
190263

191264
async def check_rx(dut, data, baud, baud_mult):
192265
dut.rx_ready.value = 0
193-
194-
# random delay
195-
await Timer(100 + random.randint(100, 500), units="ns")
196266
assert dut.rx_valid.value == 0
197267

198268
# prepare random test data
@@ -203,18 +273,44 @@ async def check_rx(dut, data, baud, baud_mult):
203273
dut.uart_rx.value = tx_bit
204274
await Timer(int(1 / baud * baud_mult * 1e12), units="ps")
205275

206-
# random delay
207-
await Timer(100 + random.randint(100, 500), units="ns")
276+
# did we receive a byte?
208277
assert dut.rx_valid.value == 1
209278

279+
# pulse RX ready to fetch data
210280
dut.rx_ready.value = 1
211-
212281
# wait for valid transition
213282
await Edge(dut.rx_valid)
214283
assert dut.rx_valid.value == 0
284+
dut.rx_ready.value = 0
215285

216286
# check payload and valid/error/overflow flags
217287
assert dut.rx_data.value == data
218288
assert dut.rx_error.value == 0
219289
assert dut.rx_overrun.value == 0
220290

291+
292+
async def fetch_data(valid, data):
293+
#valid._log.info("HERE")
294+
await Edge(valid)
295+
#await Timer(100, units="ns")
296+
#valid._log.info(f"VALID {valid}")
297+
return data.value
298+
299+
async def check_rx_concurrent(dut, data, baud, baud_mult):
300+
dut.rx_ready.value = 1
301+
assert dut.rx_valid.value == 0
302+
303+
f = cocotb.start_soon(fetch_data(dut.rx_valid, dut.rx_data))
304+
305+
# prepare random test data
306+
TEST_BITS_LSB = [(data >> s) & 1 for s in range(8)]
307+
308+
# send start bit (0), 8 data bits, stop bit (1)
309+
for tx_bit in [0] + TEST_BITS_LSB + [1]:
310+
dut.uart_rx.value = tx_bit
311+
await Timer(int(1 / baud * baud_mult * 1e12), units="ps")
312+
313+
# check payload and valid/error/overflow flags
314+
assert dut.rx_data.value == f.result()
315+
assert dut.rx_error.value == 0
316+
assert dut.rx_overrun.value == 0

0 commit comments

Comments
 (0)