SPI Flash controller for DIY Calculator

  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;

posted @ 2012-05-16 12:28  IAmAProgrammer  阅读(707)  评论(0编辑  收藏  举报