Skip to content

Commit fdd4337

Browse files
committed
test refactoring
1 parent 79e9b7f commit fdd4337

File tree

1 file changed

+138
-123
lines changed

1 file changed

+138
-123
lines changed

test/test_uart.py

Lines changed: 138 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -8,184 +8,107 @@
88

99
@cocotb.test(timeout_time=50, timeout_unit='ms')
1010
async def transmit(dut):
11-
"""TX with randomized payload / clock skew / inter-TX delay."""
11+
"""TX with randomized payload / clock frequency shift / inter-TX delay."""
1212

1313
# 50 Mhz clock
1414
cocotb.start_soon(Clock(dut.clk, 20, units='ns').start())
1515

16-
# reset
17-
dut.tx_reset.value = 1
18-
await Timer(1, units="ms")
19-
dut.tx_reset.value = 0
20-
await Timer(1, units="ms")
16+
await check_tx_reset(dut)
2117

22-
# run 100 randomized tests
18+
# carry out 100 transmissions
2319
for count in range(100):
24-
# check TX=1 and ready=1
25-
assert dut.uart_tx == 1
26-
assert dut.tx_ready.value == 1
27-
28-
# prepare random test data
29-
TEST_BYTE = random.randint(0,255) # 0xA5
30-
TEST_BITS_LSB = [(TEST_BYTE >> s) & 1 for s in range(8)]
31-
32-
# set data value and then start TX
33-
dut.tx_data.value = TEST_BYTE
34-
await Timer(100 + random.randint(0, 1000), units="ns")
35-
dut.tx_valid.value = 1
36-
37-
# wait for TX->0 transition, check TX=0 and ready=0
38-
await Edge(dut.uart_tx)
39-
assert dut.uart_tx.value == 0
40-
assert dut.tx_ready.value == 0
41-
42-
# set valid back to 0
43-
dut.tx_valid.value = 0
20+
# randomized payload
21+
TEST_BYTE = random.randint(0,255)
4422

45-
# randomized RX frequency skew (+/- 2%)
46-
skew = 1.0 + (random.random() - 0.5) / 50 * 2
23+
# randomized baud multiplier (+/- 2%)
24+
baud_mult = 1.0 + (random.random() - 0.5) / 50 * 2
4725

48-
# wait 1/2 bit
49-
await Timer(int(0.5 / 115200. * skew * 1e12), units="ps")
50-
51-
# check for start bit (0), 8 data bits, stop bit (1)
52-
for expected_bit in [0] + TEST_BITS_LSB + [1]:
53-
assert dut.uart_tx.value == expected_bit
54-
await Timer(int(1 / 115200. * skew * 1e12), units="ps")
55-
56-
assert dut.tx_ready.value == 1
26+
await check_tx(dut, TEST_BYTE, 115200, baud_mult)
5727

5828
# randomized inter-TX interval
59-
if random.random() > 0.2:
60-
await Timer(random.randint(1,5), units='us')
29+
if random.random() > 0.1:
30+
await Timer(random.randint(1,2000), units='ns')
6131

6232

6333
@cocotb.test(timeout_time=50, timeout_unit='ms')
6434
async def receive1(dut):
65-
"""RX with randomized payload / clock skew / inter-TX delay."""
35+
"""RX with randomized payload / clock frequency shift / inter-TX delay."""
6636

6737
# 50 Mhz clock
6838
cocotb.start_soon(Clock(dut.clk, 20, units='ns').start())
6939

70-
# drive input high
71-
dut.uart_rx.value = 1
72-
7340
# reset
74-
dut.rx_reset.value = 1
75-
await Timer(1, units="ms")
76-
dut.rx_reset.value = 0
77-
await Timer(1, units="ms")
41+
await check_rx_reset(dut)
7842

79-
# check valid=0, err=0
80-
assert dut.rx_valid.value == 0
81-
assert dut.rx_error.value == 0
82-
8343
# run 100 randomized tests
8444
for count in range(100):
85-
dut.rx_ready.value = 0
45+
# randomized payload
46+
TEST_BYTE = random.randint(0,255)
8647

87-
# random delay
88-
await Timer(100 + random.randint(0, 1000), units="ns")
89-
assert dut.rx_valid.value == 0
48+
# randomized baud multiplier (+/- 2%)
49+
baud_mult = 1.0 + (random.random() - 0.5) / 50 * 2
9050

91-
# prepare random test data
92-
TEST_BYTE = random.randint(0,255) # 0xA5
93-
TEST_BITS_LSB = [(TEST_BYTE >> s) & 1 for s in range(8)]
94-
95-
# randomized TX frequency skew (+/- 2%)
96-
skew = 1.0 + (random.random() - 0.5) / 50 * 2
51+
await check_rx(dut, TEST_BYTE, 115200, baud_mult)
9752

98-
# send start bit (0), 8 data bits, stop bit (1)
99-
for tx_bit in [0] + TEST_BITS_LSB + [1]:
100-
dut.uart_rx.value = tx_bit
101-
await Timer(int(1 / 115200. * skew * 1e12), units="ps")
53+
# randomized delay
54+
await Timer(random.randint(500,2000), units='ns')
10255

103-
# random delay
104-
await Timer(100 + random.randint(0, 1000), units="ns")
105-
assert dut.rx_valid.value == 1
10656

107-
dut.rx_ready.value = 1
57+
@cocotb.test(timeout_time=50, timeout_unit='ms')
58+
async def receive2(dut):
59+
"""Continuous RX with randomized payload."""
10860

109-
# wait for valid transition
110-
await Edge(dut.rx_valid)
111-
assert dut.rx_valid.value == 0
61+
# 50 Mhz clock
62+
cocotb.start_soon(Clock(dut.clk, 20, units='ns').start())
11263

113-
# check payload and valid/error/overflow flags
114-
assert dut.rx_data.value == TEST_BYTE
115-
assert dut.rx_error.value == 0
116-
assert dut.rx_overrun.value == 0
64+
# reset
65+
await check_tx_reset(dut)
11766

118-
# randomized delay
119-
await Timer(random.randint(1,5), units='us')
67+
# run 100 randomized tests
68+
for count in range(100):
69+
# randomized payload
70+
TEST_BYTE = random.randint(0,255)
71+
await check_rx(dut, TEST_BYTE, 115200, 1.0)
12072

12173

12274
@cocotb.test(timeout_time=50, timeout_unit='ms')
123-
async def receive2(dut):
124-
"""Continuous RX with randomized payload / frequency skew."""
75+
async def receive3(dut):
76+
"""Continuous RX with randomized payload / clock frequency shift."""
12577

12678
# 50 Mhz clock
12779
cocotb.start_soon(Clock(dut.clk, 20, units='ns').start())
12880

129-
# drive input high
130-
dut.uart_rx.value = 1
131-
13281
# reset
133-
dut.rx_reset.value = 1
134-
await Timer(1, units="ms")
135-
dut.rx_reset.value = 0
136-
await Timer(1, units="ms")
137-
138-
# check valid=0, err=0
139-
assert dut.rx_valid.value == 0
140-
assert dut.rx_error.value == 0
141-
142-
dut.rx_ready.value = 1
82+
await check_tx_reset(dut)
14383

14484
# run 100 randomized tests
14585
for count in range(100):
146-
# prepare random test data
147-
TEST_BYTE = random.randint(0,255) # 0xA5
148-
TEST_BITS_LSB = [(TEST_BYTE >> s) & 1 for s in range(8)]
86+
# randomized payload
87+
TEST_BYTE = random.randint(0,255)
14988

150-
# randomized TX frequency skew (+/- 2%)
151-
skew = 1.0 + (random.random() - 0.5) / 50 * 2
89+
# randomized baud multiplier (+/- 2%)
90+
baud_mult = 1.0 + (random.random() - 0.5) / 50 * 2
15291

153-
# send start bit (0), 8 data bits, stop bit (1)
154-
for tx_bit in [0] + TEST_BITS_LSB + [1]:
155-
dut.uart_rx.value = tx_bit
156-
await Timer(int(1 / 115200. * skew * 1e12), units="ps")
157-
158-
# check payload and valid/error/overflow flags
159-
assert dut.rx_data.value == TEST_BYTE
160-
assert dut.rx_error.value == 0
161-
assert dut.rx_overrun.value == 0
92+
await check_rx(dut, TEST_BYTE, 115200, baud_mult)
16293

16394

16495
@cocotb.test(timeout_time=50, timeout_unit='ms')
165-
async def receive3(dut):
96+
async def receive4(dut):
16697
"""RX overrun."""
16798

16899
# 50 Mhz clock
169100
cocotb.start_soon(Clock(dut.clk, 20, units='ns').start())
170101

171-
# drive input high
172-
dut.uart_rx.value = 1
173-
174102
# reset
175-
dut.rx_reset.value = 1
176-
await Timer(1, units="ms")
177-
dut.rx_reset.value = 0
178-
await Timer(1, units="ms")
179-
180-
# check valid=0, err=0
181-
assert dut.rx_valid.value == 0
182-
assert dut.rx_error.value == 0
103+
await check_tx_reset(dut)
183104

105+
# set RX ready low, and keep it low...
184106
dut.rx_ready.value = 0
185107

108+
# ...across 2 RX operations, until the received overruns
186109
for count in range(2):
187110
# prepare random test data
188-
TEST_BYTE = random.randint(0,255) # 0xA5
111+
TEST_BYTE = random.randint(0,255)
189112
TEST_BITS_LSB = [(TEST_BYTE >> s) & 1 for s in range(8)]
190113

191114
# send start bit (0), 8 data bits, stop bit (1)
@@ -194,12 +117,104 @@ async def receive3(dut):
194117
await Timer(int(1 / 115200. * 1e12), units="ps")
195118

196119
# check payload and valid/error/overflow flags
120+
assert dut.rx_valid.value == 1
121+
assert dut.rx_error.value == 0
197122
if (count == 0):
198123
TEST_BYTE_PREV = TEST_BYTE
199124
assert dut.rx_data.value == TEST_BYTE
200-
assert dut.rx_error.value == 0
201125
assert dut.rx_overrun.value == 0
202126
else:
203127
assert dut.rx_data.value == TEST_BYTE_PREV
204-
assert dut.rx_error.value == 0
205128
assert dut.rx_overrun.value == 1
129+
130+
131+
132+
# --- HELPER FUNCTIONS ---
133+
134+
async def check_tx_reset(dut):
135+
# reset
136+
dut.tx_reset.value = 1
137+
await Timer(1, units="ms")
138+
dut.tx_reset.value = 0
139+
await Timer(1, units="ms")
140+
141+
assert dut.tx_ready.value == 1
142+
143+
144+
async def check_rx_reset(dut):
145+
# drive input high
146+
dut.uart_rx.value = 1
147+
148+
# reset
149+
dut.rx_reset.value = 1
150+
await Timer(1, units="ms")
151+
dut.rx_reset.value = 0
152+
await Timer(1, units="ms")
153+
154+
assert dut.rx_valid.value == 0
155+
assert dut.rx_error.value == 0
156+
assert dut.rx_overrun.value == 0
157+
158+
159+
async def check_tx(dut, data, baud, baud_mult):
160+
# check TX=1 and ready=1
161+
assert dut.uart_tx == 1
162+
assert dut.tx_ready.value == 1
163+
164+
# prepare random test data
165+
TEST_BITS_LSB = [(data >> s) & 1 for s in range(8)]
166+
167+
# set data value and then start TX
168+
dut.tx_data.value = data
169+
await Timer(random.randint(100, 500), units="ns")
170+
dut.tx_valid.value = 1
171+
172+
# wait for TX->0 transition, check TX=0 and ready=0
173+
await Edge(dut.uart_tx)
174+
assert dut.uart_tx.value == 0
175+
assert dut.tx_ready.value == 0
176+
177+
# set valid back to 0
178+
dut.tx_valid.value = 0
179+
180+
# wait 1/2 bit
181+
await Timer(int(0.5 / baud * baud_mult * 1e12), units="ps")
182+
183+
# check for start bit (0), 8 data bits, stop bit (1)
184+
for expected_bit in [0] + TEST_BITS_LSB + [1]:
185+
assert dut.uart_tx.value == expected_bit
186+
await Timer(int(1.0 / baud * baud_mult * 1e12), units="ps")
187+
188+
assert dut.tx_ready.value == 1
189+
190+
191+
async def check_rx(dut, data, baud, baud_mult):
192+
dut.rx_ready.value = 0
193+
194+
# random delay
195+
await Timer(100 + random.randint(100, 500), units="ns")
196+
assert dut.rx_valid.value == 0
197+
198+
# prepare random test data
199+
TEST_BITS_LSB = [(data >> s) & 1 for s in range(8)]
200+
201+
# send start bit (0), 8 data bits, stop bit (1)
202+
for tx_bit in [0] + TEST_BITS_LSB + [1]:
203+
dut.uart_rx.value = tx_bit
204+
await Timer(int(1 / baud * baud_mult * 1e12), units="ps")
205+
206+
# random delay
207+
await Timer(100 + random.randint(100, 500), units="ns")
208+
assert dut.rx_valid.value == 1
209+
210+
dut.rx_ready.value = 1
211+
212+
# wait for valid transition
213+
await Edge(dut.rx_valid)
214+
assert dut.rx_valid.value == 0
215+
216+
# check payload and valid/error/overflow flags
217+
assert dut.rx_data.value == data
218+
assert dut.rx_error.value == 0
219+
assert dut.rx_overrun.value == 0
220+

0 commit comments

Comments
 (0)