Skip to content

Commit

Permalink
SPI Engine: Fixed delay behaviour on Chip-Select and Sleep instructio…
Browse files Browse the repository at this point in the history
…ns (#1200)

Fixed wrong behaviour on chip select instruction:
- previously, a sleep time happened before the chip select change
- the intended behaviour was for another sleep time, of equal amount, to happen after the chip select change as well
- additionally, the counter logic implementation was creating an additional factor of 2 on the sleep time

All of the above points were fixed. The changes introduced also fix another issue where the sleep instruction was likewise happening with a duration larger than intended by a factor of 2


Signed-off-by: Laez Barbosa <laez.barbosa@analog.com>
  • Loading branch information
LBFFilho authored Oct 30, 2023
1 parent 3659335 commit becc035
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 11 deletions.
10 changes: 6 additions & 4 deletions docs/library/spi_engine/instruction-format.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,12 @@ specified delay. The length of the delay depends on the module clock frequency,
the setting of the prescaler register and the t parameter of the instruction.
This delay is inserted before and after the update of the chip-select signal,
so the total execution time of the chip-select
instruction is twice the delay.
instruction is twice the delay, plus a fixed 2 clock cycles (fast clock, not prescaled)
for the internal logic.

.. math::
delay = t * \frac{div + 1}{f_{clk}}
delay = t * \frac{(div + 1)*2}{f_{clk}}
.. list-table::
:widths: 10 15 75
Expand Down Expand Up @@ -152,11 +153,12 @@ Sleep Instruction
The sleep instruction stops the execution of the command stream for the
specified amount of time. The time is based on the external clock frequency the
configuration value of the prescaler register and the time parameter of the
instruction.
instruction. A fixed delay of two clock cycles (fast, not affected by the prescaler)
is the minimum, needed by the internal logic.

.. math::
sleep\_time = \frac{(t + 1) * ((div + 1) * 2)}{f_{clk}}
sleep\_time = \frac{2+(t) * ((div + 1) * 2)}{f_{clk}}
.. list-table::
:widths: 10 15 75
Expand Down
32 changes: 25 additions & 7 deletions library/spi_engine/spi_engine_execution/spi_engine_execution.v
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ module spi_engine_execution #(

wire sleep_counter_compare;
wire cs_sleep_counter_compare;
wire cs_sleep_early_exit;
reg cs_sleep_repeat;

wire io_ready1;
wire io_ready2;
Expand All @@ -167,7 +169,10 @@ module spi_engine_execution #(

(* direct_enable = "yes" *) wire cs_gen;

assign cs_gen = inst_d1 == CMD_CHIPSELECT && cs_sleep_counter_compare == 1'b1;
assign cs_gen = inst_d1 == CMD_CHIPSELECT
&& ((cs_sleep_counter_compare == 1'b1) || cs_sleep_early_exit)
&& (cs_sleep_repeat == 1'b0)
&& (idle == 1'b0);
assign cmd_ready = idle;

always @(posedge clk) begin
Expand Down Expand Up @@ -239,17 +244,30 @@ module spi_engine_execution #(
assign trigger_tx = trigger == 1'b1 && ntx_rx == 1'b0;
assign trigger_rx = trigger == 1'b1 && ntx_rx == 1'b1;

assign sleep_counter_compare = sleep_counter == cmd_d1[7:0] && clk_div_last == 1'b1;
assign cs_sleep_counter_compare = cs_sleep_counter == cmd_d1[9:8] && clk_div_last == 1'b1;
assign sleep_counter_compare = sleep_counter == cmd_d1[7:0];
assign cs_sleep_counter_compare = cs_sleep_counter == cmd_d1[9:8];
assign cs_sleep_early_exit = (cmd_d1[9:8] == 2'b00);

always @(posedge clk) begin
if (idle == 1'b1) begin
if (resetn == 1'b0) begin
cs_sleep_repeat <= 1'b0;
end else begin
if (idle) begin
cs_sleep_repeat <= 1'b0;
end else if (cs_sleep_counter_compare && (inst_d1 == CMD_CHIPSELECT)) begin
cs_sleep_repeat <= !cs_sleep_repeat;
end
end
end

always @(posedge clk) begin
if (idle == 1'b1 || (cs_sleep_counter_compare && !cs_sleep_repeat && inst_d1 == CMD_CHIPSELECT)) begin
counter <= 'h00;
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;
counter <= (counter & BIT_COUNTER_CLEAR) + (transfer_active ? 'h1 : (2**BIT_COUNTER_WIDTH)) + BIT_COUNTER_CARRY;
end else begin
counter <= counter + (transfer_active ? 'h1 : 'h10);
counter <= counter + (transfer_active ? 'h1 : (2**BIT_COUNTER_WIDTH));
end
end
end
Expand All @@ -267,7 +285,7 @@ module spi_engine_execution #(
idle <= 1'b1;
end
CMD_CHIPSELECT: begin
if (cs_sleep_counter_compare)
if ((cs_sleep_counter_compare && cs_sleep_repeat) || cs_sleep_early_exit)
idle <= 1'b1;
end
CMD_MISC: begin
Expand Down

0 comments on commit becc035

Please sign in to comment.