1 --
2 -- Copyright (C)
2006 Johannes Hausensteiner (johannes.hausensteiner@pcl.at)
3 --
4 -- This program
is free software; you can redistribute it
and/
or
5 -- modify it under the terms
of the GNU General Public License
6 -- as published by the Free Software Foundation; either version
2
7 --
of the License,
or (at your option) any later version.
8 --
9 -- This program
is distributed
in the hope that it will be useful,
10 -- but WITHOUT ANY WARRANTY; without even the implied warranty
of
11 -- MERCHANTABILITY
or FITNESS
FOR A PARTICULAR PURPOSE. See the
12 -- GNU General Public License
for more details.
13 --
14 -- You should have received a copy
of the GNU General Public License
15 -- along
with this program;
if not,
write to the Free Software
16 -- Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA
02110-
1301, USA.
17 --
18 --
19 --
Filename: spi_ctrl.vhd
20 --
21 -- Function: SPI Flash controller
for DIY Calculator
22 --
23 --
24 --
Changelog
25 --
26 --
0.1 25.Sep.
2006 JH
new
27 --
0.2 15.Nov.
2006 JH remove old code
28 --
1.0 5.Feb.
2007 JH
new clocking scheme
29 --
1.1 4.Apr.
2007 JH implement high address
byte
30 --
1.2 16.Apr.
2007 JH clock enable
31 --
1.3 23.Apr.
2007 JH remove
all asynchronous elements
32 --
1.4 4.May
2007 JH resolve
read timing
33 --
1.5 10.May
2007 JH remove
read signal
34 --
35
36
37 library ieee;
38 use ieee.std_logic_1164.
all;
39 use ieee.std_logic_unsigned.
all;
40
41 entity spi_ctrl
is
42 port (
43 clk_in :
in std_logic;
44 rst :
in std_logic;
45 spi_clk :
out std_logic;
46 spi_cs :
out std_logic;
47 spi_din :
in std_logic;
48 spi_dout :
out std_logic;
49 sel :
in std_logic;
50 wr :
in std_logic;
51 addr :
in std_logic_vector (
2 downto 0);
52 d_in :
in std_logic_vector (
7 downto 0);
53 d_out :
out std_logic_vector (
7 downto 0)
54 );
55 end spi_ctrl;
56
57 architecture rtl
of spi_ctrl
is
58 --
clock generator
59 constant SYS_FREQ :
integer :=
25000000; --
25MHz
60 constant SPI_FREQ :
integer :=
6250000; --
6.25MHz
61 signal clk_en :
std_logic;
62 signal clk_cnt :
integer range 0 to (SYS_FREQ/SPI_FREQ)-
1;
63
64 type state_t
is (
65 IDLE,
66 TxCMD,
67 TxADD_H,
68 TxADD_M,
69 TxADD_L,
70 TxDUMMY,
71 TxDATA,
72 RxDATA,
73 WAIT1,
74 WAIT2,
75 WAIT3,
76 WAIT4,
77 WAIT6,
78 WAIT5,
79 WAIT7,
80 WAIT8,
81 CLR_CMD);
82
83 signal state, next_state : state_t;
84
85 --
transmitter
86 signal tx_reg :
std_logic_vector (
7 downto 0);
87 signal tx_sreg :
std_logic_vector (
7 downto 0);
88 signal tx_empty_set :
std_logic;
89 signal tx_empty :
std_logic;
90 signal tx_bit_cnt :
std_logic_vector (
3 downto 0);
91
92 --
receiver
93 signal rx_sreg :
std_logic_vector (
7 downto 0);
94 signal rx_ready :
std_logic;
95 signal rx_ready_set :
std_logic;
96 signal rx_bit_cnt_clr :
std_logic;
97 signal rx_bit_cnt :
std_logic_vector (
3 downto 0);
98
99 signal wr_cmd, wr_data :
std_logic;
100 signal wr_add_h, wr_add_m, wr_add_l :
std_logic;
101 signal rd_stat :
std_logic;
102 signal rd_add_h, rd_add_m, rd_add_l :
std_logic;
103 signal rd_data, rd_data1, rd_data2 :
std_logic;
104 signal spi_cs_int, spi_clk_int :
std_logic;
105
106 --
auxiliary signals
107 signal rx_enable :
std_logic;
108 signal rx_empty, rx_empty_clr :
std_logic;
109 signal tx_enable, tx_enable_d :
std_logic;
110 signal tx_new_data, tx_new_data_clr :
std_logic;
111 signal is_tx_data, is_wait6 :
std_logic;
112 signal cmd_clr, busy :
std_logic;
113
114 --
registers
115 signal cmd, tx_data, rx_data :
std_logic_vector (
7 downto 0);
116 signal add_h, add_m, add_l :
std_logic_vector (
7 downto 0);
117
118 --
FLASH commands
119 constant NOP :
std_logic_vector (
7 downto 0) := x
"FF"; -- no cmd
to execute
120 constant WREN :
std_logic_vector (
7 downto 0) := x
"06"; --
write enable
121 constant WRDI :
std_logic_vector (
7 downto 0) := x
"04"; --
write disable
122 constant RDSR :
std_logic_vector (
7 downto 0) := x
"05"; --
read status reg
123 constant WRSR :
std_logic_vector (
7 downto 0) := x
"01"; --
write stat. reg
124 constant RDCMD :
std_logic_vector (
7 downto 0) := x
"03"; --
read data
125 constant F_RD :
std_logic_vector (
7 downto 0) := x
"0B"; -- fast
read data
126 constant PP :
std_logic_vector (
7 downto 0) := x
"02"; --
page program
127 constant SE :
std_logic_vector (
7 downto 0) := x
"D8"; --
sector erase
128 constant BE :
std_logic_vector (
7 downto 0) := x
"C7"; --
bulk erase
129 constant DP :
std_logic_vector (
7 downto 0) := x
"B9"; --
deep power down
130 constant RES :
std_logic_vector (
7 downto 0) := x
"AB"; --
read signature
131 begin
132 --
assign signals
133 spi_cs <=
spi_cs_int;
134 spi_clk <=
spi_clk_int;
135 spi_dout <= tx_sreg(
7);
136
137 --
clock generator
138 spi_divider :
process (rst, clk_in)
139 begin
140 if rst =
'1' then
141 clk_cnt <=
0;
142 clk_en <=
'0';
143 spi_clk_int <=
'1';
144 elsif
falling_edge (clk_in)
then
145 if clk_cnt = ((SYS_FREQ / SPI_FREQ) -
2)
or
146 clk_cnt = ((SYS_FREQ / SPI_FREQ) -
3)
then
147 clk_cnt <= clk_cnt +
1;
148 clk_en <=
'0';
149 if tx_enable =
'1' or rx_enable =
'1' then
150 spi_clk_int <=
'0';
151 else
152 spi_clk_int <=
'1';
153 end if;
154 elsif clk_cnt = ((SYS_FREQ / SPI_FREQ) -
1)
then
155 clk_cnt <=
0;
156 clk_en <=
'1';
157 spi_clk_int <=
'1';
158 else
159 clk_cnt <= clk_cnt +
1;
160 clk_en <=
'0';
161 spi_clk_int <=
'1';
162 end if;
163 end if;
164 end process;
165
166 --
address decoder
167 process (sel, addr, wr)
168 variable input :
std_logic_vector (
4 downto 0);
169 begin
170 input := sel & addr &
wr;
171 --
defaults
172 wr_data <=
'0';
173 wr_cmd <=
'0';
174 wr_add_h <=
'0';
175 wr_add_m <=
'0';
176 wr_add_l <=
'0';
177 rd_data <=
'0';
178 rd_stat <=
'0';
179 rd_add_h <=
'0';
180 rd_add_m <=
'0';
181 rd_add_l <=
'0';
182 case input is
183 when "10000" => rd_data <=
'1';
184 when "10001" => wr_data <=
'1';
185 when "10010" => rd_stat <=
'1';
186 when "10011" => wr_cmd <=
'1';
187 when "10100" => rd_add_l <=
'1';
188 when "10101" => wr_add_l <=
'1';
189 when "10110" => rd_add_m <=
'1';
190 when "10111" => wr_add_m <=
'1';
191 when "11000" => rd_add_h <=
'1';
192 when "11001" => wr_add_h <=
'1';
193 when others =>
null;
194 end case;
195 end process;
196
197 --
read back registers
198 d_out(
0) <= (rx_data(
0)
and rd_data)
199 or (busy
and rd_stat)
200 or (add_h(
0)
and rd_add_h)
201 or (add_m(
0)
and rd_add_m)
202 or (add_l(
0)
and rd_add_l);
203
204 d_out(
1) <= (rx_data(
1)
and rd_data)
205 or (tx_empty
and rd_stat)
206 or (add_h(
1)
and rd_add_h)
207 or (add_m(
1)
and rd_add_m)
208 or (add_l(
1)
and rd_add_l);
209
210 d_out(
2) <= (rx_data(
2)
and rd_data)
211 or (rx_ready
and rd_stat)
212 or (add_h(
2)
and rd_add_h)
213 or (add_m(
2)
and rd_add_m)
214 or (add_l(
2)
and rd_add_l);
215
216 d_out(
3) <= (rx_data(
3)
and rd_data)
217 or (is_wait6
and rd_stat)
218 or (add_h(
3)
and rd_add_h)
219 or (add_m(
3)
and rd_add_m)
220 or (add_l(
3)
and rd_add_l);
221
222 d_out(
4) <= (rx_data(
4)
and rd_data)
223 or (
'0' and rd_stat)
224 or (add_h(
4)
and rd_add_h)
225 or (add_m(
4)
and rd_add_m)
226 or (add_l(
4)
and rd_add_l);
227
228 d_out(
5) <= (rx_data(
5)
and rd_data)
229 or (
'0' and rd_stat)
230 or (add_h(
5)
and rd_add_h)
231 or (add_m(
5)
and rd_add_m)
232 or (add_l(
5)
and rd_add_l);
233
234 d_out(
6) <= (rx_data(
6)
and rd_data)
235 or (
'0' and rd_stat)
236 or (add_h(
6)
and rd_add_h)
237 or (add_m(
6)
and rd_add_m)
238 or (add_l(
6)
and rd_add_l);
239
240 d_out(
7) <= (rx_data(
7)
and rd_data)
241 or (
'0' and rd_stat)
242 or (add_h(
7)
and rd_add_h)
243 or (add_m(
7)
and rd_add_m)
244 or (add_l(
7)
and rd_add_l);
245
246 --
write command
register
247 process (rst, cmd_clr, clk_in)
248 begin
249 if rst =
'1' or cmd_clr =
'1' then
250 cmd <=
NOP;
251 elsif
rising_edge (clk_in)
then
252 if wr_cmd =
'1' then
253 cmd <=
d_in;
254 end if;
255 end if;
256 end process;
257
258 --
write address high
register
259 process (rst, clk_in)
260 begin
261 if rst =
'1' then
262 add_h <= x
"00";
263 elsif
rising_edge (clk_in)
then
264 if wr_add_h =
'1' then
265 add_h <=
d_in;
266 end if;
267 end if;
268 end process;
269
270 --
write address mid
register
271 process (rst, clk_in)
272 begin
273 if rst =
'1' then
274 add_m <= x
"00";
275 elsif
rising_edge (clk_in)
then
276 if wr_add_m =
'1' then
277 add_m <=
d_in;
278 end if;
279 end if;
280 end process;
281
282 --
write address low
register
283 process (rst, clk_in)
284 begin
285 if rst =
'1' then
286 add_l <= x
"00";
287 elsif
rising_edge (clk_in)
then
288 if wr_add_l =
'1' then
289 add_l <=
d_in;
290 end if;
291 end if;
292 end process;
293
294 --
write tx data
register
295 process (rst, clk_in)
296 begin
297 if rst =
'1' then
298 tx_data <= x
"00";
299 elsif
rising_edge (clk_in)
then
300 if wr_data =
'1' then
301 tx_data <=
d_in;
302 end if;
303 end if;
304 end process;
305
306 --
new tx data flag
307 tx_new_data_clr <= tx_empty_set
and is_tx_data;
308 process (rst, tx_new_data_clr, clk_in)
309 begin
310 if rst =
'1' or tx_new_data_clr =
'1' then
311 tx_new_data <=
'0';
312 elsif
rising_edge (clk_in)
then
313 if wr_data =
'1' then
314 tx_new_data <=
'1';
315 end if;
316 end if;
317 end process;
318
319 --
advance the state machine
320 process (rst, clk_in)
321 begin
322 if rst =
'1' then
323 state <=
IDLE;
324 elsif
rising_edge (clk_in)
then
325 if clk_en =
'1' then
326 state <=
next_state;
327 end if;
328 end if;
329 end process;
330
331 --
state machine transition table
332 process (state, cmd, tx_bit_cnt, tx_new_data, rx_bit_cnt, rx_empty)
333 begin
334 case state
is
335 when IDLE =>
336 case cmd
is
337 when NOP => next_state <=
IDLE;
338 when others => next_state <=
TxCMD;
339 end case;
340
341 when TxCMD =>
342 if tx_bit_cnt < x
"7" then
343 next_state <=
TxCMD;
344 else
345 case cmd
is
346 when WREN | WRDI => next_state <=
CLR_CMD;
347 when BE | DP => next_state <=
CLR_CMD;
348 when SE | PP => next_state <=
WAIT1;
349 when RES | RDCMD => next_state <=
WAIT1;
350 when F_RD|WRSR|RDSR => next_state <=
WAIT1;
351 when others => next_state <=
CLR_CMD;
352 end case;
353 end if;
354
355 when WAIT1 =>
356 case cmd
is
357 when WREN | WRDI => next_state <=
CLR_CMD;
358 when BE | DP => next_state <=
CLR_CMD;
359 when SE | PP | RES => next_state <=
TxADD_H;
360 when RDCMD | F_RD => next_state <=
TxADD_H;
361 when WRSR => next_state <=
TxDATA;
362 when RDSR => next_state <=
RxDATA;
363 when others => next_state <=
CLR_CMD;
364 end case;
365
366 when TxADD_H =>
367 if tx_bit_cnt < x
"7" then
368 next_state <=
TxADD_H;
369 else
370 next_state <=
WAIT2;
371 end if;
372
373 when WAIT2 => next_state <=
TxADD_M;
374
375 when TxADD_M =>
376 if tx_bit_cnt < x
"7" then
377 next_state <=
TxADD_M;
378 else
379 next_state <=
WAIT3;
380 end if;
381
382 when WAIT3 => next_state <=
TxADD_L;
383
384 when TxADD_L =>
385 if tx_bit_cnt < x
"7" then
386 next_state <=
TxADD_L;
387 else
388 case cmd
is
389 when PP => next_state <=
WAIT6;
390 when SE | RES => next_state <=
WAIT4;
391 when RDCMD | F_RD => next_state <=
WAIT4;
392 when others => next_state <=
CLR_CMD;
393 end case;
394 end if;
395
396 when WAIT4 =>
397 case cmd
is
398 when F_RD => next_state <=
TxDUMMY;
399 when RES | RDCMD => next_state <=
RxDATA;
400 when others => next_state <=
CLR_CMD;
401 end case;
402
403 when TxDUMMY =>
404 if tx_bit_cnt < x
"7" then
405 next_state <=
TxDUMMY;
406 else
407 next_state <=
WAIT8;
408 end if;
409
410 when WAIT7 => next_state <=
WAIT8;
411
412 when WAIT8 =>
413 case cmd
is
414 when RDCMD | F_RD =>
415 if rx_empty =
'1' then
416 next_state <=
RxDATA;
417 else
418 next_state <=
WAIT8;
419 end if;
420 when others => next_state <=
CLR_CMD;
421 end case;
422
423 when RxDATA =>
424 if rx_bit_cnt < x
"7" then
425 next_state <=
RxDATA;
426 else
427 case cmd
is
428 when RDCMD | F_RD => next_state <=
WAIT7;
429 when RDSR | RES => next_state <=
WAIT5;
430 when others => next_state <=
CLR_CMD;
431 end case;
432 end if;
433
434 when TxDATA =>
435 if tx_bit_cnt < x
"7" then
436 next_state <=
TxDATA;
437 else
438 case cmd
is
439 when PP => next_state <=
WAIT6;
440 when others => next_state <=
CLR_CMD;
441 end case;
442 end if;
443
444 when WAIT6 =>
445 case cmd
is
446 when PP =>
447 if tx_new_data =
'1' then
448 next_state <=
TxDATA;
449 else
450 next_state <=
WAIT6;
451 end if;
452 when others => next_state <=
CLR_CMD;
453 end case;
454
455 when WAIT5 => next_state <=
CLR_CMD;
456
457 when CLR_CMD => next_state <=
IDLE;
458 end case;
459 end process;
460
461 -- state machine
output table
462 process (state, cmd, tx_data, add_m, add_l, add_h)
463 begin
464 --
default values
465 tx_enable <=
'0';
466 rx_enable <=
'0';
467 rx_bit_cnt_clr <=
'1';
468 tx_reg <= x
"FF";
469 spi_cs_int <=
'0';
470 busy <=
'1';
471 cmd_clr <=
'0';
472 is_tx_data <=
'0';
473 is_wait6 <=
'0';
474
475 case state
is
476 when IDLE =>
477 busy <=
'0';
478 when TxCMD =>
479 tx_reg <=
cmd;
480 tx_enable <=
'1';
481 spi_cs_int <=
'1';
482 when TxDATA =>
483 tx_reg <=
tx_data;
484 tx_enable <=
'1';
485 spi_cs_int <=
'1';
486 is_tx_data <=
'1';
487 when TxADD_H =>
488 tx_reg <=
add_h;
489 tx_enable <=
'1';
490 spi_cs_int <=
'1';
491 when TxADD_M =>
492 tx_reg <=
add_m;
493 tx_enable <=
'1';
494 spi_cs_int <=
'1';
495 when TxADD_L =>
496 tx_reg <=
add_l;
497 tx_enable <=
'1';
498 spi_cs_int <=
'1';
499 when TxDUMMY =>
500 tx_reg <= x
"00";
501 tx_enable <=
'1';
502 spi_cs_int <=
'1';
503 when RxDATA =>
504 rx_bit_cnt_clr <=
'0';
505 rx_enable <=
'1';
506 spi_cs_int <=
'1';
507 when WAIT1 | WAIT2 | WAIT3 | WAIT4 | WAIT8 =>
508 spi_cs_int <=
'1';
509 when WAIT6 =>
510 is_wait6 <=
'1';
511 spi_cs_int <=
'1';
512 when WAIT5 | WAIT7 =>
513 rx_bit_cnt_clr <=
'0';
514 spi_cs_int <=
'1';
515 when CLR_CMD =>
516 cmd_clr <=
'1';
517 when others =>
null;
518 end case;
519 end process;
520
521 --
the tx_empty flip flop
522 process (rst, wr_data, clk_in)
523 begin
524 if rst =
'1' then
525 tx_empty <=
'1';
526 elsif wr_data =
'1' then
527 tx_empty <=
'0';
528 elsif
rising_edge (clk_in)
then
529 if tx_empty_set =
'1' then
530 tx_empty <=
'1';
531 end if;
532 end if;
533 end process;
534
535 -- delay the tx_enable
signal
536 process (rst, clk_in)
537 begin
538 if rst =
'1' then
539 tx_enable_d <=
'0';
540 elsif
rising_edge (clk_in)
then
541 tx_enable_d <=
tx_enable;
542 end if;
543 end process;
544
545 -- transmitter shift
register and bit counter
546 process (rst, tx_reg, tx_enable_d, clk_in)
547 begin
548 if rst =
'1' then
549 tx_sreg <= x
"FF";
550 tx_bit_cnt <= x
"0";
551 tx_empty_set <=
'0';
552 elsif tx_enable_d =
'0' then
553 tx_sreg <=
tx_reg;
554 tx_bit_cnt <= x
"0";
555 tx_empty_set <=
'0';
556 elsif
rising_edge (clk_in)
then
557 if clk_en =
'1' then
558 tx_bit_cnt <= tx_bit_cnt +
1;
559 tx_sreg <= tx_sreg (
6 downto 0) &
'1';
560 if tx_bit_cnt = x
"6" and is_tx_data =
'1' then
561 tx_empty_set <=
'1';
562 else
563 tx_empty_set <=
'0';
564 end if;
565 end if;
566 end if;
567 end process;
568
569 --
synchronize rd_data
570 process (rst, clk_in)
571 begin
572 if rst =
'1' then
573 rd_data1 <=
'0';
574 elsif
falling_edge (clk_in)
then
575 rd_data1 <=
rd_data;
576 end if;
577 end process;
578
579 process (rst, clk_in)
580 begin
581 if rst =
'1' then
582 rd_data2 <=
'0';
583 elsif
falling_edge (clk_in)
then
584 if rd_data =
'0' then
585 rd_data2 <=
rd_data1;
586 end if;
587 end if;
588 end process;
589
590 --
the rx_empty flip flop
591 process (rst, clk_in)
592 begin
593 if rst =
'1' then
594 rx_empty <=
'1';
595 elsif
rising_edge (clk_in)
then
596 if rx_empty_clr =
'1' then
597 rx_empty <=
'0';
598 elsif rd_data2 =
'1' then
599 rx_empty <=
'1';
600 end if;
601 end if;
602 end process;
603
604 --
the rx_ready flip flop
605 process (rst, clk_in)
606 begin
607 if rst =
'1' then
608 rx_ready <=
'0';
609 elsif
rising_edge (clk_in)
then
610 if rd_data =
'1' then
611 rx_ready <=
'0';
612 elsif rx_ready_set =
'1' then
613 rx_ready <=
'1';
614 end if;
615 end if;
616 end process;
617
618 -- the rx_data
register
619 process (rst, clk_in)
620 begin
621 if rst =
'1' then
622 rx_data <= x
"FF";
623 elsif
rising_edge (clk_in)
then
624 if rx_ready_set =
'1' then
625 rx_data <=
rx_sreg;
626 end if;
627 end if;
628 end process;
629
630 -- receiver shift
register and bit counter
631 process (rst, rx_bit_cnt_clr, clk_in)
632 begin
633 if rst =
'1' or rx_bit_cnt_clr =
'1' then
634 rx_bit_cnt <= x
"0";
635 rx_ready_set <=
'0';
636 rx_empty_clr <=
'0';
637 rx_sreg <= x
"FF";
638 elsif
rising_edge (clk_in)
then
639 if clk_en =
'1' then
640 rx_sreg <= rx_sreg (
6 downto 0) &
spi_din;
641 case rx_bit_cnt
is
642 when x
"0" =>
643 rx_bit_cnt <= rx_bit_cnt +
1;
644 rx_ready_set <=
'0';
645 rx_empty_clr <=
'1';
646 when x
"1" | x
"2" | x
"3" | x
"4" | x
"5" | x
"6" =>
647 rx_bit_cnt <= rx_bit_cnt +
1;
648 rx_ready_set <=
'0';
649 rx_empty_clr <=
'0';
650 when x
"7" =>
651 rx_bit_cnt <= rx_bit_cnt +
1;
652 rx_ready_set <=
'1';
653 rx_empty_clr <=
'0';
654 when others =>
655 null;
656 end case;
657 end if;
658 end if;
659 end process;
660 end rtl;
http://www.diycalculator.com/
http://opencores.org/project,spiflashcontroller
1 Command classification:
2 -----------------------
3
4 Write Enable (WREN) transmit
1 byte ... cmd (
0x06)
5 Write Disable (WRDI) (
0x04)
6 Bulk Erase (BE) (
0xC7)
7 Deep Power Down (DP) (
0xB9)
8
9 Write Status reg (WRSR) transmit
1 byte ... cmd (
0x01)
10 1 byte ... SR contents
11
12 Sector Erase (SE) transmit
1 byte ... cmd (
0xD8)
13 3 bytes .. address
14
15 Page Program (PP) transmit
1 byte ... cmd (
0x02)
16 3 bytes .. address
17 1-
256 bytes .. data
18
19 Read Status reg (RDSR) transmit
1 byte ... cmd (
0x05)
20 receive
1 byte ... SR contents
21
22 Read Signature (RES) transmit
1 byte ... cmd (
0xAB)
23 3 bytes .. dummy
24 receive
1 byte ... the signature (
0x13)
25
26 Read Data (RD) transmit
1 byte ... cmd (
0x03)
27 3 bytes .. address
28 receive n bytes .. data
29
30 Fast Read Data (F_RD) transmit
1 byte ... cmd (
0x0B)
31 3 bytes .. address
32 1 byte ... dummy
33 receive n bytes .. data
1 library ieee;
2 use ieee.std_logic_1164.
all;
3 use ieee.numeric_std.
all;
4
5 entity test_spi_ctrl
is
6 end test_spi_ctrl;
7
8 architecture test
of test_spi_ctrl
is
9 signal rst, clk, sel, rd, wr :
std_logic;
10 signal addr :
std_logic_vector (
2 downto 0);
11 signal spi_clk, spi_cs, spi_din, spi_dout :
std_logic;
12 signal d_in, d_out, stat, data :
std_logic_vector (
7 downto 0);
13 --
FLASH commands
14 constant NOP :
std_logic_vector (
7 downto 0) := x
"FF"; -- no cmd
to execute
15 constant WREN :
std_logic_vector (
7 downto 0) := x
"06"; --
write enable
16 constant WRDI :
std_logic_vector (
7 downto 0) := x
"04"; --
write disable
17 constant RDSR :
std_logic_vector (
7 downto 0) := x
"05"; --
read status reg
18 constant WRSR :
std_logic_vector (
7 downto 0) := x
"01"; --
write stat. reg
19 constant RDCMD :
std_logic_vector (
7 downto 0) := x
"03"; --
read data
20 constant F_RD :
std_logic_vector (
7 downto 0) := x
"0B"; -- fast
read data
21 constant PP :
std_logic_vector (
7 downto 0) := x
"02"; --
page program
22 constant SE :
std_logic_vector (
7 downto 0) := x
"D8"; --
sector erase
23 constant BE :
std_logic_vector (
7 downto 0) := x
"C7"; --
bulk erase
24 constant DP :
std_logic_vector (
7 downto 0) := x
"B9"; --
deep power down
25 constant RES :
std_logic_vector (
7 downto 0) := x
"AB"; --
read signature
26
27 -- status
register bit masks
28 constant STAT_BUSY :
std_logic_vector (
7 downto 0) := x
"01";
29 constant STAT_TXE :
std_logic_vector (
7 downto 0) := x
"02";
30 constant STAT_RXR :
std_logic_vector (
7 downto 0) := x
"04";
31 constant STAT_WDAT :
std_logic_vector (
7 downto 0) := x
"08";
32 begin
33 dut :
entity work.spi_ctrl
34 port map (
35 clk_in =>
clk,
36 rst =>
rst,
37 spi_clk =>
spi_clk,
38 spi_cs =>
spi_cs,
39 spi_din =>
spi_din,
40 spi_dout =>
spi_dout,
41 sel =>
sel,
42 wr =>
wr,
43 addr =>
addr,
44 d_in =>
d_in,
45 d_out =>
d_out
46 );
47
48 process is
49 begin
50 clk <=
'0';
51 wait for 20 ns;
52 clk <=
'1';
53 wait for 20 ns;
54 end process;
55
56 process is
57 begin
58 rst <=
'0';
59 wait for 50 ns;
60 rst <=
'1';
61 wait for 120 ns;
62 rst <=
'0';
63 wait;
64 end process;
65
66 process
67 begin
68 --
initial condition
69 sel <=
'0';
70 addr <=
"000";
71 rd <=
'0';
72 wr <=
'0';
73 d_in <= x
"FF";
74
75 wait for 1420 ns;
76
77 --
write command WREN
78 sel <=
'1';
79 addr <=
"001";
80 d_in <=
WREN;
81 wait for 5 ns;
82 wr <=
'1';
83 wait for 100 ns;
84 wr <=
'0';
85 wait for 5 ns;
86 sel <=
'0';
87 d_in <= x
"FF";
88 wait for 2 us;
89
90 --
write command WRDI
91 sel <=
'1';
92 addr <=
"001";
93 d_in <=
WRDI;
94 wait for 5 ns;
95 wr <=
'1';
96 wait for 100 ns;
97 wr <=
'0';
98 wait for 5 ns;
99 sel <=
'0';
100 d_in <= x
"FF";
101 wait for 2 us;
102
103 --
write command WRSR: data
104 sel <=
'1';
105 addr <=
"000";
106 d_in <= x
"55";
107 wait for 5 ns;
108 wr <=
'1';
109 wait for 100 ns;
110 wr <=
'0';
111 wait for 5 ns;
112 sel <=
'0';
113 d_in <= x
"FF";
114 wait for 10 ns;
115 --
the command
116 sel <=
'1';
117 addr <=
"001";
118 d_in <=
WRSR;
119 wait for 5 ns;
120 wr <=
'1';
121 wait for 100 ns;
122 wr <=
'0';
123 wait for 5 ns;
124 sel <=
'0';
125 d_in <= x
"FF";
126 wait for 4 us;
127
128 --
write command SE:
129 --
address low
130 sel <=
'1';
131 addr <=
"010";
132 d_in <= x
"AB";
133 wait for 5 ns;
134 wr <=
'1';
135 wait for 100 ns;
136 wr <=
'0';
137 wait for 5 ns;
138 sel <=
'0';
139 d_in <= x
"FF";
140 wait for 10 ns;
141 --
address mid
142 sel <=
'1';
143 addr <=
"011";
144 d_in <= x
"CD";
145 wait for 5 ns;
146 wr <=
'1';
147 wait for 100 ns;
148 wr <=
'0';
149 wait for 5 ns;
150 sel <=
'0';
151 d_in <= x
"FF";
152 wait for 10 ns;
153 --
address high
154 sel <=
'1';
155 addr <=
"100";
156 d_in <= x
"EF";
157 wait for 5 ns;
158 wr <=
'1';
159 wait for 100 ns;
160 wr <=
'0';
161 wait for 5 ns;
162 sel <=
'0';
163 d_in <= x
"FF";
164 wait for 10 ns;
165 --
the command
166 sel <=
'1';
167 addr <=
"001";
168 d_in <=
SE;
169 wait for 5 ns;
170 wr <=
'1';
171 wait for 100 ns;
172 wr <=
'0';
173 wait for 5 ns;
174 sel <=
'0';
175 d_in <= x
"FF";
176 wait for 6.5 us;
177
178 --
write command PP:
179 --
address low
180 sel <=
'1';
181 addr <=
"010";
182 d_in <= x
"45";
183 wait for 5 ns;
184 wr <=
'1';
185 wait for 100 ns;
186 wr <=
'0';
187 wait for 5 ns;
188 sel <=
'0';
189 d_in <= x
"FF";
190 wait for 10 ns;
191 --
address mid
192 sel <=
'1';
193 addr <=
"011";
194 d_in <= x
"67";
195 wait for 5 ns;
196 wr <=
'1';
197 wait for 100 ns;
198 wr <=
'0';
199 wait for 5 ns;
200 sel <=
'0';
201 d_in <= x
"FF";
202 wait for 10 ns;
203 --
address high
204 sel <=
'1';
205 addr <=
"100";
206 d_in <= x
"89";
207 wait for 5 ns;
208 wr <=
'1';
209 wait for 100 ns;
210 wr <=
'0';
211 wait for 5 ns;
212 sel <=
'0';
213 d_in <= x
"FF";
214 wait for 10 ns;
215 --
the command
216 sel <=
'1';
217 addr <=
"001";
218 d_in <=
PP;
219 wait for 5 ns;
220 wr <=
'1';
221 wait for 100 ns;
222 wr <=
'0';
223 wait for 5 ns;
224 sel <=
'0';
225 d_in <= x
"FF";
226 wait for 100 ns;
227 --
some data
228 for i
in 0 to 20 loop
229 --
230 wait for tx_empty
231 stat <= x
"00";
232 wait for 10 ns;
233 while (stat
and STAT_WDAT) /= STAT_WDAT
loop
234 sel <=
'1';
235 addr <=
"001";
236 wait for 5 ns;
237 rd <=
'1';
238 wait for 100 ns;
239 stat <=
d_out;
240 rd <=
'0';
241 wait for 5 ns;
242 sel <=
'0';
243 wait for 1 us;
244 end loop;
245 --
write new data
246 sel <=
'1';
247 addr <=
"000";
248 d_in <=
std_logic_vector(TO_UNSIGNED(i, d_in
'Length));
249 wait for 5 ns;
250 wr <=
'1';
251 wait for 100 ns;
252 wr <=
'0';
253 wait for 5 ns;
254 sel <=
'0';
255 d_in <= x
"FF";
256 wait for 1 us;
257 end loop;
258 -- send one more
byte
259
260 wait for 10 us;
261 sel <=
'1';
262 addr <=
"000";
263
264 d_in <= x
"AA";
265 wait for 5 ns;
266 wr <=
'1';
267 wait for 100 ns;
268 wr <=
'0';
269 wait for 5 ns;
270 sel <=
'0';
271 d_in <= x
"FF";
272 wait for 1 us;
273 --
write the NOP command
to terminate
274 sel <=
'1';
275 addr <=
"001";
276
277 d_in <=
NOP;
278 wait for 5 ns;
279 wr <=
'1';
280 wait for 100 ns;
281 wr <=
'0';
282 wait for 5 ns;
283 sel <=
'0';
284 d_in <= x
"FF";
285 wait for 100 ns;
286
287
288 wait for 40 us;
289
290 --
now receive something, cmd RDSR
291 sel <=
'1';
292 addr <=
"001";
293 d_in <=
RDSR;
294 wait for 5 ns;
295 wr <=
'1';
296 wait for 100 ns;
297 wr <=
'0';
298 wait for 5 ns;
299 sel <=
'0';
300 d_in <= x
"FF";
301 -- poll
for rx_ready
302 stat <= x
"00";
303 wait for 10 ns;
304 while (stat
and STAT_RXR) /= STAT_RXR
loop
305
306 wait for 200 ns;
307 sel <=
'1';
308 addr <=
"001";
309 wait for 5 ns;
310 rd <=
'1';
311 wait for 100 ns;
312 stat <=
d_out;
313 rd <=
'0';
314 wait for 5 ns;
315 sel <=
'0';
316 end loop;
317
318 wait for 100 ns;
319 --
read the data
320 sel <=
'1';
321 addr <=
"000";
322 wait for 5 ns;
323 rd <=
'1';
324 wait for 100 ns;
325 data <=
d_out;
326 rd <=
'0';
327 wait for 5 ns;
328 sel <=
'0';
329 wait for 1.5 us;
330
331 --
RES command
332 sel <=
'1';
333 addr <=
"001";
334 d_in <=
RES;
335 wait for 5 ns;
336 wr <=
'1';
337 wait for 100 ns;
338 wr <=
'0';
339 wait for 5 ns;
340 sel <=
'0';
341 d_in <= x
"FF";
342 -- poll
for rx_ready
343 stat <= x
"00";
344 wait for 10 ns;
345 while (stat
and STAT_RXR) /= STAT_RXR
loop
346
347 wait for 200 ns;
348 sel <=
'1';
349 addr <=
"001";
350 wait for 5 ns;
351 rd <=
'1';
352 wait for 100 ns;
353 stat <=
d_out;
354 rd <=
'0';
355 wait for 5 ns;
356 sel <=
'0';
357 end loop;
358
359 wait for 100 ns;
360 --
read the data
361 sel <=
'1';
362 addr <=
"000";
363 wait for 5 ns;
364 rd <=
'1';
365 wait for 100 ns;
366 data <=
d_out;
367 rd <=
'0';
368 wait for 5 ns;
369 sel <=
'0';
370 wait for 1.5 us;
371
372 --
READ command
373 --
address low
374 sel <=
'1';
375 addr <=
"010";
376 d_in <= x
"12";
377 wait for 5 ns;
378 wr <=
'1';
379 wait for 100 ns;
380 wr <=
'0';
381 wait for 5 ns;
382 sel <=
'0';
383 d_in <= x
"FF";
384 wait for 10 ns;
385 --
address mid
386 sel <=
'1';
387 addr <=
"011";
388 d_in <= x
"34";
389 wait for 5 ns;
390 wr <=
'1';
391 wait for 100 ns;
392 wr <=
'0';
393 wait for 5 ns;
394 sel <=
'0';
395 d_in <= x
"FF";
396 wait for 10 ns;
397 --
address high
398 sel <=
'1';
399 addr <=
"100";
400 d_in <= x
"56";
401 wait for 5 ns;
402 wr <=
'1';
403 wait for 100 ns;
404 wr <=
'0';
405 wait for 5 ns;
406 sel <=
'0';
407 d_in <= x
"FF";
408 wait for 10 ns;
409 --
the command
410 sel <=
'1';
411 addr <=
"001";
412 d_in <=
RDCMD;
413 wait for 5 ns;
414 wr <=
'1';
415 wait for 100 ns;
416 wr <=
'0';
417 wait for 5 ns;
418 sel <=
'0';
419 d_in <= x
"FF";
420 --
read data
421 for i
in 1 to 10 loop
422 -- poll
for rx_ready
423 stat <= x
"00";
424 wait for 10 ns;
425 while (stat
and STAT_RXR) /= STAT_RXR
loop
426
427 wait for 200 ns;
428 sel <=
'1';
429 addr <=
"001";
430 wait for 5 ns;
431 rd <=
'1';
432 wait for 100 ns;
433 stat <=
d_out;
434 rd <=
'0';
435 wait for 5 ns;
436 sel <=
'0';
437 end loop;
438
439 wait for 100 ns;
440 --
read the data
441 sel <=
'1';
442 addr <=
"000";
443 wait for 5 ns;
444 rd <=
'1';
445 wait for 100 ns;
446 data <=
d_out;
447 rd <=
'0';
448 wait for 5 ns;
449 sel <=
'0';
450 end loop;
451
452 wait for 1 us;
453 --
write the NOP command
to terminate
454 sel <=
'1';
455 addr <=
"001";
456 d_in <=
NOP;
457 wait for 5 ns;
458 wr <=
'1';
459 wait for 100 ns;
460 wr <=
'0';
461 wait for 5 ns;
462 sel <=
'0';
463 d_in <= x
"FF";
464
465 wait;
466 end process;
467
468 process
469 begin
470 spi_din <=
'1';
471 wait for 144.880 us;
472
473 --
input data
for RDSR cmd
0x54
474 spi_din <=
'0';
475 wait for 160 ns;
476 spi_din <=
'1';
477 wait for 160 ns;
478 spi_din <=
'0';
479 wait for 160 ns;
480 spi_din <=
'1';
481 wait for 160 ns;
482 spi_din <=
'0';
483 wait for 160 ns;
484 spi_din <=
'1';
485 wait for 160 ns;
486 spi_din <=
'0';
487 wait for 160 ns;
488 spi_din <=
'0';
489 wait for 160 ns;
490
491 spi_din <=
'1';
492 wait for 7.68 us;
493
494 -------------------------------
495
496 --
input data
for RES cmd
0xAB
497 spi_din <=
'1';
498 wait for 160 ns;
499 spi_din <=
'0';
500 wait for 160 ns;
501 spi_din <=
'1';
502 wait for 160 ns;
503 spi_din <=
'0';
504 wait for 160 ns;
505 spi_din <=
'1';
506 wait for 160 ns;
507 spi_din <=
'0';
508 wait for 160 ns;
509 spi_din <=
'1';
510 wait for 160 ns;
511 spi_din <=
'1';
512 wait for 160 ns;
513
514 spi_din <=
'1';
515 wait for 8.0 us;
516
517 -------------------------------
518
519 --
input data
for RD cmd
0x01
520 spi_din <=
'0';
521 wait for 160 ns;
522 spi_din <=
'0';
523 wait for 160 ns;
524 spi_din <=
'0';
525 wait for 160 ns;
526 spi_din <=
'0';
527 wait for 160 ns;
528 spi_din <=
'0';
529 wait for 160 ns;
530 spi_din <=
'0';
531 wait for 160 ns;
532 spi_din <=
'0';
533 wait for 160 ns;
534 spi_din <=
'1';
535 wait for 160 ns;
536
537 spi_din <=
'1';
538 wait for 480 ns;
539
540 --
input data
for RD cmd
0x02
541 spi_din <=
'0';
542 wait for 160 ns;
543 spi_din <=
'0';
544 wait for 160 ns;
545 spi_din <=
'0';
546 wait for 160 ns;
547 spi_din <=
'0';
548 wait for 160 ns;
549 spi_din <=
'0';
550 wait for 160 ns;
551 spi_din <=
'0';
552 wait for 160 ns;
553 spi_din <=
'1';
554 wait for 160 ns;
555 spi_din <=
'0';
556 wait for 160 ns;
557
558 spi_din <=
'1';
559 wait for 480 ns;
560
561 --
input data
for RD cmd
0x03
562 spi_din <=
'0';
563 wait for 160 ns;
564 spi_din <=
'0';
565 wait for 160 ns;
566 spi_din <=
'0';
567 wait for 160 ns;
568 spi_din <=
'0';
569 wait for 160 ns;
570 spi_din <=
'0';
571 wait for 160 ns;
572 spi_din <=
'0';
573 wait for 160 ns;
574 spi_din <=
'1';
575 wait for 160 ns;
576 spi_din <=
'1';
577 wait for 160 ns;
578
579 spi_din <=
'1';
580 wait for 480 ns;
581
582 --
input data
for RD cmd
0x04
583 spi_din <=
'0';
584 wait for 160 ns;
585 spi_din <=
'0';
586 wait for 160 ns;
587 spi_din <=
'0';
588 wait for 160 ns;
589 spi_din <=
'0';
590 wait for 160 ns;
591 spi_din <=
'0';
592 wait for 160 ns;
593 spi_din <=
'1';
594 wait for 160 ns;
595 spi_din <=
'0';
596 wait for 160 ns;
597 spi_din <=
'0';
598 wait for 160 ns;
599
600 spi_din <=
'1';
601 wait for 480 ns;
602
603 --
input data
for RD cmd
0x05
604 spi_din <=
'0';
605 wait for 160 ns;
606 spi_din <=
'0';
607 wait for 160 ns;
608 spi_din <=
'0';
609 wait for 160 ns;
610 spi_din <=
'0';
611 wait for 160 ns;
612 spi_din <=
'0';
613 wait for 160 ns;
614 spi_din <=
'1';
615 wait for 160 ns;
616 spi_din <=
'0';
617 wait for 160 ns;
618 spi_din <=
'1';
619 wait for 160 ns;
620
621 spi_din <=
'1';
622 wait for 480 ns;
623
624 --
input data
for RD cmd
0x06
625 spi_din <=
'0';
626 wait for 160 ns;
627 spi_din <=
'0';
628 wait for 160 ns;
629 spi_din <=
'0';
630 wait for 160 ns;
631 spi_din <=
'0';
632 wait for 160 ns;
633 spi_din <=
'0';
634 wait for 160 ns;
635 spi_din <=
'1';
636 wait for 160 ns;
637 spi_din <=
'1';
638 wait for 160 ns;
639 spi_din <=
'0';
640 wait for 160 ns;
641
642 spi_din <=
'1';
643 wait for 640 ns;
644
645 --
input data
for RD cmd
0x07
646 spi_din <=
'0';
647 wait for 160 ns;
648 spi_din <=
'0';
649 wait for 160 ns;
650 spi_din <=
'0';
651 wait for 160 ns;
652 spi_din <=
'0';
653 wait for 160 ns;
654 spi_din <=
'0';
655 wait for 160 ns;
656 spi_din <=
'1';
657 wait for 160 ns;
658 spi_din <=
'1';
659 wait for 160 ns;
660 spi_din <=
'1';
661 wait for 160 ns;
662
663 spi_din <=
'1';
664 wait for 480 ns;
665
666 --
input data
for RD cmd
0x08
667 spi_din <=
'0';
668 wait for 160 ns;
669 spi_din <=
'0';
670 wait for 160 ns;
671 spi_din <=
'0';
672 wait for 160 ns;
673 spi_din <=
'0';
674 wait for 160 ns;
675 spi_din <=
'1';
676 wait for 160 ns;
677 spi_din <=
'0';
678 wait for 160 ns;
679 spi_din <=
'0';
680 wait for 160 ns;
681 spi_din <=
'0';
682 wait for 160 ns;
683
684 spi_din <=
'1';
685 wait for 480 ns;
686
687 --
input data
for RD cmd
0x09
688 spi_din <=
'0';
689 wait for 160 ns;
690 spi_din <=
'0';
691 wait for 160 ns;
692 spi_din <=
'0';
693 wait for 160 ns;
694 spi_din <=
'0';
695 wait for 160 ns;
696 spi_din <=
'1';
697 wait for 160 ns;
698 spi_din <=
'0';
699 wait for 160 ns;
700 spi_din <=
'0';
701 wait for 160 ns;
702 spi_din <=
'1';
703 wait for 160 ns;
704
705 spi_din <=
'1';
706 wait for 480 ns;
707
708 --
input data
for RD cmd
0x0A
709 spi_din <=
'0';
710 wait for 160 ns;
711 spi_din <=
'0';
712 wait for 160 ns;
713 spi_din <=
'0';
714 wait for 160 ns;
715 spi_din <=
'0';
716 wait for 160 ns;
717 spi_din <=
'1';
718 wait for 160 ns;
719 spi_din <=
'0';
720 wait for 160 ns;
721 spi_din <=
'1';
722 wait for 160 ns;
723 spi_din <=
'0';
724 wait for 160 ns;
725
726 spi_din <=
'1';
727
728 wait;
729 end process;
730 end test;
转载于:https://www.cnblogs.com/shangdawei/archive/2012/05/16/2503753.html
相关资源:数据结构—成绩单生成器