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://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;