diff --git a/docs/regmap/adi_regmap_spi_engine.txt b/docs/regmap/adi_regmap_spi_engine.txt index 681c37d45d..908b04bf33 100644 --- a/docs/regmap/adi_regmap_spi_engine.txt +++ b/docs/regmap/adi_regmap_spi_engine.txt @@ -9,7 +9,7 @@ ENDTITLE REG 0x00 VERSION -Version of the peripheral. Follows semantic versioning. Current version 1.03.00. +Version of the peripheral. Follows semantic versioning. Current version 1.03.01. ENDREG FIELD @@ -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 f91e00eb26..2c0a9f37c9 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 12876729f4..f0a58bcc93 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,12 @@ 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), + .sdo_io_ready(sdo_io_ready), .transfer_active(transfer_active), .trigger_tx(trigger_tx), .trigger_rx(trigger_rx), @@ -197,6 +201,8 @@ module spi_engine_execution #( .cs_activate(cs_activate), .end_of_sdi_latch(end_of_sdi_latch)); + assign sample_sdo = sdo_data_valid && ((trigger_tx && last_bit) || (wait_for_io || 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) @@ -380,7 +386,7 @@ module spi_engine_execution #( assign sync = cmd_d1[7:0]; assign io_ready1 = (sdi_data_valid == 1'b0 || sdi_data_ready == 1'b1) && - (sdo_enabled == 1'b0 || last_transfer == 1'b1 || sdo_data_valid == 1'b1); + (sdo_enabled == 1'b0 || last_transfer == 1'b1 || sdo_io_ready == 1'b1); assign io_ready2 = (sdi_enabled == 1'b0 || sdi_data_ready == 1'b1) && (sdo_enabled == 1'b0 || last_transfer == 1'b1 || sdo_data_valid == 1'b1); 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 6f3e999177..428c09797d 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,14 @@ 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, + output reg sdo_io_ready, input transfer_active, input trigger_tx, input trigger_rx, @@ -79,17 +81,37 @@ 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_toshiftreg) 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; + sdo_io_ready <= 1'b0; + end else begin + if (transfer_active == 1'b1 && trigger_tx == 1'b1) begin + sdo_io_ready <= 1'b0; + end + if (sample_sdo) begin + sdo_data_d <= sdo_data; + sdo_io_ready <= 1'b1; + 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,13 +120,16 @@ 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]; + assign sdo_toshiftreg = (transfer_active && trigger_tx && first_bit && sdo_enabled); + // In case of an interface with high clock rate (SCLK > 50MHz), the latch of // the SDI line can be delayed with 1, 2 or 3 SPI core clock cycle. @@ -203,7 +228,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 +253,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