Skip to content

Commit c01c2c7

Browse files
committed
Refactor I2C
Signed-off-by: Wiktoria Kuna <[email protected]> Signed-off-by: Karol Gugala <[email protected]>
1 parent 1011f0b commit c01c2c7

25 files changed

+681
-356
lines changed

.ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
include:
22
- project: chipsalliance-ci-scripts
3-
file: i3c-core.yaml
3+
file: i3c-core.yaml

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ tests-ahb-ff: ## Run all verification/cocotb/* RTL tests for AHB bus configurati
117117

118118
tests: tests-axi tests-ahb ## Run all verification/cocotb/* RTL tests fro AHB and AXI bus configurations without coverage
119119

120+
tests-i2c: ## Run all I2C tests without coverage
121+
$(MAKE) config CFG_NAME=ahb
122+
cd $(COCOTB_VERIF_DIR) && $(PYTHON) -m nox -R -t "i2c" --no-venv --forcecolor
123+
120124
# TODO: Enable full coverage flow
121125
tests-coverage: ## Run all verification/block/* RTL tests with coverage
122126
cd $(COCOTB_VERIF_DIR) && BLOCK_COVERAGE_ENABLE=1 $(PYTHON) -m nox -R -k "verify" --no-venv
@@ -139,6 +143,7 @@ tests-uvm-debug: config ## Run debugging I3C Core UVM tests with nox
139143
tests-tool: ## Run all tool tests
140144
cd $(TOOL_VERIF_DIR) && $(PYTHON) -m nox -k "verify" --no-venv
141145

146+
142147
BLOCKS_VERIFICATION_PLANS = $(shell find $(TESTPLAN_DIR) -type f -name "*.hjson" ! -name "target*.hjson" | sort)
143148
CORE_VERIFICATION_PLANS = $(shell find $(TESTPLAN_DIR) -type f -name "*target*.hjson" | sort)
144149
verification-docs:

src/ctrl/controller_standby.sv

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -247,11 +247,53 @@ module controller_standby
247247

248248
assign i2c_rx_queue_flush_o = '0;
249249

250+
// I2C operates on 32 bit TTI data
251+
logic i2c_rx_queue_wvalid_int;
252+
logic rx_queue_wready_int;
253+
logic [31:0] i2c_rx_queue_wdata_int;
254+
255+
// 32 -> 8 on rx_queue
256+
width_converter_Nto8 xconv_i2c_rx_queue
257+
(
258+
.clk_i(clk_i),
259+
.rst_ni(rst_ni),
260+
261+
.sink_valid_i(i2c_rx_queue_wvalid_int),
262+
.sink_ready_o(rx_queue_wready_int),
263+
.sink_data_i (i2c_rx_queue_wdata_int),
264+
265+
.source_valid_o(i2c_rx_queue_wvalid_o),
266+
.source_ready_i(rx_queue_wready_i),
267+
.source_data_o(i2c_rx_queue_wdata_o),
268+
.source_flush_i(i2c_rx_queue_flush_o)
269+
);
270+
271+
272+
logic tx_queue_rvalid_int;
273+
logic i2c_tx_queue_rready_int;
274+
logic [31:0] tx_queue_rdata_int;
275+
// 8 -> 32 on tx_queue
276+
width_converter_8toN xconv_i2c_tx_queue
277+
(
278+
279+
.clk_i(clk_i),
280+
.rst_ni(rst_ni),
281+
282+
.sink_valid_i(tx_queue_rvalid_i),
283+
.sink_ready_o(i2c_tx_queue_rready_o),
284+
.sink_data_i(tx_queue_rdata_i),
285+
.sink_flush_i(1'b0),
286+
287+
.source_valid_o(tx_queue_rvalid_int),
288+
.source_ready_i(i2c_tx_queue_rready_int),
289+
.source_data_o(tx_queue_rdata_int)
290+
);
291+
250292
controller_standby_i2c #(
251293
.TtiRxDescDataWidth(TtiRxDescDataWidth),
252294
.TtiTxDescDataWidth(TtiTxDescDataWidth),
253-
.TtiRxDataWidth(TtiRxDataWidth),
254-
.TtiTxDataWidth(TtiTxDataWidth),
295+
.TtiRxDataWidth(32),
296+
.TtiTxDataWidth(32),
255297
.TtiRxDescThldWidth(TtiRxDescThldWidth),
256298
.TtiTxDescThldWidth(TtiTxDescThldWidth),
257299
.TtiRxThldWidth(TtiRxThldWidth),
@@ -284,19 +326,19 @@ module controller_standby
284326
.rx_queue_ready_thld_i(rx_queue_ready_thld_i),
285327
.rx_queue_ready_thld_trig_i(rx_queue_ready_thld_trig_i),
286328
.rx_queue_empty_i(rx_queue_empty_i),
287-
.rx_queue_wvalid_o(i2c_rx_queue_wvalid_o),
288-
.rx_queue_wready_i(rx_queue_wready_i),
289-
.rx_queue_wdata_o(i2c_rx_queue_wdata_o),
329+
.rx_queue_wvalid_o(i2c_rx_queue_wvalid_int),
330+
.rx_queue_wready_i(rx_queue_wready_int),
331+
.rx_queue_wdata_o(i2c_rx_queue_wdata_int),
290332
// .rx_queue_flush_o(i2c_rx_queue_flush_o), // TODO: Add flush support for I2C
291333
.tx_queue_full_i(tx_queue_full_i),
292334
.tx_queue_start_thld_i(tx_queue_start_thld_i),
293335
.tx_queue_start_thld_trig_i(tx_queue_start_thld_trig_i),
294336
.tx_queue_ready_thld_i(tx_queue_ready_thld_i),
295337
.tx_queue_ready_thld_trig_i(tx_queue_ready_thld_trig_i),
296338
.tx_queue_empty_i(tx_queue_empty_i),
297-
.tx_queue_rvalid_i(tx_queue_rvalid_i),
298-
.tx_queue_rready_o(i2c_tx_queue_rready_o),
299-
.tx_queue_rdata_i(tx_queue_rdata_i),
339+
.tx_queue_rvalid_i(tx_queue_rvalid_int),
340+
.tx_queue_rready_o(i2c_tx_queue_rready_int),
341+
.tx_queue_rdata_i(tx_queue_rdata_int),
300342
.bus_start_o(i2c_bus_start_o),
301343
.bus_rstart_o(i2c_bus_rstart_o),
302344
.bus_stop_o(i2c_bus_stop_o),

src/ctrl/controller_standby_i2c.sv

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ module controller_standby_i2c
108108
logic tx_fifo_valid_int;
109109
logic tx_fifo_ready_int;
110110

111+
logic rnw_int;
112+
111113
logic [AcqFifoWidth-1:0] acq_fifo_data_int;
112114
logic [AcqFifoDepthWidth-1:0] acq_fifo_depth_int;
113115
logic acq_fifo_ready_int;
@@ -132,6 +134,8 @@ module controller_standby_i2c
132134
.acq_fifo_wready_i(acq_fifo_ready_int),
133135
.acq_fifo_depth_o (acq_fifo_depth_int),
134136

137+
.rnw_i(rnw_int),
138+
135139
// TTI FIFOs
136140
.cmd_fifo_rdata_i (tx_desc_queue_rdata_i),
137141
.cmd_fifo_rvalid_i(tx_desc_queue_rvalid_i),
@@ -196,6 +200,7 @@ module controller_standby_i2c
196200
// Others
197201
.target_enable_i(i2c_standby_en_i),
198202
.target_idle_o(unused_target_idle_o),
203+
.target_rnw_o(rnw_int),
199204
.target_sr_p_cond_o(unused_target_sr_p_cond_o),
200205
.event_target_nack_o(unused_event_target_nack_o),
201206
.event_cmd_complete_o(unused_event_cmd_complete_o),

src/ctrl/flow_standby_i2c.sv

Lines changed: 74 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ module flow_standby_i2c
1616
output logic [AcqFifoDepthWidth-1:0] acq_fifo_depth_o,
1717
input logic acq_fifo_wready_i,
1818

19+
input logic rnw_i,
20+
1921
output logic tx_fifo_rvalid_o,
2022
input logic tx_fifo_rready_i,
2123
output logic [TxFifoWidth-1:0] tx_fifo_rdata_o,
@@ -31,12 +33,12 @@ module flow_standby_i2c
3133
input logic response_fifo_wready_i,
3234

3335
// TX FIFO
34-
input logic [7:0] tx_fifo_rdata_i,
36+
input logic [31:0] tx_fifo_rdata_i,
3537
input logic tx_fifo_rvalid_i,
3638
output logic tx_fifo_rready_o,
3739

3840
// RX FIFO
39-
output logic [7:0] rx_fifo_wdata_o,
41+
output logic [31:0] rx_fifo_wdata_o,
4042
output logic rx_fifo_wvalid_o,
4143
input logic rx_fifo_wready_i,
4244

@@ -59,6 +61,8 @@ module flow_standby_i2c
5961
state_t state_d, state_q;
6062
// Buffer for holding elements returned by I2C target FSM
6163
logic [AcqFifoWidth-1:0] fifo_buf[4];
64+
// FF for storing data to be sent over I2C
65+
logic [31:0] tx_fifo_rdata_d;
6266
// Are we currently mid-transfer?
6367
logic transfer_active;
6468
// Number of data bytes held in `fifo_buf`
@@ -86,31 +90,65 @@ module flow_standby_i2c
8690
logic is_start_read;
8791
logic xfer_read;
8892
logic pop_command_from_tti;
93+
logic pop_dword_from_tti;
8994
logic pop_data_from_tti;
95+
logic acq_fifo_wvalid_d;
96+
97+
logic [AcqFifoWidth-1:0] acq_fifo_wdata_d;
9098

91-
assign rx_fifo_wdata_o = fifo_buf[0][7:0];
99+
assign rx_fifo_wdata_o = {fifo_buf[3][7:0], fifo_buf[2][7:0], fifo_buf[1][7:0], fifo_buf[0][7:0]};
92100
assign byte_count = transaction_byte_count[1:0];
93101

94102
assign acq_fifo_wdata_byte_id = i2c_acq_byte_id_e'(acq_fifo_wdata_i[AcqFifoWidth-1:8]);
95-
assign start_detected = acq_fifo_wvalid_i & (acq_fifo_wdata_byte_id == AcqStart);
96-
assign stop_detected = acq_fifo_wvalid_i & (acq_fifo_wdata_byte_id == AcqStop);
97-
assign data_detected = acq_fifo_wvalid_i & (acq_fifo_wdata_byte_id == AcqData);
98-
assign nack_detected = acq_fifo_wvalid_i & (acq_fifo_wdata_byte_id == AcqNack);
99-
assign restart_detected = acq_fifo_wvalid_i & (acq_fifo_wdata_byte_id == AcqRestart);
100-
assign is_start_read = acq_fifo_wvalid_i &
101-
( acq_fifo_wdata_byte_id == AcqStart ||
102-
acq_fifo_wdata_byte_id == AcqRestart ||
103-
acq_fifo_wdata_byte_id == AcqNackStart );
104-
105-
// TODO: Bug: Set proper ACQ FIFO depth
106-
// [LINT_ERROR: CombLoop] The signal 'acq_fifo_depth_o' is on a comb loop
107-
// path between the 'flow_standby_i2c' and 'i2c_target_fsm' modules, e.g.:
108-
// In 'flow_standby_i2c':
109-
// acq_fifo_wvalid_i -> state_d -> acq_fifo_depth_o
110-
// In 'i2c_target_fsm':
111-
// acq_fifo_depth_i -> stretch_addr -> acq_fifo_wvalid_o
103+
always_ff @(posedge clk_i or negedge rst_ni) begin: control_ff
104+
if (!rst_ni) begin
105+
start_detected <= '0;
106+
stop_detected <= '0;
107+
data_detected <= '0;
108+
nack_detected <= '0;
109+
restart_detected <= '0;
110+
is_start_read <= '0;
111+
acq_fifo_wvalid_d <= '0;
112+
acq_fifo_wdata_d <= '0;
113+
end else begin
114+
start_detected <= acq_fifo_wvalid_i & (acq_fifo_wdata_byte_id == AcqStart);
115+
stop_detected <= acq_fifo_wvalid_i & (acq_fifo_wdata_byte_id == AcqStop);
116+
data_detected <= acq_fifo_wvalid_i & (acq_fifo_wdata_byte_id == AcqData);
117+
nack_detected <= acq_fifo_wvalid_i & (acq_fifo_wdata_byte_id == AcqNack);
118+
restart_detected <= acq_fifo_wvalid_i & (acq_fifo_wdata_byte_id == AcqRestart);
119+
is_start_read <= acq_fifo_wvalid_i & rnw_i;
120+
acq_fifo_wvalid_d <= acq_fifo_wvalid_i;
121+
acq_fifo_wdata_d <= acq_fifo_wdata_i;
122+
end
123+
end
124+
125+
// store data to send
126+
always_ff @(posedge clk_i or negedge rst_ni) begin: latch_tx_data
127+
if (!rst_ni) begin
128+
tx_fifo_rdata_d <= '0;
129+
end else begin
130+
if (tx_fifo_rready_o) tx_fifo_rdata_d <= tx_fifo_rdata_i;
131+
end
132+
end
133+
134+
always_comb
135+
case(byte_count)
136+
0: begin
137+
tx_fifo_rdata_o = tx_fifo_rdata_d[7:0];
138+
end
139+
1: begin
140+
tx_fifo_rdata_o = tx_fifo_rdata_d[15:8];
141+
end
142+
2: begin
143+
tx_fifo_rdata_o = tx_fifo_rdata_d[23:16];
144+
end
145+
3: begin
146+
tx_fifo_rdata_o = tx_fifo_rdata_d[31:24];
147+
end
148+
endcase
149+
112150
assign acq_fifo_depth_o = xfer_read ? 0 : {{(AcqFifoDepthWidth - 3){1'b0}},
113-
state_d == PushDWordToTTIQueue,
151+
state_q == PushDWordToTTIQueue,
114152
transaction_byte_count[1:0]};
115153

116154
always_ff @(posedge clk_i or negedge rst_ni) begin : state_transition
@@ -127,13 +165,7 @@ module flow_standby_i2c
127165
if (!xfer_read) begin
128166
// Write transfer
129167
if (data_detected) begin
130-
fifo_buf[byte_count] <= acq_fifo_wdata_i;
131-
end
132-
end else begin
133-
// Read transfer
134-
if (pop_data_from_tti) begin
135-
// TODO(verilator) fails to consftify loop variable for AstSelExtract
136-
fifo_buf[0] <= {AcqData, tx_fifo_rdata_i[7:0]};
168+
fifo_buf[byte_count] <= acq_fifo_wdata_d;
137169
end
138170
end
139171
end
@@ -190,7 +222,7 @@ module flow_standby_i2c
190222
end : get_command_from_tti
191223

192224
// State combo logic
193-
225+
assign pop_data_from_tti = tx_fifo_rvalid_i & xfer_read & (push_byte | pop_dword_from_tti);
194226
always_comb begin : state_outputs
195227
err_o = 0;
196228
rx_fifo_wvalid_o = 0;
@@ -204,7 +236,7 @@ module flow_standby_i2c
204236
tx_fifo_rready_o = 0;
205237
tx_fifo_rvalid_o = 0;
206238
pop_command_from_tti = 0;
207-
pop_data_from_tti = 0;
239+
pop_dword_from_tti = 0;
208240

209241
unique case (state_q)
210242
AwaitStart: begin
@@ -226,21 +258,20 @@ module flow_standby_i2c
226258
cmd_fifo_rready_o = 1;
227259
tx_fifo_rready_o = 1;
228260
pop_command_from_tti = cmd_fifo_rvalid_i;
229-
pop_data_from_tti = tx_fifo_rvalid_i;
230261
xfer_read = 1;
231262
end
232263
PopDWordFromTTIQueue: begin
233264
tx_fifo_rready_o = 1;
234-
pop_data_from_tti = tx_fifo_rvalid_i;
235265
xfer_read = 1;
266+
pop_dword_from_tti = 1;
236267
end
237268
SendByte: begin
238269
xfer_read = 1;
239-
push_byte = tx_fifo_rready_i;
240270
tx_fifo_rvalid_o = 1;
241271
end
242272
SwitchByteToSend: begin
243273
xfer_read = 1;
274+
push_byte = 1; //tx_fifo_rvalid_i;
244275
end
245276
AwaitStopOrRestart: begin
246277
end
@@ -250,9 +281,6 @@ module flow_standby_i2c
250281

251282
activate_transfer = start_detected;
252283
deactivate_transfer = stop_detected | restart_detected;
253-
254-
if (xfer_read) tx_fifo_rdata_o = fifo_buf[byte_count][7:0];
255-
else tx_fifo_rdata_o = 0;
256284
end : state_outputs
257285

258286
always_comb begin : state_function
@@ -268,7 +296,7 @@ module flow_standby_i2c
268296
if (stop_detected | restart_detected) begin
269297
state_d = (byte_count != 0) ? PushDWordToTTIQueue : PushResponseToTTIQueue;
270298
end else if (data_detected) state_d = (byte_count == 3) ? PushDWordToTTIQueue : ReceiveByte;
271-
else if (acq_fifo_wvalid_i) state_d = ReportError;
299+
else if (acq_fifo_wvalid_d) state_d = ReportError;
272300
end
273301
PushDWordToTTIQueue:
274302
if (rx_fifo_wready_i) state_d = transfer_active ? ReceiveByte : PushResponseToTTIQueue;
@@ -278,18 +306,18 @@ module flow_standby_i2c
278306
// but invalidated one cycle later.
279307
if (stop_detected | restart_detected)
280308
state_d = PushDWordToTTIQueue;
281-
else state_d = acq_fifo_wvalid_i ? ReportError : PushDWordToTTIQueue;
309+
else state_d = acq_fifo_wvalid_d ? ReportError : PushDWordToTTIQueue;
282310
PushResponseToTTIQueue: begin
283311
state_d = PushResponseToTTIQueue;
284312
if (response_fifo_wready_i) state_d = AwaitStart;
285313
// We can't wait any longer if there's a new byte, because we might be full
286-
else if (acq_fifo_wvalid_i) state_d = ReportError;
314+
else if (acq_fifo_wvalid_d) state_d = ReportError;
287315
end
288316
PopCommandFromTTIQueue: begin
289317
state_d = PopCommandFromTTIQueue;
290318
if (cmd_fifo_rvalid_i) begin
291319
if (cmd_fifo_rdata_i.data_length == 0) state_d = ReportError;
292-
else state_d = tx_fifo_rvalid_i ? SendByte : PopDWordFromTTIQueue;
320+
else state_d = (byte_count == 3) ? PopDWordFromTTIQueue : SendByte;
293321
end
294322
if (nack_detected) state_d = ReportError;
295323
end
@@ -300,17 +328,20 @@ module flow_standby_i2c
300328
end
301329
SendByte: begin
302330
state_d = SendByte;
303-
if (tx_fifo_rready_i)
304-
if (transaction_byte_count + 1 == read_transaction_length) state_d = AwaitStopOrRestart;
331+
if (tx_fifo_rready_i == 1'b1) begin
332+
if (transaction_byte_count + 1 == read_transaction_length) begin
333+
state_d = AwaitStopOrRestart;
334+
end
305335
else
306336
// Let the counter increment in a another cycle, so we hold tx_fifo_rvalid
307337
// with the correct byte set
308338
state_d = SwitchByteToSend;
339+
end
309340
if (nack_detected) state_d = ReportError;
310341
end
311342
SwitchByteToSend: begin
312343
state_d = SendByte;
313-
if ((byte_count == 0) & (transaction_byte_count != read_transaction_length))
344+
if ((byte_count == 3) & (transaction_byte_count != read_transaction_length))
314345
state_d = PopDWordFromTTIQueue;
315346
if (nack_detected) state_d = ReportError;
316347
end

src/ctrl/i2c_target_fsm.sv

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ module i2c_target_fsm
3131
input [AcqFifoWidth-1:0] acq_fifo_rdata_i, // only used for assertion
3232

3333
output logic target_idle_o, // indicates the target is idle
34+
output logic target_rnw_o, // indicates r/w transaction
3435

3536
input [15:0] t_r_i, // rise time of both SDA and SCL in clock units
3637
input [15:0] tsu_dat_i, // data setup time in clock units
@@ -342,6 +343,7 @@ module i2c_target_fsm
342343
state_e state_q, state_d;
343344

344345
logic rw_bit_q;
346+
assign target_rnw_o = rw_bit_q;
345347
always_ff @(posedge clk_i or negedge rst_ni) begin
346348
if (!rst_ni) begin
347349
rw_bit_q <= '0;

src/hci/axi_adapter.sv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ module axi_adapter #(
195195
s_cpuif_addr = i3c_req_addr[CsrAddrWidth-1:0];
196196
end
197197
generate
198-
if (AxiDataWidth === CsrDataWidth) begin
198+
if (AxiDataWidth == CsrDataWidth) begin
199199
assign s_cpuif_wr_biten = i3c_req_wbiten;
200200
assign s_cpuif_wr_data = i3c_req_wdata;
201201
assign i3c_req_rdata = s_cpuif_rd_data;

0 commit comments

Comments
 (0)