Add Tercel PHY reset synchronization
[microwatt.git] / spi_rxtx.vhdl
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4
5 library work;
6 use work.wishbone_types.all;
7
8 entity spi_rxtx is
9 generic (
10 DATA_LINES : positive := 1; -- Number of data lines
11 -- 1=MISO/MOSI, otherwise 2 or 4
12 INPUT_DELAY : natural range 0 to 1 := 1 -- Delay latching of SPI input:
13 -- 0=no delay, 1=clk/2
14 );
15 port (
16 clk : in std_ulogic;
17 rst : in std_ulogic;
18
19 --
20 -- Clock divider
21 -- SCK = CLK/((CLK_DIV+1)*2) : 0=CLK/2, 1=CLK/4, 2=CLK/6....
22 --
23 -- This need to be changed before a command.
24 -- XX TODO add handshake
25 clk_div_i : in natural range 0 to 255;
26
27 --
28 -- Command port (includes write data)
29 --
30
31 -- Valid & ready: command sampled when valid=1 and ready=1
32 cmd_valid_i : in std_ulogic;
33 cmd_ready_o : out std_ulogic;
34
35 -- Command modes:
36 -- 000 : Single bit read+write
37 -- 010 : Single bit read
38 -- 011 : Single bit write
39 -- 100 : Dual read
40 -- 101 : Dual write
41 -- 110 : Quad read
42 -- 111 : Quad write
43 cmd_mode_i : in std_ulogic_vector(2 downto 0);
44
45 -- # clocks-1 in a command (#bits-1)
46 cmd_clks_i : in std_ulogic_vector(2 downto 0);
47
48 -- Write data (sampled with command)
49 cmd_txd_i : in std_ulogic_vector(7 downto 0);
50
51 --
52 -- Read data port. Data valid when d_ack=1, no ready
53 -- signal, receiver must be ready
54 --
55 d_rxd_o : out std_ulogic_vector(7 downto 0);
56 d_ack_o : out std_ulogic := '0';
57
58 -- Set when all commands are done. Needed for callers to know when
59 -- to release CS#
60 bus_idle_o : out std_ulogic;
61
62 --
63 -- SPI port. These might need to go into special IOBUFs or STARTUPE2 on
64 -- Xilinx.
65 --
66 -- Data lines are organized as follow:
67 --
68 -- DATA_LINES = 1
69 --
70 -- sdat_o(0) is MOSI (master output slave input)
71 -- sdat_i(0) is MISO (master input slave output)
72 --
73 -- DATA_LINES > 1
74 --
75 -- sdat_o(0..n) are DQ(0..n)
76 -- sdat_i(0..n) are DQ(0..n)
77 --
78 -- as such, beware that:
79 --
80 -- sdat_o(0) is MOSI (master output slave input)
81 -- sdat_i(1) is MISO (master input slave output)
82 --
83 -- In order to leave dealing with the details of how to wire the tristate
84 -- and bidirectional pins to the system specific toplevel, we separate
85 -- the input and output signals, and provide a "sdat_oe" signal which
86 -- is the "output enable" of each line.
87 --
88 sck : out std_ulogic;
89 sdat_o : out std_ulogic_vector(DATA_LINES-1 downto 0);
90 sdat_oe : out std_ulogic_vector(DATA_LINES-1 downto 0);
91 sdat_i : in std_ulogic_vector(DATA_LINES-1 downto 0)
92 );
93 end entity spi_rxtx;
94
95 architecture rtl of spi_rxtx is
96
97 -- Internal clock signal. Output is gated by sck_en_int
98 signal sck_0 : std_ulogic;
99 signal sck_1 : std_ulogic;
100
101 -- Clock divider latch
102 signal clk_div : natural range 0 to 255;
103
104 -- 1 clk pulses indicating when to send and when to latch
105 --
106 -- Typically for CPOL=CPHA
107 -- sck_send is sck falling edge
108 -- sck_recv is sck rising edge
109 --
110 -- Those pulses are generated "ahead" of the corresponding
111 -- edge so then are "seen" at the rising sysclk edge matching
112 -- the corresponding sck edgeg.
113 signal sck_send : std_ulogic;
114 signal sck_recv : std_ulogic;
115
116 -- Command mode latch
117 signal cmd_mode : std_ulogic_vector(2 downto 0);
118
119 -- Output shift register (use fifo ?)
120 signal oreg : std_ulogic_vector(7 downto 0);
121
122 -- Input latch
123 signal dat_i_l : std_ulogic_vector(DATA_LINES-1 downto 0);
124
125 -- Data ack latch
126 signal dat_ack_l : std_ulogic;
127
128 -- Delayed recv signal for the read machine
129 signal sck_recv_d : std_ulogic := '0';
130
131 -- Input shift register (use fifo ?)
132 signal ireg : std_ulogic_vector(7 downto 0) := (others => '0');
133
134 -- Bit counter
135 signal bit_count : std_ulogic_vector(2 downto 0);
136
137 -- Next/start/stop command signals. Set when counter goes negative
138 signal next_cmd : std_ulogic;
139 signal start_cmd : std_ulogic;
140 signal end_cmd : std_ulogic;
141
142 function data_single(mode : std_ulogic_vector(2 downto 0)) return boolean is
143 begin
144 return mode(2) = '0';
145 end;
146 function data_dual(mode : std_ulogic_vector(2 downto 0)) return boolean is
147 begin
148 return mode(2 downto 1) = "10";
149 end;
150 function data_quad(mode : std_ulogic_vector(2 downto 0)) return boolean is
151 begin
152 return mode(2 downto 1) = "11";
153 end;
154 function data_write(mode : std_ulogic_vector(2 downto 0)) return boolean is
155 begin
156 return mode(0) = '1';
157 end;
158
159 type state_t is (STANDBY, DATA);
160 signal state : state_t := STANDBY;
161 begin
162
163 -- We don't support multiple data lines at this point
164 assert DATA_LINES = 1 or DATA_LINES = 2 or DATA_LINES = 4
165 report "Unsupported DATA_LINES configuration !" severity failure;
166
167 -- Clock generation
168 --
169 -- XX HARD WIRE CPOL=1 CPHA=1 for now
170 sck_gen: process(clk)
171 variable counter : integer range 0 to 255;
172 begin
173 if rising_edge(clk) then
174 if rst = '1' then
175 sck_0 <= '1';
176 sck_1 <= '1';
177 sck_send <= '0';
178 sck_recv <= '0';
179 clk_div <= 0;
180 counter := 0;
181 elsif counter = clk_div then
182 counter := 0;
183
184 -- Latch new divider
185 clk_div <= clk_div_i;
186
187 -- Internal version of the clock
188 sck_0 <= not sck_0;
189
190 -- Generate send/receive pulses to run out state machine
191 sck_recv <= not sck_0;
192 sck_send <= sck_0;
193 else
194 counter := counter + 1;
195 sck_recv <= '0';
196 sck_send <= '0';
197 end if;
198
199 -- Delayed version of the clock to line up with
200 -- the up/down signals
201 --
202 -- XXX Figure out a better way
203 if (state = DATA and end_cmd = '0') or (next_cmd = '1' and cmd_valid_i = '1') then
204 sck_1 <= sck_0;
205 else
206 sck_1 <= '1';
207 end if;
208 end if;
209 end process;
210
211 -- SPI clock
212 sck <= sck_1;
213
214 -- Ready to start the next command. This is set on the clock down
215 -- after the counter goes negative.
216 -- Note: in addition to latching a new command, this will cause
217 -- the counter to be reloaded.
218 next_cmd <= '1' when sck_send = '1' and bit_count = "111" else '0';
219
220 -- We start a command when we have a valid request at that time.
221 start_cmd <= next_cmd and cmd_valid_i;
222
223 -- We end commands if we get start_cmd and there's nothing to
224 -- start. This sends up to standby holding CLK high
225 end_cmd <= next_cmd and not cmd_valid_i;
226
227 -- Generate cmd_ready. It will go up and down with sck, we could
228 -- gate it with cmd_valid to make it look cleaner but that would
229 -- add yet another combinational loop on the wishbone that I'm
230 -- to avoid.
231 cmd_ready_o <= next_cmd;
232
233 -- Generate bus_idle_o
234 bus_idle_o <= '1' when state = STANDBY else '0';
235
236 -- Main state machine. Also generates cmd and data ACKs
237 machine: process(clk)
238 begin
239 if rising_edge(clk) then
240 if rst = '1' then
241 state <= STANDBY;
242 cmd_mode <= "000";
243 else
244 -- First clk down of a new cycle. Latch a request if any
245 -- or get out.
246 if start_cmd = '1' then
247 state <= DATA;
248 cmd_mode <= cmd_mode_i;
249 elsif end_cmd = '1' then
250 state <= STANDBY;
251 end if;
252 end if;
253 end if;
254 end process;
255
256 -- Run the bit counter in DATA state. It will update on rising
257 -- SCK edges. It starts at d_clks on command latch
258 count_bit: process(clk)
259 begin
260 if rising_edge(clk) then
261 if rst = '1' then
262 bit_count <= (others => '0');
263 else
264 if start_cmd = '1' then
265 bit_count <= cmd_clks_i;
266 elsif state /= DATA then
267 bit_count <= (others => '1');
268 elsif sck_recv = '1' then
269 bit_count <= std_ulogic_vector(unsigned(bit_count) - 1);
270 end if;
271 end if;
272 end if;
273 end process;
274
275 -- Shift output data
276 shift_out: process(clk)
277 begin
278 if rising_edge(clk) then
279 -- Starting a command
280 if start_cmd = '1' then
281 oreg <= cmd_txd_i(7 downto 0);
282 elsif sck_send = '1' then
283 -- Get shift amount
284 if data_single(cmd_mode) then
285 oreg <= oreg(6 downto 0) & '0';
286 elsif data_dual(cmd_mode) then
287 oreg <= oreg(5 downto 0) & "00";
288 else
289 oreg <= oreg(3 downto 0) & "0000";
290 end if;
291 end if;
292 end if;
293 end process;
294
295 -- Data out
296 sdat_o(0) <= oreg(7);
297 dl2: if DATA_LINES > 1 generate
298 sdat_o(1) <= oreg(6);
299 end generate;
300 dl4: if DATA_LINES > 2 generate
301 sdat_o(2) <= oreg(5);
302 sdat_o(3) <= oreg(4);
303 end generate;
304
305 -- Data lines direction
306 dlines: process(all)
307 begin
308 for i in DATA_LINES-1 downto 0 loop
309 sdat_oe(i) <= '0';
310 if state = DATA then
311 -- In single mode, we always enable MOSI, otherwise
312 -- we control the output enable based on the direction
313 -- of transfer.
314 --
315 if i = 0 and (data_single(cmd_mode) or data_write(cmd_mode)) then
316 sdat_oe(i) <= '1';
317 end if;
318 if i = 1 and data_dual(cmd_mode) and data_write(cmd_mode) then
319 sdat_oe(i) <= '1';
320 end if;
321 if i > 0 and data_quad(cmd_mode) and data_write(cmd_mode) then
322 sdat_oe(i) <= '1';
323 end if;
324 end if;
325 end loop;
326 end process;
327
328 -- Latch input data no delay
329 input_delay_0: if INPUT_DELAY = 0 generate
330 process(clk)
331 begin
332 if rising_edge(clk) then
333 dat_i_l <= sdat_i;
334 end if;
335 end process;
336 end generate;
337
338 -- Latch input data half clock delay
339 input_delay_1: if INPUT_DELAY = 1 generate
340 process(clk)
341 begin
342 if falling_edge(clk) then
343 dat_i_l <= sdat_i;
344 end if;
345 end process;
346 end generate;
347
348 -- Shift input data
349 shift_in: process(clk)
350 begin
351 if rising_edge(clk) then
352
353 -- Delay the receive signal to match the input latch
354 if state = DATA then
355 sck_recv_d <= sck_recv;
356 else
357 sck_recv_d <= '0';
358 end if;
359
360 -- Generate read data acks
361 if bit_count = "000" and sck_recv = '1' then
362 dat_ack_l <= not cmd_mode(0);
363 else
364 dat_ack_l <= '0';
365 end if;
366
367 -- And delay them as well
368 d_ack_o <= dat_ack_l;
369
370 -- Shift register on delayed data & receive signal
371 if sck_recv_d = '1' then
372 if DATA_LINES = 1 then
373 ireg <= ireg(6 downto 0) & dat_i_l(0);
374 else
375 if data_dual(cmd_mode) then
376 ireg <= ireg(5 downto 0) & dat_i_l(1) & dat_i_l(0);
377 elsif data_quad(cmd_mode) then
378 ireg <= ireg(3 downto 0) & dat_i_l(3) & dat_i_l(2) & dat_i_l(1) & dat_i_l(0);
379 else
380 assert(data_single(cmd_mode));
381 ireg <= ireg(6 downto 0) & dat_i_l(1);
382 end if;
383 end if;
384 end if;
385 end if;
386 end process;
387
388 -- Data recieve register
389 d_rxd_o <= ireg;
390
391 end architecture;