spi.v 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. `timescale 1ns / 1ps
  2. //////////////////////////////////////////////////////////////////////////////////
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 21:16:09 07/10/2009
  7. // Design Name:
  8. // Module Name: spi
  9. // Project Name:
  10. // Target Devices:
  11. // Tool versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //////////////////////////////////////////////////////////////////////////////////
  21. module spi(
  22. input clk,
  23. input SCK,
  24. input MOSI,
  25. inout MISO,
  26. input SSEL,
  27. output cmd_ready,
  28. output param_ready,
  29. output [7:0] cmd_data,
  30. output [7:0] param_data,
  31. input [7:0] input_data,
  32. output [31:0] byte_cnt,
  33. output [2:0] bit_cnt
  34. );
  35. reg [7:0] cmd_data_r;
  36. reg [7:0] param_data_r;
  37. reg [2:0] SSELr;
  38. reg [2:0] SSELSCKr;
  39. always @(posedge clk) SSELr <= {SSELr[1:0], SSEL};
  40. always @(posedge SCK) SSELSCKr <= {SSELSCKr[1:0], SSEL};
  41. wire SSEL_inactive = SSELr[1];
  42. wire SSEL_active = ~SSELr[1]; // SSEL is active low
  43. wire SSEL_startmessage = (SSELr[2:1]==2'b10); // message starts at falling edge
  44. wire SSEL_endmessage = (SSELr[2:1]==2'b01); // message stops at rising edge
  45. // bit count for one SPI byte + byte count for the message
  46. reg [2:0] bitcnt;
  47. initial bitcnt = 3'b000;
  48. wire bitcnt_msb = bitcnt[2];
  49. reg [2:0] bitcnt_wrap_r;
  50. always @(posedge clk) bitcnt_wrap_r <= {bitcnt_wrap_r[1:0], bitcnt_msb};
  51. wire byte_received_sync = (bitcnt_wrap_r[2:1] == 2'b10);
  52. reg [31:0] byte_cnt_r;
  53. reg byte_received; // high when a byte has been received
  54. reg [7:0] byte_data_received;
  55. assign bit_cnt = bitcnt;
  56. always @(posedge SCK) begin
  57. if(SSELSCKr[1]) bitcnt <= 3'b000;
  58. else bitcnt <= bitcnt + 3'b001;
  59. end
  60. always @(posedge SCK) begin
  61. if(~SSELSCKr[1]) begin
  62. byte_data_received <= {byte_data_received[6:0], MOSI};
  63. end
  64. if(~SSELSCKr[1] && bitcnt==3'b111) byte_received <= 1'b1;
  65. else byte_received <= 1'b0;
  66. end
  67. //reg [2:0] byte_received_r;
  68. //always @(posedge clk) byte_received_r <= {byte_received_r[1:0], byte_received};
  69. //wire byte_received_sync = (byte_received_r[2:1] == 2'b01);
  70. always @(posedge clk) begin
  71. if(SSEL_inactive) begin
  72. byte_cnt_r <= 16'h0000;
  73. end else if(byte_received_sync) begin
  74. byte_cnt_r <= byte_cnt_r + 16'h0001;
  75. end
  76. end
  77. reg [7:0] byte_data_sent;
  78. assign MISO = ~SSEL ? input_data[7-bitcnt] : 1'bZ; // send MSB first
  79. reg cmd_ready_r;
  80. reg param_ready_r;
  81. reg cmd_ready_r2;
  82. reg param_ready_r2;
  83. assign cmd_ready = cmd_ready_r;
  84. assign param_ready = param_ready_r;
  85. assign cmd_data = cmd_data_r;
  86. assign param_data = param_data_r;
  87. assign byte_cnt = byte_cnt_r;
  88. always @(posedge clk) cmd_ready_r2 = byte_received_sync && byte_cnt_r == 32'h0;
  89. always @(posedge clk) param_ready_r2 = byte_received_sync && byte_cnt_r > 32'h0;
  90. // fill registers
  91. always @(posedge clk) begin
  92. if (SSEL_startmessage)
  93. cmd_data_r <= 8'h00;
  94. else if(cmd_ready_r2)
  95. cmd_data_r <= byte_data_received;
  96. else if(param_ready_r2)
  97. param_data_r <= byte_data_received;
  98. end
  99. // delay ready signals by one clock
  100. always @(posedge clk) begin
  101. cmd_ready_r <= cmd_ready_r2;
  102. param_ready_r <= param_ready_r2;
  103. end
  104. endmodule