Skip to content

Commit 9145331

Browse files
glaserfclayton8
authored andcommitted
[src] Source sda_oe from a register and hard-wire I3C Target
- Remove the sda_oe comb logic to bus_tx_flow and put it behind a register - Hard-wire the I3C Target device to the pads for de-risking Signed-off-by: Florian Glaser <glaserf@lowrisc.org>
1 parent e39aa90 commit 9145331

File tree

7 files changed

+72
-36
lines changed

7 files changed

+72
-36
lines changed

src/ctrl/bus_tx_flow.sv

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ module bus_tx_flow import i3c_pkg::*; (
3434
// Open Drain / Push Pull
3535
output logic sel_od_pp_o,
3636

37+
// Output enable for SDA pad
38+
output logic sda_oe_o,
39+
3740
// Output I3C SDA bus line
3841
output logic sda_o
3942
);
@@ -42,14 +45,16 @@ module bus_tx_flow import i3c_pkg::*; (
4245
logic bit_counter_en;
4346
logic [3:0] bit_counter_q, bit_counter_d;
4447

48+
// Registers for all critical signals directly connected to the SDA pad
4549
i3c_byte_t req_value_q, req_value_d;
4650
i3c_drive_e drive_mode_q, drive_mode_d;
51+
logic sda_oe_q, sda_oe_d;
4752

4853
logic tx_done; // Indicates finished bit write
4954
logic bus_tx_done; // Feedback to requester that transfer is done
5055
logic req_error;
5156

52-
// TODO
57+
// TODO Can probably be removed
5358
assign req_error = 1'b0;
5459

5560
typedef enum logic [2:0] {
@@ -63,6 +68,24 @@ module bus_tx_flow import i3c_pkg::*; (
6368

6469
tx_state_e state_d, state_q;
6570

71+
// SDA is simply the MSB of the data shift register. No further logic or muxing.
72+
// Similar for pad drive mode and output enable.
73+
assign sda_o = req_value_q[7];
74+
assign sel_od_pp_o = drive_mode_q;
75+
assign sda_oe_o = sda_oe_q;
76+
77+
/*
78+
Truth table for sda_oe.
79+
80+
sel_od_pp_o | sda_o || sda_oe_o | IO state
81+
------------+--------++----------+-----------
82+
0 | 0 || 1 | 0
83+
0 | 1 || 0 | hi-z
84+
1 | 0 || 1 | 0
85+
1 | 1 || 1 | 1
86+
*/
87+
assign sda_oe_d = drive_mode_d || !req_value_d[7];
88+
6689
// Common logic whenever a transfer gets started, including back-to-back transfers
6790
function automatic tx_state_e start_transfer(
6891
input bus_tx_req_t bus_tx_req,
@@ -122,7 +145,6 @@ module bus_tx_flow import i3c_pkg::*; (
122145

123146
endfunction : start_transfer
124147

125-
126148
// Bit counter used for byte transfers
127149
always_comb begin
128150
bit_counter_d = bit_counter_q;
@@ -136,10 +158,7 @@ module bus_tx_flow import i3c_pkg::*; (
136158
end
137159
end
138160

139-
// SDA is simply the MSB of the data shift register. No further logic or muxing.
140-
assign sda_o = req_value_q[7];
141-
assign sel_od_pp_o = drive_mode_q;
142-
161+
// Main FSM which handles all low-level bus details in terms of transmitting
143162
always_comb begin : tx_fsm
144163
bit_counter_en = 1'b0;
145164

@@ -289,11 +308,13 @@ module bus_tx_flow import i3c_pkg::*; (
289308
bit_counter_q <= '0;
290309
req_value_q <= '1;
291310
drive_mode_q <= OpenDrain;
311+
sda_oe_q <= 1'b0;
292312
state_q <= Idle;
293313
end else begin
294314
bit_counter_q <= bit_counter_d;
295315
req_value_q <= req_value_d;
296316
drive_mode_q <= drive_mode_d;
317+
sda_oe_q <= sda_oe_d;
297318
state_q <= state_d;
298319
end
299320
end

src/ctrl/controller.sv

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ module controller
6767
input logic sda_i,
6868
output logic scl_o,
6969
output logic sda_o,
70+
output logic sda_oe_o,
7071
output logic sel_od_pp_o,
7172
input logic arbitration_lost_i,
7273

@@ -271,6 +272,8 @@ module controller
271272
output logic in_hdr_mode_o
272273
);
273274

275+
localparam int unsigned RecoveryMode = 'h3;
276+
274277
logic phy_en;
275278
logic [1:0] phy_mux_select;
276279
logic i2c_active_en;
@@ -339,25 +342,30 @@ module controller
339342
bus_state_t ctrl_bus_i[4];
340343
logic ctrl_scl_o[4];
341344
logic ctrl_sda_o[4];
345+
logic ctrl_sda_oe_o[4];
342346
logic ctrl_sel_od_pp_i[4];
343347

344-
localparam int unsigned RecoveryMode = 'h3;
345-
always_comb begin : mux_4_to_1
346-
scl_o = ctrl_scl_o[phy_mux_select];
347-
sda_o = ctrl_sda_o[phy_mux_select];
348-
sel_od_pp_o = ctrl_sel_od_pp_i[phy_mux_select];
348+
assign ctrl_sda_oe_o[0] = 1'b0;
349+
assign ctrl_sda_oe_o[1] = 1'b0;
349350

351+
// NOTE: For now, the I3C standby (target) device is hard-wired onto the bus for risk mitigation
352+
assign scl_o = ctrl_scl_o[3];
353+
assign sda_o = ctrl_sda_o[3];
354+
assign sda_oe_o = ctrl_sda_oe_o[3];
355+
assign sel_od_pp_o = ctrl_sel_od_pp_i[3];
356+
357+
assign ctrl_bus_i[3] = bus;
358+
359+
// Tieoff of all other devices
360+
always_comb begin : mux_tieoff
350361
// Default
351-
for (int i=0; i<4; i++) begin
352-
ctrl_bus_i[i] = '0;
353-
ctrl_bus_i[i].sda.value = '1;
354-
ctrl_bus_i[i].scl.value = '1;
355-
ctrl_bus_i[i].sda.stable_high = '1;
356-
ctrl_bus_i[i].scl.stable_high = '1;
362+
for (int i=0; i<3; i++) begin
363+
ctrl_bus_i[i] = '0;
364+
ctrl_bus_i[i].sda.value = 1'b1;
365+
ctrl_bus_i[i].scl.value = 1'b1;
366+
ctrl_bus_i[i].sda.stable_high = 1'b1;
367+
ctrl_bus_i[i].scl.stable_high = 1'b1;
357368
end
358-
359-
// Muxed
360-
ctrl_bus_i[phy_mux_select] = bus;
361369
end
362370

363371
configuration xconfiguration (
@@ -496,6 +504,7 @@ module controller
496504
.ctrl_bus_i(ctrl_bus_i[2:3]),
497505
.ctrl_scl_o(ctrl_scl_o[2:3]),
498506
.ctrl_sda_o(ctrl_sda_o[2:3]),
507+
.ctrl_sda_oe_o(ctrl_sda_oe_o[2:3]),
499508
.phy_sel_od_pp_o(ctrl_sel_od_pp_i[2:3]),
500509
.arbitration_lost_i(arbitration_lost_i),
501510
.rx_desc_queue_full_i(tti_rx_desc_queue_full_i),

src/ctrl/controller_standby.sv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ module controller_standby
3434
input bus_state_t ctrl_bus_i[2],
3535
output logic ctrl_scl_o[2],
3636
output logic ctrl_sda_o[2],
37+
output logic ctrl_sda_oe_o[2],
3738
output logic phy_sel_od_pp_o[2],
3839
input logic arbitration_lost_i,
3940

@@ -327,6 +328,8 @@ module controller_standby
327328
.source_data_o(tx_queue_rdata_int)
328329
);
329330

331+
assign ctrl_sda_oe_o[0] = 1'b0;
332+
330333
controller_standby_i2c #(
331334
.TtiRxDescDataWidth(TtiRxDescDataWidth),
332335
.TtiTxDescDataWidth(TtiTxDescDataWidth),
@@ -421,6 +424,7 @@ module controller_standby
421424
.ctrl_bus_i(ctrl_bus_i[1]),
422425
.ctrl_scl_o(ctrl_scl_o[1]),
423426
.ctrl_sda_o(ctrl_sda_o[1]),
427+
.ctrl_sda_oe_o(ctrl_sda_oe_o[1]),
424428
.arbitration_lost_i(arbitration_lost_i),
425429
.phy_sel_od_pp_o(phy_sel_od_pp_o[1]),
426430
.rx_desc_queue_wvalid_o(i3c_rx_desc_queue_wvalid_o),

src/ctrl/controller_standby_i3c.sv

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ module controller_standby_i3c
2323
input bus_state_t ctrl_bus_i,
2424
output logic ctrl_scl_o,
2525
output logic ctrl_sda_o,
26+
output logic ctrl_sda_oe_o,
2627
output logic phy_sel_od_pp_o,
2728
input logic arbitration_lost_i,
2829

@@ -609,6 +610,7 @@ module controller_standby_i3c
609610
.tx_rsp_o(bus_tx_rsp),
610611

611612
.sel_od_pp_o(phy_sel_od_pp_o),
613+
.sda_oe_o (ctrl_sda_oe_o),
612614
.sda_o (ctrl_sda_o)
613615
);
614616

src/i3c.sv

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ module i3c
190190
input logic i3c_sda_i, // serial data input from i3c bus
191191
output logic i3c_sda_o, // serial data output to i3c bus
192192

193+
output logic i3c_sda_oe_o, // Pad output enable
193194
output logic sel_od_pp_o, // 0 - Open Drain, 1 - Push Pull
194195

195196
// DAT memory export interface
@@ -478,6 +479,7 @@ module i3c
478479
logic ctrl2phy_scl;
479480
logic ctrl2phy_sda;
480481
logic ctrl_sel_od_pp;
482+
logic ctrl_sda_oe;
481483

482484
// Configuration
483485
logic phy_en;
@@ -590,6 +592,7 @@ module i3c
590592
.sda_i(phy2ctrl_sda),
591593
.scl_o(ctrl2phy_scl),
592594
.sda_o(ctrl2phy_sda),
595+
.sda_oe_o(ctrl_sda_oe),
593596
.sel_od_pp_o(ctrl_sel_od_pp),
594597
.arbitration_lost_i(arbitration_lost_q),
595598

@@ -1288,6 +1291,8 @@ module i3c
12881291
.ctrl_sda_i(ctrl2phy_sda),
12891292
.ctrl_scl_o(phy2ctrl_scl),
12901293
.ctrl_sda_o(phy2ctrl_sda),
1294+
.ctrl_sda_oe_i(ctrl_sda_oe),
1295+
.ctrl_sda_oe_o(i3c_sda_oe_o),
12911296
.sel_od_pp_i(ctrl_sel_od_pp),
12921297
.sel_od_pp_o(sel_od_pp_o)
12931298
);

src/i3c_wrapper.sv

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -217,11 +217,12 @@ module i3c_wrapper #(
217217
`endif
218218
`endif
219219

220-
.i3c_scl_i (scl_i),
221-
.i3c_scl_o (scl_o),
222-
.i3c_sda_i (sda_i),
223-
.i3c_sda_o (sda_o),
224-
.sel_od_pp_o(sel_od_pp_o),
220+
.i3c_scl_i (scl_i),
221+
.i3c_scl_o (scl_o),
222+
.i3c_sda_i (sda_i),
223+
.i3c_sda_o (sda_o),
224+
.i3c_sda_oe_o(sda_oe),
225+
.sel_od_pp_o (sel_od_pp_o),
225226

226227
.dat_mem_src_i (dat_mem_src),
227228
.dat_mem_sink_o(dat_mem_sink),
@@ -274,18 +275,7 @@ module i3c_wrapper #(
274275
.cfg_i('0) // Unused
275276
);
276277

277-
/*
278-
Truth table.
279278

280-
sel_od_pp_o | sda_o || sda_oe | IO state
281-
------------+--------++--------+-----------
282-
0 | 0 || 1 | 0
283-
0 | 1 || 0 | hi-z
284-
1 | 0 || 1 | 0
285-
1 | 1 || 1 | 1
286-
*/
287-
288-
assign sda_oe = sel_od_pp_o || !sda_o;
289279
assign scl_oe = 1'b0;
290280

291281
endmodule

src/phy/i3c_phy.sv

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ module i3c_phy (
2020
output logic ctrl_scl_o,
2121
output logic ctrl_sda_o,
2222

23+
// Pad output enable
24+
input logic ctrl_sda_oe_i,
25+
output logic ctrl_sda_oe_o,
26+
2327
// Open-Drain / Push-Pull control
2428
input logic sel_od_pp_i,
2529
output logic sel_od_pp_o
@@ -59,5 +63,6 @@ module i3c_phy (
5963
assign sda_o = ctrl_sda_i;
6064
assign scl_o = ctrl_scl_i;
6165
assign sel_od_pp_o = sel_od_pp_i;
66+
assign ctrl_sda_oe_o = ctrl_sda_oe_i;
6267

6368
endmodule

0 commit comments

Comments
 (0)