├── .gitattributes ├── LICENSE ├── README.md └── Verilog ├── sim └── SPI_Slave_TB.sv └── source └── SPI_Slave.v /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 russell-merrick 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # spi-slave 2 | -------------------------------------------------------------------------------- /Verilog/sim/SPI_Slave_TB.sv: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Description: Simple test bench for SPI Master and Slave modules 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | module SPI_Slave_TB (); 6 | 7 | parameter SPI_MODE = 1; // CPOL = 0, CPHA = 1 8 | parameter SPI_CLK_DELAY = 20; // 2.5 MHz 9 | parameter MAIN_CLK_DELAY = 2; // 25 MHz 10 | 11 | logic w_CPOL; // clock polarity 12 | logic w_CPHA; // clock phase 13 | 14 | assign w_CPOL = (SPI_MODE == 2) | (SPI_MODE == 3); 15 | assign w_CPHA = (SPI_MODE == 1) | (SPI_MODE == 3); 16 | 17 | logic r_Rst_L = 1'b0; 18 | 19 | logic [7:0] dataPayload[0:255]; 20 | logic [7:0] dataLength; 21 | 22 | // CPOL=0, clock idles 0. CPOL=1, clock idles 1 23 | // logic r_SPI_Clk = w_CPOL ? 1'b1 : 1'b0; 24 | logic w_SPI_Clk; 25 | logic r_SPI_En = 1'b0; 26 | logic r_Clk = 1'b0; 27 | logic w_SPI_CS_n; 28 | logic w_SPI_MOSI; 29 | logic w_SPI_MISO; 30 | 31 | // Master Specific 32 | logic [7:0] r_Master_TX_Byte = 0; 33 | logic r_Master_TX_DV = 1'b0; 34 | logic r_Master_CS_n = 1'b1; 35 | logic w_Master_TX_Ready; 36 | logic r_Master_RX_DV; 37 | logic [7:0] r_Master_RX_Byte; 38 | 39 | // Slave Specific 40 | logic w_Slave_RX_DV, r_Slave_TX_DV; 41 | logic [7:0] w_Slave_RX_Byte, r_Slave_TX_Byte; 42 | 43 | // Clock Generators: 44 | always #(MAIN_CLK_DELAY) r_Clk = ~r_Clk; 45 | 46 | // Instantiate UUT 47 | SPI_Slave #(.SPI_MODE(SPI_MODE)) SPI_Slave_UUT 48 | ( 49 | // Control/Data Signals, 50 | .i_Rst_L(r_Rst_L), // FPGA Reset 51 | .i_Clk(r_Clk), // FPGA Clock 52 | .o_RX_DV(w_Slave_RX_DV), // Data Valid pulse (1 clock cycle) 53 | .o_RX_Byte(w_Slave_RX_Byte), // Byte received on MOSI 54 | .i_TX_DV(w_Slave_RX_DV), // Data Valid pulse 55 | .i_TX_Byte(w_Slave_RX_Byte), // Byte to serialize to MISO (set up for loopback) 56 | 57 | // SPI Interface 58 | .i_SPI_Clk(w_SPI_Clk), 59 | .o_SPI_MISO(w_SPI_MISO), 60 | .i_SPI_MOSI(w_SPI_MOSI), 61 | .i_SPI_CS_n(r_Master_CS_n) 62 | ); 63 | 64 | // Instantiate Master to drive Slave 65 | SPI_Master 66 | #(.SPI_MODE(SPI_MODE), 67 | .CLKS_PER_HALF_BIT(2), 68 | .NUM_SLAVES(1)) SPI_Master_UUT 69 | ( 70 | // Control/Data Signals, 71 | .i_Rst_L(r_Rst_L), // FPGA Reset 72 | .i_Clk(r_Clk), // FPGA Clock 73 | 74 | // TX (MOSI) Signals 75 | .i_TX_Byte(r_Master_TX_Byte), // Byte to transmit on MOSI 76 | .i_TX_DV(r_Master_TX_DV), // Data Valid Pulse with i_TX_Byte 77 | .o_TX_Ready(w_Master_TX_Ready), // Transmit Ready for Byte 78 | 79 | // RX (MISO) Signals 80 | .o_RX_DV(r_Master_RX_DV), // Data Valid pulse (1 clock cycle) 81 | .o_RX_Byte(r_Master_RX_Byte), // Byte received on MISO 82 | 83 | // SPI Interface 84 | .o_SPI_Clk(w_SPI_Clk), 85 | .i_SPI_MISO(w_SPI_MISO), 86 | .o_SPI_MOSI(w_SPI_MOSI) 87 | ); 88 | 89 | 90 | // Sends a single byte from master to slave. Will drive CS on its own. 91 | task SendSingleByte(input [7:0] data); 92 | @(posedge r_Clk); 93 | r_Master_TX_Byte <= data; 94 | r_Master_TX_DV <= 1'b1; 95 | r_Master_CS_n <= 1'b0; 96 | @(posedge r_Clk); 97 | r_Master_TX_DV <= 1'b0; 98 | @(posedge w_Master_TX_Ready); 99 | r_Master_CS_n <= 1'b1; 100 | endtask // SendSingleByte 101 | 102 | 103 | // Sends a multi-byte transfer from master to slave. Drives CS on its own. 104 | task SendMultiByte(input [7:0] data[0:255], input [7:0] length); 105 | integer ii; 106 | 107 | @(posedge r_Clk); 108 | r_Master_CS_n <= 1'b0; 109 | 110 | for (ii=0; ii