Skip to content

Commit 9e37e9d

Browse files
arjenroodselaarnathanaelhuffman
authored andcommitted
Implement controller rx watchdog, restore remaining integration tests
1 parent af1110e commit 9e37e9d

File tree

7 files changed

+118
-59
lines changed

7 files changed

+118
-59
lines changed

hdl/ip/bsv/ignition/IgnitionController.bsv

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -929,7 +929,8 @@ module mkController #(
929929
transceiver_.transmitter_output_disable_timeout_ticks_remaining = 0;
930930
transceiver_.transmitter_output_enabled = True;
931931
end
932-
else if (transceiver.transmitter_output_enabled) begin
932+
else if (transceiver.transmitter_output_enabled &&
933+
transceiver.transmitter_output_disable_timeout_ticks_remaining == 0) begin
933934
transceiver_.transmitter_output_disable_timeout_ticks_remaining =
934935
fromInteger(parameters.transmitter_output_disable_timeout);
935936
end
@@ -939,7 +940,8 @@ module mkController #(
939940
transceiver_.transmitter_output_disable_timeout_ticks_remaining = 0;
940941
transceiver_.transmitter_output_enabled = True;
941942
end
942-
else if (transceiver.transmitter_output_enabled) begin
943+
else if (transceiver.transmitter_output_enabled &&
944+
transceiver.transmitter_output_disable_timeout_ticks_remaining == 0) begin
943945
transceiver_.transmitter_output_disable_timeout_ticks_remaining =
944946
fromInteger(parameters.transmitter_output_disable_timeout);
945947
end
@@ -950,6 +952,11 @@ module mkController #(
950952
end
951953
endcase
952954

955+
$display("%5t [Controller %02d] Transmitter output enable mode ",
956+
$time,
957+
current_controller,
958+
fshow(transceiver_.transmitter_output_enable_mode));
959+
953960
if (transceiver.transmitter_output_enabled &&
954961
!transceiver_.transmitter_output_enabled) begin
955962
$display("%5t [Controller %02d] Transmitter output disabled",
@@ -1332,7 +1339,8 @@ module mkController #(
13321339

13331340
if (transceiver.transmitter_output_enable_mode ==
13341341
EnabledWhenReceiverAligned &&
1335-
transceiver.transmitter_output_enabled) begin
1342+
transceiver.transmitter_output_enabled &&
1343+
transceiver.transmitter_output_disable_timeout_ticks_remaining == 0) begin
13361344
// A ReceiverReset means the receiver is not aligned anymore
13371345
// and the disable timeout counter should be started.
13381346
transceiver_.transmitter_output_disable_timeout_ticks_remaining =

hdl/ip/bsv/ignition/IgnitionReceiver.bsv

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,7 @@ endinstance
582582
interface ControllerReceiver #(numeric type n);
583583
interface Vector#(n, DeserializerClient) rx;
584584
interface Get#(ReceiverEvent#(n)) events;
585+
method Action tick_1khz();
585586
endinterface
586587

587588
interface DeserializerChannel #(numeric type n);
@@ -665,6 +666,10 @@ module mkControllerReceiver (ControllerReceiver#(n))
665666
NumAlias#(TLog#(n), id_sz));
666667
Vector#(n, DeserializerChannel#(n))
667668
channels <- mapM(mkDeserializerChannel, genVector);
669+
Vector#(n, Reg#(Bool)) channels_locked <- replicateM(mkReg(False));
670+
671+
Reg#(UInt#(9)) watchdog_ticks_remaining <- mkRegU();
672+
Reg#(Bool) watchdog_fired <- mkDReg(False);
668673

669674
// Use a regular FIFO here but of size two, allowing it to act as a skid
670675
// buffer. This decouples the demux pipeline from the receiver logic,
@@ -1228,11 +1233,30 @@ module mkControllerReceiver (ControllerReceiver#(n))
12281233
channels[id].set_search_for_comma(!receive_state_2_next.aligned);
12291234
channels[id].set_invert_polarity(
12301235
receive_state_2_next.polarity_inverted);
1236+
1237+
channels_locked[id] <=
1238+
receive_state_2_next.aligned &&
1239+
receive_state_2_next.locked;
12311240
end
12321241
endrule
12331242

1243+
for (Integer id = 0; id < valueOf(n); id = id + 1) begin
1244+
(* fire_when_enabled *)
1245+
rule do_channel_locked_watchdog
1246+
(watchdog_fired && !channels_locked[fromInteger(id)]);
1247+
channels[fromInteger(id)].request_reset();
1248+
endrule
1249+
end
1250+
12341251
interface Vector rx = map(deserializer_client, channels);
12351252
interface Get events = toGet(receiver_events);
1253+
1254+
method Action tick_1khz();
1255+
// This automatically rolls over from 0, restarting the watchdog
1256+
// timer.
1257+
watchdog_ticks_remaining <= watchdog_ticks_remaining - 1;
1258+
watchdog_fired <= (watchdog_ticks_remaining == 0);
1259+
endmethod
12361260
endmodule
12371261

12381262
typedef struct {

hdl/ip/bsv/ignition/IgnitionTransceiver.bsv

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ interface ControllerTransceiver#(numeric type n);
372372
interface Vector#(n, Tuple2#(Bool, GetPut#(Bit#(1)))) serial;
373373
interface Get#(ReceiverEvent#(n)) rx;
374374
interface Put#(TransmitterEvent#(n)) tx;
375+
method Action tick_1khz();
375376
endinterface
376377

377378
interface ControllerTransceiverClient#(numeric type n);
@@ -425,6 +426,7 @@ module mkControllerTransceiver (ControllerTransceiver#(n))
425426
deserializers);
426427
interface Get rx = receiver.events;
427428
interface Put tx = toPut(tx_ev);
429+
method tick_1khz = receiver.tick_1khz;
428430
endmodule
429431

430432
module mkControllerTransceiver36 (ControllerTransceiver#(36));

hdl/ip/bsv/ignition/test/IgnitionControllerAndTargetBench.bsv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ module mkIgnitionControllerAndTargetBench #(
155155
ControllerTransceiver#(4) controller_txr <- mkControllerTransceiver();
156156

157157
mkConnection(asIfc(tick), asIfc(controller_.tick_1mhz));
158+
mkConnection(asIfc(tick), asIfc(controller_txr.tick_1khz));
158159

159160
// Set this TX strobe ~180 degrees out of phase from Target TX.
160161
Strobe#(3) controller_tx_strobe <- mkLimitStrobe(1, 5, 3);

hdl/ip/bsv/ignition/test/IntegrationTests.bsv

Lines changed: 71 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ module mkControllerTargetPresentTest (Empty);
6868
endaction
6969
par
7070
await(bench.controller.presence_summary[0]);
71-
await_set(bench.target.controller0_present);
71+
await(bench.target.controller0_present);
7272
endpar
7373

7474
assert_controller_register_eq(
@@ -92,40 +92,63 @@ module mkTargetRoTFaultTest (Empty);
9292
10 * max(protocol_parameters.hello_interval,
9393
protocol_parameters.status_interval));
9494

95-
// let controller_state = bench.controller.registers.controller_state;
96-
// let target_system_status = bench.controller.registers.target_system_status;
97-
// let target_system_faults = bench.controller.registers.target_system_faults;
95+
Reg#(SystemFaults) target_system_events <- mkReg(defaultValue);
96+
97+
function read_controller_0_register_into(id, d) =
98+
read_controller_register_into(bench.controller, 0, id, asIfc(d));
99+
100+
function read_controller_0_registers_while(predicate) =
101+
seq
102+
while(predicate) seq
103+
read_controller_0_register_into(
104+
TargetSystemEvents,
105+
target_system_events);
106+
// Avoid a tight loop reading the registers otherwise the
107+
// Controller will not make progress due to this interface
108+
// having the highest priority.
109+
repeat(3) bench.await_tick();
110+
endseq
111+
endseq;
98112

99113
mkAutoFSM(seq
100-
// action
101-
// bench.controller_to_target.set_state(Connected);
102-
// bench.target_to_controller.set_state(Connected);
103-
// endaction
104-
// par
105-
// await_set(controller_state.target_present);
106-
// await_set(target_system_status.controller0_detected);
107-
// endpar
108-
109-
// // Assert no target system faults and set an RoT fault.
110-
// assert_eq(
111-
// target_system_faults,
112-
// defaultValue,
113-
// "expected no target system faults");
114-
// bench.set_target_system_faults(system_faults_rot);
115-
116-
// // Assert the fault is observed by the Controller.
117-
// await_set(target_system_faults.rot_fault);
118-
// assert_set(target_system_faults.rot_fault, "expected RoT fault");
119-
120-
// // Resolve the RoT fault.
121-
// bench.set_target_system_faults(system_faults_none);
122-
123-
// // Assert the RoT fault cleared.
124-
// await_not_set(target_system_faults.rot_fault);
125-
// assert_eq(
126-
// target_system_faults,
127-
// defaultValue,
128-
// "expected no target system faults");
114+
action
115+
bench.controller_to_target.set_state(Connected);
116+
bench.target_to_controller.set_state(Connected);
117+
bench.controller.registers.request.put(
118+
RegisterRequest {
119+
id: 0,
120+
register: TransceiverState,
121+
op: tagged Write extend(
122+
{pack(EnabledWhenReceiverAligned), 4'h0})});
123+
endaction
124+
par
125+
await(bench.controller.presence_summary[0]);
126+
await(bench.target.controller0_present);
127+
endpar
128+
129+
// Assert no Target system faults and set an RoT fault.
130+
assert_controller_register_eq(
131+
bench.controller, 0, TargetSystemEvents,
132+
system_faults_none,
133+
"expected no target system faults");
134+
bench.set_target_system_faults(system_faults_rot);
135+
136+
// Assert the fault is observed by the Controller.
137+
read_controller_0_registers_while(!target_system_events.rot);
138+
assert_controller_register_eq(
139+
bench.controller, 0, TargetSystemEvents,
140+
system_faults_rot,
141+
"expected an RoT faults");
142+
143+
// Resolve the RoT fault.
144+
bench.set_target_system_faults(system_faults_none);
145+
146+
// Assert the RoT fault cleared.
147+
read_controller_0_registers_while(target_system_events.rot);
148+
assert_controller_register_eq(
149+
bench.controller, 0, TargetSystemEvents,
150+
system_faults_none,
151+
"expected no target system faults");
129152
endseq);
130153
endmodule
131154

@@ -369,31 +392,20 @@ module mkReceiversLockedTimeoutTest (Empty);
369392
mkIgnitionControllerAndTargetBench(parameters, 1000);
370393

371394
mkAutoFSM(seq
395+
clear_controller_counter(bench.controller, 0, ControllerReceiverReset);
396+
372397
// The link between Controller and Target is not connected, causing both
373398
// receivers never to reach locked state.
374-
375-
// Reset the controller link status register, clearing any events.
376-
// action
377-
// let _ <- bench.controller.registers.controller_link_status;
378-
// endaction
379-
380399
par
381-
// repeat(4) seq
382-
// await(bench.controller_receiver_locked_timeout);
383-
384-
// // Wait for the receiver reset event bit to be set in the link
385-
// // status register.
386-
// // action
387-
// // let link_status <-
388-
// // bench.controller.registers.controller_link_status;
389-
390-
// // await_set(link_status.receiver_reset_event);
391-
// // endaction
392-
// endseq
393-
394400
repeat(4) await(bench.target_receiver_locked_timeout[0]);
395401
repeat(4) await(bench.target_receiver_locked_timeout[1]);
396402
endpar
403+
404+
assert_controller_counter_eq(
405+
bench.controller,
406+
0, ControllerReceiverReset,
407+
3,
408+
"expected Controller reset events");
397409
endseq);
398410
endmodule
399411

@@ -417,9 +429,12 @@ module mkNoLockedTimeoutIfReceiversLockedTest (Empty);
417429
!bench.controller_receiver_locked_timeout,
418430
"expected no Controller receiver locked timeout");
419431

420-
continuousAssert(
421-
!bench.target_receiver_locked_timeout[0],
422-
"expected no receiver locked timeout for Target link 0");
432+
(* fire_when_enabled *)
433+
rule do_assert_target_receiver_locked_timeout
434+
(bench.controller_transmitter_output_enabled);
435+
assert_true(!bench.target_receiver_locked_timeout[0],
436+
"expected no receiver locked timeout for Target link 0");
437+
endrule
423438

424439
mkAutoFSM(seq
425440
action
@@ -429,7 +444,7 @@ module mkNoLockedTimeoutIfReceiversLockedTest (Empty);
429444
RegisterRequest {
430445
id: 0,
431446
register: TransceiverState,
432-
op: tagged Write 'h20});
447+
op: tagged Write ({2'h0, pack(AlwaysEnabled), 4'h0})});
433448
endaction
434449

435450
par

hdl/projects/sidecar/mainboard/SidecarMainboardController.bsv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ interface MainboardController #(numeric type n_ignition_controllers);
9393
interface Registers registers;
9494
interface Controller#(n_ignition_controllers) ignition_controller;
9595
interface ReadOnly#(Status) status;
96+
method Bool ignition_tick_1khz();
9697
endinterface
9798

9899
module mkMainboardController #(Parameters parameters)
@@ -223,6 +224,8 @@ module mkMainboardController #(Parameters parameters)
223224
interface Controller ignition_controller = ignition;
224225

225226
interface ReadOnly status = regToReadOnly(status_r);
227+
228+
method ignition_tick_1khz = tick_1khz;
226229
endmodule
227230

228231
endpackage

hdl/projects/sidecar/mainboard/SidecarMainboardControllerTop.bsv

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,12 @@ module mkSidecarMainboardControllerTop
522522

523523
mkConnection(ignition_txr, controller.ignition_controller.txr);
524524

525+
// Connect the transceiver watchdog timer.
526+
(* fire_when_enabled *)
527+
rule do_ignition_txr_watchdog (controller.ignition_tick_1khz);
528+
ignition_txr.tick_1khz();
529+
endrule
530+
525531
//
526532
// Cubbies
527533
//

0 commit comments

Comments
 (0)