spi_master.v 8.35 KB
Newer Older
1
// © 2017 - 2020 Raptor Engineering, LLC
2 3 4 5 6
//
// Released under the terms of the AGPL v3
// See the LICENSE file for full details
//
// SPI mode 3 transfer
7
// Single data rate, standard unidirectional transfer
8 9 10 11 12 13 14 15 16 17 18 19
module spi_master_interface(
		input wire platform_clock,
		input wire reset,
		input wire [7:0] tx_data,
		output reg [7:0] rx_data,
		input wire hold_ss_active,
		input wire cycle_start,
		output reg transaction_complete,

		output reg spi_clock,
		output reg spi_mosi,
		input wire spi_miso,
20 21 22
		output reg spi_ss_n,
		output reg spi_hold_n,
		output reg spi_wp_n
23 24
	);

25
	reg [3:0] transfer_state = 0;
26 27 28 29 30
	reg [7:0] data_shift_out = 0;

	reg [7:0] state_iteration = 0;
	reg ss_state_at_idle = 1'b1;

31 32 33 34
	reg cycle_start_reg = 0;
	reg hold_ss_active_reg = 0;
	reg [7:0] tx_data_reg = 0;

35 36 37 38
	always @(posedge platform_clock) begin
		if (reset) begin
			transfer_state <= 0;
			state_iteration <= 0;
39
			transaction_complete <= 1;
40 41
			spi_clock <= 1'b1;
			spi_mosi <= 1'b0;
42
			spi_ss_n <= 1'b1;
43 44
			spi_hold_n <= 1'b1;
			spi_wp_n <= 1'b1;
45 46 47 48 49 50 51
			ss_state_at_idle <= 1'b1;
		end else begin
			case (transfer_state)
				0: begin
					// Idle state
					spi_clock <= 1'b1;
					spi_mosi <= 1'b0;
52
					spi_ss_n <= ss_state_at_idle;
53 54
					transaction_complete <= 0;
					state_iteration <= 0;
55
					if (cycle_start_reg) begin
56
						// Set up transfer
57
						rx_data <= 0;
58
						data_shift_out <= tx_data_reg;
59 60 61 62 63

						// Drive frame start
						spi_clock <= 1'b1;
						spi_ss_n <= 1'b0;

64 65
						transfer_state <= 1;
					end else begin
66
						if (!hold_ss_active_reg) begin
67
							ss_state_at_idle <= 1'b1;
68
						end
69 70 71 72
						transfer_state <= 0;
					end
				end
				1: begin
73 74
					// Shift out TX byte / toggle clock
					spi_clock <= 1'b0;
75
					spi_ss_n <= 1'b0;
76 77
					spi_mosi <= data_shift_out[7];
					data_shift_out <= data_shift_out << 1;
78
					transfer_state <= 2;
79
				end
80
				2: begin
81
					// Shift in RX byte / toggle clock
82
					spi_clock <= 1'b1;
83
					spi_ss_n <= 1'b0;
84
					rx_data <= {rx_data[6:0], spi_miso};
85 86
					state_iteration <= state_iteration + 1;
					if (state_iteration >= 7) begin
87
						if (hold_ss_active_reg) begin
88 89 90 91 92
							ss_state_at_idle <= 1'b0;
						end else begin
							ss_state_at_idle <= 1'b1;
						end
						transaction_complete <= 1;
93
						transfer_state <= 3;
94
					end else begin
95
						transfer_state <= 1;
96 97
					end
				end
98
				3: begin
99
					// Wait for host to deassert transaction request
100
					if (!cycle_start_reg) begin
101 102 103 104 105
						transaction_complete <= 0;
						transfer_state <= 0;
					end
					spi_clock <= 1'b1;
					spi_mosi <= 1'b0;
106
					spi_ss_n <= ss_state_at_idle;
107
				end
108
				default: begin
109
					transfer_state <= 0;
110
				end
111 112
			endcase
		end
113 114 115 116 117

		// Avoid glitches from signals crossing clock domains
		cycle_start_reg <= cycle_start;
		hold_ss_active_reg = hold_ss_active;
		tx_data_reg <= tx_data;
118 119
	end

120 121 122 123 124 125 126 127
endmodule

// SPI mode 3 transfer
// Single data rate, quad transfer
// This module assumes it is on the same clock domain as the external control logic
module spi_master_interface_quad(
		input wire platform_clock,
		input wire reset,
128 129
		input wire [31:0] tx_data,
		output reg [31:0] rx_data,
130 131 132
		input wire [7:0] dummy_cycle_count,
		input wire hold_ss_active,
		input wire qspi_mode_active,
133
		input wire qspi_transfer_mode,		// 0 == byte transfer, 1 == word transfer
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
		input wire qspi_transfer_direction,	// 0 == read (input), 1 == write (output)
		input wire cycle_start,
		output reg transaction_complete,

		output reg spi_clock,
		output reg spi_d0_out,
		input wire spi_d0_in,
		output reg spi_d1_out,
		input wire spi_d1_in,
		output reg spi_d2_out,
		input wire spi_d2_in,
		output reg spi_d3_out,
		input wire spi_d3_in,
		output reg spi_ss_n,
		output reg spi_data_direction,		// 0 == tristate (input), 1 == driven (output)
		output reg spi_quad_mode_pin_enable
	);

	reg [3:0] transfer_state = 0;
153
	reg [31:0] data_shift_out = 0;
154 155 156 157 158 159 160

	reg [7:0] state_iteration = 0;
	reg ss_state_at_idle = 1'b1;

	reg [7:0] dummy_cycle_count_reg = 0;
	reg [7:0] dummy_cycle_ctr = 0;

161 162 163
	reg qspi_transfer_mode_reg = 0;
	reg [3:0] qspi_transfer_cycle_stop_value = 1;

164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
	always @(posedge platform_clock) begin
		if (reset) begin
			transfer_state <= 0;
			state_iteration <= 0;
			transaction_complete <= 1;
			dummy_cycle_count_reg <= 0;
			spi_clock <= 1'b1;
			spi_d0_out <= 1'b0;
			spi_d1_out <= 1'b1;
			spi_d2_out <= 1'b1;
			spi_d3_out <= 1'b1;
			spi_ss_n <= 1'b1;
			ss_state_at_idle <= 1'b1;
			spi_data_direction <= 1'b0;
			spi_quad_mode_pin_enable <= 1'b0;
		end else begin
			case (transfer_state)
				0: begin
					// Idle state
					spi_clock <= 1'b1;
					spi_d0_out <= 1'b0;
					spi_ss_n <= ss_state_at_idle;
					transaction_complete <= 0;
					state_iteration <= 0;
					if (cycle_start) begin
						// Set up transfer
						rx_data <= 0;
						dummy_cycle_count_reg <= dummy_cycle_count;
						data_shift_out <= tx_data;
						spi_quad_mode_pin_enable <= qspi_mode_active;
						spi_data_direction <= qspi_transfer_direction;
195 196 197 198 199 200 201 202
						qspi_transfer_mode_reg <= qspi_transfer_mode;
						if (qspi_transfer_mode == 0) begin
							// Byte transfer (2 nibbles per word)
							qspi_transfer_cycle_stop_value <= 1;
						end else begin
							// Word transfer (4 bytes / 8 nibbles per word)
							qspi_transfer_cycle_stop_value <= 7;
						end
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221

						// Drive frame start
						spi_clock <= 1'b1;
						spi_ss_n <= 1'b0;

						transfer_state <= 1;
					end else begin
						if (!hold_ss_active) begin
							ss_state_at_idle <= 1'b1;
						end
						spi_quad_mode_pin_enable <= 0;
						transfer_state <= 0;
					end
				end
				1: begin
					// Shift out TX byte / toggle clock
					spi_clock <= 1'b0;
					spi_ss_n <= 1'b0;
					if (spi_quad_mode_pin_enable) begin
222 223 224 225 226 227 228 229 230 231 232
						if (qspi_transfer_mode_reg) begin
							spi_d3_out <= data_shift_out[31];
							spi_d2_out <= data_shift_out[30];
							spi_d1_out <= data_shift_out[29];
							spi_d0_out <= data_shift_out[28];
						end else begin
							spi_d3_out <= data_shift_out[7];
							spi_d2_out <= data_shift_out[6];
							spi_d1_out <= data_shift_out[5];
							spi_d0_out <= data_shift_out[4];
						end
233 234 235 236 237 238 239 240 241 242 243 244 245
						data_shift_out <= data_shift_out << 4;
					end else begin
						spi_d0_out <= data_shift_out[7];
						data_shift_out <= data_shift_out << 1;
					end
					transfer_state <= 2;
				end
				2: begin
					// Shift in RX byte / toggle clock
					spi_clock <= 1'b1;
					spi_ss_n <= 1'b0;
					state_iteration <= state_iteration + 1;
					if (spi_quad_mode_pin_enable) begin
246 247 248 249 250 251
						if (qspi_transfer_mode_reg) begin
							rx_data <= {rx_data[27:0], spi_d3_in, spi_d2_in, spi_d1_in, spi_d0_in};
						end else begin
							rx_data <= {rx_data[3:0], spi_d3_in, spi_d2_in, spi_d1_in, spi_d0_in};
						end
						if (state_iteration >= qspi_transfer_cycle_stop_value) begin
252 253 254 255 256 257
							if (hold_ss_active) begin
								ss_state_at_idle <= 1'b0;
							end else begin
								ss_state_at_idle <= 1'b1;
							end
							if (dummy_cycle_count_reg == 0) begin
258
								transaction_complete <= 1;
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
								transfer_state <= 3;
							end else begin
								dummy_cycle_ctr <= 0;
								transfer_state <= 4;
							end
						end else begin
							transfer_state <= 1;
						end
					end else begin
						rx_data <= {rx_data[6:0], spi_d1_in};
						if (state_iteration >= 7) begin
							if (hold_ss_active) begin
								ss_state_at_idle <= 1'b0;
							end else begin
								ss_state_at_idle <= 1'b1;
							end
							transaction_complete <= 1;
							if (dummy_cycle_count_reg == 0) begin
								transfer_state <= 3;
							end else begin
								dummy_cycle_ctr <= 0;
								transfer_state <= 4;
							end
						end else begin
							transfer_state <= 1;
						end
					end
				end
				3: begin
					// Wait for host to deassert transaction request
					if (!cycle_start) begin
						transaction_complete <= 0;
						transfer_state <= 0;
					end
					spi_clock <= 1'b1;
					spi_d0_out <= 1'b0;
					spi_d1_out <= 1'b1;
					spi_d2_out <= 1'b1;
					spi_d3_out <= 1'b1;
					spi_ss_n <= ss_state_at_idle;
					spi_data_direction <= 0;
					spi_quad_mode_pin_enable <= 0;
				end
				4: begin
					// Increment counter / toggle clock
					spi_clock <= 1'b0;
					dummy_cycle_ctr <= dummy_cycle_ctr + 1;

					transfer_state <= 5;
				end
				5: begin
					if (dummy_cycle_ctr < dummy_cycle_count_reg) begin
						transfer_state <= 4;
					end else begin
313
						transaction_complete <= 1;
314 315 316 317 318 319 320 321 322 323 324 325 326 327
						transfer_state <= 3;
					end

					// Toggle clock
					spi_clock <= 1'b1;
				end
				default: begin
					transfer_state <= 0;
				end
			endcase
		end
	end

endmodule