Add Tercel PHY reset synchronization
[microwatt.git] / tercel / phy.v
1 // © 2017 - 2022 Raptor Engineering, LLC
2 //
3 // Released under the terms of the GPL v3
4 // See the LICENSE file for full details
5
6 // SPI mode 3 transfer
7 // Single data rate, quad transfer
8 // This module assumes it is on the same clock domain as the external control logic
9 module spi_master_phy_quad(
10 input wire platform_clock,
11 input wire reset,
12 output wire ready,
13 input wire [31:0] tx_data,
14 output reg [31:0] rx_data,
15 input wire [7:0] dummy_cycle_count,
16 input wire hold_ss_active,
17 input wire qspi_mode_active,
18 input wire qspi_transfer_mode, // 0 == byte transfer, 1 == word transfer
19 input wire qspi_transfer_direction, // 0 == read (input), 1 == write (output)
20 input wire cycle_start,
21 output reg transaction_complete,
22
23 output reg spi_clock,
24 output reg spi_d0_out,
25 input wire spi_d0_in,
26 output reg spi_d1_out,
27 input wire spi_d1_in,
28 output reg spi_d2_out,
29 input wire spi_d2_in,
30 output reg spi_d3_out,
31 input wire spi_d3_in,
32 output reg spi_ss_n,
33 output reg spi_data_direction, // 0 == tristate (input), 1 == driven (output)
34 output reg spi_quad_mode_pin_enable
35 );
36
37 reg phy_ready = 0;
38
39 reg [3:0] transfer_state = 0;
40 reg [31:0] data_shift_out = 0;
41
42 reg [7:0] state_iteration = 0;
43 reg ss_state_at_idle = 1'b1;
44
45 reg [7:0] dummy_cycle_count_reg = 0;
46 reg [7:0] dummy_cycle_ctr = 0;
47
48 reg qspi_transfer_mode_reg = 0;
49 reg [7:0] sspi_transfer_cycle_stop_value = 0;
50 reg [3:0] qspi_transfer_cycle_stop_value = 0;
51
52 assign ready = phy_ready;
53
54 always @(posedge platform_clock) begin
55 if (reset) begin
56 phy_ready <= 0;
57 transfer_state <= 0;
58 state_iteration <= 0;
59 transaction_complete <= 1;
60 dummy_cycle_count_reg <= 0;
61 spi_clock <= 1'b1;
62 spi_d0_out <= 1'b0;
63 spi_d1_out <= 1'b1;
64 spi_d2_out <= 1'b1;
65 spi_d3_out <= 1'b1;
66 spi_ss_n <= 1'b1;
67 ss_state_at_idle <= 1'b1;
68 spi_data_direction <= 1'b0;
69 spi_quad_mode_pin_enable <= 1'b0;
70 end else begin
71 case (transfer_state)
72 0: begin
73 // Idle state
74 spi_clock <= 1'b1;
75 spi_d0_out <= 1'b0;
76 spi_ss_n <= ss_state_at_idle;
77 transaction_complete <= 0;
78 state_iteration <= 0;
79 if (cycle_start) begin
80 // Set up transfer
81 rx_data <= 0;
82 dummy_cycle_count_reg <= dummy_cycle_count;
83 data_shift_out <= tx_data;
84 spi_quad_mode_pin_enable <= qspi_mode_active;
85 spi_data_direction <= qspi_transfer_direction;
86 qspi_transfer_mode_reg <= qspi_transfer_mode;
87 if (qspi_transfer_mode == 0) begin
88 // Byte transfer (2 nibbles per word)
89 qspi_transfer_cycle_stop_value <= 1;
90 sspi_transfer_cycle_stop_value <= 7;
91 end else begin
92 // Word transfer (4 bytes / 8 nibbles per word)
93 qspi_transfer_cycle_stop_value <= 7;
94 sspi_transfer_cycle_stop_value <= 31;
95 end
96
97 // Drive frame start
98 spi_clock <= 1'b1;
99 spi_ss_n <= 1'b0;
100
101 transfer_state <= 1;
102 phy_ready <= 0;
103 end else begin
104 if (!hold_ss_active) begin
105 ss_state_at_idle <= 1'b1;
106 end
107 spi_quad_mode_pin_enable <= 0;
108 transfer_state <= 0;
109 phy_ready <= 1;
110 end
111 end
112 1: begin
113 // Shift out TX byte / toggle clock
114 spi_clock <= 1'b0;
115 spi_ss_n <= 1'b0;
116 if (spi_quad_mode_pin_enable) begin
117 if (qspi_transfer_mode_reg) begin
118 spi_d3_out <= data_shift_out[31];
119 spi_d2_out <= data_shift_out[30];
120 spi_d1_out <= data_shift_out[29];
121 spi_d0_out <= data_shift_out[28];
122 end else begin
123 spi_d3_out <= data_shift_out[7];
124 spi_d2_out <= data_shift_out[6];
125 spi_d1_out <= data_shift_out[5];
126 spi_d0_out <= data_shift_out[4];
127 end
128 data_shift_out <= data_shift_out << 4;
129 end else begin
130 if (qspi_transfer_mode_reg) begin
131 spi_d0_out <= data_shift_out[31];
132 end else begin
133 spi_d0_out <= data_shift_out[7];
134 end
135 data_shift_out <= data_shift_out << 1;
136 end
137 transfer_state <= 2;
138 end
139 2: begin
140 // Shift in RX byte / toggle clock
141 spi_clock <= 1'b1;
142 spi_ss_n <= 1'b0;
143 state_iteration <= state_iteration + 1;
144 if (spi_quad_mode_pin_enable) begin
145 if (qspi_transfer_mode_reg) begin
146 rx_data <= {rx_data[27:0], spi_d3_in, spi_d2_in, spi_d1_in, spi_d0_in};
147 end else begin
148 rx_data <= {rx_data[3:0], spi_d3_in, spi_d2_in, spi_d1_in, spi_d0_in};
149 end
150 if (state_iteration >= qspi_transfer_cycle_stop_value) begin
151 if (hold_ss_active) begin
152 ss_state_at_idle <= 1'b0;
153 end else begin
154 ss_state_at_idle <= 1'b1;
155 end
156 if (dummy_cycle_count_reg == 0) begin
157 transaction_complete <= 1;
158 transfer_state <= 3;
159 end else begin
160 dummy_cycle_ctr <= 0;
161 transfer_state <= 4;
162 end
163 end else begin
164 transfer_state <= 1;
165 end
166 end else begin
167 if (qspi_transfer_mode_reg) begin
168 rx_data <= {rx_data[30:0], spi_d1_in};
169 end else begin
170 rx_data <= {rx_data[6:0], spi_d1_in};
171 end
172 if (state_iteration >= sspi_transfer_cycle_stop_value) begin
173 if (hold_ss_active) begin
174 ss_state_at_idle <= 1'b0;
175 end else begin
176 ss_state_at_idle <= 1'b1;
177 end
178 transaction_complete <= 1;
179 if (dummy_cycle_count_reg == 0) begin
180 transfer_state <= 3;
181 end else begin
182 dummy_cycle_ctr <= 0;
183 transfer_state <= 4;
184 end
185 end else begin
186 transfer_state <= 1;
187 end
188 end
189 end
190 3: begin
191 // Wait for host to deassert transaction request
192 if (!cycle_start) begin
193 transaction_complete <= 0;
194 transfer_state <= 0;
195 end
196 spi_clock <= 1'b1;
197 spi_d0_out <= 1'b0;
198 spi_d1_out <= 1'b1;
199 spi_d2_out <= 1'b1;
200 spi_d3_out <= 1'b1;
201 spi_ss_n <= ss_state_at_idle;
202 spi_data_direction <= 0;
203 spi_quad_mode_pin_enable <= 0;
204 end
205 4: begin
206 // Increment counter / toggle clock
207 spi_clock <= 1'b0;
208 dummy_cycle_ctr <= dummy_cycle_ctr + 1;
209
210 transfer_state <= 5;
211 end
212 5: begin
213 if (dummy_cycle_ctr < dummy_cycle_count_reg) begin
214 transfer_state <= 4;
215 end else begin
216 transaction_complete <= 1;
217 transfer_state <= 3;
218 end
219
220 // Toggle clock
221 spi_clock <= 1'b1;
222 end
223 default: begin
224 transfer_state <= 0;
225 end
226 endcase
227 end
228 end
229
230 endmodule