spi_slave_mod.v 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // vim: ts=4 sw=4 noexpandtab
  2. /*
  3. * SPI bus slave
  4. *
  5. * Copyright (c) 2019 Michael Buesch <m@bues.ch>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program; if not, write to the Free Software Foundation, Inc.,
  19. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20. */
  21. `ifndef SPI_SLAVE_MOD_V_
  22. `define SPI_SLAVE_MOD_V_
  23. `include "sync_signal_mod.v"
  24. module spi_slave #(
  25. parameter WORDSIZE = 8, /* Size of SPI word. Can be anything from 1 to 32. */
  26. parameter CPOL = 0, /* SPI clock polarity. Can be 0 or 1. */
  27. parameter CPHA = 0, /* SPI clock phase. Can be 0 or 1. */
  28. parameter MSB_FIRST = 1, /* MSB transmit first enable. Can be 0 or 1. */
  29. ) (
  30. input clk, /* clock */
  31. input mosi, /* SPI bus MOSI signal */
  32. output miso, /* SPI bus MISO signal */
  33. input sck, /* SPI bus clock signal */
  34. input ss, /* SPI bus slave select signal */
  35. output rx_irq, /* Receive interrupt */
  36. output [WORDSIZE - 1 : 0] rx_data, /* Received data */
  37. input [WORDSIZE - 1 : 0] tx_data, /* Transmit data */
  38. );
  39. /* Synchronized input signals. */
  40. wire mosi_s;
  41. wire sck_rising_s;
  42. wire sck_falling_s;
  43. wire ss_s;
  44. sync_signal sync_mosi(.clk(clk), .in(mosi), .out(mosi_s));
  45. sync_signal sync_sck(.clk(clk), .in(sck), .rising(sck_rising_s), .falling(sck_falling_s));
  46. sync_signal sync_ss(.clk(clk), .in(ss), .out(ss_s));
  47. /* SCK sample and setup edges. */
  48. wire sck_sample_edge;
  49. wire sck_setup_edge;
  50. assign sck_sample_edge = (CPOL ^ CPHA) ? sck_falling_s : sck_rising_s;
  51. assign sck_setup_edge = (CPOL ^ CPHA) ? sck_rising_s : sck_falling_s;
  52. /* Output buffers. */
  53. reg miso_r;
  54. reg rx_irq_r;
  55. reg [WORDSIZE - 1 : 0] rx_data_r;
  56. assign miso = miso_r;
  57. assign rx_irq = rx_irq_r;
  58. assign rx_data = rx_data_r;
  59. /* Receive and transmit shift registers. */
  60. reg [WORDSIZE - 1 : 0] rx_shiftreg;
  61. reg [WORDSIZE - 1 : 0] tx_shiftreg;
  62. reg [5:0] bit_count;
  63. initial begin
  64. bit_count <= 0;
  65. rx_shiftreg <= 0;
  66. tx_shiftreg <= 0;
  67. miso_r <= 0;
  68. rx_irq_r <= 0;
  69. rx_data_r <= 0;
  70. end
  71. always @(posedge clk) begin
  72. /* Check if slave select is not active */
  73. if (ss_s) begin
  74. bit_count <= 0;
  75. rx_shiftreg <= 0;
  76. tx_shiftreg <= 0;
  77. miso_r <= 0;
  78. rx_irq_r <= 0;
  79. /* Check if slave select is active */
  80. end else begin
  81. /* Check if we are at the start of a word. */
  82. if (bit_count == 0) begin
  83. if (CPHA) begin
  84. /* Reload the TX shift register. */
  85. tx_shiftreg <= tx_data;
  86. miso_r <= 0;
  87. end else begin
  88. /* Reload the TX shift register and
  89. * put the first bit onto the bus. */
  90. if (MSB_FIRST) begin
  91. tx_shiftreg <= tx_data << 1;
  92. miso_r <= tx_data[WORDSIZE - 1];
  93. end else begin
  94. tx_shiftreg <= tx_data >> 1;
  95. miso_r <= tx_data[0];
  96. end
  97. end
  98. /* Check if we are at a setup edge of SCK. */
  99. end else if (sck_setup_edge) begin
  100. /* Put the next bit onto the bus. */
  101. if (MSB_FIRST) begin
  102. miso_r <= tx_shiftreg[WORDSIZE - 1];
  103. tx_shiftreg <= tx_shiftreg << 1;
  104. end else begin
  105. miso_r <= tx_shiftreg[0];
  106. tx_shiftreg <= tx_shiftreg >> 1;
  107. end
  108. end
  109. /* Check if we are at a sample edge of SCK. */
  110. if (sck_sample_edge && (bit_count < WORDSIZE)) begin
  111. /* Get the next bit from the bus. */
  112. if (MSB_FIRST) begin
  113. rx_shiftreg <= rx_shiftreg << 1;
  114. rx_shiftreg[0] <= mosi_s;
  115. end else begin
  116. rx_shiftreg <= rx_shiftreg >> 1;
  117. rx_shiftreg[WORDSIZE - 1] <= mosi_s;
  118. end
  119. bit_count <= bit_count + 1;
  120. end
  121. /* If we received a full word, trigger the RX interrupt. */
  122. if (bit_count >= WORDSIZE) begin
  123. bit_count <= 0;
  124. rx_data_r <= rx_shiftreg;
  125. rx_irq_r <= 1;
  126. end else begin
  127. rx_irq_r <= 0;
  128. end
  129. end
  130. end
  131. endmodule
  132. `endif /* SPI_SLAVE_MOD_V_ */