Skip to content

Commit b2bfaa8

Browse files
committed
fixing formal workflow and adding tests with pat
1 parent 2a9d88c commit b2bfaa8

File tree

4 files changed

+41
-73
lines changed

4 files changed

+41
-73
lines changed
File renamed without changes.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
![](../../workflows/gds/badge.svg) ![](../../workflows/docs/badge.svg) ![](../../workflows/test/badge.svg) ![](../../workflows/fpga/badge.svg)
1+
![](../../workflows/gds/badge.svg) ![](../../workflows/docs/badge.svg) ![](../../workflows/test/badge.svg) ![](../../workflows/fpga/badge.svg) ![](../../workflows/docs/formal.svg)
22

33
# TinyQV Full Peripheral Template for Tiny Tapeout
44

src/peripheral.v

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,50 +35,45 @@ module tqvp_stevej_watchdog (
3535
reg [31:0] window_start;
3636
reg [31:0] window_close;
3737
reg watchdog_enabled; // has the user enabled the design
38-
reg pat; // has the user patted the watchdog this window?
3938
reg saw_pat; // destination is an output pin, driving high means the watchdog was pat and reset.
4039

4140
always @(posedge clk) begin
4241
if (!rst_n) begin
4342
window_start <= 32'b0;
4443
window_close <= 32'b0;
4544
watchdog_enabled <= 1'b0;
46-
pat <= 1'b0;
4745
saw_pat <= 1'b0;
4846
timer <= 32'b0;
4947
end else begin
48+
watchdog_enabled <= watchdog_enabled;
49+
timer <= timer;
50+
window_start <= window_start;
51+
window_close <= window_close;
52+
saw_pat <= saw_pat;
53+
5054
if (address == 6'h0) begin // Address 0 is ENABLE
5155
if (data_write_n != 2'b11) begin
52-
watchdog_enabled <= data_in[0];
56+
watchdog_enabled <= 1;
5357
timer <= 32'b0;
5458
end
55-
end
56-
57-
if (address == 6'h1) begin // Address 1 is WINDOW_START
59+
end else if (address == 6'h1) begin // Address 1 is WINDOW_START
5860
if (data_write_n != 2'b11) begin
5961
window_start <= data_in;
6062
end
61-
end
62-
63-
if (address == 6'h2) begin // Address 2 is WINDOW_CLOSE
63+
end else if (address == 6'h2) begin // Address 2 is WINDOW_CLOSE
6464
if (data_write_n != 2'b11) begin
6565
window_close <= data_in;
6666
end
67-
end
68-
69-
if (address == 6'h3) begin // Address 3 is PAT
67+
end else if (address == 6'h3) begin // Address 3 is PAT
7068
if (data_write_n != 2'b11) begin
7169
saw_pat <= 1'b1;
7270
timer <= 32'b0;
7371
end
74-
end else begin
75-
saw_pat <= 1'b0;
7672
end
7773

7874
if (!timer_expired) begin
7975
timer <= timer + 32'b1;
8076
end
81-
8277
end
8378
end
8479

@@ -95,9 +90,11 @@ module tqvp_stevej_watchdog (
9590
assign after_window_close = timer > window_close;
9691

9792
assign timer_expired = watchdog_enabled && after_window_start && after_window_close;
93+
9894
assign interrupt_high = timer_expired;
9995
assign interrupt_low = !timer_expired;
10096
assign user_interrupt = interrupt_high;
97+
10198
assign uo_out = {interrupt_high, interrupt_low, saw_pat, watchdog_enabled, after_window_start, after_window_close, 2'b00};
10299

103100
// Addresses

test/test.py

Lines changed: 28 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -58,19 +58,27 @@ async def test_enabled_with_window_close(dut):
5858

5959
dut._log.info("Test project behavior")
6060
# Test writing 10 to WATCHDOG_CLOSE register
61-
await tqv.write_word_reg(2, 0xA)
62-
assert await tqv.read_word_reg(2) == 0xA
61+
await tqv.write_word_reg(2, 0xAAA)
62+
assert await tqv.read_word_reg(2) == 0xAAA
6363

6464
# Test enabling watchdog timer by writing to interrupt.
6565
await tqv.write_word_reg(0, 0x1)
66+
assert await tqv.read_word_reg(0) == 0x1
67+
68+
# Send pat immediately
69+
await tqv.write_word_reg(3, 0x1)
70+
assert await tqv.read_word_reg(3) == 0x1
6671

67-
await ClockCycles(dut.clk, 5)
68-
# no interrupts, no pat seen, watchdog has been enabled, timer not expired
69-
assert dut.uo_out.value == 0b01010000
72+
await ClockCycles(dut.clk, 0xAA)
73+
assert dut.uo_out.value != 0b10111100 # we should not trigger at this point.
74+
75+
# Checking that the watchdog does eventually fire
76+
await ClockCycles(dut.clk, 0xAAA)
77+
assert dut.uo_out.value == 0b10111100
7078

7179
# Test that enabling the watchdog timer with a WINDOW_CLOSE of 10 results in an expired timer in 10 cycles.
7280
@cocotb.test()
73-
async def test_enabled_with_window_close(dut):
81+
async def test_enabled_with_window_close2_and_immediate_pat(dut):
7482
dut._log.info("Start")
7583

7684
# Set the clock period to 100 ns (10 MHz)
@@ -89,84 +97,47 @@ async def test_enabled_with_window_close(dut):
8997
dut._log.info("Test project behavior")
9098
# Set WINDOW_CLOSE
9199
await tqv.write_word_reg(2, 0xAAA) # 2730 cycles
100+
assert await tqv.read_word_reg(2) == 0xAAA
92101

93102
# Test enabling watchdog timer by writing to interrupt.
94103
await tqv.write_word_reg(0, 0x1)
95104

105+
# Send pat immediately
106+
await tqv.write_word_reg(3, 0x1)
107+
assert await tqv.read_word_reg(3) == 0x1
108+
96109
await ClockCycles(dut.clk, 1)
97110
# watchdog has been enabled, no pat seen, timer expired
98111
# no interrupt, no pat seen, watchdog enabled, after_window_start, window has not closed.
99-
assert dut.uo_out.value == 0b01011000 # this is actually 0b10011100 so the timer has expired after 1 clock cycle.
112+
assert dut.uo_out.value != 0b10011100 # we should not have triggered.
113+
assert dut.uo_out.value == 0b01111000
100114

101115
# Check that the watchdog is enabled but not triggered for 10 cycles.
102116
for _ in range(10):
103117
await ClockCycles(dut.clk, 1)
104118
# watchdog has been enabled, no pat seen, timer expired
105119
# no interrupt, no pat seen, watchdog enabled, after_window_start, window has not closed.
106-
assert dut.uo_out.value == 0b01011000
120+
assert dut.uo_out.value == 0b01111000
107121

108122
# TODO: Mystery! For some unknown reason we only need 101, and not (2730 - already used) cycles, for the watchdog to trigger.
109-
await ClockCycles(dut.clk, 101)
123+
await ClockCycles(dut.clk, 0xAAA)
110124
# interrupt, watchdog enabled, after_window_start, after_window_close
111-
assert dut.uo_out.value == 0b1001_1100
125+
assert dut.uo_out.value == 0b1011_1100
112126

113127
# interrupts, no pat seen, watchdog enabled, after_window_start
114128
# After enough clock cycles, this should be 0b10011000 which indicates the watchdog has been triggered.
115129
timer_elapsed = 0
116130
for _ in range(10):
117-
if dut.uo_out.value != 0b0101_1000:
118-
assert dut.uo_out.value == 0b1001_1100
119-
if dut.uo_out.value == 0b1001_1100:
131+
if dut.uo_out.value != 0b0111_1000:
132+
assert dut.uo_out.value == 0b1011_1100
133+
if dut.uo_out.value == 0b1011_1100:
120134
timer_elapsed = 1
121135
assert timer_elapsed
122136

123137

124138
# Test that enabling the watchdog timer with a WINDOW_OPEN of 5 and a WINDOW_CLOSE of 10 doesn't
125139
# trigger outside the window but does trigger inside the window.
126140

127-
# Test that enabling the watchdog timer with a WINDOW_CLOSE of 10 results in an expired timer in 10 cycles.
128-
@cocotb.test()
129-
async def test_enabled_with_window_start_and_close_no_pat(dut):
130-
dut._log.info("Start")
131-
132-
# Set the clock period to 100 ns (10 MHz)
133-
clock = Clock(dut.clk, 100, units="ns")
134-
cocotb.start_soon(clock.start())
135-
136-
# Interact with your design's registers through this TinyQV class.
137-
# This will allow the same test to be run when your design is integrated
138-
# with TinyQV - the implementation of this class will be replaces with a
139-
# different version that uses Risc-V instructions instead of the SPI
140-
# interface to read and write the registers.
141-
tqv = TinyQV(dut)
142-
# Reset
143-
await tqv.reset()
144-
145-
dut._log.info("Test project behavior")
146-
# Writing 5 to WATCHDOG_START register
147-
await tqv.write_word_reg(1, 0x5)
148-
# Writing 10 to WATCHDOG_CLOSE register
149-
await tqv.write_word_reg(2, 0xBBB)
150-
# Enabling watchdog timer
151-
await tqv.write_word_reg(0, 0x1)
152-
153-
await ClockCycles(dut.clk, 1)
154-
# watchdog should not have tripped after 1 cycle when configured for 0xBBB cycles
155-
assert dut.uo_out.value != 0b10011000
156-
assert dut.uo_out.value == 0b01011100
157-
158-
# The watchdog should not trigger in less cycles than configured.
159-
await ClockCycles(dut.clk, 0xAA)
160-
# If this assertion fails, the watchdog triggered too quickly from our perspective.
161-
assert dut.uo_out.value != 0b10011100
162-
163-
await ClockCycles(dut.clk, 0xA00)
164-
assert dut.uo_out.value == 0b01111000
165-
166-
await ClockCycles(dut.clk, 0xBBB)
167-
assert dut.uo_out.value == 0b10111100
168-
169-
170141

171142
# Test that enabling the watchdog timer with a WINDOW_CLOSE of 10 results in an expired timer in 10 cycles.
172143
@cocotb.test()
@@ -194,7 +165,7 @@ async def test_enabled_with_window_start_and_close_early_pat(dut):
194165
# Enabling watchdog timer
195166
await tqv.write_word_reg(0, 0x1)
196167

197-
# immediately patting
168+
# immediately patting to reset the timer.
198169
await tqv.write_word_reg(3, 0x1)
199170

200171

0 commit comments

Comments
 (0)