From e26bac36a8afd95c21f1f0982a1cb964c45c0122 Mon Sep 17 00:00:00 2001 From: Laez Barbosa Date: Thu, 15 Aug 2024 16:52:17 -0300 Subject: [PATCH] SPI Engine Execution: pipeline sdo alignment Split path between sdo data input and sdo shift register, which includes a barrel shifter. Signed-off-by: Laez Barbosa --- docs/regmap/adi_regmap_spi_engine.txt | 2 +- .../axi_spi_engine/axi_spi_engine.v | 2 +- .../spi_engine_execution.v | 7 +++- .../spi_engine_execution_shiftreg.v | 41 +++++++++++++------ 4 files changed, 37 insertions(+), 15 deletions(-) diff --git a/docs/regmap/adi_regmap_spi_engine.txt b/docs/regmap/adi_regmap_spi_engine.txt index 681c37d45d8..003cdd526f9 100644 --- a/docs/regmap/adi_regmap_spi_engine.txt +++ b/docs/regmap/adi_regmap_spi_engine.txt @@ -25,7 +25,7 @@ RO ENDFIELD FIELD -[7:0] 0x00000000 +[7:0] 0x00000001 VERSION_PATCH RO ENDFIELD diff --git a/library/spi_engine/axi_spi_engine/axi_spi_engine.v b/library/spi_engine/axi_spi_engine/axi_spi_engine.v index f91e00eb264..2c0a9f37c97 100644 --- a/library/spi_engine/axi_spi_engine/axi_spi_engine.v +++ b/library/spi_engine/axi_spi_engine/axi_spi_engine.v @@ -133,7 +133,7 @@ module axi_spi_engine #( input [7:0] offload_sync_data ); - localparam PCORE_VERSION = 'h010300; + localparam PCORE_VERSION = 'h010301; localparam S_AXI = 0; localparam UP_FIFO = 1; diff --git a/library/spi_engine/spi_engine_execution/spi_engine_execution.v b/library/spi_engine/spi_engine_execution/spi_engine_execution.v index 2bfdac3026c..67cae0d18a4 100644 --- a/library/spi_engine/spi_engine_execution/spi_engine_execution.v +++ b/library/spi_engine/spi_engine_execution/spi_engine_execution.v @@ -163,6 +163,8 @@ module spi_engine_execution #( wire end_of_sdi_latch; + wire sample_sdo; + (* direct_enable = "yes" *) wire cs_gen; spi_engine_execution_shiftreg #( @@ -186,10 +188,11 @@ module spi_engine_execution #( .sdi_data_ready(sdi_data_ready), .sdo_enabled(sdo_enabled), .sdi_enabled(sdi_enabled), - .current_instr(inst_d1), + .current_cmd(cmd_d1), .sdo_idle_state(sdo_idle_state), .left_aligned(left_aligned), .word_length(word_length), + .sample_sdo(sample_sdo), .transfer_active(transfer_active), .trigger_tx(trigger_tx), .trigger_rx(trigger_rx), @@ -198,6 +201,8 @@ module spi_engine_execution #( .end_of_sdi_latch(end_of_sdi_latch) ); + assign sample_sdo = (trigger_tx && last_bit) || exec_transfer_cmd; + assign cs_gen = inst_d1 == CMD_CHIPSELECT && ((cs_sleep_counter_compare == 1'b1) || cs_sleep_early_exit) && (cs_sleep_repeat == 1'b0) diff --git a/library/spi_engine/spi_engine_execution/spi_engine_execution_shiftreg.v b/library/spi_engine/spi_engine_execution/spi_engine_execution_shiftreg.v index 8a98534a595..b12dbbd1068 100644 --- a/library/spi_engine/spi_engine_execution/spi_engine_execution_shiftreg.v +++ b/library/spi_engine/spi_engine_execution/spi_engine_execution_shiftreg.v @@ -48,7 +48,7 @@ module spi_engine_execution_shiftreg #( input resetn, // spi io - input sdi, + input [NUM_OF_SDI-1:0] sdi, output sdo_int, input echo_sclk, @@ -63,12 +63,13 @@ module spi_engine_execution_shiftreg #( // cfg and status input sdo_enabled, input sdi_enabled, - input [2:0] current_instr, + input [15:0] current_cmd, input sdo_idle_state, input [7:0] left_aligned, input [7:0] word_length, // timing from main fsm + input sample_sdo, input transfer_active, input trigger_tx, input trigger_rx, @@ -79,17 +80,32 @@ module spi_engine_execution_shiftreg #( reg [7:0] sdi_counter = 8'b0; reg [(DATA_WIDTH-1):0] data_sdo_shift = 'h0; + reg [(DATA_WIDTH-1):0] aligned_sdo_data, sdo_data_d; wire last_sdi_bit; reg [SDI_DELAY+1:0] trigger_rx_d = {(SDI_DELAY+2){1'b0}}; wire trigger_rx_s; + wire [2:0] current_instr = current_cmd[14:12]; always @(posedge clk) begin - if (resetn == 1'b0) + if (resetn == 1'b0) begin sdo_data_ready <= 1'b0; - else if (sdo_enabled == 1'b1 && first_bit == 1'b1 && trigger_tx == 1'b1 && transfer_active == 1'b1) + end else if (sdo_enabled == 1'b1 && first_bit == 1'b1 && trigger_tx == 1'b1 && transfer_active == 1'b1) begin sdo_data_ready <= 1'b1; - else if (sdo_data_valid == 1'b1) + end else if (sdo_data_valid == 1'b1) begin sdo_data_ready <= 1'b0; + end + end + + // pipelined shifter for sdo_data + always @(posedge clk ) begin + if (resetn == 1'b0) begin + aligned_sdo_data <= 0; + end else begin + if (sample_sdo) begin + sdo_data_d <= sdo_data; + end + aligned_sdo_data <= sdo_data_d << left_aligned; + end end // Load the SDO parallel data into the SDO shift register. In case of a custom @@ -98,10 +114,11 @@ module spi_engine_execution_shiftreg #( if (!sdo_enabled || (current_instr != CMD_TRANSFER)) begin data_sdo_shift <= {DATA_WIDTH{sdo_idle_state}}; end else if (transfer_active == 1'b1 && trigger_tx == 1'b1) begin - if (first_bit == 1'b1) - data_sdo_shift <= sdo_data << left_aligned; //TODO: check if this could/should be pipelined - else - data_sdo_shift <= {data_sdo_shift[(DATA_WIDTH-2):0], 1'b0}; + if (first_bit == 1'b1) begin + data_sdo_shift <= aligned_sdo_data; + end else begin + data_sdo_shift <= {data_sdo_shift[(DATA_WIDTH-2):0], 1'b0}; + end end end assign sdo_int = data_sdo_shift[DATA_WIDTH-1]; @@ -203,7 +220,7 @@ module spi_engine_execution_shiftreg #( // sdi_data_valid is synchronous to SPI clock, so synchronize the // last_sdi_bit to SPI clock - reg [3:0] last_sdi_bit_m = 4'b0; //FIXME: bad synchronizer (cs_activate shouldn't be connected here), also why not just use sync_bits? + reg [3:0] last_sdi_bit_m = 4'b0; //FIXME: why not just use sync_bits? always @(posedge clk) begin if (cs_activate) begin last_sdi_bit_m <= 4'b0; @@ -228,8 +245,8 @@ module spi_engine_execution_shiftreg #( if (cs_activate) begin num_of_transfers <= 8'b0; end else begin - if (cmd_d1[15:12] == 4'b0) begin - num_of_transfers <= cmd_d1[7:0] + 1'b1; // cmd_d1 contains the NUM_OF_TRANSFERS - 1 + if (current_instr == CMD_TRANSFER) begin + num_of_transfers <= current_cmd[7:0] + 1'b1; // current_cmd contains the NUM_OF_TRANSFERS - 1 end end end