diff --git a/docs/regmap/adi_regmap_i3c_controller.txt b/docs/regmap/adi_regmap_i3c_controller.txt
index 29694acfd0..ae3be78893 100644
--- a/docs/regmap/adi_regmap_i3c_controller.txt
+++ b/docs/regmap/adi_regmap_i3c_controller.txt
@@ -62,23 +62,6 @@ ENDFIELD
############################################################################################
############################################################################################
-REG
-0x03
-PARAMETERS
-Controller parameters values.
-ENDREG
-
-FIELD
-[3:0] 0x00000000
-MAX_DEVS
-RO
-Maximum number of peripherals in the bus (does not count the controller).
-Valid range is 0 to 15 devices.
-ENDFIELD
-
-############################################################################################
-############################################################################################
-
REG
0x10
ENABLE
@@ -140,6 +123,12 @@ CMDR_PENDING
RW
If set to 0 the CMDR_PENDING interrupt is masked.
+FIELD
+[6] 0x00
+IBI_PENDING
+RW
+If set to 0 the IBI_PENDING interrupt is masked.
+
############################################################################################
############################################################################################
@@ -387,14 +376,14 @@ FIELD
[1] 0x1
IBI_EMPTY
RO
-If there is no element to be read in the IBIR FIFO.
+If there is no element to be read in the IBI FIFO.
ENDFIELD
FIELD
[2] 0x1
SDI_EMPTY
RO
-If there is no element to be read in the IBIR FIFO.
+If there is no element to be read in the SDI FIFO.
ENDFIELD
############################################################################################
@@ -402,16 +391,42 @@ ENDFIELD
REG
0x40
-DAA_STATUS :TODO: Update to be a high level controller state, with DAA one of the states.
+OPS
ENDREG
FIELD
[0] 0x??
-DAA_STATUS_IN_PROGRESS
+OPS_MODE
+WO
+Set 0 to private transfers, 1 to offload.
+Setting to DAA automatically trigger the DAA process.
+ENDFIELD
+
+FIELD
+[4:1] 0x??
+OPS_OFFLOAD_LENGTH
+WO
+Offload commands length.
+ENDFIELD
+
+[5] 0x0
+OPS_STATUS_DAA
RO
This bit is set to 1 when the assignment is in progress.
ENDFIELD
+[6] 0x0
+OPS_STATUS_PRIV_TRANSFER TODO: These status signals
+RO
+This bit is set to 1 when a private transfer is in progress.
+ENDFIELD
+
+[7] 0x0
+OPS_STATUS_OFFLOAD
+RO
+This bit is set to 1 when a offload transfer is in progress.
+ENDFIELD
+
############################################################################################
############################################################################################
@@ -533,7 +548,7 @@ ENDFIELD
############################################################################################
REG
-0x90
+0xa0
DEVS_CTRL
ENDREG
@@ -559,3 +574,23 @@ ENDFIELD
############################################################################################
############################################################################################
+
+REG
+0xb[0-f]
+OFFLOAD_CMD_*
+Offload command memory. Write commands in sequence to these addresses and update the
+OFFLOAD_CMD_LENGTH register.
+ENDREG
+
+############################################################################################
+############################################################################################
+
+REG
+0xc[0-f]
+OFFLOAD_SDO_*
+Offload SDO memory.
+The length is infered by the commands and reset after each burst.
+ENDREG
+
+############################################################################################
+############################################################################################
diff --git a/library/i3c_controller/axi_i3c_controller/axi_i3c_controller.v b/library/i3c_controller/axi_i3c_controller/axi_i3c_controller.v
index ceafb4893c..e38fb85199 100644
--- a/library/i3c_controller/axi_i3c_controller/axi_i3c_controller.v
+++ b/library/i3c_controller/axi_i3c_controller/axi_i3c_controller.v
@@ -38,6 +38,7 @@
module axi_i3c_controller #(
parameter ID = 0,
+ parameter OFFLOAD = 1,
parameter MM_IF_TYPE = 0,
parameter ASYNC_I3C_CLK = 0,
parameter ADDRESS_WIDTH = 8, // Const
@@ -110,21 +111,29 @@ module axi_i3c_controller #(
input wire sdi_valid,
input wire [DATA_WIDTH-1:0] sdi,
+ input wire offload_sdi_ready,
+ output wire offload_sdi_valid,
+ output wire [DATA_WIDTH-1:0] offload_sdi,
+
output wire ibi_ready,
input wire ibi_valid,
input wire [DATA_WIDTH-1:0] ibi,
+ input wire quiet_times,
+
+ input wire offload_trigger,
+
// uP accessible info
input wire rmap_daa_status,
output reg [1:0] rmap_ibi_config,
output reg [29:0] rmap_devs_ctrl_mr,
input wire [14:0] rmap_devs_ctrl,
- input rmap_dev_char_e,
- input rmap_dev_char_we,
- input [5:0] rmap_dev_char_addr,
- input [31:0] rmap_dev_char_wdata,
- output [8:0] rmap_dev_char_rdata
+ input wire rmap_dev_char_e,
+ input wire rmap_dev_char_we,
+ input wire [5:0] rmap_dev_char_addr,
+ input wire [31:0] rmap_dev_char_wdata,
+ output wire [8:0] rmap_dev_char_rdata
);
localparam PCORE_VERSION = 'h12345678;
@@ -197,7 +206,8 @@ module axi_i3c_controller #(
// Scratch register
reg [31:0] up_scratch = 'h00;
- reg cmdr_id_pending = 1'b0;
+ reg cmdr_pending = 1'b0;
+ reg ibi_pending = 1'b0;
generate if (MM_IF_TYPE == S_AXI) begin
@@ -266,12 +276,13 @@ module axi_i3c_controller #(
endgenerate
// IRQ handling
- reg [5:0] up_irq_mask = 6'h0;
- wire [5:0] up_irq_source;
- wire [5:0] up_irq_pending;
+ reg [6:0] up_irq_mask = 7'h0;
+ wire [6:0] up_irq_source;
+ wire [6:0] up_irq_pending;
assign up_irq_source = {
- cmdr_id_pending,
+ ibi_pending,
+ cmdr_pending,
up_ibi_fifo_almost_full,
up_sdi_fifo_almost_full,
up_sdo_fifo_almost_empty,
@@ -296,7 +307,7 @@ module axi_i3c_controller #(
end else begin
up_wack_ff <= up_wreq_s;
if (up_wreq_s) begin
- case (up_waddr_s)
+ case (up_waddr_s[7:0])
`I3C_REGMAP_ENABLE: up_sw_reset <= up_wdata_s[0];
`I3C_REGMAP_SCRATCH: up_scratch <= up_wdata_s;
endcase
@@ -304,6 +315,24 @@ module axi_i3c_controller #(
end
end
+ reg [4:0] ops;
+ reg [4:0] ops_candidate;
+ wire ops_mode;
+ wire [3:0] ops_offload_len;
+ wire offload_idle;
+ assign ops_mode = ops[0];
+ assign ops_offload_len = ops[4:1];
+
+ always @(posedge clk) begin
+ if (!up_sw_resetn) begin
+ ops <= 6'd0;
+ end else if (quiet_times) begin
+ if ((~ops_mode & ~cmd_valid_w) | (ops_mode & offload_idle)) begin
+ ops <= ops_candidate;
+ end
+ end
+ end
+
// the software reset should reset all the registers
always @(posedge clk) begin
rmap_devs_ctrl_mr <= 'd0;
@@ -311,20 +340,22 @@ module axi_i3c_controller #(
up_irq_mask <= 'h00;
rmap_ibi_config <= 'h00;
devs_ctrl_0 <= 1'b0;
+ ops_candidate <= 6'd0;
end else begin
if (up_wreq_s) begin
- case (up_waddr_s)
- `I3C_REGMAP_IRQ_MASK: up_irq_mask <= up_wdata_s[5:0];
+ case (up_waddr_s[7:0])
+ `I3C_REGMAP_IRQ_MASK: up_irq_mask <= up_wdata_s[6:0];
`I3C_REGMAP_IBI_CONFIG: rmap_ibi_config <= up_wdata_s[1:0];
`I3C_REGMAP_DEVS_CTRL: rmap_devs_ctrl_mr <= {up_wdata_s[31:17], up_wdata_s[15:1]};
+ `I3C_REGMAP_OPS: ops_candidate <= up_wdata_s[5:0];
default: begin
end
endcase
// Special cases for the controller
- if (up_waddr_s == {`I3C_REGMAP_DEV_CHAR_0_, 4'd0}) begin
+ if (up_waddr_s[7:0] == {`I3C_REGMAP_DEV_CHAR_0_, 4'd0}) begin
devs_ctrl_0 <= 1'b1;
- end else if (up_waddr_s == `I3C_REGMAP_DEVS_CTRL & up_wdata_s[16] == 1'b1) begin
+ end else if (up_waddr_s[7:0] == `I3C_REGMAP_DEVS_CTRL & up_wdata_s[16] == 1'b1) begin
devs_ctrl_0 <= 1'b0;
end
end
@@ -343,13 +374,11 @@ module axi_i3c_controller #(
reg devs_ctrl_0;
wire [15:0] rmap_devs_ctrl_w = {rmap_devs_ctrl, devs_ctrl_0};
- integer i;
always @(posedge clk) begin
- case (up_raddr_s)
+ case (up_raddr_s[7:0])
`I3C_REGMAP_VERSION: up_rdata_ff <= PCORE_VERSION;
`I3C_REGMAP_PERIPHERAL_ID: up_rdata_ff <= ID;
`I3C_REGMAP_SCRATCH: up_rdata_ff <= up_scratch;
- `I3C_REGMAP_PARAMETERS: up_rdata_ff <= {28'd0, MAX_DEVS[3:0]};
`I3C_REGMAP_ENABLE: up_rdata_ff <= up_sw_reset;
`I3C_REGMAP_IRQ_MASK: up_rdata_ff <= up_irq_mask;
`I3C_REGMAP_IRQ_PENDING: up_rdata_ff <= up_irq_pending;
@@ -363,7 +392,7 @@ module axi_i3c_controller #(
`I3C_REGMAP_SDI_FIFO: up_rdata_ff <= sdi_fifo_data;
`I3C_REGMAP_IBI_FIFO: up_rdata_ff <= ibi_fifo_data;
`I3C_REGMAP_FIFO_STATUS: up_rdata_ff <= {sdi_fifo_empty, ibi_fifo_empty, cmdr_fifo_empty};
- `I3C_REGMAP_DAA_STATUS: up_rdata_ff <= rmap_daa_status;
+ `I3C_REGMAP_OPS: up_rdata_ff <= {rmap_daa_status, ops};
`I3C_REGMAP_DEV_CHAR_1_0: up_rdata_ff <= PID[47:16];
`I3C_REGMAP_DEV_CHAR_2_0: up_rdata_ff <= {PID[16:0], BCR, DCR};
`I3C_REGMAP_DEVS_CTRL: up_rdata_ff <= {16'd0, rmap_devs_ctrl_w};
@@ -371,27 +400,30 @@ module axi_i3c_controller #(
endcase
end
// NOTE: Could pre-load the Controller PID in the BRAM instead.
- assign up_rdata_ff_w = up_raddr_s[7:4] == `I3C_REGMAP_DEV_CHAR_0_ ? dev_char_out :
+ assign up_rdata_ff_w = up_raddr_s[7:4] == `I3C_REGMAP_DEV_CHAR_0_ ? dev_char_douta :
+ up_raddr_s[7:4] == `I3C_REGMAP_OFFLOAD_CMD_ ? offload_douta :
+ up_raddr_s[7:4] == `I3C_REGMAP_OFFLOAD_SDO_ ? offload_douta :
~|up_raddr_s[3:0] ? up_rdata_ff :
- up_raddr_s[7:4] == `I3C_REGMAP_DEV_CHAR_1_ ? dev_char_out :
- up_raddr_s[7:4] == `I3C_REGMAP_DEV_CHAR_2_ ? dev_char_out :
+ up_raddr_s[7:4] == `I3C_REGMAP_DEV_CHAR_1_ ? dev_char_douta :
+ up_raddr_s[7:4] == `I3C_REGMAP_DEV_CHAR_2_ ? dev_char_douta :
up_rdata_ff;
- wire dev_char_e;
- wire dev_char_wr;
- wire dev_char_rd;
- wire [31:0] dev_char_out;
- wire [5:0] dev_char_addr;
+ wire dev_char_ea;
+ wire dev_char_wea;
+ wire dev_char_rea;
+ wire [31:0] dev_char_douta;
+ wire [5:0] dev_char_addra;
+
ad_mem_dual #(
.DATA_WIDTH(32),
.ADDRESS_WIDTH(6)
) i_dev_char_1_2 (
.clka(clk),
- .wea(dev_char_wr),
- .ea(dev_char_e),
- .addra(dev_char_addr),
+ .wea(dev_char_wea),
+ .ea(dev_char_ea),
+ .addra(dev_char_addra),
.dina(up_wdata_s),
- .douta(dev_char_out),
+ .douta(dev_char_douta),
.clkb(clk),
.web(rmap_dev_char_we),
.eb(rmap_dev_char_e),
@@ -399,27 +431,136 @@ module axi_i3c_controller #(
.dinb(rmap_dev_char_wdata),
.doutb(rmap_dev_char_rdata)
);
-
- assign dev_char_addr = up_wreq_s ?
- {up_waddr_s[7], up_waddr_s[6] & up_waddr_s[4], up_waddr_s[3:0]} :
- {up_raddr_s[7], up_raddr_s[6] & up_raddr_s[4], up_raddr_s[3:0]};
- assign dev_char_rd = up_rreq_s == 1'b1 &&
- (up_raddr_s[7:4] == `I3C_REGMAP_DEV_CHAR_0_ |
- up_raddr_s[7:4] == `I3C_REGMAP_DEV_CHAR_1_ |
- up_raddr_s[7:4] == `I3C_REGMAP_DEV_CHAR_2_ );
- assign dev_char_wr = up_wreq_s == 1'b1 &&
- (up_waddr_s[7:4] == `I3C_REGMAP_DEV_CHAR_0_ |
- up_waddr_s[7:4] == `I3C_REGMAP_DEV_CHAR_2_ );
- assign dev_char_e = dev_char_rd | dev_char_wr;
-
+
+ assign dev_char_addra = up_wreq_s ?
+ {up_waddr_s[7], up_waddr_s[4], up_waddr_s[3:0]} :
+ {up_raddr_s[7], up_raddr_s[4], up_raddr_s[3:0]};
+ assign dev_char_rea = up_rreq_s == 1'b1 &&
+ (up_raddr_s[7:4] == `I3C_REGMAP_DEV_CHAR_0_ |
+ up_raddr_s[7:4] == `I3C_REGMAP_DEV_CHAR_1_ |
+ up_raddr_s[7:4] == `I3C_REGMAP_DEV_CHAR_2_ );
+ assign dev_char_wea = up_wreq_s == 1'b1 &&
+ (up_waddr_s[7:4] == `I3C_REGMAP_DEV_CHAR_0_ |
+ up_waddr_s[7:4] == `I3C_REGMAP_DEV_CHAR_2_ );
+ assign dev_char_ea = dev_char_rea | dev_char_wea;
+
+ wire [31:0] offload_douta;
+ wire [31:0] offload_cmd;
+ wire [31:0] offload_sdo;
+ wire offload_cmd_valid;
+ wire offload_sdo_valid;
+ generate if (OFFLOAD == 1) begin
+ wire offload_ea;
+ wire offload_wea;
+ wire offload_rea;
+ wire [4:0] offload_addra;
+ wire offload_eb;
+ wire [4:0] offload_addrb;
+ wire [31:0] offload_doutb;
+
+ ad_mem_dual #(
+ .DATA_WIDTH(32),
+ .ADDRESS_WIDTH(5)
+ ) i_dev_char_1_2 (
+ .clka(clk),
+ .wea(offload_wea),
+ .ea(offload_ea),
+ .addra(offload_addra),
+ .dina(up_wdata_s),
+ .douta(offload_douta),
+ .clkb(clk),
+ .web(1'b0),
+ .eb(offload_eb),
+ .addrb(offload_addrb),
+ .dinb('d0),
+ .doutb(offload_doutb)
+ );
+
+ assign offload_addra = up_wreq_s ?
+ {up_waddr_s[6], up_waddr_s[3:0]} :
+ {up_raddr_s[6], up_raddr_s[3:0]};
+ assign offload_rea = up_rreq_s == 1'b1 &&
+ (up_raddr_s[7:4] == `I3C_REGMAP_OFFLOAD_CMD_ |
+ up_raddr_s[7:4] == `I3C_REGMAP_OFFLOAD_SDO_ );
+ assign offload_wea = up_wreq_s == 1'b1 &&
+ (up_waddr_s[7:4] == `I3C_REGMAP_OFFLOAD_CMD_ |
+ up_waddr_s[7:4] == `I3C_REGMAP_OFFLOAD_SDO_ );
+ assign offload_ea = offload_rea | offload_wea;
+
+
+ reg [1:0] smt;
+ reg [3:0] k;
+ reg [3:0] j;
+ localparam [1:0]
+ cmd_setup = 0,
+ cmd_transfer = 1,
+ sdo_setup = 2,
+ sdo_transfer = 3;
+
+ always @(posedge clk) begin
+ if (!i3c_reset_n | ~ops_mode | ops_offload_len == 0) begin
+ smt <= cmd_setup;
+ k <= 'd0;
+ end else begin
+ case (smt)
+ cmd_setup: begin
+ if (offload_trigger | k != 0) begin
+ smt <= cmd_transfer;
+ if (k == ops_offload_len - 1) begin
+ k <= 0;
+ end else begin
+ k <= k + 1;
+ end
+ end
+ j <= 0;
+ end
+ cmd_transfer: begin
+ if (cmd_ready) begin
+ smt <= sdo_setup;
+ end
+ end
+ sdo_setup: begin
+ smt <= sdo_transfer;
+ end
+ sdo_transfer: begin
+ if (cmd_ready) begin
+ smt <= cmd_setup;
+ end else if (sdo_ready) begin
+ smt <= sdo_setup;
+ j <= j + 1;
+ end
+ end
+ default: begin
+ smt <= cmd_setup;
+ end
+ endcase
+ end
+ end
+ assign offload_idle = smt == cmd_setup & k == 0;
+ assign offload_addrb = smt[1] == 1'b0 ? {1'b0,k} : {1'b1,j};
+ assign offload_eb = smt[0] == 1'b0 & ops_mode;
+ assign offload_cmd_valid = smt == cmd_transfer;
+ assign offload_sdo_valid = smt == sdo_transfer;
+ assign offload_cmd = offload_doutb;
+ assign offload_sdo = offload_doutb;
+ end
+ endgenerate
+
+
always @(posedge clk) begin
if (up_sw_resetn == 1'b0) begin
- cmdr_id_pending <= 1'b0;
+ cmdr_pending <= 1'b0;
+ ibi_pending <= 1'b0;
end else begin
if (cmdr_fifo_valid == 1'b1) begin
- cmdr_id_pending <= 1'b1;
+ cmdr_pending <= 1'b1;
end else if (up_wreq_s == 1'b1 && up_waddr_s == `I3C_REGMAP_IRQ_PENDING && up_wdata_s[`I3C_REGMAP_IRQ_PENDING_CMDR_PENDING] == 1'b1) begin
- cmdr_id_pending <= 1'b0;
+ cmdr_pending <= 1'b0;
+ end
+ if (ibi_fifo_valid == 1'b1) begin
+ ibi_pending <= 1'b1;
+ end else if (up_wreq_s == 1'b1 && up_waddr_s == `I3C_REGMAP_IRQ_PENDING && up_wdata_s[`I3C_REGMAP_IRQ_PENDING_IBI_PENDING] == 1'b1) begin
+ ibi_pending <= 1'b0;
end
end
end
@@ -441,6 +582,12 @@ module axi_i3c_controller #(
end
endgenerate
+ wire [31:0] cmd_w;
+ wire cmd_valid_w;
+ wire cmd_ready_w;
+ assign cmd = ~ops_mode ? cmd_w : offload_cmd;
+ assign cmd_valid = ~ops_mode ? cmd_valid_w : offload_cmd_valid;
+ assign cmd_ready_w = ~ops_mode ? cmd_ready : 1'b0;
assign cmd_fifo_valid = up_wreq_s == 1'b1 && up_waddr_s == `I3C_REGMAP_CMD_FIFO;
assign cmd_fifo_data = up_wdata_s;
@@ -463,14 +610,18 @@ module axi_i3c_controller #(
.s_axis_almost_full(),
.m_axis_aclk(clk_1),
.m_axis_aresetn(i3c_reset_n),
- .m_axis_ready(cmd_ready),
- .m_axis_valid(cmd_valid),
- .m_axis_data(cmd),
+ .m_axis_ready(cmd_ready_w),
+ .m_axis_valid(cmd_valid_w),
+ .m_axis_data(cmd_w),
.m_axis_tlast(),
.m_axis_empty(),
.m_axis_almost_empty(cmd_fifo_almost_empty),
.m_axis_level());
+ wire cmdr_valid_w;
+ wire cmdr_ready_w;
+ assign cmdr_ready = ~ops_mode ? cmdr_ready_w : 1'b1; // In offload, discard cmdr
+ assign cmdr_valid_w = ~ops_mode ? cmdr_valid : 1'b0;
assign cmdr_fifo_ready = up_rreq_s == 1'b1 && up_raddr_s == `I3C_REGMAP_CMDR_FIFO;
util_axis_fifo #(
@@ -483,8 +634,8 @@ module axi_i3c_controller #(
) i_cmdr_fifo (
.s_axis_aclk(clk_1),
.s_axis_aresetn(i3c_reset_n),
- .s_axis_ready(cmdr_ready),
- .s_axis_valid(cmdr_valid),
+ .s_axis_ready(cmdr_ready_w),
+ .s_axis_valid(cmdr_valid_w),
.s_axis_data(cmdr),
.s_axis_room(),
.s_axis_tlast(),
@@ -500,6 +651,12 @@ module axi_i3c_controller #(
.m_axis_empty(cmdr_fifo_empty),
.m_axis_almost_empty());
+ wire [31:0] sdo_w;
+ wire sdo_valid_w;
+ wire sdo_ready_w;
+ assign sdo = ~ops_mode ? sdo_w : offload_sdo;
+ assign sdo_valid = ~ops_mode ? sdo_valid_w : offload_sdo_valid;
+ assign sdo_ready_w = ~ops_mode ? sdo_ready : 1'b0;
assign sdo_fifo_valid = up_wreq_s == 1'b1 && up_waddr_s == `I3C_REGMAP_SDO_FIFO;
assign sdo_fifo_data = up_wdata_s[31:0];
@@ -522,14 +679,20 @@ module axi_i3c_controller #(
.s_axis_almost_full(),
.m_axis_aclk(clk_1),
.m_axis_aresetn(i3c_reset_n),
- .m_axis_ready(sdo_ready),
- .m_axis_valid(sdo_valid),
- .m_axis_data(sdo),
+ .m_axis_ready(sdo_ready_w),
+ .m_axis_valid(sdo_valid_w),
+ .m_axis_data(sdo_w),
.m_axis_tlast(),
.m_axis_level(),
.m_axis_empty(),
.m_axis_almost_empty(sdo_fifo_almost_empty));
+ wire sdi_valid_w;
+ wire sdi_ready_w;
+ assign offload_sdi = sdi;
+ assign offload_sdi_valid = ops_mode ? sdi_valid : 1'b0;
+ assign sdi_valid_w = ~ops_mode ? sdi_valid : 1'b0;
+ assign sdi_ready = ops_mode ? offload_sdi_ready : sdi_ready_w;
assign sdi_fifo_ready = up_rreq_s == 1'b1 && up_raddr_s == `I3C_REGMAP_SDI_FIFO;
util_axis_fifo #(
@@ -542,8 +705,8 @@ module axi_i3c_controller #(
) i_sdi_fifo (
.s_axis_aclk(clk_1),
.s_axis_aresetn(i3c_reset_n),
- .s_axis_ready(sdi_ready),
- .s_axis_valid(sdi_valid),
+ .s_axis_ready(sdi_ready_w),
+ .s_axis_valid(sdi_valid_w),
.s_axis_data(sdi),
.s_axis_room(),
.s_axis_tlast(),
diff --git a/library/i3c_controller/axi_i3c_controller/axi_i3c_controller_hw.tcl b/library/i3c_controller/axi_i3c_controller/axi_i3c_controller_hw.tcl
index 295f555338..aa354447f3 100644
--- a/library/i3c_controller/axi_i3c_controller/axi_i3c_controller_hw.tcl
+++ b/library/i3c_controller/axi_i3c_controller/axi_i3c_controller_hw.tcl
@@ -26,6 +26,7 @@ ad_ip_parameter MAX_DEVS INTEGER 15
ad_ip_parameter PID INTEGER 0xC00FFE123456
ad_ip_parameter DCR INTEGER 0x7B
ad_ip_parameter BCR INTEGER 0x40
+ad_ip_parameter OFFLOAD INTEGER 0
proc p_elaboration {} {
@@ -37,6 +38,7 @@ proc p_elaboration {} {
set pid [get_parameter_value "PID"]
set dcr [get_parameter_value "DCR"]
set bcr [get_parameter_value "BCR"]
+ set offload [get_parameter_value "OFFLOAD"]
# interrupt
@@ -103,6 +105,10 @@ proc p_elaboration {} {
}
+ if {!($offload)} {
+ lappend disabled_intfs offload offload_trigger
+ }
+
if {!($async_i3c_clk)} {
lappend disabled_intfs i3c_clk
}
@@ -117,43 +123,48 @@ proc p_elaboration {} {
ad_interface reset i3c_reset_n output 1
add_interface cmd axi4stream start
- add_interface_port cmd cmd_ready tready input 1
- add_interface_port cmd cmd_valid tvalid output 1
- add_interface_port cmd cmd_data tdata output 32
+ add_interface_port cmd cmd_ready tready input 1
+ add_interface_port cmd cmd_valid tvalid output 1
+ add_interface_port cmd cmd_data tdata output 32
set_interface_property cmd associatedClock if_i3c_clk
set_interface_property cmd associatedReset if_i3c_reset_n
add_interface cmdr axi4stream end
- add_interface_port cmdr cmdr_ready tready output 1
- add_interface_port cmdr cmdr_valid tvalid input 1
- add_interface_port cmdr cmdr_data tdata input 32
+ add_interface_port cmdr cmdr_ready tready output 1
+ add_interface_port cmdr cmdr_valid tvalid input 1
+ add_interface_port cmdr cmdr_data tdata input 32
set_interface_property cmdr associatedClock if_i3c_clk
set_interface_property cmdr associatedReset if_i3c_reset_n
add_interface sdo axi4stream start
- add_interface_port sdo sdo_ready tready input 1
- add_interface_port sdo sdo_valid tvalid output 1
- add_interface_port sdo sdo_data tdata output 32
+ add_interface_port sdo sdo_ready tready input 1
+ add_interface_port sdo sdo_valid tvalid output 1
+ add_interface_port sdo sdo_data tdata output 32
set_interface_property sdo associatedClock if_i3c_clk
set_interface_property sdo associatedReset if_i3c_reset_n
add_interface sdi axi4stream end
- add_interface_port sdi sdi_ready tready output 1
- add_interface_port sdi sdi_valid tvalid input 1
- add_interface_port sdi sdi_data tdata input 32
+ add_interface_port sdi sdi_ready tready output 1
+ add_interface_port sdi sdi_valid tvalid input 1
+ add_interface_port sdi sdi_data tdata input 32
set_interface_property sdi associatedClock if_i3c_clk
set_interface_property sdi associatedReset if_i3c_reset_n
add_interface ibi axi4stream end
- add_interface_port ibi ibi_ready tready output 1
- add_interface_port ibi ibi_valid tvalid input 1
- add_interface_port ibi ibi_data tdata input 32
+ add_interface_port ibi ibi_ready tready output 1
+ add_interface_port ibi ibi_valid tvalid input 1
+ add_interface_port ibi ibi_data tdata input 32
set_interface_property ibi associatedClock if_i3c_clk
set_interface_property ibi associatedReset if_i3c_reset_n
+
+ add_interface offload axi4stream start
+ add_interface_port offload offload_sdi_ready tready input 1
+ add_interface_port offload offload_sdi_valid tvalid output 1
+ add_interface_port offload offload_sdi_data tdata output 32
}
diff --git a/library/i3c_controller/axi_i3c_controller/axi_i3c_controller_ip.tcl b/library/i3c_controller/axi_i3c_controller/axi_i3c_controller_ip.tcl
index 82b099b295..830861b007 100644
--- a/library/i3c_controller/axi_i3c_controller/axi_i3c_controller_ip.tcl
+++ b/library/i3c_controller/axi_i3c_controller/axi_i3c_controller_ip.tcl
@@ -46,9 +46,20 @@ adi_add_bus "ctrl" "master" \
{"ibi_ready" "IBI_READY"} \
{"ibi_valid" "IBI_VALID"} \
{"ibi" "IBI_DATA"} \
+ {"quiet_times" "QUIET_TIMES"} \
}
adi_add_bus_clock "i3c_clk" "ctrl" "i3c_reset_n" "master"
+adi_add_bus "offload" "master" \
+ "xilinx.com:interface:axis_rtl:1.0" \
+ "xilinx.com:interface:axis:1.0" \
+ {
+ {"offload_sdi_ready" "OFFLOAD_SDI_READY"} \
+ {"offload_sdi_valid" "OFFLOAD_SDI_VALID"} \
+ {"offload_sdi" "OFFLOAD_SDI"} \
+ }
+adi_add_bus_clock "i3c_clk" "offload" "i3c_reset_n" "master"
+
adi_add_bus "rmap" "master" \
"analog.com:interface:i3c_controller_rmap_rtl:1.0" \
"analog.com:interface:i3c_controller_rmap:1.0" \
@@ -96,6 +107,11 @@ adi_set_ports_dependency "up_rack" \
adi_set_ports_dependency "i3c_clk" \
"(spirit:decode(id('MODELPARAM_VALUE.ASYNC_I3C_CLK')) = 1)"
+adi_set_ports_dependency "offload" \
+ "(spirit:decode(id('MODELPARAM_VALUE.OFFLOAD')) = 1)"
+adi_set_ports_dependency "offload_trigger" \
+ "(spirit:decode(id('MODELPARAM_VALUE.OFFLOAD')) = 1)"
+
## Parameter validations
set cc [ipx::current_core]
@@ -149,6 +165,14 @@ set_property -dict [list \
# ] \
# [ipx::get_user_parameters BCR -of_objects $cc]
+## OFFLOAD
+set_property -dict [list \
+ "value_format" "bool" \
+ "value" "true" \
+ ] \
+ [ipx::get_user_parameters OFFLOAD -of_objects $cc]
+
+
## Customize IP Layout
## Remove the automatically generated GUI page
@@ -203,6 +227,13 @@ set_property -dict [list \
"display_name" "Controller's BCR" \
"tooltip" "\[BCR\] Controller's bus characteristics" \
] [ipgui::get_guiparamspec -name "BCR" -component $cc]
+
+ipgui::add_param -name "OFFLOAD" -component $cc -parent $general_group
+set_property -dict [list \
+ "display_name" "Offload engine" \
+ "tooltip" "\[OFFLOAD\] Allows to offload output data to a external receiver, like a DMA" \
+] [ipgui::get_guiparamspec -name "OFFLOAD" -component $cc]
+
## Create and save the XGUI file
ipx::create_xgui_files $cc
diff --git a/library/i3c_controller/axi_i3c_controller/i3c_controller_regmap.v b/library/i3c_controller/axi_i3c_controller/i3c_controller_regmap.v
index 60064d42dd..7689610a33 100644
--- a/library/i3c_controller/axi_i3c_controller/i3c_controller_regmap.v
+++ b/library/i3c_controller/axi_i3c_controller/i3c_controller_regmap.v
@@ -1,34 +1,37 @@
`ifndef I3C_CONTROLLER_REGMAP_V
`define I3C_CONTROLLER_REGMAP_V
-`define I3C_REGMAP_VERSION 14'h00
-`define I3C_REGMAP_PERIPHERAL_ID 14'h01
-`define I3C_REGMAP_SCRATCH 14'h02
-`define I3C_REGMAP_PARAMETERS 14'h03
-`define I3C_REGMAP_ENABLE 14'h10
-`define I3C_REGMAP_IRQ_MASK 14'h20
-`define I3C_REGMAP_IRQ_PENDING 14'h21
-`define I3C_REGMAP_IRQ_SOURCE 14'h22
-`define I3C_REGMAP_CMD_FIFO_ROOM 14'h30
-`define I3C_REGMAP_CMDR_FIFO_LEVEL 14'h31
-`define I3C_REGMAP_SDO_FIFO_ROOM 14'h32
-`define I3C_REGMAP_SDI_FIFO_LEVEL 14'h33
-`define I3C_REGMAP_IBI_FIFO_LEVEL 14'h34
-`define I3C_REGMAP_CMD_FIFO 14'h35
-`define I3C_REGMAP_CMDR_FIFO 14'h36
-`define I3C_REGMAP_SDO_FIFO 14'h37
-`define I3C_REGMAP_SDI_FIFO 14'h38
-`define I3C_REGMAP_IBI_FIFO 14'h39
-`define I3C_REGMAP_FIFO_STATUS 14'h3a
-`define I3C_REGMAP_DAA_STATUS 14'h40
-`define I3C_REGMAP_IBI_CONFIG 14'h50
+`define I3C_REGMAP_VERSION 8'h00
+`define I3C_REGMAP_PERIPHERAL_ID 8'h01
+`define I3C_REGMAP_SCRATCH 8'h02
+`define I3C_REGMAP_PARAMETERS 8'h03
+`define I3C_REGMAP_ENABLE 8'h10
+`define I3C_REGMAP_IRQ_MASK 8'h20
+`define I3C_REGMAP_IRQ_PENDING 8'h21
+`define I3C_REGMAP_IRQ_SOURCE 8'h22
+`define I3C_REGMAP_CMD_FIFO_ROOM 8'h30
+`define I3C_REGMAP_CMDR_FIFO_LEVEL 8'h31
+`define I3C_REGMAP_SDO_FIFO_ROOM 8'h32
+`define I3C_REGMAP_SDI_FIFO_LEVEL 8'h33
+`define I3C_REGMAP_IBI_FIFO_LEVEL 8'h34
+`define I3C_REGMAP_CMD_FIFO 8'h35
+`define I3C_REGMAP_CMDR_FIFO 8'h36
+`define I3C_REGMAP_SDO_FIFO 8'h37
+`define I3C_REGMAP_SDI_FIFO 8'h38
+`define I3C_REGMAP_IBI_FIFO 8'h39
+`define I3C_REGMAP_FIFO_STATUS 8'h3a
+`define I3C_REGMAP_OPS 8'h40
+`define I3C_REGMAP_IBI_CONFIG 8'h50
`define I3C_REGMAP_DEV_CHAR_0_ 4'h6
`define I3C_REGMAP_DEV_CHAR_1_ 4'h7
-`define I3C_REGMAP_DEV_CHAR_1_0 14'h70
+`define I3C_REGMAP_DEV_CHAR_1_0 8'h70
`define I3C_REGMAP_DEV_CHAR_2_ 4'h8
-`define I3C_REGMAP_DEV_CHAR_2_0 14'h80
-`define I3C_REGMAP_DEVS_CTRL 14'h90
+`define I3C_REGMAP_DEV_CHAR_2_0 8'h80
+`define I3C_REGMAP_DEVS_CTRL 8'ha0
+`define I3C_REGMAP_OFFLOAD_CMD_ 4'hb
+`define I3C_REGMAP_OFFLOAD_SDO_ 4'hc
`define I3C_REGMAP_IRQ_PENDING_CMDR_PENDING 5
+`define I3C_REGMAP_IRQ_PENDING_IBI_PENDING 6
`endif
diff --git a/library/i3c_controller/i3c_controller_core/Makefile b/library/i3c_controller/i3c_controller_core/Makefile
index fa1d6d4f8e..b9f0edcf6a 100644
--- a/library/i3c_controller/i3c_controller_core/Makefile
+++ b/library/i3c_controller/i3c_controller_core/Makefile
@@ -8,7 +8,6 @@ LIBRARY_NAME := i3c_controller_core
GENERIC_DEPS += i3c_controller_core.v
GENERIC_DEPS += i3c_controller_framing.v
-GENERIC_DEPS += i3c_controller_daa.v
GENERIC_DEPS += i3c_controller_phy_sda.v
GENERIC_DEPS += i3c_controller_word.v
GENERIC_DEPS += i3c_controller_word_cmd.v
diff --git a/library/i3c_controller/i3c_controller_core/i3c_controller_core.v b/library/i3c_controller/i3c_controller_core/i3c_controller_core.v
index ab9e830738..73d8821a79 100644
--- a/library/i3c_controller/i3c_controller_core/i3c_controller_core.v
+++ b/library/i3c_controller/i3c_controller_core/i3c_controller_core.v
@@ -58,10 +58,9 @@ module i3c_controller_core #(
input wire [11:0] cmdp_buffer_len,
input wire [6:0] cmdp_da,
input wire cmdp_rnw,
- input wire cmdp_do_daa,
- output wire cmdp_do_daa_ready,
output wire cmdp_ready,
output wire cmdp_cancelled,
+ output wire cmdp_idle_bus,
// Byte stream
@@ -107,16 +106,10 @@ module i3c_controller_core #(
wire rx_stop;
wire rx_nack;
- wire cmdp_ready_w;
- wire cmdp_valid_w;
-
- wire cmdw_framing_valid;
- wire cmdw_daa_valid;
+ wire cmdw_valid;
wire cmdw_ready;
wire cmdw_mux;
- wire [`CMDW_HEADER_WIDTH+8:0] cmdw_framing;
- wire [`CMDW_HEADER_WIDTH+8:0] cmdw_daa;
- wire [`CMDW_HEADER_WIDTH+8:0] cmdw_ibi;
+ wire [`CMDW_HEADER_WIDTH+8:0] cmdw;
wire cmdw_nack;
wire cmdw_rx_ready;
@@ -137,36 +130,13 @@ module i3c_controller_core #(
wire idle_bus;
- i3c_controller_daa #(
- .MAX_DEVS(MAX_DEVS)
- ) i_i3c_controller_daa (
- .reset_n(reset_n),
- .clk(clk),
- .cmdp_do_daa(cmdp_do_daa),
- .cmdp_do_daa_ready(cmdp_do_daa_ready),
- .cmdw_valid(cmdw_daa_valid),
- .cmdw_ready(cmdw_ready),
- .cmdw(cmdw_daa),
- .cmdw_nack(cmdw_nack),
- .idle_bus(idle_bus),
- .pid_bcr_dcr_tick(pid_bcr_dcr_tick),
- .pid_bcr_dcr(pid_bcr_dcr),
- .rmap_daa_status(rmap_daa_status),
- .rmap_devs_ctrl_mr(rmap_devs_ctrl_mr),
- .rmap_devs_ctrl(rmap_devs_ctrl),
- .rmap_dev_char_e(rmap_dev_char_e),
- .rmap_dev_char_we(rmap_dev_char_we),
- .rmap_dev_char_addr(rmap_dev_char_addr),
- .rmap_dev_char_wdata(rmap_dev_char_wdata),
- .rmap_dev_char_rdata(rmap_dev_char_rdata)
- );
-
i3c_controller_framing #(
+ .MAX_DEVS(MAX_DEVS)
) i_i3c_controller_framing (
.reset_n(reset_n),
.clk(clk),
- .cmdp_valid(cmdp_valid_w),
- .cmdp_ready(cmdp_ready_w),
+ .cmdp_valid(cmdp_valid),
+ .cmdp_ready(cmdp_ready),
.cmdp_ccc(cmdp_ccc),
.cmdp_ccc_bcast(cmdp_ccc_bcast),
.cmdp_ccc_id(cmdp_ccc_id),
@@ -183,9 +153,9 @@ module i3c_controller_core #(
.sdi_ready(sdi_ready),
.sdi_valid(sdi_valid),
.sdi(sdi),
- .cmdw_valid(cmdw_framing_valid),
+ .cmdw_valid(cmdw_valid),
.cmdw_ready(cmdw_ready),
- .cmdw(cmdw_framing),
+ .cmdw(cmdw),
.cmdw_nack(cmdw_nack),
.cmdw_rx_ready(cmdw_rx_ready),
.cmdw_rx_valid(cmdw_rx_valid),
@@ -194,19 +164,25 @@ module i3c_controller_core #(
.idle_bus(idle_bus),
.ibi_requested(ibi_requested),
.ibi_requested_auto(ibi_requested_auto),
- .rmap_ibi_config(rmap_ibi_config)
+ .pid_bcr_dcr_tick(pid_bcr_dcr_tick),
+ .pid_bcr_dcr(pid_bcr_dcr),
+ .rmap_ibi_config(rmap_ibi_config),
+ .rmap_devs_ctrl_mr(rmap_devs_ctrl_mr),
+ .rmap_devs_ctrl(rmap_devs_ctrl),
+ .rmap_dev_char_e(rmap_dev_char_e),
+ .rmap_dev_char_we(rmap_dev_char_we),
+ .rmap_dev_char_addr(rmap_dev_char_addr),
+ .rmap_dev_char_wdata(rmap_dev_char_wdata),
+ .rmap_dev_char_rdata(rmap_dev_char_rdata)
);
i3c_controller_word #(
) i_i3c_controller_word (
.reset_n(reset_n),
.clk(clk),
- .cmdw_framing_valid(cmdw_framing_valid),
- .cmdw_daa_valid(cmdw_daa_valid),
+ .cmdw_valid(cmdw_valid),
.cmdw_ready(cmdw_ready),
- .cmdw_mux(cmdw_mux),
- .cmdw_framing(cmdw_framing),
- .cmdw_daa(cmdw_daa),
+ .cmdw(cmdw),
.cmdw_nack(cmdw_nack),
.cmdw_rx_ready(cmdw_rx_ready),
.cmdw_rx_valid(cmdw_rx_valid),
@@ -268,10 +244,7 @@ module i3c_controller_core #(
.sda(sda)
);
- assign cmdw_mux = cmdp_do_daa_ready;
- assign cmdp_ready = cmdp_ready_w & cmdp_do_daa_ready;
- assign cmdp_valid_w = cmdp_valid & cmdp_do_daa_ready;
-
assign ibi = {ibi_da, ibi_mdb};
assign ibi_valid = ibi_tick;
+ assign cmdp_idle_bus = idle_bus;
endmodule
diff --git a/library/i3c_controller/i3c_controller_core/i3c_controller_core_hw.tcl b/library/i3c_controller/i3c_controller_core/i3c_controller_core_hw.tcl
index 1b5560f3fb..6c54d94c9c 100644
--- a/library/i3c_controller/i3c_controller_core/i3c_controller_core_hw.tcl
+++ b/library/i3c_controller/i3c_controller_core/i3c_controller_core_hw.tcl
@@ -7,7 +7,6 @@ set_module_property ELABORATION_CALLBACK p_elaboration
ad_ip_files i3c_controller_core [list \
i3c_controller_core.v \
i3c_controller_framing.v \
- i3c_controller_daa.v \
i3c_controller_phy_sda.v \
i3c_controller_word.v \
i3c_controller_word_cmd.v \
diff --git a/library/i3c_controller/i3c_controller_core/i3c_controller_core_ip.tcl b/library/i3c_controller/i3c_controller_core/i3c_controller_core_ip.tcl
index de1ec68948..04254814d5 100644
--- a/library/i3c_controller/i3c_controller_core/i3c_controller_core_ip.tcl
+++ b/library/i3c_controller/i3c_controller_core/i3c_controller_core_ip.tcl
@@ -6,7 +6,6 @@ adi_ip_files i3c_controller_core [list \
"i3c_controller_core_constr.ttcl" \
"i3c_controller_core.v" \
"i3c_controller_framing.v" \
- "i3c_controller_daa.v" \
"i3c_controller_phy_sda.v" \
"i3c_controller_word.v" \
"i3c_controller_word_cmd.v" \
@@ -48,9 +47,8 @@ adi_add_bus "cmdp" "slave" \
{"cmdp_buffer_len" "CMDP_BUFFER_LEN"} \
{"cmdp_da" "CMDP_DA"} \
{"cmdp_rnw" "CMDP_RNW"} \
- {"cmdp_do_daa" "CMDP_DO_DAA"} \
- {"cmdp_do_daa_ready" "CMDP_DO_DAA_READY"} \
{"cmdp_cancelled" "CMDP_CANCELLED"} \
+ {"cmdp_idle_bus" "CMDP_IDLE_BUS"} \
}
adi_add_bus_clock "clk" "cmdp" "reset_n"
diff --git a/library/i3c_controller/i3c_controller_core/i3c_controller_daa.v b/library/i3c_controller/i3c_controller_core/i3c_controller_daa.v
index d9d803df21..d11c266f35 100644
--- a/library/i3c_controller/i3c_controller_core/i3c_controller_daa.v
+++ b/library/i3c_controller/i3c_controller_core/i3c_controller_daa.v
@@ -54,7 +54,6 @@
* finishing the DAA. At B, goto on sm state before A, Sr.
* The first and last ACK are mandatory in the flowchart, if a NACK is received,
* it is considered an error and the module resets.
- * The controller writes in push-pull mode.
*/
`timescale 1ns/100ps
@@ -123,7 +122,7 @@ module i3c_controller_daa #(
always @(posedge clk) begin
if (!reset_n) begin
smt <= idle;
- smr <= request;
+ smr <= request;
sm <= `CMDW_NOP;
j <= 0;
cmdw_body <= 8'h00;
@@ -132,7 +131,7 @@ module i3c_controller_daa #(
rmap_devs_ctrl <= 'd0;
end else if (cmdw_nack) begin
smt <= idle;
- smr <= request;
+ smr <= request;
cmdw_body <= 8'h00;
ctrl <= 1'b0;
end else begin
@@ -145,8 +144,8 @@ module i3c_controller_daa #(
end else if (idle_bus) begin
lock <= 1'b0;
end
- rmap_devs_ctrl <= (rmap_devs_ctrl | rmap_devs_ctrl_mr[14:0])
- & ~rmap_devs_ctrl_mr[29:15];
+ rmap_devs_ctrl <= (rmap_devs_ctrl | rmap_devs_ctrl_mr[14:0])
+ & ~rmap_devs_ctrl_mr[29:15];
end
transfer: begin
if (cmdw_ready) begin
diff --git a/library/i3c_controller/i3c_controller_core/i3c_controller_framing.v b/library/i3c_controller/i3c_controller_core/i3c_controller_framing.v
index 52f763ec2f..7efcbca33c 100644
--- a/library/i3c_controller/i3c_controller_core/i3c_controller_framing.v
+++ b/library/i3c_controller/i3c_controller_core/i3c_controller_framing.v
@@ -36,66 +36,101 @@
* Frames commands to the word module.
* That means, cojoins cmdp and sdio bus into single interface cmdw.
* It is the main state-machine for the Command Descriptors received.
+ *
+ * When doing the dynamic address assigment (DAA), the process is:
+ * Controller | Peripheral | Flow
+ * -----------------|-------------|---------
+ * S,0x7e,RnW=0 | | │
+ * | ACK | │
+ * ENTDAA,T | | │
+ * Sr | | ┌─►│
+ * 0x7e,RnW=1 | | │ ▼
+ * | ACK | │ A──┐
+ * | PID+BCR+DCR | │ │ │
+ * DA, Par | | │ ▼ │
+ * | ACK | └──B │
+ * P | | C◄─┘
+ *
+ * Notes
+ * From A with ACK, continue flow to B, or with NACK, goto C Stop,
+ * finishing the DAA. At B, goto on sm state before A, Sr.
+ * The first and last ACK are mandatory in the flowchart, if a NACK is received,
+ * it is considered an error and the module resets.
+ * The whole DAA occurs in OD, hence the Start as Sr in the SM below.
*/
`timescale 1ns/100ps
-`default_nettype none
+`default_nettype wire
`include "i3c_controller_word_cmd.v"
module i3c_controller_framing #(
+ parameter MAX_DEVS = 15
) (
- input wire clk,
- input wire reset_n,
+ input clk,
+ input reset_n,
// Command parsed
- input wire cmdp_valid,
- output wire cmdp_ready,
- input wire cmdp_ccc,
- input wire cmdp_ccc_bcast,
- input wire [6:0] cmdp_ccc_id,
- input wire cmdp_bcast_header,
- input wire [1:0] cmdp_xmit,
- input wire cmdp_sr,
- input wire [11:0] cmdp_buffer_len,
- input wire [6:0] cmdp_da,
- input wire cmdp_rnw,
- output wire cmdp_cancelled, // by the peripheral
+ input cmdp_valid,
+ output cmdp_ready,
+ input cmdp_ccc,
+ input cmdp_ccc_bcast,
+ input [6:0] cmdp_ccc_id,
+ input cmdp_bcast_header,
+ input [1:0] cmdp_xmit,
+ input cmdp_sr,
+ input [11:0] cmdp_buffer_len,
+ input [6:0] cmdp_da,
+ input cmdp_rnw,
+ output cmdp_cancelled, // by the peripheral
// Byte stream
- output wire sdo_ready,
- input wire sdo_valid,
- input wire [7:0] sdo,
+ output sdo_ready,
+ input sdo_valid,
+ input [7:0] sdo,
- input wire sdi_ready,
- output wire sdi_valid,
- output wire [7:0] sdi,
+ input sdi_ready,
+ output sdi_valid,
+ output [7:0] sdi,
// Word command
- output wire cmdw_valid,
- input wire cmdw_ready,
- output wire [`CMDW_HEADER_WIDTH+8:0] cmdw,
- input wire cmdw_nack,
+ output cmdw_valid,
+ input cmdw_ready,
+ output [`CMDW_HEADER_WIDTH+8:0] cmdw,
+ input cmdw_nack,
- output wire cmdw_rx_ready,
- input wire cmdw_rx_valid,
- input wire [7:0] cmdw_rx,
+ output cmdw_rx_ready,
+ input cmdw_rx_valid,
+ input [7:0] cmdw_rx,
// Raw SDO input & bus condition
- input wire rx,
- input wire idle_bus,
+ input rx,
+ input idle_bus,
// IBI interface
- input wire ibi_requested,
- output reg ibi_requested_auto,
+ input ibi_requested,
+ output reg ibi_requested_auto,
+
+ // DAA interface
+
+ input pid_bcr_dcr_tick,
+ input [31:0] pid_bcr_dcr,
// uP accessible info
- input wire [1:0] rmap_ibi_config
+ input [1:0] rmap_ibi_config,
+ input [29:0] rmap_devs_ctrl_mr,
+ output reg [14:0] rmap_devs_ctrl,
+ output rmap_dev_char_e,
+ output rmap_dev_char_we,
+ output [5:0] rmap_dev_char_addr,
+ output [31:0] rmap_dev_char_wdata,
+ input [8:0] rmap_dev_char_rdata
+
);
wire ibi_enable;
wire ibi_auto;
@@ -115,23 +150,42 @@ module i3c_controller_framing #(
reg [`CMDW_HEADER_WIDTH:0] sm;
reg [7:0] cmdw_body;
reg sr;
+ reg ctrl_daa;
+ reg [3:0] j;
- reg [1:0] smt;
- localparam [1:0]
+ reg [2:0] smt;
+ localparam [2:0]
setup = 0,
transfer = 1,
setup_sdo = 2,
- cleanup = 3;
+ cleanup = 3,
+ seek = 4,
+ commit = 5;
+ reg [0:0] smr;
+ localparam [0:0]
+ request = 0,
+ read = 1;
reg cmdp_valid_reg;
+ localparam [6:0]
+ CCC_ENTDAA = 'h07;
+
always @(posedge clk) begin
if (!reset_n) begin
sm <= `CMDW_NOP;
smt <= setup;
+ smr <= request;
+ ctrl_daa <= 1'b0;
+ rmap_devs_ctrl <= 'd0;
+ j <= 0;
end else if (cmdw_nack) begin
sm <= `CMDW_NOP;
smt <= cleanup;
+ smr <= request;
+ ctrl_daa <= 1'b0;
end else begin
+ rmap_devs_ctrl <= (rmap_devs_ctrl | rmap_devs_ctrl_mr[14:0])
+ & ~rmap_devs_ctrl_mr[29:15];
// SDI Ready is are not checked, data will be lost
// if it do not accept/provide data when needed.
case (smt)
@@ -147,7 +201,7 @@ module i3c_controller_framing #(
end else begin
sm <= cmdw_ready ? `CMDW_NOP : sm;
end
- cmdp_valid_reg <= cmdp_valid;
+ cmdp_valid_reg <= cmdp_valid;
cmdp_ccc_reg <= cmdp_ccc;
cmdp_ccc_bcast_reg <= cmdp_ccc_bcast;
cmdp_ccc_id_reg <= cmdp_ccc_id;
@@ -170,16 +224,26 @@ module i3c_controller_framing #(
case(sm)
`CMDW_NOP: begin
smt <= setup;
+ j <= 0;
end
`CMDW_SR,
`CMDW_START: begin
cmdw_body <= {cmdp_da, cmdp_rnw}; // Attention to RnW here
- sm <= ~cmdp_bcast_header_reg & ~cmdp_ccc_reg ? `CMDW_TARGET_ADDR_OD : `CMDW_BCAST_7E_W0;
+ sm <= ctrl_daa ? `CMDW_BCAST_7E_W1 :
+ ~cmdp_bcast_header_reg & ~cmdp_ccc_reg ? `CMDW_TARGET_ADDR_OD : `CMDW_BCAST_7E_W0;
+ ctrl_daa <= 1'b0;
end
`CMDW_BCAST_7E_W0: begin
- sm <= cmdp_ccc_reg ? `CMDW_CCC_PP : `CMDW_MSG_SR;
+ sm <= cmdp_ccc_reg ?
+ (cmdp_ccc_id_reg == CCC_ENTDAA ? `CMDW_CCC_OD : `CMDW_CCC_PP) :
+ `CMDW_MSG_SR;
cmdw_body <= {cmdp_ccc_bcast_reg, cmdp_ccc_id_reg}; // Attention to BCAST here
end
+ `CMDW_CCC_OD: begin
+ // Occurs only during the DAA
+ sm <= `CMDW_START;
+ ctrl_daa <= 1'b1;
+ end
`CMDW_CCC_PP: begin
if (cmdp_ccc_bcast_reg) begin
sm <= `CMDW_MSG_SR;
@@ -192,6 +256,22 @@ module i3c_controller_framing #(
sm <= `CMDW_NOP;
end
end
+ `CMDW_BCAST_7E_W1: begin
+ // Occurs only during the DAA
+ sm <= `CMDW_DAA_DEV_CHAR_1;
+ end
+ `CMDW_DAA_DEV_CHAR_1: begin
+ sm <= `CMDW_DAA_DEV_CHAR_2;
+ smt <= seek;
+ end
+ `CMDW_DAA_DEV_CHAR_2: begin
+ sm <= `CMDW_DYN_ADDR;
+ cmdw_body <= rmap_dev_char_rdata;
+ end
+ `CMDW_DYN_ADDR: begin
+ sm <= j == MAX_DEVS ? `CMDW_STOP : `CMDW_START;
+ smt <= commit;
+ end
`CMDW_MSG_SR: begin
cmdw_body <= {cmdp_da, cmdp_rnw}; // Attention to RnW here
sm <= `CMDW_TARGET_ADDR_PP;
@@ -250,6 +330,29 @@ module i3c_controller_framing #(
end
smt <= cmdp_buffer_len_reg == 0 ? setup : smt;
end
+ seek: begin
+ case (smr)
+ request: begin
+ end
+ read: begin
+ if (rmap_devs_ctrl[j] == 1'b0 & rmap_dev_char_rdata[8] == 1'b1) begin
+ smt <= transfer;
+ end
+ if (rmap_dev_char_rdata[8] == 1'b0) begin
+ // If I2C, just set it as attached
+ rmap_devs_ctrl[j] <= 1'b1;
+ end
+ j <= j + 1;
+ end
+ endcase
+ smr <= ~smr;
+ end
+ commit: begin
+ if (cmdw_ready) begin
+ rmap_devs_ctrl[j-1] <= 1'b1;
+ smt <= transfer;
+ end
+ end
default: begin
smt <= setup;
end
@@ -257,6 +360,18 @@ module i3c_controller_framing #(
end
end
+ reg [1:0] k;
+ wire [1:0] l;
+ always @(posedge clk) begin
+ k <= ~reset_n ? 2'b01 :
+ pid_bcr_dcr_tick ? {k[0],k[1]} : k;
+ end
+ assign l = smt == seek ? 2'b00 : k;
+ assign rmap_dev_char_addr = {l,j};
+ assign rmap_dev_char_wdata = pid_bcr_dcr;
+ assign rmap_dev_char_we = pid_bcr_dcr_tick;
+ assign rmap_dev_char_e = smt == seek | pid_bcr_dcr_tick;
+
assign cmdp_ready = smt == setup & cmdw_ready & !cmdw_nack & reset_n;
assign sdo_ready = (smt == setup_sdo | smt == cleanup) & reset_n;
assign cmdw = {sm, cmdw_body};
diff --git a/library/i3c_controller/i3c_controller_core/i3c_controller_word.v b/library/i3c_controller/i3c_controller_core/i3c_controller_word.v
index f5aee65f92..6c3dcd4018 100644
--- a/library/i3c_controller/i3c_controller_core/i3c_controller_word.v
+++ b/library/i3c_controller/i3c_controller_core/i3c_controller_word.v
@@ -49,15 +49,11 @@ module i3c_controller_word #(
// Word command
- input wire cmdw_mux,
output reg cmdw_nack,
// NACK is HIGH when an ACK is not satisfied in the I3C bus, acts as reset.
- output wire cmdw_framing_valid,
- output wire cmdw_daa_valid,
+ output wire cmdw_valid,
output wire cmdw_ready,
- input wire [`CMDW_HEADER_WIDTH+8:0] cmdw_framing, // From Framing
- input wire [`CMDW_HEADER_WIDTH+8:0] cmdw_daa, // From DAA
-
+ input wire [`CMDW_HEADER_WIDTH+8:0] cmdw,
input wire cmdw_rx_ready,
output reg cmdw_rx_valid,
@@ -101,8 +97,6 @@ module i3c_controller_word #(
wire ibi_auto;
wire [`CMDW_HEADER_WIDTH:0] cmdw_header;
- wire [`CMDW_HEADER_WIDTH+8:0] cmdw;
- wire cmdw_valid;
reg cmd_ready_reg;
reg [7:0] cmdw_body;
@@ -110,9 +104,7 @@ module i3c_controller_word #(
reg [`CMDW_HEADER_WIDTH:0] sm_reg;
reg [`CMDW_HEADER_WIDTH:0] sm_reg_2;
reg [8:0] cmdw_rx_reg;
- reg cmdw_rx_valid_reg;
- reg ibi_tick_reg;
reg [8:0] ibi_da_reg;
reg [8:0] ibi_mdb_reg;
@@ -178,6 +170,8 @@ module i3c_controller_word #(
localparam [0:0]
setup = 0,
transfer = 1;
+ reg ibi_da_valid;
+ wire ibi_should_ack;
always @(posedge clk) begin
cmdw_nack <= 1'b0;
@@ -269,15 +263,16 @@ module i3c_controller_word #(
`CMDW_BCAST_7E_W0: begin
// During the header broadcast, the peripheral shall issue an IBI, due
// to this the SDO is monitored and if the controller loses arbitration,
- // shall ACK if IBI is enabled and receive the MDB, of NACK and Sr.
+ // shall ACK if IBI is enabled and receive the MDB+bytes (if the DCR says so),
+ // or NACK and Sr.
// In both cases, the cmd's transfer will continue after the IBI is
// resolved;
if (i[2:1] == 2'b11) begin
// 1'b0+RnW=0
cmd <= ibi_requested ? `MOD_BIT_CMD_READ : {`MOD_BIT_CMD_WRITE_,1'b0,1'b0};
end else if (i == 8) begin
- if (ibi_requested) begin
- cmd <= ibi_enable ? `MOD_BIT_CMD_ACK_IBI : `MOD_BIT_CMD_READ;
+ if (ibi_requested) begin // also ibi_len ...
+ cmd <= ibi_enable ? `MOD_BIT_CMD_ACK_IBI : `MOD_BIT_CMD_READ; // & ibi_ack
end else begin
// ACK
cmd <= `MOD_BIT_CMD_ACK_SDR;
@@ -287,6 +282,13 @@ module i3c_controller_word #(
// 6'b111111
cmd <= `MOD_BIT_CMD_READ;
end
+
+ if (i == 7) begin
+ if (ibi_requested) begin
+ ibi_da_valid <= 1'b1;
+ end
+ end
+
end
`CMDW_BCAST_7E_W1: begin
if (i == 7) begin
@@ -371,11 +373,9 @@ module i3c_controller_word #(
end
assign cmdw_ready = smt == setup; // i == 0 & cmd_ready_reg & reset_n;
- assign cmdw = cmdw_mux ? cmdw_framing : cmdw_daa;
- assign cmdw_valid = cmdw_mux ? cmdw_framing_valid : cmdw_daa_valid;
assign cmdw_header = cmdw[`CMDW_HEADER_WIDTH+8 -: `CMDW_HEADER_WIDTH+1];
assign cmdw_rx = cmdw_rx_reg[8:1];
- assign clk_sel = cmdw_mux ? clk_sel_reg[1] : 1'b0; // DAA must occur in OD
+ assign clk_sel = clk_sel_reg[1];
assign ibi_da = ibi_da_reg [8:2];
assign ibi_mdb = ibi_mdb_reg[8:1];
diff --git a/library/i3c_controller/i3c_controller_host_interface/i3c_controller_cmd_parser.v b/library/i3c_controller/i3c_controller_host_interface/i3c_controller_cmd_parser.v
index 6cd285759a..cac26f4c89 100644
--- a/library/i3c_controller/i3c_controller_host_interface/i3c_controller_cmd_parser.v
+++ b/library/i3c_controller/i3c_controller_host_interface/i3c_controller_cmd_parser.v
@@ -74,8 +74,6 @@ module i3c_controller_cmd_parser #(
output wire [11:0] cmdp_buffer_len,
output wire [6:0] cmdp_da,
output wire cmdp_rnw,
- output wire cmdp_do_daa,
- input wire cmdp_do_daa_ready,
input wire cmdp_cancelled,
input wire rd_bytes_ready,
@@ -84,7 +82,6 @@ module i3c_controller_cmd_parser #(
output wire wr_bytes_valid,
input wire [11:0] wr_bytes_lvl
);
- wire [6:0] cmd_ccc_id;
wire [11:0] cmdr1_len;
wire buffer_len_valid;
reg [31:0] cmdr1;
@@ -94,8 +91,6 @@ module i3c_controller_cmd_parser #(
reg [3:0] cmdr_error;
reg [7:0] cmdr_sync;
- localparam [6:0] CCC_ENTDAA = 7'h7;
-
localparam [3:0]
NO_ERROR = 4'd0,
CE0_ERROR = 4'd1,
@@ -109,9 +104,7 @@ module i3c_controller_cmd_parser #(
xfer_await = 2,
xfer_await_ready = 3,
ccc_await = 4,
- daa_await = 5,
- daa_await_ready = 6,
- receipt = 7;
+ receipt = 5;
always @(posedge clk) begin
if (!reset_n) begin
@@ -158,13 +151,7 @@ module i3c_controller_cmd_parser #(
end
ccc_await: begin
cmdr2 <= cmd[7:0];
- sm <= cmd_valid ? (cmd_ccc_id == CCC_ENTDAA ? daa_await : xfer_await) : sm;
- end
- daa_await: begin
- sm <= !cmdp_do_daa_ready ? daa_await_ready : sm;
- end
- daa_await_ready: begin
- sm <= cmdp_do_daa_ready ? receipt : sm;
+ sm <= cmd_valid ? xfer_await : sm;
end
receipt: begin
if (cmdr_ready) begin
@@ -179,14 +166,12 @@ module i3c_controller_cmd_parser #(
end
end
- assign cmd_ready = (sm == receive || sm == ccc_await) & reset_n & cmdp_do_daa_ready;
+ assign cmd_ready = (sm == receive || sm == ccc_await) & reset_n;
assign cmdp_valid = sm == xfer_await & reset_n;
- assign cmdp_do_daa = sm == daa_await & reset_n;
assign cmdp_ccc = cmdr1[30];
assign cmdp_ccc_bcast = cmdr2[7];
assign cmdp_ccc_id = cmdr2[6:0];
- assign cmd_ccc_id = cmd [6:0];
assign cmdp_bcast_header = cmdr1[29];
assign cmdp_xmit = cmdr1[28:27];
assign cmdp_buffer_len = cmdr1[23:12];
diff --git a/library/i3c_controller/i3c_controller_host_interface/i3c_controller_host_interface.v b/library/i3c_controller/i3c_controller_host_interface/i3c_controller_host_interface.v
index 182e005809..8795a8951b 100644
--- a/library/i3c_controller/i3c_controller_host_interface/i3c_controller_host_interface.v
+++ b/library/i3c_controller/i3c_controller_host_interface/i3c_controller_host_interface.v
@@ -66,6 +66,8 @@ module i3c_controller_host_interface #(
output wire ibi_valid,
output wire [DATA_WIDTH-1:0] ibi,
+ output reg quiet_times,
+
// Command parsed
output wire cmdp_valid,
@@ -79,9 +81,8 @@ module i3c_controller_host_interface #(
output wire [11:0] cmdp_buffer_len,
output wire [6:0] cmdp_da,
output wire cmdp_rnw,
- output wire cmdp_do_daa,
- input wire cmdp_do_daa_ready,
input wire cmdp_cancelled,
+ input wire cmdp_idle_bus,
// Byte stream
@@ -179,8 +180,6 @@ module i3c_controller_host_interface #(
.cmdp_buffer_len(cmdp_buffer_len),
.cmdp_da(cmdp_da),
.cmdp_rnw(cmdp_rnw),
- .cmdp_do_daa(cmdp_do_daa),
- .cmdp_do_daa_ready(cmdp_do_daa_ready),
.cmdp_cancelled(cmdp_cancelled),
.rd_bytes_ready(rd_bytes_ready),
@@ -189,4 +188,8 @@ module i3c_controller_host_interface #(
.wr_bytes_valid(wr_bytes_valid),
.wr_bytes_lvl(wr_bytes_lvl)
);
+
+ always @(posedge clk) begin
+ quiet_times <= cmdp_idle_bus;
+ end
endmodule
diff --git a/library/i3c_controller/i3c_controller_host_interface/i3c_controller_host_interface_hw.tcl b/library/i3c_controller/i3c_controller_host_interface/i3c_controller_host_interface_hw.tcl
index fe570b967f..e6349d00cd 100644
--- a/library/i3c_controller/i3c_controller_host_interface/i3c_controller_host_interface_hw.tcl
+++ b/library/i3c_controller/i3c_controller_host_interface/i3c_controller_host_interface_hw.tcl
@@ -26,7 +26,7 @@ proc p_elaboration {} {
set_interface_property sync associatedReset if_resetn
# physical I3C interface
- ad_interface clock scl output 1
- ad_interface signal sda inout 1
+ ad_interface clock scl output 1
+ ad_interface signal sda inout 1
}
diff --git a/library/i3c_controller/i3c_controller_host_interface/i3c_controller_host_interface_ip.tcl b/library/i3c_controller/i3c_controller_host_interface/i3c_controller_host_interface_ip.tcl
index 595723078a..204e32015c 100644
--- a/library/i3c_controller/i3c_controller_host_interface/i3c_controller_host_interface_ip.tcl
+++ b/library/i3c_controller/i3c_controller_host_interface/i3c_controller_host_interface_ip.tcl
@@ -24,21 +24,22 @@ adi_add_bus "ctrl" "slave" \
"analog.com:interface:i3c_controller_ctrl_rtl:1.0" \
"analog.com:interface:i3c_controller_ctrl:1.0" \
{
- {"cmd_ready" "CMD_READY"} \
- {"cmd_valid" "CMD_VALID"} \
- {"cmd" "CMD_DATA"} \
- {"cmdr_ready" "CMDR_READY"} \
- {"cmdr_valid" "CMDR_VALID"} \
- {"cmdr" "CMDR_DATA"} \
- {"sdo_ready" "SDO_READY"} \
- {"sdo_valid" "SDO_VALID"} \
- {"sdo" "SDO_DATA"} \
- {"sdi_ready" "SDI_READY"} \
- {"sdi_valid" "SDI_VALID"} \
- {"sdi" "SDI_DATA"} \
- {"ibi_ready" "IBI_READY"} \
- {"ibi_valid" "IBI_VALID"} \
- {"ibi" "IBI_DATA"} \
+ {"cmd_ready" "CMD_READY"} \
+ {"cmd_valid" "CMD_VALID"} \
+ {"cmd" "CMD_DATA"} \
+ {"cmdr_ready" "CMDR_READY"} \
+ {"cmdr_valid" "CMDR_VALID"} \
+ {"cmdr" "CMDR_DATA"} \
+ {"sdo_ready" "SDO_READY"} \
+ {"sdo_valid" "SDO_VALID"} \
+ {"sdo" "SDO_DATA"} \
+ {"sdi_ready" "SDI_READY"} \
+ {"sdi_valid" "SDI_VALID"} \
+ {"sdi" "SDI_DATA"} \
+ {"ibi_ready" "IBI_READY"} \
+ {"ibi_valid" "IBI_VALID"} \
+ {"ibi" "IBI_DATA"} \
+ {"quiet_times" "QUIET_TIMES"} \
}
adi_add_bus_clock "clk" "ctrl" "reset_n"
@@ -46,20 +47,19 @@ adi_add_bus "cmdp" "master" \
"analog.com:interface:i3c_controller_cmdp_rtl:1.0" \
"analog.com:interface:i3c_controller_cmdp:1.0" \
{
- {"cmdp_valid" "CMDP_VALID"} \
- {"cmdp_ready" "CMDP_READY"} \
- {"cmdp_ccc" "CMDP_CCC"} \
- {"cmdp_ccc_bcast" "CMDP_CCC_BCAST"} \
- {"cmdp_ccc_id" "CMDP_CCC_ID"} \
- {"cmdp_bcast_header" "CMDP_BCAST_HEADER"} \
- {"cmdp_xmit" "CMDP_XMIT"} \
- {"cmdp_sr" "CMDP_SR"} \
- {"cmdp_buffer_len" "CMDP_BUFFER_LEN"} \
- {"cmdp_da" "CMDP_DA"} \
- {"cmdp_rnw" "CMDP_RNW"} \
- {"cmdp_do_daa" "CMDP_DO_DAA"} \
- {"cmdp_do_daa_ready" "CMDP_DO_DAA_READY"} \
- {"cmdp_cancelled" "CMDP_CANCELLED"} \
+ {"cmdp_valid" "CMDP_VALID"} \
+ {"cmdp_ready" "CMDP_READY"} \
+ {"cmdp_ccc" "CMDP_CCC"} \
+ {"cmdp_ccc_bcast" "CMDP_CCC_BCAST"} \
+ {"cmdp_ccc_id" "CMDP_CCC_ID"} \
+ {"cmdp_bcast_header" "CMDP_BCAST_HEADER"} \
+ {"cmdp_xmit" "CMDP_XMIT"} \
+ {"cmdp_sr" "CMDP_SR"} \
+ {"cmdp_buffer_len" "CMDP_BUFFER_LEN"} \
+ {"cmdp_da" "CMDP_DA"} \
+ {"cmdp_rnw" "CMDP_RNW"} \
+ {"cmdp_cancelled" "CMDP_CANCELLED"} \
+ {"cmdp_idle_bus" "CMDP_IDLE_BUS"} \
}
adi_add_bus_clock "clk" "cmdp" "reset_n"
diff --git a/library/i3c_controller/interfaces/i3c_controller_cmdp_rtl.xml b/library/i3c_controller/interfaces/i3c_controller_cmdp_rtl.xml
index 40ec721333..aeeca1fffc 100644
--- a/library/i3c_controller/interfaces/i3c_controller_cmdp_rtl.xml
+++ b/library/i3c_controller/interfaces/i3c_controller_cmdp_rtl.xml
@@ -177,22 +177,7 @@
- CMDP_DO_DAA
-
-
- required
- 1
- out
-
-
- required
- 1
- in
-
-
-
-
- CMDP_DO_DAA_READY
+ CMDP_CANCELLED
required
@@ -207,7 +192,7 @@
- CMDP_CANCELLED
+ CMDP_IDLE_BUS
required
diff --git a/library/i3c_controller/interfaces/i3c_controller_ctrl_rtl.xml b/library/i3c_controller/interfaces/i3c_controller_ctrl_rtl.xml
index 79e1cccde8..36609a59a5 100644
--- a/library/i3c_controller/interfaces/i3c_controller_ctrl_rtl.xml
+++ b/library/i3c_controller/interfaces/i3c_controller_ctrl_rtl.xml
@@ -10,7 +10,7 @@
spirit:library="interface"
spirit:name="i3c_controller_ctrl"
spirit:version="1.0"/>
-
+
CMD_READY
@@ -236,5 +236,20 @@
+
+ QUIET_TIMES
+
+
+ required
+ 1
+ in
+
+
+ required
+ 1
+ out
+
+
+
diff --git a/library/i3c_controller/scripts/i3c_controller.tcl b/library/i3c_controller/scripts/i3c_controller.tcl
index b4696650f2..755461683f 100644
--- a/library/i3c_controller/scripts/i3c_controller.tcl
+++ b/library/i3c_controller/scripts/i3c_controller.tcl
@@ -1,4 +1,4 @@
-proc i3c_controller_create {{name "i3c_controller"} {async_i3c_clk 0} {clk_div "4"} {sim_device "7SERIES"}} {
+proc i3c_controller_create {{name "i3c_controller"} {async_i3c_clk 0} {clk_div "4"} {sim_device "7SERIES"} {offload 1}} {
create_bd_cell -type hier $name
current_bd_instance /$name
@@ -10,9 +10,14 @@ proc i3c_controller_create {{name "i3c_controller"} {async_i3c_clk 0} {clk_div "
create_bd_pin -dir I -type rst reset_n
create_bd_pin -dir O irq
create_bd_intf_pin -mode Master -vlnv analog.com:interface:i3c_controller_rtl:1.0 m_i3c
+ if {$offload == 1} {
+ create_bd_pin -dir I trigger
+ create_bd_intf_pin -mode Master -vlnv xilinx.com:interface:axis_rtl:1.0 m_offload
+ }
ad_ip_instance axi_i3c_controller axi_regmap
ad_ip_parameter axi_regmap CONFIG.ASYNC_I3C_CLK $async_i3c_clk
+ ad_ip_parameter axi_regmap CONFIG.OFFLOAD $offload
ad_ip_instance i3c_controller_host_interface host_interface
@@ -28,6 +33,10 @@ proc i3c_controller_create {{name "i3c_controller"} {async_i3c_clk 0} {clk_div "
ad_connect clk host_interface/clk
ad_connect clk core/clk
}
+ if {$offload == 1} {
+ ad_connect trigger axi_regmap/offload_trigger
+ ad_connect axi_regmap/offload m_offload
+ }
ad_connect core/i3c m_i3c
ad_connect clk axi_regmap/s_axi_aclk
diff --git a/projects/__i3c_ardz/common/__i3c_ardz_bd.tcl b/projects/__i3c_ardz/common/__i3c_ardz_bd.tcl
index e8e22e1c2d..e74feab291 100644
--- a/projects/__i3c_ardz/common/__i3c_ardz_bd.tcl
+++ b/projects/__i3c_ardz/common/__i3c_ardz_bd.tcl
@@ -5,18 +5,48 @@ source $ad_hdl_dir/library/i3c_controller/scripts/i3c_controller.tcl
set async_i3c_clk 0
set sim_device "7SERIES"
set clk_div "4"
+set offload 1
set hier_i3c_controller i3c_controller_0
-i3c_controller_create $hier_i3c_controller $async_i3c_clk $clk_div $sim_device
-
+i3c_controller_create $hier_i3c_controller $async_i3c_clk $clk_div $sim_device $offload
+
+# pwm to trigger on offload data burst
+ad_ip_instance axi_pwm_gen i3c_offload_pwm
+ad_ip_parameter i3c_offload_pwm CONFIG.PULSE_0_PERIOD 120
+ad_ip_parameter i3c_offload_pwm CONFIG.PULSE_0_WIDTH 1
+
+# dma to receive offload data stream
+ad_ip_instance axi_dmac i3c_offload_dma
+ad_ip_parameter i3c_offload_dma CONFIG.DMA_TYPE_SRC 1
+ad_ip_parameter i3c_offload_dma CONFIG.DMA_TYPE_DEST 0
+ad_ip_parameter i3c_offload_dma CONFIG.CYCLIC 0
+ad_ip_parameter i3c_offload_dma CONFIG.SYNC_TRANSFER_START 0
+ad_ip_parameter i3c_offload_dma CONFIG.AXI_SLICE_SRC 0
+ad_ip_parameter i3c_offload_dma CONFIG.AXI_SLICE_DEST 1
+ad_ip_parameter i3c_offload_dma CONFIG.DMA_2D_TRANSFER 0
+ad_ip_parameter i3c_offload_dma CONFIG.DMA_DATA_WIDTH_SRC 32
+ad_ip_parameter i3c_offload_dma CONFIG.DMA_DATA_WIDTH_DEST 64
+
+ad_connect $sys_cpu_clk i3c_offload_pwm/ext_clk
+ad_connect $sys_cpu_clk i3c_offload_pwm/s_axi_aclk
+ad_connect sys_cpu_resetn i3c_offload_pwm/s_axi_aresetn
+ad_connect i3c_offload_pwm/pwm_0 $hier_i3c_controller/trigger
+
+ad_connect i3c_offload_dma/s_axis $hier_i3c_controller/m_offload
ad_connect $hier_i3c_controller/m_i3c i3c_controller_0
ad_connect $sys_cpu_clk $hier_i3c_controller/clk
+ad_connect $sys_cpu_clk i3c_offload_dma/s_axis_aclk
ad_connect sys_cpu_resetn $hier_i3c_controller/reset_n
+ad_connect sys_cpu_resetn i3c_offload_dma/m_dest_axi_aresetn
ad_cpu_interconnect 0x44a00000 $hier_i3c_controller/axi_regmap
+ad_cpu_interconnect 0x44a30000 i3c_offload_dma
+ad_cpu_interconnect 0x44b00000 i3c_offload_pwm
+ad_cpu_interrupt "ps-13" "mb-13" i3c_offload_dma/irq
ad_cpu_interrupt "ps-12" "mb-12" /$hier_i3c_controller/irq
-#ad_mem_hp1_interconnect $sys_cpu_clk sys_ps7/S_AXI_HP1
+ad_mem_hp1_interconnect $sys_cpu_clk sys_ps7/S_AXI_HP1
+ad_mem_hp1_interconnect $sys_cpu_clk i3c_offload_dma/m_dest_axi
diff --git a/projects/__i3c_ardz/coraz7s/system_constr.xdc b/projects/__i3c_ardz/coraz7s/system_constr.xdc
index 2aa2226424..25a45f4796 100644
--- a/projects/__i3c_ardz/coraz7s/system_constr.xdc
+++ b/projects/__i3c_ardz/coraz7s/system_constr.xdc
@@ -19,8 +19,6 @@ set_multicycle_path -from [get_clocks clk_fpga_0] -to [get_ports i3c_controller_
set_multicycle_path -from [get_clocks clk_fpga_0] -to [get_ports i3c_controller_0_scl] -setup 2
set_multicycle_path -from [get_clocks clk_fpga_0] -to [get_ports i3c_controller_0_scl] -hold 1
-#set_multicycle_path -from [get_clocks clk_fpga_0] -to [get_clocks clk_1] -setup 4
-#set_multicycle_path -from [get_clocks clk_fpga_0] -to [get_clocks clk_1] -hold 3
set_multicycle_path -from [get_clocks clk_1] -to [get_clocks clk_fpga_0] -setup 4
set_multicycle_path -from [get_clocks clk_1] -to [get_clocks clk_fpga_0] -hold 3