当前位置:   article > 正文

SMT32通过SPI读写FPGA的寄存器_spi读写寄存器流程

spi读写寄存器流程

关于SPI的主机和从机请看;https://blog.csdn.net/qq_40893012/article/details/103995154

本设计在FPGA用32个寄存器构建了一个8bit*32的ROM,可通过STM32使用SPI写入命令字节来实现对32个寄存器的读写操作。

命令字节的格式:

bit 7:读写控制位,

      1:W

      0:R

bit6-bit2:寄存器地址

bit1-bit0:未使用

stm32的代码基于正电原子的探索者开发板和工程,使用软件模拟SPI,FPGA使用Verilog编写。

SPI的特性为:时钟空闲时为高电平,在时钟的下降沿将数据输出,在时钟的上升沿读取数据。

主要代码:

FPGA代码:

1 SPI从机部分

  1. // 32位二段式状态机spi模块
  2. module spi_slave16bit(
  3. input wire clk,
  4. input rst_n,
  5. input wire CS,
  6. input wire SCK,
  7. input wire MOSI,
  8. output reg MISO,
  9. output reg [5:0]rom_addr,
  10. output reg busy,//spi给fpga其他模块,busy=1时,禁止FPGA读写
  11. input wire[15:0] data_to_out,
  12. output reg[15:0] data_had_receive,
  13. output rxd_over //rx 2byte will generate pulse
  14. );
  15. reg [1:0] state;
  16. parameter IDLE = 2'b00;
  17. parameter TRANS = 2'b01;
  18. parameter WAIT = 2'b10;
  19. reg [1:0]CS_buf;
  20. wire CS_falling_flag;
  21. wire CS_rising_flag;
  22. always@(posedge clk)
  23. begin
  24. CS_buf[1] <= CS_buf[0];
  25. CS_buf[0] <= CS;
  26. end
  27. assign CS_falling_flag = CS_buf[1] &(~CS_buf[0]);
  28. assign CS_rising_flag = (~CS_buf[1]) & CS_buf[0];
  29. reg [1:0]SCK_buf;
  30. wire SCK_falling_flag;
  31. wire SCK_rising_flag;
  32. always@(posedge clk)
  33. begin
  34. SCK_buf[1] <= SCK_buf[0];
  35. SCK_buf[0] <= SCK;
  36. end
  37. assign SCK_falling_flag = SCK_buf[1]&(~SCK_buf[0]);
  38. assign SCK_rising_flag = (~SCK_buf[1])&SCK_buf[0];
  39. reg [5:0]count;
  40. // state machine
  41. always@(posedge clk)
  42. begin
  43. case(state)
  44. IDLE:begin
  45. if(CS_falling_flag==1) state <= TRANS;
  46. end
  47. TRANS:begin
  48. if(count == 6'b010000) state <= WAIT; // 传完16个数
  49. else if (CS_rising_flag==1) state <= IDLE; // 意外结束
  50. end
  51. WAIT:begin
  52. if (CS_rising_flag) state <= IDLE;
  53. end
  54. endcase
  55. end
  56. // count
  57. always@(posedge clk)
  58. begin
  59. case(state)
  60. IDLE: count<=6'b0;
  61. TRANS:begin
  62. if(SCK_rising_flag == 1) count <= count + 6'b1;
  63. end
  64. endcase
  65. end
  66. // MISO
  67. always@(posedge clk)
  68. begin
  69. if ((state == TRANS)&&(SCK_falling_flag == 1))
  70. begin
  71. case(count)
  72. 6'b000000: MISO <= data_to_out[15];
  73. 6'b000001: MISO <= data_to_out[14];
  74. 6'b000010: MISO <= data_to_out[13];
  75. 6'b000011: MISO <= data_to_out[12];
  76. 6'b000100: MISO <= data_to_out[11];
  77. 6'b000101: MISO <= data_to_out[10];
  78. 6'b000110: MISO <= data_to_out[9];
  79. 6'b000111: MISO <= data_to_out[8];
  80. 6'b001000: MISO <= data_to_out[7];
  81. 6'b001001: MISO <= data_to_out[6];
  82. 6'b001010: MISO <= data_to_out[5];
  83. 6'b001011: MISO <= data_to_out[4];
  84. 6'b001100: MISO <= data_to_out[3];
  85. 6'b001101: MISO <= data_to_out[2];
  86. 6'b001110: MISO <= data_to_out[1];
  87. 6'b001111: MISO <= data_to_out[0];
  88. /* 6'b010000: MISO <= data_to_out[15];
  89. 6'b010001: MISO <= data_to_out[14];
  90. 6'b010010: MISO <= data_to_out[13];
  91. 6'b010011: MISO <= data_to_out[12];
  92. 6'b010100: MISO <= data_to_out[11];
  93. 6'b010101: MISO <= data_to_out[10];
  94. 6'b010110: MISO <= data_to_out[9];
  95. 6'b010111: MISO <= data_to_out[8];
  96. 6'b011000: MISO <= data_to_out[7];
  97. 6'b011001: MISO <= data_to_out[6];
  98. 6'b011010: MISO <= data_to_out[5];
  99. 6'b011011: MISO <= data_to_out[4];
  100. 6'b011100: MISO <= data_to_out[3];
  101. 6'b011101: MISO <= data_to_out[2];
  102. 6'b011110: MISO <= data_to_out[1];
  103. 6'b011111: MISO <= data_to_out[0]; */
  104. endcase
  105. end
  106. end
  107. // MOSI
  108. reg rxd_flag_r;
  109. always@(posedge clk or negedge rst_n)
  110. begin
  111. if(!rst_n)
  112. rxd_flag_r <= 0;
  113. else
  114. begin
  115. if ((state == TRANS)&&(SCK_rising_flag == 1))
  116. begin
  117. case(count)
  118. 6'b000000: begin data_had_receive[15] <= MOSI;rxd_flag_r<=1'b0;end
  119. 6'b000001: data_had_receive[14] <= MOSI;
  120. 6'b000010: data_had_receive[13] <= MOSI;
  121. 6'b000011: data_had_receive[12] <= MOSI;
  122. 6'b000100: data_had_receive[11] <= MOSI;
  123. 6'b000101: begin
  124. data_had_receive[10] <= MOSI; //set rom addr
  125. rom_addr[5:0] <= {data_had_receive[15:11],MOSI};
  126. end
  127. 6'b000110: data_had_receive[9] <= MOSI;
  128. 6'b000111: data_had_receive[8] <= MOSI;
  129. 6'b001000: data_had_receive[7] <= MOSI;
  130. 6'b001001: data_had_receive[6] <= MOSI;
  131. 6'b001010: data_had_receive[5] <= MOSI;
  132. 6'b001011: data_had_receive[4] <= MOSI;
  133. 6'b001100: data_had_receive[3] <= MOSI;
  134. 6'b001101: data_had_receive[2] <= MOSI;
  135. 6'b001110: data_had_receive[1] <= MOSI;
  136. 6'b001111: begin data_had_receive[0] <= MOSI; rxd_flag_r<=1'b1;end
  137. /* 6'b010000: data_had_receive[15] <= MOSI;
  138. 6'b010001: data_had_receive[14] <= MOSI;
  139. 6'b010010: data_had_receive[13] <= MOSI;
  140. 6'b010011: data_had_receive[12] <= MOSI;
  141. 6'b010100: data_had_receive[11] <= MOSI;
  142. 6'b010101: data_had_receive[10] <= MOSI;
  143. 6'b010110: data_had_receive[9] <= MOSI;
  144. 6'b010111: data_had_receive[8] <= MOSI;
  145. 6'b011000: data_had_receive[7] <= MOSI;
  146. 6'b011001: data_had_receive[6] <= MOSI;
  147. 6'b011010: data_had_receive[5] <= MOSI;
  148. 6'b011011: data_had_receive[4] <= MOSI;
  149. 6'b011100: data_had_receive[3] <= MOSI;
  150. 6'b011101: data_had_receive[2] <= MOSI;
  151. 6'b011110: data_had_receive[1] <= MOSI;
  152. 6'b011111: data_had_receive[0] <= MOSI; */
  153. endcase
  154. end
  155. end
  156. end
  157. reg rxd_flag_r0,rxd_flag_r1;
  158. always@(negedge rst_n or posedge clk)
  159. begin
  160. if(!rst_n)
  161. begin
  162. rxd_flag_r0 <= 1'b0;
  163. rxd_flag_r1 <= 1'b0;
  164. end
  165. else
  166. begin
  167. rxd_flag_r0 <= rxd_flag_r;
  168. rxd_flag_r1 <= rxd_flag_r0;
  169. end
  170. end
  171. assign rxd_over = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;
  172. // busy
  173. always@(posedge clk)
  174. begin
  175. case(state)
  176. IDLE: busy <= 0;
  177. TRANS: busy <= 1;
  178. WAIT: busy <= 0;
  179. endcase
  180. end
  181. endmodule

2 寄存器构成ROM模块

  1. module spi_rom
  2. (
  3. rst,
  4. rxd_flag,
  5. reg_addr,
  6. reg_out,
  7. rxd_in_spi
  8. );
  9. input rst,rxd_flag;
  10. input [5:0] reg_addr;
  11. input [15:0] rxd_in_spi;
  12. output reg [7:0] reg_out;
  13. reg [7:0] REG_ROM[31:0];
  14. always@(negedge rst or posedge rxd_flag)
  15. begin
  16. if(!rst)
  17. begin
  18. REG_ROM[0] <= 8'd0;
  19. REG_ROM[1] <= 8'd1;
  20. REG_ROM[2] <= 8'd2;
  21. REG_ROM[3] <= 8'd3;
  22. REG_ROM[4] <= 8'd4;
  23. REG_ROM[5] <= 8'd5;
  24. REG_ROM[6] <= 8'd6;
  25. REG_ROM[7] <= 8'd7;
  26. REG_ROM[8] <= 8'd8;
  27. REG_ROM[9] <= 8'd9;
  28. REG_ROM[10] <= 8'd10;
  29. REG_ROM[11] <= 8'd11;
  30. REG_ROM[12] <= 8'd12;
  31. REG_ROM[13] <= 8'd13;
  32. REG_ROM[14] <= 8'd14;
  33. REG_ROM[15] <= 8'd15;
  34. REG_ROM[16] <= 8'd16;
  35. REG_ROM[17] <= 8'd17;
  36. REG_ROM[18] <= 8'd18;
  37. REG_ROM[19] <= 8'd19;
  38. REG_ROM[20] <= 8'd20;
  39. REG_ROM[21] <= 8'd21;
  40. REG_ROM[22] <= 8'd22;
  41. REG_ROM[23] <= 8'd23;
  42. REG_ROM[24] <= 8'd24;
  43. REG_ROM[25] <= 8'd25;
  44. REG_ROM[26] <= 8'd26;
  45. REG_ROM[27] <= 8'd27;
  46. REG_ROM[28] <= 8'd28;
  47. REG_ROM[29] <= 8'd29;
  48. REG_ROM[30] <= 8'd30;
  49. REG_ROM[31] <= 8'd31;
  50. end
  51. else
  52. begin
  53. if(rxd_in_spi[15]==1'b1)
  54. REG_ROM[rxd_in_spi[14:10]] = rxd_in_spi[7:0];
  55. end
  56. end
  57. always@(reg_addr)
  58. begin
  59. if(reg_addr[5]==0)
  60. reg_out=REG_ROM[reg_addr[4:0]];
  61. else reg_out=8'd0; //if write and next byte will tx 8'b0
  62. end
  63. /* always@(posedge rxd_flag)
  64. begin
  65. if(rxd_in_spi[15]==1'b1)
  66. REG_ROM[rxd_in_spi[14:10]] = rxd_in_spi[7:0];
  67. end */
  68. endmodule

3 顶层模块

  1. module TEST_MODULE
  2. (
  3. clk,
  4. rst,
  5. cs,
  6. sck,
  7. MOSI,
  8. MISO,
  9. led_pin,
  10. rxd_over
  11. );
  12. input clk,rst,cs,sck,MOSI;
  13. output MISO,led_pin,rxd_over;
  14. wire rxd_flag;
  15. wire [5:0] rom_addr;
  16. wire [7:0] reg_out;
  17. wire [15:0]rxd_in_spi;
  18. wire spi_busy;
  19. wire rxd_over;
  20. wire [7:0] dat_to_out;
  21. //always@(posedge clk)
  22. //begin
  23. // if(!spi_busy)
  24. // dat_to_out[15:8] <= 8'd255;
  25. //end
  26. LED_module LED_module_inst
  27. (
  28. .clk(clk),
  29. .rst(rst),
  30. .led_pin(led_pin)
  31. );
  32. spi_slave16bit(
  33. .clk(clk),
  34. .rst_n(rst),
  35. .CS(cs),
  36. .SCK(sck),
  37. .MOSI(MOSI),
  38. .MISO(MISO),
  39. .rom_addr(rom_addr),
  40. .busy(spi_busy),//spi给fpga其他模块,busy=1时,禁止FPGA读写
  41. .data_to_out({8'hff,dat_to_out}),//first byte TX 0hff
  42. .data_had_receive(rxd_in_spi),
  43. .rxd_over(rxd_over)
  44. );
  45. spi_rom spi_rom_inst
  46. (
  47. .rst(rst),
  48. .rxd_flag(rxd_over),
  49. .reg_addr(rom_addr),
  50. .reg_out(dat_to_out),
  51. .rxd_in_spi(rxd_in_spi)
  52. );
  53. endmodule

SMT32部分

1 头文件及部分定义 

  1. #define SPI_CS PGout(7)
  2. #define SPI_MISO PBin(4)
  3. #define SPI_MOSI PBout(5)
  4. #define SPI_CLK PBout(3)
  5. void soft_spi_ioinit(void);
  6. u8 get_cmd(u8 wr,u8 addr);
  7. u8 spi_read2byte(u8 reg_addr);
  8. u8 spi_write2byte(u8 reg_addr,u8 dat);

2 函数声明部分

  1. void soft_spi_ioinit()
  2. {
  3. GPIO_InitTypeDef GPIO_InitStructure;
  4. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);//ʹÄÜGPIOB,GʱÖÓ
  5. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //CS
  6. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//ÆÕͨÊä³öģʽ
  7. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//ÍÆÍìÊä³ö
  8. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;//100MHz
  9. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//ÉÏÀ­
  10. GPIO_Init(GPIOG, &GPIO_InitStructure);//³õʼ»¯PG6,7
  11. SPI_CS=1; //SPIƬѡȡÏû
  12. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//ʹÄÜGPIOAʱÖÓ
  13. //GPIOFB3,5³õʼ»¯ÉèÖÃ
  14. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_5;//PB3~5¸´Óù¦ÄÜÊä³ö
  15. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//¸´Óù¦ÄÜ
  16. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//ÍÆÍìÊä³ö
  17. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;//100MHz
  18. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//ÉÏÀ­
  19. GPIO_Init(GPIOB, &GPIO_InitStructure);//³õʼ»¯
  20. SPI_CLK = 1;
  21. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;//PB3~5¸´Óù¦ÄÜÊä³ö
  22. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//ÆÕͨÊäÈëģʽ
  23. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;//100M
  24. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//ÉÏÀ­
  25. GPIO_Init(GPIOB, &GPIO_InitStructure);//³õʼ»¯
  26. }
  27. u8 get_cmd(u8 wr,u8 addr)//wr=1:w wr=0:r addr:0-31
  28. {
  29. u8 reg=0;
  30. //if(wr) reg = 128;
  31. reg = wr;
  32. reg = reg<<5;
  33. reg = reg+addr;
  34. reg =reg<<2;
  35. return reg;
  36. };
  37. u8 spi_read2byte(u8 reg_addr) //reg_addr:0-31
  38. {
  39. u32 tmp=0;
  40. u8 i=0;
  41. u8 addr;
  42. SPI_CS = 1;
  43. SPI_CLK = 1;
  44. SPI_CS = 0;
  45. addr = get_cmd(0,reg_addr);
  46. delay_us(1);
  47. for(i=0;i<8;i++)
  48. {
  49. SPI_CLK = 1;
  50. if(addr&0x80)SPI_MOSI = 1;
  51. else SPI_MOSI = 0;
  52. addr = addr<<1;
  53. delay_us(1);
  54. SPI_CLK = 0;
  55. delay_us(1);
  56. SPI_CLK = 1;
  57. tmp =tmp<<1;
  58. tmp = tmp+SPI_MISO;
  59. }
  60. delay_us(2);
  61. for(i=0;i<8;i++)
  62. {
  63. SPI_CLK = 1;
  64. SPI_MOSI = 1;
  65. delay_us(1);
  66. SPI_CLK = 0;
  67. delay_us(1);
  68. SPI_CLK = 1;
  69. tmp =tmp<<1;
  70. tmp = tmp+SPI_MISO;
  71. }
  72. SPI_CLK = 1;
  73. SPI_CS = 1;
  74. return tmp&0x00ff;
  75. }
  76. u8 spi_write2byte(u8 reg_addr,u8 dat)
  77. {
  78. u32 tmp=0;
  79. int i=0;
  80. u8 addr;
  81. u8 dat_buff = dat;
  82. SPI_CS = 1;
  83. SPI_CLK = 1;
  84. SPI_CS = 0;
  85. delay_us(1);
  86. addr = get_cmd(1,reg_addr);
  87. for(i=0;i<8;i++)
  88. {
  89. SPI_CLK = 1;
  90. if(addr&0x80)SPI_MOSI = 1;
  91. else SPI_MOSI = 0;
  92. addr = addr<<1;
  93. delay_us(1);
  94. SPI_CLK = 0;
  95. delay_us(1);
  96. SPI_CLK = 1;
  97. tmp =tmp<<1;
  98. tmp = tmp+SPI_MISO;
  99. }
  100. delay_us(2);
  101. for(i=0;i<8;i++)
  102. {
  103. SPI_CLK = 1;
  104. if(dat_buff&0x80)SPI_MOSI = 1;
  105. else SPI_MOSI = 0;
  106. dat_buff = dat_buff<<1;
  107. delay_us(1);
  108. SPI_CLK = 0;
  109. delay_us(1);
  110. SPI_CLK = 1;
  111. tmp =tmp<<1;
  112. tmp = tmp+SPI_MISO;
  113. }
  114. SPI_CLK = 1;
  115. SPI_CS = 1;
  116. return tmp&0x00ff;
  117. }

3 主函数

  1. int main(void)
  2. {
  3. u8 key,mode;
  4. u8 t=0;
  5. u32 error_num=0;
  6. u32 read_num=0;
  7. u32 rec=0;
  8. u8 tmp_buf[33];
  9. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//ÉèÖÃϵͳÖжÏÓÅÏȼ¶·Ö×é2
  10. delay_init(168); //³õʼ»¯ÑÓʱº¯Êý
  11. uart_init(115200); //³õʼ»¯´®¿Ú²¨ÌØÂÊΪ115200
  12. LED_Init(); //³õʼ»¯LED
  13. // LCD_Init(); //LCD³õʼ»¯
  14. // KEY_Init(); //°´¼ü³õʼ»¯
  15. // NRF24L01_Init(); //³õʼ»¯NRF24L01
  16. soft_spi_ioinit();
  17. //NRF24L01_Read_Reg(reg);
  18. while(1)
  19. {
  20. for(t=0;t<32;t++)
  21. {
  22. //key = get_reg(0,t);
  23. key = rand()%100;
  24. spi_write2byte(t,key);
  25. rec = spi_read2byte(t);
  26. if(rec!=key)
  27. {
  28. error_num++;
  29. printf("error_num = %d\r\n",error_num);
  30. }
  31. read_num++;
  32. if(read_num%100==0)
  33. {
  34. printf("error_num = %d\r\n",error_num);
  35. }
  36. printf("send = %d rec_num = %d read_num = %d\r\n",key,rec,read_num);
  37. rec = 0;
  38. //if(key==5)
  39. //else printf("key = %d ERROR\r\n",key);
  40. delay_ms(100);
  41. }
  42. t++;
  43. }
  44. }

运行结果

读写上万次无错误

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/509822
推荐阅读
相关标签
  

闽ICP备14008679号