Skip to content

Commit af1110e

Browse files
arjenroodselaarnathanaelhuffman
authored andcommitted
Implement/enable tx output enable, enable Ignition register writes
1 parent 0f89c0f commit af1110e

12 files changed

+432
-143
lines changed

hdl/ip/bsv/ignition/IgnitionController.bsv

Lines changed: 179 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ export CounterAddress(..);
1111
export CounterId(..);
1212
export Counter(..);
1313
export Counters(..);
14+
export TransmitterOutputEnableMode(..);
1415

1516
export mkController;
1617
export read_controller_register_into;
1718
export clear_controller_counter;
1819
export read_controller_counter_into;
20+
export transceiver_state_value;
1921

2022
import BRAMCore::*;
2123
import BRAMFIFO::*;
@@ -41,12 +43,14 @@ import IgnitionTransmitter::*;
4143

4244
typedef struct {
4345
Integer tick_period;
46+
Integer transmitter_output_disable_timeout;
4447
IgnitionProtocol::Parameters protocol;
4548
} Parameters;
4649

4750
instance DefaultValue#(Parameters);
4851
defaultValue = Parameters {
4952
tick_period: 1000,
53+
transmitter_output_disable_timeout: 100,
5054
protocol: defaultValue};
5155
endinstance
5256

@@ -121,6 +125,13 @@ typedef UInt#(8) Counter;
121125
typedef Server#(RegisterRequest#(n), Bit#(8)) Registers#(numeric type n);
122126
typedef Server#(CounterAddress#(n), Counter) Counters#(numeric type n);
123127

128+
typedef enum {
129+
Disabled = 0,
130+
EnabledWhenReceiverAligned = 1,
131+
EnabledWhenTargetPresent = 2,
132+
AlwaysEnabled = 3
133+
} TransmitterOutputEnableMode deriving (Bits, Eq, FShow);
134+
124135
// An interface for a Controller with `n` "channels" which processes events
125136
// submitted by a receiver, answers requests from upstack software and generates
126137
// events for a transmitter.
@@ -247,7 +258,6 @@ module mkController #(
247258
//
248259
FIFOF#(Bit#(8)) software_response <- mkFIFOF();
249260
FIFOF#(TransmitterEvent#(n)) transmitter_events <- mkFIFOF();
250-
FIFOF#(Bool) transmitter_output_enabled_events <- mkFIFOF();
251261

252262
let event_handler_idle =
253263
!(software_request.notEmpty ||
@@ -899,16 +909,63 @@ module mkController #(
899909
software_request.first.op,
900910
software_request.first.register)) matches
901911
{tagged Read, TransceiverState}:
902-
respond_with(transceiver);
912+
respond_with(pack(transceiver)[5:0]);
903913

904914
{tagged Write .b, TransceiverState}: begin
905-
let request = TransceiverRegister'(unpack(truncate(b)));
915+
TransceiverRegister request = unpack(extend(b));
916+
TransceiverRegister transceiver_ = transceiver;
917+
918+
transceiver_.transmitter_output_enable_mode =
919+
request.transmitter_output_enable_mode;
920+
921+
case (request.transmitter_output_enable_mode)
922+
Disabled: begin
923+
transceiver_.transmitter_output_disable_timeout_ticks_remaining = 0;
924+
transceiver_.transmitter_output_enabled = False;
925+
end
926+
927+
EnabledWhenReceiverAligned:
928+
if (transceiver.receiver_status.receiver_aligned) begin
929+
transceiver_.transmitter_output_disable_timeout_ticks_remaining = 0;
930+
transceiver_.transmitter_output_enabled = True;
931+
end
932+
else if (transceiver.transmitter_output_enabled) begin
933+
transceiver_.transmitter_output_disable_timeout_ticks_remaining =
934+
fromInteger(parameters.transmitter_output_disable_timeout);
935+
end
936+
937+
EnabledWhenTargetPresent:
938+
if (presence.present) begin
939+
transceiver_.transmitter_output_disable_timeout_ticks_remaining = 0;
940+
transceiver_.transmitter_output_enabled = True;
941+
end
942+
else if (transceiver.transmitter_output_enabled) begin
943+
transceiver_.transmitter_output_disable_timeout_ticks_remaining =
944+
fromInteger(parameters.transmitter_output_disable_timeout);
945+
end
946+
947+
AlwaysEnabled: begin
948+
transceiver_.transmitter_output_disable_timeout_ticks_remaining = 0;
949+
transceiver_.transmitter_output_enabled = True;
950+
end
951+
endcase
952+
953+
if (transceiver.transmitter_output_enabled &&
954+
!transceiver_.transmitter_output_enabled) begin
955+
$display("%5t [Controller %02d] Transmitter output disabled",
956+
$time,
957+
current_controller);
958+
end
959+
else if (!transceiver.transmitter_output_enabled &&
960+
transceiver_.transmitter_output_enabled) begin
961+
$display("%5t [Controller %02d] Transmitter output enabled",
962+
$time,
963+
current_controller);
964+
end
906965

907-
// Update the transceiver register. A change to the transmitter
908-
// output enable mode is applied by on the next tick event. See
909-
// `do_handle_tick_event`.
910-
transceiver.transmitter_output_mode <=
911-
request.transmitter_output_mode;
966+
// Update the transceiver register. Any changes are applied on
967+
// the next tick event. See `do_handle_tick_event`.
968+
transceiver <= transceiver_;
912969
end
913970

914971
{tagged Read, ControllerState}:
@@ -978,9 +1035,10 @@ module mkController #(
9781035
let target_timeout = False;
9791036
let hello_sent = False;
9801037

981-
// Copy the `presence` register so indiviual fields can be updated as
982-
// appropriate.
1038+
// Copy the `presence` and `transceiver` registers so indiviual fields
1039+
// can be updated as appropriate.
9831040
let presence_ = presence;
1041+
let transceiver_ = transceiver;
9841042

9851043
// Update the presence history if a Status message timeout occures.
9861044
if (presence.status_message_timeout_ticks_remaining == 0) begin
@@ -1017,38 +1075,71 @@ module mkController #(
10171075
presence <= presence_;
10181076
presence_summary_r[current_controller] <= presence_.present;
10191077

1078+
// Count down until the next Hello.
1079+
if (hello_timer.ticks_remaining == 0) begin
1080+
hello_timer.ticks_remaining <=
1081+
fromInteger(parameters.protocol.hello_interval);
1082+
end
1083+
else begin
1084+
hello_timer.ticks_remaining <= hello_timer.ticks_remaining - 1;
1085+
end
1086+
1087+
// Count down the transmitter disable timeout if the counter is active.
1088+
if (transceiver.transmitter_output_disable_timeout_ticks_remaining != 0) begin
1089+
transceiver_.transmitter_output_disable_timeout_ticks_remaining =
1090+
transceiver.transmitter_output_disable_timeout_ticks_remaining - 1;
1091+
end
1092+
// Start the disable timeout counter if the Target has been declared not
1093+
// present.
1094+
else if (transceiver.transmitter_output_enable_mode ==
1095+
EnabledWhenTargetPresent &&
1096+
presence.present &&
1097+
!presence_.present) begin
1098+
transceiver_.transmitter_output_disable_timeout_ticks_remaining =
1099+
fromInteger(parameters.transmitter_output_disable_timeout);
1100+
end
1101+
1102+
// Disable the transmitter output if the transmitter disable output
1103+
// timer expires. A count of one is used as the timeout here since this
1104+
// does not have to be precise and allows a value of zero to indicate
1105+
// the counter is not active.
1106+
if (transceiver.transmitter_output_enabled &&
1107+
transceiver.transmitter_output_disable_timeout_ticks_remaining == 1) begin
1108+
$display("%5t [Controller %02d] Transmitter output disabled",
1109+
$time,
1110+
current_controller);
1111+
1112+
transceiver_.transmitter_output_enabled = False;
1113+
end
1114+
1115+
// Write back the transceiver state.
1116+
transceiver <= transceiver_;
1117+
10201118
// Transmit an Hello message if the Hello timer expires.
10211119
if (hello_timer.ticks_remaining == 0) begin
10221120
$display("%5t [Controller %02d] Hello",
10231121
$time,
10241122
current_controller);
10251123

1026-
hello_timer.ticks_remaining <=
1027-
fromInteger(parameters.protocol.hello_interval);
1028-
10291124
transmitter_events.enq(
10301125
TransmitterEvent {
10311126
id: current_controller,
10321127
ev: tagged Message tagged Hello});
10331128

10341129
hello_sent = True;
10351130
end
1036-
// Count down the Hello timer.
1131+
// Transmit an OutputEnable event otherwise. These are sent every tick
1132+
// so that even if a state change in the output enable is requested
1133+
// during the same tick as the Hello message above the state will
1134+
// converge at most one tick later.
10371135
else begin
1038-
hello_timer.ticks_remaining <= hello_timer.ticks_remaining - 1;
1136+
transmitter_events.enq(
1137+
TransmitterEvent {
1138+
id: current_controller,
1139+
ev: tagged OutputEnabled
1140+
transceiver_.transmitter_output_enabled});
10391141
end
10401142

1041-
// Update the transmitter output enable based on its enable mode and
1042-
// Target presence.
1043-
case (transceiver.transmitter_output_mode)
1044-
Disabled:
1045-
transmitter_output_enabled_events.enq(False);
1046-
EnabledWhenTargetPresent:
1047-
transmitter_output_enabled_events.enq(presence.present);
1048-
AlwaysEnabled:
1049-
transmitter_output_enabled_events.enq(True);
1050-
endcase
1051-
10521143
// Enqueue a request to update the appropriate counters.
10531144
if (status_timeout || target_timeout || hello_sent) begin
10541145
enq_countable_application_events(
@@ -1106,6 +1197,25 @@ module mkController #(
11061197
presence <= presence_;
11071198
presence_summary_r[current_controller] <= presence_.present;
11081199

1200+
// Update the transmitter output enabled state if configured.
1201+
// The actual TransmitterEvent will be sent on the next tick.
1202+
// See the Tick handler.
1203+
TransceiverRegister transceiver_ = transceiver;
1204+
1205+
if (transceiver.transmitter_output_enable_mode ==
1206+
EnabledWhenTargetPresent &&
1207+
!presence.present &&
1208+
presence_.present) begin
1209+
$display("%5t [Controller %02d] Transmitter output enabled",
1210+
$time,
1211+
current_controller);
1212+
1213+
transceiver_.transmitter_output_enabled = True;
1214+
transceiver_.transmitter_output_disable_timeout_ticks_remaining = 0;
1215+
end
1216+
1217+
transceiver <= transceiver_;
1218+
11091219
enq_countable_application_events(
11101220
CountableApplicationEvents {
11111221
status_received: True,
@@ -1216,14 +1326,45 @@ module mkController #(
12161326
$time,
12171327
current_controller);
12181328

1219-
transceiver.receiver_status <= link_status_none;
1329+
TransceiverRegister transceiver_ = transceiver;
1330+
1331+
transceiver_.receiver_status = link_status_none;
1332+
1333+
if (transceiver.transmitter_output_enable_mode ==
1334+
EnabledWhenReceiverAligned &&
1335+
transceiver.transmitter_output_enabled) begin
1336+
// A ReceiverReset means the receiver is not aligned anymore
1337+
// and the disable timeout counter should be started.
1338+
transceiver_.transmitter_output_disable_timeout_ticks_remaining =
1339+
fromInteger(parameters.transmitter_output_disable_timeout);
1340+
end
1341+
1342+
// Write back the transceiver state.
1343+
transceiver <= transceiver_;
12201344

12211345
enq_countable_transceiver_events(
12221346
countable_transceiver_events_receiver_reset);
12231347
end
12241348

12251349
tagged ReceiverStatusChange .current_status: begin
1226-
transceiver.receiver_status <= current_status;
1350+
TransceiverRegister transceiver_ = transceiver;
1351+
1352+
transceiver_.receiver_status = current_status;
1353+
1354+
if (transceiver.transmitter_output_enable_mode ==
1355+
EnabledWhenReceiverAligned &&
1356+
!transceiver.transmitter_output_enabled &&
1357+
current_status.receiver_aligned) begin
1358+
$display("%5t [Controller %02d] Transmitter output enabled",
1359+
$time,
1360+
current_controller);
1361+
1362+
transceiver_.transmitter_output_enabled = True;
1363+
transceiver_.transmitter_output_disable_timeout_ticks_remaining = 0;
1364+
end
1365+
1366+
// Write back the transceiver state.
1367+
transceiver <= transceiver_;
12271368

12281369
enq_countable_transceiver_events(
12291370
determine_transceiver_events(
@@ -1255,11 +1396,6 @@ module mkController #(
12551396
event_handler_state <= AwaitingEvent;
12561397
endrule
12571398

1258-
(* fire_when_enabled *)
1259-
rule do_discard_transmitter_output_enabled_events;
1260-
transmitter_output_enabled_events.deq();
1261-
endrule
1262-
12631399
interface ControllerTransceiverClient txr;
12641400
interface Get tx = toGet(transmitter_events);
12651401
interface Put rx = toPut(receiver_events);
@@ -1332,16 +1468,10 @@ typedef struct {
13321468
Maybe#(t) data;
13331469
} RegisterFileRequest#(numeric type n, type t) deriving (Bits, Eq, FShow);
13341470

1335-
typedef enum {
1336-
Disabled = 0,
1337-
EnabledWhenTargetPresent = 1,
1338-
AlwaysEnabled = 2
1339-
} TransmitterOutputMode deriving (Bits, Eq, FShow);
1340-
13411471
typedef struct {
13421472
ControllerId#(n) id;
13431473
union tagged {
1344-
TransmitterOutputMode SetTransmitterOutputMode;
1474+
TransmitterOutputEnableMode SetTransmitterOutputEnableMode;
13451475
SystemPowerRequest SystemPowerRequest;
13461476
} ev;
13471477
} SoftwareEvent#(numeric type n) deriving (Bits, Eq, FShow);
@@ -1447,8 +1577,9 @@ typedef struct {
14471577
} PresenceRegister deriving (Bits, FShow);
14481578

14491579
typedef struct {
1450-
TransmitterOutputMode transmitter_output_mode;
1451-
Bit#(1) reserved;
1580+
UInt#(8) transmitter_output_disable_timeout_ticks_remaining;
1581+
TransmitterOutputEnableMode transmitter_output_enable_mode;
1582+
Bool transmitter_output_enabled;
14521583
LinkStatus receiver_status;
14531584
} TransceiverRegister deriving (Bits, FShow);
14541585

@@ -1522,6 +1653,12 @@ function Stmt read_controller_counter_into(
15221653
endaction
15231654
endseq;
15241655

1656+
function Bit#(8) transceiver_state_value(
1657+
TransmitterOutputEnableMode mode,
1658+
Bool transmitter_status,
1659+
LinkStatus receiver_status) =
1660+
{2'h0, pack(mode), pack(transmitter_status), pack(receiver_status)};
1661+
15251662
// Given a bit_vector_t with zero or more bits indicating requests and a
15261663
// bit_vector_t with exactly one bit set indicating the preferred (next) request
15271664
// to select, round-robin select the next request.

0 commit comments

Comments
 (0)