@@ -48,7 +48,7 @@ module spi_engine_execution_shiftreg #(
48
48
input resetn,
49
49
50
50
// spi io
51
- input sdi,
51
+ input [NUM_OF_SDI - 1 : 0 ] sdi,
52
52
output sdo_int,
53
53
input echo_sclk,
54
54
@@ -63,12 +63,14 @@ module spi_engine_execution_shiftreg #(
63
63
// cfg and status
64
64
input sdo_enabled,
65
65
input sdi_enabled,
66
- input [2 :0 ] current_instr ,
66
+ input [15 :0 ] current_cmd ,
67
67
input sdo_idle_state,
68
68
input [7 :0 ] left_aligned,
69
69
input [7 :0 ] word_length,
70
70
71
71
// timing from main fsm
72
+ input sample_sdo,
73
+ output reg sdo_io_ready,
72
74
input transfer_active,
73
75
input trigger_tx,
74
76
input trigger_rx,
@@ -79,17 +81,37 @@ module spi_engine_execution_shiftreg #(
79
81
80
82
reg [7 :0 ] sdi_counter = 8'b0 ;
81
83
reg [(DATA_WIDTH- 1 ):0 ] data_sdo_shift = 'h0;
84
+ reg [(DATA_WIDTH- 1 ):0 ] aligned_sdo_data, sdo_data_d;
82
85
wire last_sdi_bit;
83
86
reg [SDI_DELAY+ 1 :0 ] trigger_rx_d = {(SDI_DELAY+ 2 ){1'b0 }};
84
87
wire trigger_rx_s;
88
+ wire [2 :0 ] current_instr = current_cmd[14 :12 ];
85
89
86
90
always @(posedge clk) begin
87
- if (resetn == 1'b0 )
91
+ if (resetn == 1'b0 ) begin
88
92
sdo_data_ready <= 1'b0 ;
89
- else if (sdo_enabled == 1'b1 && first_bit == 1'b1 && trigger_tx == 1'b1 && transfer_active == 1'b1 )
93
+ end else if (sdo_toshiftreg) begin
90
94
sdo_data_ready <= 1'b1 ;
91
- else if (sdo_data_valid == 1'b1 )
95
+ end else if (sdo_data_valid == 1'b1 ) begin
92
96
sdo_data_ready <= 1'b0 ;
97
+ end
98
+ end
99
+
100
+ // pipelined shifter for sdo_data
101
+ always @(posedge clk ) begin
102
+ if (resetn == 1'b0 ) begin
103
+ aligned_sdo_data <= 0 ;
104
+ sdo_io_ready <= 1'b0 ;
105
+ end else begin
106
+ if (transfer_active == 1'b1 && trigger_tx == 1'b1 ) begin
107
+ sdo_io_ready <= 1'b0 ;
108
+ end
109
+ if (sample_sdo) begin
110
+ sdo_data_d <= sdo_data;
111
+ sdo_io_ready <= 1'b1 ;
112
+ end
113
+ aligned_sdo_data <= sdo_data_d << left_aligned;
114
+ end
93
115
end
94
116
95
117
// Load the SDO parallel data into the SDO shift register. In case of a custom
@@ -98,13 +120,16 @@ module spi_engine_execution_shiftreg #(
98
120
if (! sdo_enabled || (current_instr != CMD_TRANSFER)) begin
99
121
data_sdo_shift <= {DATA_WIDTH{sdo_idle_state}};
100
122
end else if (transfer_active == 1'b1 && trigger_tx == 1'b1 ) begin
101
- if (first_bit == 1'b1 )
102
- data_sdo_shift <= sdo_data << left_aligned; // TODO: check if this could/should be pipelined
103
- else
104
- data_sdo_shift <= {data_sdo_shift[(DATA_WIDTH- 2 ):0 ], 1'b0 };
123
+ if (first_bit == 1'b1 ) begin
124
+ data_sdo_shift <= aligned_sdo_data;
125
+ end else begin
126
+ data_sdo_shift <= {data_sdo_shift[(DATA_WIDTH- 2 ):0 ], 1'b0 };
127
+ end
105
128
end
106
129
end
107
130
assign sdo_int = data_sdo_shift[DATA_WIDTH- 1 ];
131
+ assign sdo_toshiftreg = (transfer_active && trigger_tx && first_bit && sdo_enabled);
132
+
108
133
109
134
// In case of an interface with high clock rate (SCLK > 50MHz), the latch of
110
135
// the SDI line can be delayed with 1, 2 or 3 SPI core clock cycle.
@@ -203,7 +228,7 @@ module spi_engine_execution_shiftreg #(
203
228
// sdi_data_valid is synchronous to SPI clock, so synchronize the
204
229
// last_sdi_bit to SPI clock
205
230
206
- 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?
231
+ reg [3 :0 ] last_sdi_bit_m = 4'b0 ; // FIXME: why not just use sync_bits?
207
232
always @(posedge clk) begin
208
233
if (cs_activate) begin
209
234
last_sdi_bit_m <= 4'b0 ;
@@ -228,8 +253,8 @@ module spi_engine_execution_shiftreg #(
228
253
if (cs_activate) begin
229
254
num_of_transfers <= 8'b0 ;
230
255
end else begin
231
- if (cmd_d1[ 15 : 12 ] == 4'b0 ) begin
232
- num_of_transfers <= cmd_d1 [7 :0 ] + 1'b1 ; // cmd_d1 contains the NUM_OF_TRANSFERS - 1
256
+ if (current_instr == CMD_TRANSFER ) begin
257
+ num_of_transfers <= current_cmd [7 :0 ] + 1'b1 ; // current_cmd contains the NUM_OF_TRANSFERS - 1
233
258
end
234
259
end
235
260
end
0 commit comments