微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 关于FPGA 模拟SPI

关于FPGA 模拟SPI

时间:10-02 整理:3721RD 点击:
最近在学习SPI  从网上COPY了以下代码

  1. /***********************************************************************************************
  2. * SPI MASTER
  3. * January 2007
  4. ************************************************************************************************/
  5. `timescale 10ns/1ns
  6. module SPI_Master ( miso, mosi, sclk, ss, data_bus, CS, addr, pro_clk, WR, RD);

  7. inout [7:0] data_bus;           // 8 bit bidirectional data bus
  8. input pro_clk;                  // Host Processor clock
  9. input miso;                     // Master in slave out
  10. input [1:0] addr;               // A1 and A0, lower bits of address bus
  11. input CS;                       // Chip Select
  12. input WR, RD;                   // Write and read enables

  13. output mosi;                    // Master out slave in
  14. output sclk;                    // SPI clock
  15. output [7:0] ss;                // 8 slave select lines

  16. reg [7:0] shift_register;        // Shift register
  17. reg [7:0] txdata;                // Transmit buffer
  18. reg [7:0] rxdata;                // Receive buffer
  19. reg [7:0] data_out;              // Data output register
  20. reg [7:0] data_out_en;           // Data output enable
  21. reg [7:0] control, status;       // Control Register COntrols things like ss, CPOL, CPHA, clock divider
  22.                                  // Status Register is a dummy register never used.

  23. reg [7:0] clk_divide;            // Clock divide counter
  24. reg [3:0] count;                 // SPI word length counter
  25. reg sclk;                        
  26. reg slave_cs;                    // Slave cs flag
  27. reg mosi;                                           // Master out slave in
  28. reg spi_word_send;               // Will send a new spi word.

  29. wire [7:0] data_bus;
  30. wire [7:0] data_in = data_bus;
  31. wire spi_clk_gen;
  32. wire [2:0] divide_factor = control[2:0];
  33. wire CPOL = control[3];         
  34. wire CPHA = control[4];
  35. wire [7:0]ss;


  36. /* Slave Select lines */
  37. assign ss[7] = ~( control[7] &  control[6] &  control[5] & (~slave_cs));
  38. assign ss[6] = ~( control[7] &  control[6] & ~control[5] & (~slave_cs));
  39. assign ss[5] = ~( control[7] & ~control[6] &  control[5] & (~slave_cs));
  40. assign ss[4] = ~( control[7] & ~control[6] & ~control[5] & (~slave_cs));
  41. assign ss[3] = ~(~control[7] &  control[6] &  control[5] & (~slave_cs));
  42. assign ss[2] = ~(~control[7] &  control[6] & ~control[5] & (~slave_cs));
  43. assign ss[1] = ~(~control[7] & ~control[6] &  control[5] & (~slave_cs));
  44. assign ss[0] = ~(~control[7] & ~control[6] & ~control[5] & (~slave_cs));

  45. /* clock divide */
  46. assign spi_clk_gen = clk_divide[divide_factor];

  47. /* Clock Divider */
  48. always @ (negedge pro_clk) begin
  49.     clk_divide = clk_divide + 1;     
  50. end

  51. /* Reading the miso line and shifting */
  52. always @ (posedge (sclk ^ (CPHA ^ CPOL)) or posedge spi_word_send) begin
  53.     if (spi_word_send) begin
  54.         shift_register[7:0] = txdata;
  55.     end else begin
  56.         shift_register = shift_register << 1;
  57.         shift_register[0] <= miso;
  58.     end
  59. end

  60. /* Writing the mosi */
  61. always @ (negedge (sclk ^ (CPHA ^ CPOL)) or posedge spi_word_send) begin
  62.     if (spi_word_send) begin
  63.         mosi = txdata[7];
  64.     end else begin
  65.         mosi = shift_register[7];
  66.     end
  67. end

  68. /* Contolling the interrupt bit in the status bit */
  69. always @ (posedge slave_cs or posedge spi_word_send) begin
  70.     if (spi_word_send) begin
  71.         status[0] = 0;
  72.     end else begin
  73.             status = 8'h01;
  74.           rxdata = shift_register;         // updating read buffer
  75.         end
  76. end
  77.    
  78. /* New SPI wrod starts when the transmit buffer is updated */
  79. always @ (posedge pro_clk) begin
  80.     if (spi_word_send) begin
  81.         slave_cs <= 0;
  82.     end else if ((count == 8) & ~(sclk ^ CPOL)) begin
  83.         slave_cs <= 1;
  84.     end   
  85. end

  86. /* New Spi word is intiated when transmit buffer is updated */
  87. always @ (posedge pro_clk) begin
  88.     if (CS & WR & addr[1] & ~addr[0]) begin
  89.         spi_word_send <=1;
  90.     end else begin
  91.         spi_word_send <=0;
  92.     end
  93. end

  94. /* Generating the SPI clock */
  95. always @ (posedge spi_clk_gen) begin
  96.     if (~slave_cs) begin
  97.         sclk = ~sclk;
  98.     end else if (~CPOL) begin
  99.         sclk = 0;
  100.     end else begin
  101.         sclk = 1;
  102.     end
  103. end

  104. /* Counting SPI word length */
  105. always @ (posedge sclk or posedge slave_cs) begin
  106.     if (slave_cs) begin
  107.         count = 0;
  108.     end else begin   
  109.         count = count + 1;
  110.     end
  111. end

  112. /* Reading, writing SPI registers */
  113. always @ (posedge pro_clk) begin
  114.     if (CS) begin
  115.         case (addr)
  116.         2'b00 : if (WR) control <= data_in;
  117.         2'b01 : if (RD) data_out <= status;   // Void
  118.                   2'b10 : if (WR) txdata <= data_in;
  119.                   2'b11 : if (RD) data_out <= rxdata;
  120.         endcase
  121.     end
  122. end

  123. /* Controlling the data out enable */
  124. always @ (RD or data_out) begin
  125.     if (RD)
  126.     data_out_en = data_out;
  127.     else
  128.     data_out_en = 8'bz;
  129. end

  130. assign data_bus = data_out_en;

  131. initial
  132. begin
  133.     mosi = 0;
  134.     //sclk = 0;
  135.     control = 0;
  136.     count = 0;
  137.     slave_cs = 1;
  138.     txdata = 0;
  139.     rxdata = 0;
  140.     clk_divide = 0;
  141.     data_out = 0;
  142. end

  143. endmodule

  144. /********************************************** END ******************************************************************/

复制代码

可能是我对SPI理解得还不够深  在FPGA作为master时
像INPUT里面的addr WR RD
OUTPUT 里面的 SS这些都是干什么的呢?
SPI总线不是最多四条就够了吗。
求解释。最好是有应用的实例
比如 我想FPGA发送1HZ方波 让单片机的LED闪动 应该怎么接?

先看看SPI的时序图,要不然通信协议都不会,不太好搞。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top