spi_master.sv 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. //
  2. // spi_master.sv
  3. //
  4. // Simple byte-oriented SPI master unit with optional multiwidth support
  5. // (1, 2, 4, 8).
  6. //
  7. // The output SPI clock equals the system clock /2 unless clk_en is used
  8. // to throttle the output clock.
  9. //
  10. // spi_io[0] = DI, spi_io[1] = DO in single bit mode.
  11. //
  12. // All unused spi_io are driven to 1.
  13. //
  14. //
  15. // XXX: add clock polarity, MSB/LSB options
  16. //
  17. module spi_master
  18. #(
  19. parameter width = 1, // Width of SPI data
  20. parameter n_cs = 1, // Number of CS# outputs
  21. parameter CPOL = 0, // Inverted SPI clock polarity
  22. parameter cs_delay = 1,
  23. parameter io_max = max(ilog2c(width)-1, 1)
  24. )
  25. (
  26. input rst_n, // Unit reset
  27. input clk, // System clock
  28. input clk_en, // SPI clock enable
  29. input [7:0] d, // System data in
  30. output [7:0] q, // System data out
  31. input req, // Session request
  32. input dir, // Session is write (for multibit)
  33. input [1:0] iowidth, // Session width (lg2)
  34. output sack, // Session started
  35. output eack, // Session ended
  36. input [n_cs-1:0] cs, // Device select (active high)
  37. output spi_sck, // SPI clock
  38. inout [min(ilog2c(width)-1, 1):0] spi_io, // SPI data
  39. output [n_cs-1:0] spi_cs_n // SPI CS# lines
  40. );
  41. localparam ctr_max = max(ilog2c(cs_delay)-1,2);
  42. reg spi_clk;
  43. reg spi_sck_q;
  44. reg spi_active;
  45. reg [ilog2c(width)-1:0] spi_width;
  46. reg [ctr_max:0] spi_ctr;
  47. reg [n_cs-1:0] spi_cs_q;
  48. reg [7:0] spi_out_q;
  49. reg [1:0] spi_oe_q;
  50. reg d_dir;
  51. reg [7:0] d_out;
  52. reg [7:0] d_in;
  53. reg [7:0] q_q;
  54. reg sack_q;
  55. reg eack_q;
  56. assign spi_cs_n = ~spi_cs_q;
  57. assign spi_sck = spi_sck_q ^ CPOL;
  58. wire spi_cs_changed = |(spi_cs_q ^ cs);
  59. assign spi_io[0] = spi_oe_q[0] ? spi_out_q[0] : 1'bz;
  60. assign spi_io[io_max:1] = spi_oe_q[1] ? spi_out_q[io_max:1] : {io_max{1'bz}};
  61. always @(negedge rst_n or posedge clk)
  62. if (~rst_n)
  63. begin
  64. spi_clk <= 1'b0;
  65. spi_active <= 1'b0;
  66. spi_width <= 4'b0001;
  67. spi_ctr <= 1'b0;
  68. spi_cs_q <= 1'b0;
  69. spi_out_q <= 8'hFF;
  70. spi_oe_q <= 2'b10;
  71. sack_q <= 1'b0;
  72. eack_q <= 1'b0;
  73. d_out <= 8'hFF;
  74. d_in <= 8'hxx;
  75. q_q <= 8'hxx;
  76. end
  77. else
  78. begin
  79. sack_q <= 1'b0;
  80. eack_q <= 1'b0;
  81. if (clk_en)
  82. begin
  83. spi_ctr <= spi_ctr - 1'b1;
  84. spi_clk <= spi_ctr[0] & spi_active;
  85. if (~spi_ctr[0])
  86. begin
  87. case (spi_width)
  88. 4'd1:
  89. d_in <= { d_in[6:0], spi_io[0] };
  90. 4'd2:
  91. d_in <= { d_in[5:0], spi_io[1:0] };
  92. 4'd4:
  93. d_in <= { d_in[3:0], spi_io[3:0] };
  94. 4'd8:
  95. d_in <= spi_io;
  96. default:
  97. d_in <= 8'hxx;
  98. endcase // case 2'd3
  99. end // if (~spi_ctr[0])
  100. else
  101. begin
  102. if (spi_active)
  103. begin
  104. spi_out_q <= 8'hFF;
  105. if (~|spi_ctr[ctr_max:1])
  106. begin
  107. eack_q <= 1'b1;
  108. q_q <= d_in;
  109. spi_active <= 1'b0;
  110. end
  111. case (spi_width)
  112. 4'd1:
  113. begin
  114. d_out <= { d_out[6:0], 1'b1 };
  115. spi_out_q[1] <= d_out[7];
  116. end
  117. 4'd2:
  118. begin
  119. d_out <= { d_out[5:0], 2'b11 };
  120. spi_out_q[1:0] <= d_out[7:6];
  121. end
  122. 4'd4:
  123. begin
  124. d_out <= { d_out[3:0], 4'b1111 };
  125. spi_out_q[3:0] <= d_out[7:4];
  126. end
  127. 4'd8:
  128. begin
  129. d_out <= 8'hFF;
  130. spi_out_q <= d_out;
  131. end
  132. default:
  133. begin
  134. d_out <= 8'hxx;
  135. spi_out_q <= 8'hxx;
  136. end
  137. endcase // case (spi_width)
  138. end // if (spi_active)
  139. else
  140. begin
  141. spi_cs_q <= cs;
  142. d_out <= d;
  143. spi_out_q <= 8'hFF;
  144. if (cs_delay != 0 &&
  145. (spi_cs_changed | ~|spi_ctr[ctr_max:1]))
  146. begin
  147. if (spi_cs_changed)
  148. spi_ctr[ctr_max:1] <= cs_delay;
  149. spi_oe_q <= 2'b10; // As for 1-bit mode
  150. end
  151. else if (cs_delay == 0 || ~|spi_ctr[ctr_max:1])
  152. begin
  153. if (req)
  154. begin
  155. case (iowidth)
  156. 2'd0:
  157. begin
  158. spi_width <= 4'b0001;
  159. spi_ctr[ctr_max:1] <= 3'd8;
  160. spi_oe_q <= 2'b10;
  161. end
  162. 2'd1:
  163. if (width < 2)
  164. begin
  165. spi_width <= 4'b000x;
  166. spi_ctr[ctr_max:1] <= 1'bx;
  167. spi_oe_q <= 2'bxx;
  168. end
  169. else
  170. begin
  171. spi_width <= 4'b0010;
  172. spi_ctr[ctr_max:1] <= 3'd4;
  173. spi_oe_q <= {2{dir}};
  174. end
  175. 2'd2:
  176. if (width < 4)
  177. begin
  178. spi_width <= 4'b00xx;
  179. spi_ctr[ctr_max:1] <= 1'bx;
  180. spi_oe_q <= 2'bxx;
  181. end
  182. else
  183. begin
  184. spi_width <= 4'b0100;
  185. spi_ctr[ctr_max:1] <= 3'd2;
  186. spi_oe_q <= {2{dir}};
  187. end
  188. 2'd3:
  189. if (width < 8)
  190. begin
  191. spi_width <= 4'b0xxx;
  192. spi_ctr[ctr_max:1] <= 1'bx;
  193. spi_oe_q <= 2'bxx;
  194. end
  195. else
  196. begin
  197. spi_width <= 4'b1000;
  198. spi_ctr[ctr_max:1] <= 3'd1;
  199. spi_oe_q <= {2{dir}};
  200. end
  201. endcase // case (iowidth)
  202. spi_active <= 1'b1;
  203. sack_q <= 1'b1;
  204. end // if (req)
  205. end // if (cs_delay == 0 || ~|spi_ctr[ctr_max:1])
  206. end // else: !if(spi_active)
  207. end // else: !if(~spi_ctr[0])
  208. end // if (clk_en)
  209. end // else: !if(~rst_n)
  210. endmodule // spi_master