From 5dc2ab9fe71099de941bd2ee89f2cac02e3c54c6 Mon Sep 17 00:00:00 2001 From: Arpadi Date: Thu, 26 Sep 2019 13:17:49 +0300 Subject: [PATCH] spi_engine/execution: dynamic length bugfix ip can now send multiple words per transfer with dynamic data length --- .../spi_engine_execution.v | 47 ++++++++++--------- 1 file changed, 26 insertions(+), 21 deletions(-) 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 fad79177aca..61b1edb5f93 100644 --- a/library/spi_engine/spi_engine_execution/spi_engine_execution.v +++ b/library/spi_engine/spi_engine_execution/spi_engine_execution.v @@ -97,6 +97,9 @@ localparam REG_WORD_LENGTH = 2'b10; localparam BIT_COUNTER_WIDTH = DATA_WIDTH > 16 ? 5 : DATA_WIDTH > 8 ? 4 : 3; +localparam BIT_COUNTER_CARRY = 2** (BIT_COUNTER_WIDTH + 1); +localparam BIT_COUNTER_CLEAR = {{8{1'b1}}, {BIT_COUNTER_WIDTH{1'b0}}, 1'b1}; + reg sclk_int = 1'b0; wire sdo_int_s; reg sdo_t_int = 1'b0; @@ -130,7 +133,7 @@ wire end_of_word; reg [7:0] sdi_counter = 8'b0; -assign first_bit = bit_counter == 'h0; +assign first_bit = ((bit_counter == 'h0) || (bit_counter == word_length)); assign last_bit = bit_counter == word_length - 1; assign end_of_word = last_bit == 1'b1 && ntx_rx == 1'b1 && clk_div_last == 1'b1; @@ -143,20 +146,6 @@ reg [7:0] clk_div = DEFAULT_CLK_DIV; wire sdo_enabled = cmd_d1[8]; wire sdi_enabled = cmd_d1[9]; -wire last_sdi_bit = (sdi_counter == word_length-1); - -wire trigger_tx = trigger == 1'b1 && ntx_rx == 1'b0; -wire trigger_rx = trigger == 1'b1 && ntx_rx == 1'b1; - -reg trigger_rx_d1 = 1'b0; -reg trigger_rx_d2 = 1'b0; -reg trigger_rx_d3 = 1'b0; - -wire trigger_rx_s = (SDI_DELAY == 2'b00) ? trigger_rx : - (SDI_DELAY == 2'b01) ? trigger_rx_d1 : - (SDI_DELAY == 2'b10) ? trigger_rx_d2 : - (SDI_DELAY == 2'b11) ? trigger_rx_d3 : trigger_rx; - // supporting max 8 SDI channel reg [(DATA_WIDTH-1):0] data_sdo_shift = 'h0; reg [(DATA_WIDTH-1):0] data_sdi_shift = 'h0; @@ -240,16 +229,23 @@ always @(posedge clk) begin end end +wire trigger_tx = trigger == 1'b1 && ntx_rx == 1'b0; +wire trigger_rx = trigger == 1'b1 && ntx_rx == 1'b1; wire sleep_counter_compare = sleep_counter == cmd_d1[7:0] && clk_div_last == 1'b1; wire cs_sleep_counter_compare = cs_sleep_counter == cmd_d1[9:8] && clk_div_last == 1'b1; wire cs_sleep_counter_compare2 = cs_sleep_counter2 == {cmd_d1[9:8],1'b1} && clk_div_last == 1'b1; always @(posedge clk) begin - if (idle == 1'b1) + if (idle == 1'b1) begin counter <= 'h00; - else if (clk_div_last == 1'b1 && wait_for_io == 1'b0) - counter <= counter + (transfer_active ? 'h1 : 'h10); + end else if (clk_div_last == 1'b1 && wait_for_io == 1'b0) begin + if (bit_counter == word_length) begin + counter <= (counter & BIT_COUNTER_CLEAR) + (transfer_active ? 'h1 : 'h10) + BIT_COUNTER_CARRY; + end else begin + counter <= counter + (transfer_active ? 'h1 : 'h10); + end + end end always @(posedge clk) begin @@ -310,8 +306,7 @@ assign sync = cmd_d1[7:0]; always @(posedge clk) begin if (resetn == 1'b0) sdo_data_ready <= 1'b0; - else if (sdo_enabled == 1'b1 && first_bit == 1'b1 && trigger_tx == 1'b1 && - transfer_active == 1'b1) + else if (sdo_enabled == 1'b1 && first_bit == 1'b1 && trigger_tx == 1'b1 && transfer_active == 1'b1) sdo_data_ready <= 1'b1; else if (sdo_data_valid == 1'b1) sdo_data_ready <= 1'b0; @@ -393,12 +388,21 @@ assign sdo_int_s = data_sdo_shift[DATA_WIDTH-1]; // next SCLK edge must be used to flop the SDI line, to compensate the overall // delay of the read path +reg trigger_rx_d1 = 1'b0; +reg trigger_rx_d2 = 1'b0; +reg trigger_rx_d3 = 1'b0; + always @(posedge clk) begin trigger_rx_d1 <= trigger_rx; trigger_rx_d2 <= trigger_rx_d1; trigger_rx_d3 <= trigger_rx_d2; end +wire trigger_rx_s = (SDI_DELAY == 2'b00) ? trigger_rx : + (SDI_DELAY == 2'b01) ? trigger_rx_d1 : + (SDI_DELAY == 2'b10) ? trigger_rx_d2 : + (SDI_DELAY == 2'b11) ? trigger_rx_d3 : trigger_rx; + always @(posedge clk) begin if (inst_d1 == CMD_CHIPSELECT) begin data_sdi_shift <= {DATA_WIDTH{1'b0}}; @@ -442,6 +446,7 @@ assign sdi_data = (NUM_OF_SDI == 1) ? data_sdi_shift : data_sdi_shift_3, data_sdi_shift_2, data_sdi_shift_1, data_sdi_shift} : data_sdi_shift; +wire last_sdi_bit = (sdi_counter == word_length-1); always @(posedge clk) begin if (resetn == 1'b0) begin sdi_counter <= 8'b0; @@ -460,7 +465,7 @@ always @(posedge clk) begin end end -// Additional register stage to improve timing +// Additional register stage to imrpove timing always @(posedge clk) begin sclk <= sclk_int; sdo <= sdo_int_s;