[i2c, rtl] Target features addition
1. Interrupt when host fails to complete a transaction
2. Clock stretching by target after a complete transaction (read and/or write)
3. Automatic clock stretching by target when ACQ FIFO is full
Signed-off-by: Igor Kouznetsov <igor.kouznetsov@wdc.com>
diff --git a/hw/ip/i2c/data/i2c.hjson b/hw/ip/i2c/data/i2c.hjson
index a12bf0f..b02c775 100644
--- a/hw/ip/i2c/data/i2c.hjson
+++ b/hw/ip/i2c/data/i2c.hjson
@@ -58,6 +58,9 @@
{ name: "ack_stop"
desc: "raised if STOP is received after ACK (host sends both signals)."
}
+ { name: "host_timeout"
+ desc: "raised if the host stops sending the clock during an ongoing transaction."
+ }
]
// REGISTER definition
@@ -493,5 +496,36 @@
{ bits: "7:0" }
]
}
+ { name: "STRETCH_CTRL"
+ desc: "I2C target clock stretching control"
+ swaccess: "rw"
+ hwaccess: "hro"
+ fields: [
+ { bits: "0"
+ name: "ENABLEADDR"
+ desc: "Enable clock stretching after address matching completes"
+ }
+ { bits: "1"
+ name: "ENABLETX"
+ desc: "Enable clock stretching after ongoing transmit (read) transaction completes"
+ }
+ { bits: "2"
+ name: "ENABLEACQ"
+ desc: "Enable clock stretching after ongoing acquire (write) transaction completes"
+ }
+ { bits: "3"
+ name: "STOP"
+ desc: "Stop clock stretching and resume normal operation"
+ }
+ ]
+ }
+ { name: "HOST_TIMEOUT_CTRL"
+ desc: "I2C host clock generation timeout value (in units of input clock frequency)"
+ swaccess: "rw"
+ hwaccess: "hro"
+ fields: [
+ { bits: "31:0" }
+ ]
+ }
]
}
diff --git a/hw/ip/i2c/rtl/i2c.sv b/hw/ip/i2c/rtl/i2c.sv
index c24a22e..1b42210 100644
--- a/hw/ip/i2c/rtl/i2c.sv
+++ b/hw/ip/i2c/rtl/i2c.sv
@@ -37,7 +37,8 @@
output logic intr_tx_nonempty_o,
output logic intr_tx_overflow_o,
output logic intr_acq_overflow_o,
- output logic intr_ack_stop_o
+ output logic intr_ack_stop_o,
+ output logic intr_host_timeout_o
);
import i2c_reg_pkg::*;
@@ -83,7 +84,8 @@
.intr_tx_nonempty_o,
.intr_tx_overflow_o,
.intr_acq_overflow_o,
- .intr_ack_stop_o
+ .intr_ack_stop_o,
+ .intr_host_timeout_o
);
// For I2C, in standard, fast and fast-plus modes, outputs simulated as open-drain outputs.
@@ -117,5 +119,6 @@
`ASSERT_KNOWN(IntrTxOflwKnownO_A, intr_tx_overflow_o)
`ASSERT_KNOWN(IntrAcqOflwKnownO_A, intr_acq_overflow_o)
`ASSERT_KNOWN(IntrAckStopKnownO_A, intr_ack_stop_o)
+ `ASSERT_KNOWN(IntrHostTimeoutKnownO_A, intr_host_timeout_o)
endmodule
diff --git a/hw/ip/i2c/rtl/i2c_core.sv b/hw/ip/i2c/rtl/i2c_core.sv
index 32a6e97..ec3092a 100644
--- a/hw/ip/i2c/rtl/i2c_core.sv
+++ b/hw/ip/i2c/rtl/i2c_core.sv
@@ -30,7 +30,8 @@
output logic intr_tx_nonempty_o,
output logic intr_tx_overflow_o,
output logic intr_acq_overflow_o,
- output logic intr_ack_stop_o
+ output logic intr_ack_stop_o,
+ output logic intr_host_timeout_o
);
logic [15:0] thigh;
@@ -45,6 +46,11 @@
logic [15:0] t_buf;
logic [30:0] stretch_timeout;
logic timeout_enable;
+ logic stretch_en_addr;
+ logic stretch_en_tx;
+ logic stretch_en_acq;
+ logic stretch_stop;
+ logic [31:0] host_timeout;
logic scl_out_fsm;
logic sda_out_fsm;
@@ -64,6 +70,7 @@
logic event_tx_overflow;
logic event_acq_overflow;
logic event_ack_stop;
+ logic event_host_timeout;
logic [15:0] scl_rx_val;
logic [15:0] sda_rx_val;
@@ -196,6 +203,11 @@
assign t_buf = reg2hw.timing4.t_buf.q;
assign stretch_timeout = reg2hw.timeout_ctrl.val.q;
assign timeout_enable = reg2hw.timeout_ctrl.en.q;
+ assign stretch_en_addr = reg2hw.stretch_ctrl.enableaddr.q;
+ assign stretch_en_tx = reg2hw.stretch_ctrl.enabletx.q;
+ assign stretch_en_acq = reg2hw.stretch_ctrl.enableacq.q;
+ assign stretch_stop = reg2hw.stretch_ctrl.stop.q;
+ assign host_timeout = reg2hw.host_timeout_ctrl.q;
assign i2c_fifo_rxrst = reg2hw.fifo_ctrl.rxrst.q & reg2hw.fifo_ctrl.rxrst.qe;
assign i2c_fifo_fmtrst = reg2hw.fifo_ctrl.fmtrst.q & reg2hw.fifo_ctrl.fmtrst.qe;
@@ -384,6 +396,7 @@
.tx_fifo_rready_o (tx_fifo_rready),
.tx_fifo_rdata_i (tx_fifo_rdata),
+ .acq_fifo_wready_i (acq_fifo_wready),
.acq_fifo_wvalid_o (acq_fifo_wvalid),
.acq_fifo_wdata_o (acq_fifo_wdata),
@@ -402,6 +415,11 @@
.t_buf_i (t_buf),
.stretch_timeout_i (stretch_timeout),
.timeout_enable_i (timeout_enable),
+ .stretch_en_addr_i (stretch_en_addr),
+ .stretch_en_tx_i (stretch_en_tx),
+ .stretch_en_acq_i (stretch_en_acq),
+ .stretch_stop_i (stretch_stop),
+ .host_timeout_i (host_timeout),
.target_address0_i (target_address0),
.target_mask0_i (target_mask0),
@@ -416,7 +434,8 @@
.event_trans_complete_o (event_trans_complete),
.event_tx_empty_o (event_tx_empty),
.event_tx_nonempty_o (event_tx_nonempty),
- .event_ack_stop_o (event_ack_stop)
+ .event_ack_stop_o (event_ack_stop),
+ .event_host_timeout_o (event_host_timeout)
);
prim_intr_hw #(.Width(1)) intr_hw_fmt_watermark (
@@ -614,4 +633,17 @@
.intr_o (intr_ack_stop_o)
);
+ prim_intr_hw #(.Width(1)) intr_hw_host_timeout (
+ .clk_i,
+ .rst_ni,
+ .event_intr_i (event_host_timeout),
+ .reg2hw_intr_enable_q_i (reg2hw.intr_enable.host_timeout.q),
+ .reg2hw_intr_test_q_i (reg2hw.intr_test.host_timeout.q),
+ .reg2hw_intr_test_qe_i (reg2hw.intr_test.host_timeout.qe),
+ .reg2hw_intr_state_q_i (reg2hw.intr_state.host_timeout.q),
+ .hw2reg_intr_state_de_o (hw2reg.intr_state.host_timeout.de),
+ .hw2reg_intr_state_d_o (hw2reg.intr_state.host_timeout.d),
+ .intr_o (intr_host_timeout_o)
+ );
+
endmodule
diff --git a/hw/ip/i2c/rtl/i2c_fsm.sv b/hw/ip/i2c/rtl/i2c_fsm.sv
index 7bc7d9b..da2f3c6 100644
--- a/hw/ip/i2c/rtl/i2c_fsm.sv
+++ b/hw/ip/i2c/rtl/i2c_fsm.sv
@@ -36,6 +36,7 @@
output logic tx_fifo_rready_o, // populates tx_fifo
input [7:0] tx_fifo_rdata_i, // byte in tx_fifo to be sent to host
+ input logic acq_fifo_wready_i, // low if acq_fifo is full
output logic acq_fifo_wvalid_o, // high if there is valid data in acq_fifo
output logic [9:0] acq_fifo_wdata_o, // byte and signal in acq_fifo read from target
@@ -54,6 +55,11 @@
input [15:0] t_buf_i, // bus free time between STOP and START in clock units
input [30:0] stretch_timeout_i, // max time target may stretch the clock
input timeout_enable_i, // assert if target stretches clock past max
+ input stretch_en_addr_i, // enable target stretching clock after address matching
+ input stretch_en_tx_i, // enable target stretching clock after transmit transaction
+ input stretch_en_acq_i, // enable target stretching clock after acquire transaction
+ input stretch_stop_i, // stop stretching clock and resume normal operation
+ input [31:0] host_timeout_i, // max time target waits for host to pull clock down
input logic [6:0] target_address0_i,
input logic [6:0] target_mask0_i,
@@ -68,7 +74,8 @@
output logic event_trans_complete_o, // Transaction is complete
output logic event_tx_empty_o, // tx_fifo is empty but data is needed
output logic event_tx_nonempty_o, // tx_fifo is nonempty after stop
- output logic event_ack_stop_o // target received stop after ack
+ output logic event_ack_stop_o, // target received stop after ack
+ output logic event_host_timeout_o // host ceased sending SCL pulses during ongoing transactn
);
// I2C bus clock timing variables
@@ -107,6 +114,7 @@
logic address_match; // indicates one of target's addresses matches the one sent by host
logic [7:0] input_byte; // register for reads from host
logic input_byte_clr;// clear input_byte contents
+ logic [31:0] scl_high_cnt; // counter for continuously released scl_i
// Target bit counter variables
logic [3:0] bit_idx; // bit index including ack/nack
@@ -273,6 +281,17 @@
end
end
+ // Counter for continuously released SCL state
+ always_ff @ (posedge clk_i or negedge rst_ni) begin : scl_high_counter
+ if (!rst_ni) begin
+ scl_high_cnt <= 32'd0;
+ end else if (scl_i) begin
+ scl_high_cnt <= scl_high_cnt + 1'b1;
+ end else begin
+ scl_high_cnt <= 32'd0;
+ end
+ end
+
// Deserializer for a byte read from the bus on the target side
assign address0_match = ((input_byte[7:1] & target_mask0_i) == target_address0_i);
assign address1_match = ((input_byte[7:1] & target_mask1_i) == target_address1_i);
@@ -310,7 +329,8 @@
AddrRead, AddrAckWait, AddrAckSetup, AddrAckPulse, AddrAckHold,
TransmitWait, TransmitSetup, TransmitPulse, TransmitHold, TransmitAck,
AcquireByte, AcquireAckWait, AcquireAckSetup, AcquireAckPulse, AcquireAckHold,
- PopTxFifo, StretchClock, AcquireSrP
+ PopTxFifo, AcquireSrP, StretchTxEmpty, StretchAcqFull, StretchAddr,
+ StretchAcquire, StretchTransmit
} state_e;
state_e state_q, state_d;
@@ -587,13 +607,6 @@
target_idle_o = 1'b0;
tx_fifo_rready_o = 1'b1;
end
- // StretchClock: target stretches the clock
- StretchClock : begin
- target_idle_o = 1'b0;
- tx_fifo_rready_o = 1'b1;
- scl_temp = 1'b0;
- if (tx_fifo_depth_i == '0) event_tx_empty_o = 1'b1;
- end
// AcquireByte: target acquires a byte
AcquireByte : begin
target_idle_o = 1'b0;
@@ -628,6 +641,33 @@
acq_fifo_wvalid_o = 1'b1;
if (tx_fifo_depth_i != '0) event_tx_nonempty_o = 1'b1;
end
+ // StretchAddr: target stretches the clock after matching an address
+ StretchAddr : begin
+ target_idle_o = 1'b0;
+ scl_temp = 1'b0;
+ end
+ // StretchAcquire: target stretches the clock after acquiring a byte
+ StretchAcquire : begin
+ target_idle_o = 1'b0;
+ scl_temp = 1'b0;
+ end
+ // StretchTransmit: target stretches the clock after transmitting a byte
+ StretchTransmit : begin
+ target_idle_o = 1'b0;
+ scl_temp = 1'b0;
+ end
+ // StretchTxEmpty: target stretches the clock when tx_fifo is empty
+ StretchTxEmpty : begin
+ target_idle_o = 1'b0;
+ tx_fifo_rready_o = 1'b1;
+ scl_temp = 1'b0;
+ if (tx_fifo_depth_i == '0) event_tx_empty_o = 1'b1;
+ end
+ // StretchAcqFull: target stretches the clock when acq_fifo is full
+ StretchAcqFull : begin
+ target_idle_o = 1'b0;
+ scl_temp = 1'b0;
+ end
// default
default : begin
host_idle_o = 1'b1;
@@ -958,7 +998,8 @@
// AddrAckWait: pause before acknowledging
AddrAckWait : begin
if (tcount_q == 20'd1) begin
- state_d = AddrAckSetup;
+ if (stretch_en_addr_i) state_d = StretchAddr;
+ else state_d = AddrAckSetup;
end
end
// AddrAckSetup: target pulls SDA low while SCL is low
@@ -981,8 +1022,11 @@
state_d = TransmitWait;
load_tcount = 1'b1;
tcount_sel = tClockLow;
- end else state_d = StretchClock;
- end else state_d = AcquireByte;
+ end else state_d = StretchTxEmpty;
+ end else begin
+ if (acq_fifo_wready_i) state_d = AcquireByte;
+ else state_d = StretchAcqFull;
+ end
end
end
@@ -1019,8 +1063,10 @@
// TransmitAck: target waits for host to ACK transmission
TransmitAck : begin
if (scl_i) begin
- if (host_ack) state_d = PopTxFifo;
- else begin
+ if (host_ack) begin
+ if (stretch_en_tx_i) state_d = StretchTransmit;
+ else state_d = PopTxFifo;
+ end else begin
if (start_det || stop_det) state_d = AcquireSrP;
end
end
@@ -1031,18 +1077,7 @@
if (!target_enable_i) begin
state_d = Idle;
end else if (tx_fifo_depth_i == 6'd1 && !tx_fifo_wvalid_i) begin
- state_d = StretchClock;
- end else begin
- state_d = TransmitWait;
- load_tcount = 1'b1;
- tcount_sel = tClockLow;
- end
- end
-
- // StretchClock: target stretches the clock
- StretchClock : begin
- if (tx_fifo_depth_i == '0) begin
- state_d = StretchClock;
+ state_d = StretchTxEmpty;
end else begin
state_d = TransmitWait;
load_tcount = 1'b1;
@@ -1062,7 +1097,8 @@
// AcquireAckWait: pause before acknowledging
AcquireAckWait : begin
if (tcount_q == 20'd1) begin
- state_d = AcquireAckSetup;
+ if (stretch_en_acq_i) state_d = StretchAcquire;
+ else state_d = AcquireAckSetup;
end
end
// AcquireAckSetup: target pulls SDA low while SCL is low
@@ -1092,6 +1128,41 @@
state_d = Idle;
end
+ // StretchAddr: target stretches the clock after matching an address
+ StretchAddr : begin
+ if (!stretch_stop_i) state_d = StretchAddr;
+ else state_d = AddrAckSetup;
+ end
+
+ // StretchAcquire: target stretches the clock after acquiring a byte
+ StretchAcquire : begin
+ if (!stretch_stop_i) state_d = StretchAcquire;
+ else state_d = AcquireAckSetup;
+ end
+
+ // StretchTransmit: target stretches the clock after transmitting a byte
+ StretchTransmit : begin
+ if (!stretch_stop_i) state_d = StretchTransmit;
+ else state_d = PopTxFifo;
+ end
+
+ // StretchTxEmpty: target stretches the clock when tx_fifo is empty
+ StretchTxEmpty : begin
+ if (tx_fifo_depth_i == '0) begin
+ state_d = StretchTxEmpty;
+ end else begin
+ state_d = TransmitWait;
+ load_tcount = 1'b1;
+ tcount_sel = tClockLow;
+ end
+ end
+
+ // StretchAcqFull: target stretches the clock when acq_fifo is full
+ StretchAcqFull : begin
+ if (acq_fifo_wready_i) state_d = AcquireByte;
+ else state_d = StretchAcqFull;
+ end
+
// default
default : begin
state_d = Idle;
@@ -1124,4 +1195,7 @@
assign scl_o = scl_temp;
assign sda_o = sda_temp;
+ // Host ceased sending SCL pulses during ongoing transaction
+ assign event_host_timeout_o = (!target_idle_o & (scl_high_cnt > host_timeout_i)) ? 1'b1 : 1'b0;
+
endmodule
diff --git a/hw/ip/i2c/rtl/i2c_reg_pkg.sv b/hw/ip/i2c/rtl/i2c_reg_pkg.sv
index 5b4770a..08c0772 100644
--- a/hw/ip/i2c/rtl/i2c_reg_pkg.sv
+++ b/hw/ip/i2c/rtl/i2c_reg_pkg.sv
@@ -58,6 +58,9 @@
struct packed {
logic q;
} ack_stop;
+ struct packed {
+ logic q;
+ } host_timeout;
} i2c_reg2hw_intr_state_reg_t;
typedef struct packed {
@@ -106,6 +109,9 @@
struct packed {
logic q;
} ack_stop;
+ struct packed {
+ logic q;
+ } host_timeout;
} i2c_reg2hw_intr_enable_reg_t;
typedef struct packed {
@@ -169,6 +175,10 @@
logic q;
logic qe;
} ack_stop;
+ struct packed {
+ logic q;
+ logic qe;
+ } host_timeout;
} i2c_reg2hw_intr_test_reg_t;
typedef struct packed {
@@ -336,6 +346,25 @@
logic qe;
} i2c_reg2hw_txdata_reg_t;
+ typedef struct packed {
+ struct packed {
+ logic q;
+ } enableaddr;
+ struct packed {
+ logic q;
+ } enabletx;
+ struct packed {
+ logic q;
+ } enableacq;
+ struct packed {
+ logic q;
+ } stop;
+ } i2c_reg2hw_stretch_ctrl_reg_t;
+
+ typedef struct packed {
+ logic [31:0] q;
+ } i2c_reg2hw_host_timeout_ctrl_reg_t;
+
typedef struct packed {
struct packed {
@@ -398,6 +427,10 @@
logic d;
logic de;
} ack_stop;
+ struct packed {
+ logic d;
+ logic de;
+ } host_timeout;
} i2c_hw2reg_intr_state_reg_t;
typedef struct packed {
@@ -475,30 +508,32 @@
// Register to internal design logic //
///////////////////////////////////////
typedef struct packed {
- i2c_reg2hw_intr_state_reg_t intr_state; // [348:334]
- i2c_reg2hw_intr_enable_reg_t intr_enable; // [333:319]
- i2c_reg2hw_intr_test_reg_t intr_test; // [318:289]
- i2c_reg2hw_ctrl_reg_t ctrl; // [288:287]
- i2c_reg2hw_rdata_reg_t rdata; // [286:278]
- i2c_reg2hw_fdata_reg_t fdata; // [277:259]
- i2c_reg2hw_fifo_ctrl_reg_t fifo_ctrl; // [258:244]
- i2c_reg2hw_ovrd_reg_t ovrd; // [243:241]
- i2c_reg2hw_timing0_reg_t timing0; // [240:209]
- i2c_reg2hw_timing1_reg_t timing1; // [208:177]
- i2c_reg2hw_timing2_reg_t timing2; // [176:145]
- i2c_reg2hw_timing3_reg_t timing3; // [144:113]
- i2c_reg2hw_timing4_reg_t timing4; // [112:81]
- i2c_reg2hw_timeout_ctrl_reg_t timeout_ctrl; // [80:49]
- i2c_reg2hw_target_id_reg_t target_id; // [48:21]
- i2c_reg2hw_acqdata_reg_t acqdata; // [20:9]
- i2c_reg2hw_txdata_reg_t txdata; // [8:0]
+ i2c_reg2hw_intr_state_reg_t intr_state; // [388:373]
+ i2c_reg2hw_intr_enable_reg_t intr_enable; // [372:357]
+ i2c_reg2hw_intr_test_reg_t intr_test; // [356:325]
+ i2c_reg2hw_ctrl_reg_t ctrl; // [324:323]
+ i2c_reg2hw_rdata_reg_t rdata; // [322:314]
+ i2c_reg2hw_fdata_reg_t fdata; // [313:295]
+ i2c_reg2hw_fifo_ctrl_reg_t fifo_ctrl; // [294:280]
+ i2c_reg2hw_ovrd_reg_t ovrd; // [279:277]
+ i2c_reg2hw_timing0_reg_t timing0; // [276:245]
+ i2c_reg2hw_timing1_reg_t timing1; // [244:213]
+ i2c_reg2hw_timing2_reg_t timing2; // [212:181]
+ i2c_reg2hw_timing3_reg_t timing3; // [180:149]
+ i2c_reg2hw_timing4_reg_t timing4; // [148:117]
+ i2c_reg2hw_timeout_ctrl_reg_t timeout_ctrl; // [116:85]
+ i2c_reg2hw_target_id_reg_t target_id; // [84:57]
+ i2c_reg2hw_acqdata_reg_t acqdata; // [56:45]
+ i2c_reg2hw_txdata_reg_t txdata; // [44:36]
+ i2c_reg2hw_stretch_ctrl_reg_t stretch_ctrl; // [35:32]
+ i2c_reg2hw_host_timeout_ctrl_reg_t host_timeout_ctrl; // [31:0]
} i2c_reg2hw_t;
///////////////////////////////////////
// Internal design logic to register //
///////////////////////////////////////
typedef struct packed {
- i2c_hw2reg_intr_state_reg_t intr_state; // [113:84]
+ i2c_hw2reg_intr_state_reg_t intr_state; // [115:84]
i2c_hw2reg_status_reg_t status; // [83:74]
i2c_hw2reg_rdata_reg_t rdata; // [73:66]
i2c_hw2reg_fifo_status_reg_t fifo_status; // [65:42]
@@ -527,6 +562,8 @@
parameter logic [BlockAw-1:0] I2C_TARGET_ID_OFFSET = 7'h 44;
parameter logic [BlockAw-1:0] I2C_ACQDATA_OFFSET = 7'h 48;
parameter logic [BlockAw-1:0] I2C_TXDATA_OFFSET = 7'h 4c;
+ parameter logic [BlockAw-1:0] I2C_STRETCH_CTRL_OFFSET = 7'h 50;
+ parameter logic [BlockAw-1:0] I2C_HOST_TIMEOUT_CTRL_OFFSET = 7'h 54;
// Register Index
@@ -550,11 +587,13 @@
I2C_TIMEOUT_CTRL,
I2C_TARGET_ID,
I2C_ACQDATA,
- I2C_TXDATA
+ I2C_TXDATA,
+ I2C_STRETCH_CTRL,
+ I2C_HOST_TIMEOUT_CTRL
} i2c_id_e;
// Register width information to check illegal writes
- parameter logic [3:0] I2C_PERMIT [20] = '{
+ parameter logic [3:0] I2C_PERMIT [22] = '{
4'b 0011, // index[ 0] I2C_INTR_STATE
4'b 0011, // index[ 1] I2C_INTR_ENABLE
4'b 0011, // index[ 2] I2C_INTR_TEST
@@ -574,7 +613,9 @@
4'b 1111, // index[16] I2C_TIMEOUT_CTRL
4'b 1111, // index[17] I2C_TARGET_ID
4'b 0011, // index[18] I2C_ACQDATA
- 4'b 0001 // index[19] I2C_TXDATA
+ 4'b 0001, // index[19] I2C_TXDATA
+ 4'b 0001, // index[20] I2C_STRETCH_CTRL
+ 4'b 1111 // index[21] I2C_HOST_TIMEOUT_CTRL
};
endpackage
diff --git a/hw/ip/i2c/rtl/i2c_reg_top.sv b/hw/ip/i2c/rtl/i2c_reg_top.sv
index 3bbbbcd..7a3c3fc 100644
--- a/hw/ip/i2c/rtl/i2c_reg_top.sv
+++ b/hw/ip/i2c/rtl/i2c_reg_top.sv
@@ -116,6 +116,9 @@
logic intr_state_ack_stop_qs;
logic intr_state_ack_stop_wd;
logic intr_state_ack_stop_we;
+ logic intr_state_host_timeout_qs;
+ logic intr_state_host_timeout_wd;
+ logic intr_state_host_timeout_we;
logic intr_enable_fmt_watermark_qs;
logic intr_enable_fmt_watermark_wd;
logic intr_enable_fmt_watermark_we;
@@ -161,6 +164,9 @@
logic intr_enable_ack_stop_qs;
logic intr_enable_ack_stop_wd;
logic intr_enable_ack_stop_we;
+ logic intr_enable_host_timeout_qs;
+ logic intr_enable_host_timeout_wd;
+ logic intr_enable_host_timeout_we;
logic intr_test_fmt_watermark_wd;
logic intr_test_fmt_watermark_we;
logic intr_test_rx_watermark_wd;
@@ -191,6 +197,8 @@
logic intr_test_acq_overflow_we;
logic intr_test_ack_stop_wd;
logic intr_test_ack_stop_we;
+ logic intr_test_host_timeout_wd;
+ logic intr_test_host_timeout_we;
logic ctrl_enablehost_qs;
logic ctrl_enablehost_wd;
logic ctrl_enablehost_we;
@@ -320,6 +328,21 @@
logic acqdata_signal_re;
logic [7:0] txdata_wd;
logic txdata_we;
+ logic stretch_ctrl_enableaddr_qs;
+ logic stretch_ctrl_enableaddr_wd;
+ logic stretch_ctrl_enableaddr_we;
+ logic stretch_ctrl_enabletx_qs;
+ logic stretch_ctrl_enabletx_wd;
+ logic stretch_ctrl_enabletx_we;
+ logic stretch_ctrl_enableacq_qs;
+ logic stretch_ctrl_enableacq_wd;
+ logic stretch_ctrl_enableacq_we;
+ logic stretch_ctrl_stop_qs;
+ logic stretch_ctrl_stop_wd;
+ logic stretch_ctrl_stop_we;
+ logic [31:0] host_timeout_ctrl_qs;
+ logic [31:0] host_timeout_ctrl_wd;
+ logic host_timeout_ctrl_we;
// Register instances
// R[intr_state]: V(False)
@@ -714,6 +737,32 @@
);
+ // F[host_timeout]: 15:15
+ prim_subreg #(
+ .DW (1),
+ .SWACCESS("W1C"),
+ .RESVAL (1'h0)
+ ) u_intr_state_host_timeout (
+ .clk_i (clk_i ),
+ .rst_ni (rst_ni ),
+
+ // from register interface
+ .we (intr_state_host_timeout_we),
+ .wd (intr_state_host_timeout_wd),
+
+ // from internal hardware
+ .de (hw2reg.intr_state.host_timeout.de),
+ .d (hw2reg.intr_state.host_timeout.d ),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.intr_state.host_timeout.q ),
+
+ // to register interface (read)
+ .qs (intr_state_host_timeout_qs)
+ );
+
+
// R[intr_enable]: V(False)
// F[fmt_watermark]: 0:0
@@ -1106,6 +1155,32 @@
);
+ // F[host_timeout]: 15:15
+ prim_subreg #(
+ .DW (1),
+ .SWACCESS("RW"),
+ .RESVAL (1'h0)
+ ) u_intr_enable_host_timeout (
+ .clk_i (clk_i ),
+ .rst_ni (rst_ni ),
+
+ // from register interface
+ .we (intr_enable_host_timeout_we),
+ .wd (intr_enable_host_timeout_wd),
+
+ // from internal hardware
+ .de (1'b0),
+ .d ('0 ),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.intr_enable.host_timeout.q ),
+
+ // to register interface (read)
+ .qs (intr_enable_host_timeout_qs)
+ );
+
+
// R[intr_test]: V(True)
// F[fmt_watermark]: 0:0
@@ -1333,6 +1408,21 @@
);
+ // F[host_timeout]: 15:15
+ prim_subreg_ext #(
+ .DW (1)
+ ) u_intr_test_host_timeout (
+ .re (1'b0),
+ .we (intr_test_host_timeout_we),
+ .wd (intr_test_host_timeout_wd),
+ .d ('0),
+ .qre (),
+ .qe (reg2hw.intr_test.host_timeout.qe),
+ .q (reg2hw.intr_test.host_timeout.q ),
+ .qs ()
+ );
+
+
// R[ctrl]: V(False)
// F[enablehost]: 0:0
@@ -2523,9 +2613,142 @@
);
+ // R[stretch_ctrl]: V(False)
+
+ // F[enableaddr]: 0:0
+ prim_subreg #(
+ .DW (1),
+ .SWACCESS("RW"),
+ .RESVAL (1'h0)
+ ) u_stretch_ctrl_enableaddr (
+ .clk_i (clk_i ),
+ .rst_ni (rst_ni ),
+
+ // from register interface
+ .we (stretch_ctrl_enableaddr_we),
+ .wd (stretch_ctrl_enableaddr_wd),
+
+ // from internal hardware
+ .de (1'b0),
+ .d ('0 ),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.stretch_ctrl.enableaddr.q ),
+
+ // to register interface (read)
+ .qs (stretch_ctrl_enableaddr_qs)
+ );
- logic [19:0] addr_hit;
+ // F[enabletx]: 1:1
+ prim_subreg #(
+ .DW (1),
+ .SWACCESS("RW"),
+ .RESVAL (1'h0)
+ ) u_stretch_ctrl_enabletx (
+ .clk_i (clk_i ),
+ .rst_ni (rst_ni ),
+
+ // from register interface
+ .we (stretch_ctrl_enabletx_we),
+ .wd (stretch_ctrl_enabletx_wd),
+
+ // from internal hardware
+ .de (1'b0),
+ .d ('0 ),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.stretch_ctrl.enabletx.q ),
+
+ // to register interface (read)
+ .qs (stretch_ctrl_enabletx_qs)
+ );
+
+
+ // F[enableacq]: 2:2
+ prim_subreg #(
+ .DW (1),
+ .SWACCESS("RW"),
+ .RESVAL (1'h0)
+ ) u_stretch_ctrl_enableacq (
+ .clk_i (clk_i ),
+ .rst_ni (rst_ni ),
+
+ // from register interface
+ .we (stretch_ctrl_enableacq_we),
+ .wd (stretch_ctrl_enableacq_wd),
+
+ // from internal hardware
+ .de (1'b0),
+ .d ('0 ),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.stretch_ctrl.enableacq.q ),
+
+ // to register interface (read)
+ .qs (stretch_ctrl_enableacq_qs)
+ );
+
+
+ // F[stop]: 3:3
+ prim_subreg #(
+ .DW (1),
+ .SWACCESS("RW"),
+ .RESVAL (1'h0)
+ ) u_stretch_ctrl_stop (
+ .clk_i (clk_i ),
+ .rst_ni (rst_ni ),
+
+ // from register interface
+ .we (stretch_ctrl_stop_we),
+ .wd (stretch_ctrl_stop_wd),
+
+ // from internal hardware
+ .de (1'b0),
+ .d ('0 ),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.stretch_ctrl.stop.q ),
+
+ // to register interface (read)
+ .qs (stretch_ctrl_stop_qs)
+ );
+
+
+ // R[host_timeout_ctrl]: V(False)
+
+ prim_subreg #(
+ .DW (32),
+ .SWACCESS("RW"),
+ .RESVAL (32'h0)
+ ) u_host_timeout_ctrl (
+ .clk_i (clk_i ),
+ .rst_ni (rst_ni ),
+
+ // from register interface
+ .we (host_timeout_ctrl_we),
+ .wd (host_timeout_ctrl_wd),
+
+ // from internal hardware
+ .de (1'b0),
+ .d ('0 ),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.host_timeout_ctrl.q ),
+
+ // to register interface (read)
+ .qs (host_timeout_ctrl_qs)
+ );
+
+
+
+
+ logic [21:0] addr_hit;
always_comb begin
addr_hit = '0;
addr_hit[ 0] = (reg_addr == I2C_INTR_STATE_OFFSET);
@@ -2548,6 +2771,8 @@
addr_hit[17] = (reg_addr == I2C_TARGET_ID_OFFSET);
addr_hit[18] = (reg_addr == I2C_ACQDATA_OFFSET);
addr_hit[19] = (reg_addr == I2C_TXDATA_OFFSET);
+ addr_hit[20] = (reg_addr == I2C_STRETCH_CTRL_OFFSET);
+ addr_hit[21] = (reg_addr == I2C_HOST_TIMEOUT_CTRL_OFFSET);
end
assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
@@ -2575,6 +2800,8 @@
if (addr_hit[17] && reg_we && (I2C_PERMIT[17] != (I2C_PERMIT[17] & reg_be))) wr_err = 1'b1 ;
if (addr_hit[18] && reg_we && (I2C_PERMIT[18] != (I2C_PERMIT[18] & reg_be))) wr_err = 1'b1 ;
if (addr_hit[19] && reg_we && (I2C_PERMIT[19] != (I2C_PERMIT[19] & reg_be))) wr_err = 1'b1 ;
+ if (addr_hit[20] && reg_we && (I2C_PERMIT[20] != (I2C_PERMIT[20] & reg_be))) wr_err = 1'b1 ;
+ if (addr_hit[21] && reg_we && (I2C_PERMIT[21] != (I2C_PERMIT[21] & reg_be))) wr_err = 1'b1 ;
end
assign intr_state_fmt_watermark_we = addr_hit[0] & reg_we & ~wr_err;
@@ -2622,6 +2849,9 @@
assign intr_state_ack_stop_we = addr_hit[0] & reg_we & ~wr_err;
assign intr_state_ack_stop_wd = reg_wdata[14];
+ assign intr_state_host_timeout_we = addr_hit[0] & reg_we & ~wr_err;
+ assign intr_state_host_timeout_wd = reg_wdata[15];
+
assign intr_enable_fmt_watermark_we = addr_hit[1] & reg_we & ~wr_err;
assign intr_enable_fmt_watermark_wd = reg_wdata[0];
@@ -2667,6 +2897,9 @@
assign intr_enable_ack_stop_we = addr_hit[1] & reg_we & ~wr_err;
assign intr_enable_ack_stop_wd = reg_wdata[14];
+ assign intr_enable_host_timeout_we = addr_hit[1] & reg_we & ~wr_err;
+ assign intr_enable_host_timeout_wd = reg_wdata[15];
+
assign intr_test_fmt_watermark_we = addr_hit[2] & reg_we & ~wr_err;
assign intr_test_fmt_watermark_wd = reg_wdata[0];
@@ -2712,6 +2945,9 @@
assign intr_test_ack_stop_we = addr_hit[2] & reg_we & ~wr_err;
assign intr_test_ack_stop_wd = reg_wdata[14];
+ assign intr_test_host_timeout_we = addr_hit[2] & reg_we & ~wr_err;
+ assign intr_test_host_timeout_wd = reg_wdata[15];
+
assign ctrl_enablehost_we = addr_hit[3] & reg_we & ~wr_err;
assign ctrl_enablehost_wd = reg_wdata[0];
@@ -2852,6 +3088,21 @@
assign txdata_we = addr_hit[19] & reg_we & ~wr_err;
assign txdata_wd = reg_wdata[7:0];
+ assign stretch_ctrl_enableaddr_we = addr_hit[20] & reg_we & ~wr_err;
+ assign stretch_ctrl_enableaddr_wd = reg_wdata[0];
+
+ assign stretch_ctrl_enabletx_we = addr_hit[20] & reg_we & ~wr_err;
+ assign stretch_ctrl_enabletx_wd = reg_wdata[1];
+
+ assign stretch_ctrl_enableacq_we = addr_hit[20] & reg_we & ~wr_err;
+ assign stretch_ctrl_enableacq_wd = reg_wdata[2];
+
+ assign stretch_ctrl_stop_we = addr_hit[20] & reg_we & ~wr_err;
+ assign stretch_ctrl_stop_wd = reg_wdata[3];
+
+ assign host_timeout_ctrl_we = addr_hit[21] & reg_we & ~wr_err;
+ assign host_timeout_ctrl_wd = reg_wdata[31:0];
+
// Read data return
always_comb begin
reg_rdata_next = '0;
@@ -2872,6 +3123,7 @@
reg_rdata_next[12] = intr_state_tx_overflow_qs;
reg_rdata_next[13] = intr_state_acq_overflow_qs;
reg_rdata_next[14] = intr_state_ack_stop_qs;
+ reg_rdata_next[15] = intr_state_host_timeout_qs;
end
addr_hit[1]: begin
@@ -2890,6 +3142,7 @@
reg_rdata_next[12] = intr_enable_tx_overflow_qs;
reg_rdata_next[13] = intr_enable_acq_overflow_qs;
reg_rdata_next[14] = intr_enable_ack_stop_qs;
+ reg_rdata_next[15] = intr_enable_host_timeout_qs;
end
addr_hit[2]: begin
@@ -2908,6 +3161,7 @@
reg_rdata_next[12] = '0;
reg_rdata_next[13] = '0;
reg_rdata_next[14] = '0;
+ reg_rdata_next[15] = '0;
end
addr_hit[3]: begin
@@ -3014,6 +3268,17 @@
reg_rdata_next[7:0] = '0;
end
+ addr_hit[20]: begin
+ reg_rdata_next[0] = stretch_ctrl_enableaddr_qs;
+ reg_rdata_next[1] = stretch_ctrl_enabletx_qs;
+ reg_rdata_next[2] = stretch_ctrl_enableacq_qs;
+ reg_rdata_next[3] = stretch_ctrl_stop_qs;
+ end
+
+ addr_hit[21]: begin
+ reg_rdata_next[31:0] = host_timeout_ctrl_qs;
+ end
+
default: begin
reg_rdata_next = '1;
end