Skip to content

Commit

Permalink
spi_engine/execution: dynamic length bugfix
Browse files Browse the repository at this point in the history
ip can now send multiple words per transfer with dynamic data length
  • Loading branch information
sarpadi authored and StancaPop committed Oct 28, 2019
1 parent 2ea8838 commit 5dc2ab9
Showing 1 changed file with 26 additions and 21 deletions.
47 changes: 26 additions & 21 deletions library/spi_engine/spi_engine_execution/spi_engine_execution.v
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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}};
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down

0 comments on commit 5dc2ab9

Please sign in to comment.