当前位置:   article > 正文

FPGA SPI 驱动程序_fpga spi 程序

fpga spi 程序

1.引言

此驱动程序已经完成很久了,花了2个星期的时间,主要是提升程序运行的效率。最近整理文件的时候又看到了,记录一下。

2.程序框架分解

  1. module adc7254_Ctrl(
  2. input sys_clk, //system clkc 50M
  3. input reset_n, //reset flag
  4. input iData_a_in, //ADC to fpga
  5. input iData_b_in,
  6. output sclk_out, //to ADC
  7. output cs_out, //to ADC
  8. output sdin, //to ADC
  9. output [11:0] oData_a, //get data
  10. output [11:0] oData_b //get data
  11. );
  12. wire clk_200M; //PLL驱动
  13. AD_PLL AD_PLL_inst(
  14. .inclk0(sys_clk),
  15. .c0(Clk_200M),
  16. .c1(sclk_out)
  17. );
  18. wire En_conv,En_send; //定义ADC发送和接收程序的状态切换时间
  19. adc_test adc_test_inst(
  20. .iRst_n(reset_n),
  21. .iDclk(sclk_out),
  22. .iSend_down(Send_down),
  23. .oAdc_rst_n(adc_rst_n),
  24. .oEn_conv(En_conv),
  25. .oEn_send(En_send)
  26. );
  27. wire Send_down; //ADC指令发送部分
  28. adc_in_send adc_in_send_inst
  29. (
  30. .iClk_200M(Clk_200M),
  31. .iRst_n(adc_rst_n),
  32. .iDcLK(sclk_out),
  33. .iEn_send(En_send),
  34. .oSDATA(sdin),
  35. .oSend_down(Send_down)
  36. );
  37. wire Conv_down;
  38. adc_out_conv adc_out_conv_inst //ADC数据采样部分
  39. (
  40. .iClk_200M ( Clk_200M ),
  41. .iRst_n ( adc_rst_n ),
  42. .iEn_conv ( En_conv ),
  43. .iDcLK ( sclk_out ),
  44. .iData_a_in ( iData_a_in ),
  45. .iData_b_in ( iData_b_in ),
  46. .oData_a ( oData_a ),
  47. .oData_b ( oData_b ),
  48. .oConv_down ( Conv_down )
  49. );
  50. assign cs_out = Conv_down & Send_down; //状态完成
  51. endmodule

3.子任务分解

(1)状态控制程序

其主要是以空状态,写状态,读状态三个状态顺序执行的。

  1. module adc_test(
  2. input iRst_n,
  3. input iDclk,
  4. input iSend_down,
  5. output oAdc_rst_n,
  6. output reg oEn_send,
  7. output reg oEn_conv
  8. );
  9. reg [1:0] state;
  10. reg [5:0] sclk_cnt;
  11. localparam state_IDLE = 2'd0;
  12. localparam state_Write = 2'd1;
  13. localparam state_Read = 2'd3;
  14. assign oAdc_rst_n = (iRst_n & state);
  15. always @(posedge iDclk or negedge iRst_n) begin
  16. if(!iRst_n)begin
  17. sclk_cnt <= 6'd0;
  18. state <= state_IDLE;
  19. oEn_conv = 1'd0;
  20. oEn_send = 1'd0;
  21. end else begin
  22. case(state)
  23. state_IDLE:
  24. begin
  25. if (sclk_cnt > 6'd30 ) begin
  26. sclk_cnt <= 6'd0;
  27. state <= state_Write;
  28. oEn_conv = 1'd0;
  29. oEn_send = 1'd1;
  30. end else begin
  31. sclk_cnt <= sclk_cnt + 1'd1;
  32. state <= state_IDLE;
  33. oEn_conv = 1'd0;
  34. oEn_send = 1'd0;
  35. end
  36. end
  37. state_Write:
  38. begin
  39. if (iSend_down == 1'd1 && sclk_cnt > 6'd30 ) begin
  40. sclk_cnt <= 0;
  41. state <= state_Read;
  42. oEn_conv = 1'd1;
  43. oEn_send = 1'd0;
  44. end else begin
  45. sclk_cnt <= sclk_cnt + 1'd1;
  46. state <= state_Write;
  47. oEn_conv = 1'd0;
  48. oEn_send = 1'd1;
  49. end
  50. end
  51. state_Read:
  52. begin
  53. state <= state_Read;
  54. sclk_cnt <= 1'd0;
  55. oEn_conv = 1'd1;
  56. oEn_send = 1'd0;
  57. end
  58. endcase
  59. end
  60. end
  61. endmodule

(2)写命令程序部分

  1. module adc_in_send(
  2. input iClk_200M, //200M
  3. input iRst_n,
  4. input iDcLK, //最小T>60ns
  5. input iEn_send,
  6. output oSDATA,
  7. output oSend_down
  8. );
  9. //==================使能接收标志位en==================//
  10. //一旦启动不会突然停止除非复位信号到来
  11. reg en;
  12. reg [5:0] sclk_cnt;
  13. always @(posedge iDcLK or negedge iRst_n ) begin
  14. if (!iRst_n) begin
  15. en <= 1'd0;
  16. sclk_cnt <= 6'd0;
  17. end else if ( iEn_send == 1'd1 && sclk_cnt == 6'd0 ) begin
  18. en <= 1'd1;
  19. sclk_cnt <= 6'd32;
  20. end else if ( sclk_cnt > 6'd1 ) begin
  21. en <= en;
  22. sclk_cnt <= sclk_cnt - 1'd1;
  23. end else if (oSend_down == 1'd1 && sclk_cnt == 6'd1 ) begin
  24. en <= 1'd0;
  25. sclk_cnt <= sclk_cnt - 1'd1;
  26. end else begin
  27. en <= en;
  28. sclk_cnt <= sclk_cnt;
  29. end
  30. end
  31. //==================使能接收标志位en==================//
  32. //==================SDATA输出操作=========================//
  33. reg [15:0]CFR_16bit_data = 16'h8840; //需要写入寄存器中的数据
  34. assign oSDATA = (en > 1'd0) ? ((sclk_cnt > 6'd17) ? CFR_16bit_data[sclk_cnt-6'd17] : 0 ): 0;
  35. //==================SDATA操作=========================//
  36. //==================oSend_down操作======================//
  37. assign oSend_down = (sclk_cnt > 6'd1) ? 0 : 1;
  38. //==================oSend_down操作======================//
  39. endmodule

(3)读数据程序部分

  1. module adc_out_conv(
  2. input iClk_200M, //200M
  3. input iRst_n,
  4. input iData_a_in,
  5. input iData_b_in,
  6. input iDcLK, //最小T=60ns
  7. input iEn_conv,
  8. output reg [11:0] oData_a,
  9. output reg [11:0] oData_b,
  10. output oConv_down //T>70ns
  11. );
  12. //下降沿接收
  13. //==================使能接收标志位en==================//
  14. //一旦启动不会突然停止除非复位信号到来
  15. reg en;//接收使能标志位
  16. reg [5:0] sclk_cnt;
  17. always @(posedge iDcLK or negedge iRst_n ) begin
  18. if (!iRst_n) begin
  19. en <= 1'd0;
  20. sclk_cnt <= 5'd0;
  21. end else if (iEn_conv == 1'd1 && sclk_cnt == 4'd0) begin
  22. en <= 1'd1;
  23. sclk_cnt <= 6'd17;
  24. end else if (sclk_cnt > 4'd1) begin
  25. en <= en;
  26. sclk_cnt <= sclk_cnt - 1'd1;
  27. end else if (oConv_down == 1'd1 && sclk_cnt == 4'd1)begin
  28. en <= 1'd0;
  29. sclk_cnt <= sclk_cnt - 1'd1;
  30. end else begin
  31. en <= en;
  32. sclk_cnt <= sclk_cnt;
  33. end
  34. end
  35. //==================使能接收标志位en==================//
  36. //==================dclk时钟采样==================//
  37. reg [6:0] dclk;
  38. always@(posedge iClk_200M or negedge iRst_n) begin
  39. if(!iRst_n) begin
  40. dclk <= 7'd0;
  41. end else if(!en) begin
  42. dclk <= 7'd0;
  43. end else begin
  44. dclk <= {dclk[5:0],iDcLK};
  45. end
  46. end
  47. //==================dclk时钟采样==================//
  48. //==================状态切换==================//
  49. reg [1:0] state;
  50. parameter state_IDLE = 2'd0;
  51. parameter state_Read = 2'd1;
  52. parameter state_Write = 2'd2;
  53. always@(posedge iClk_200M or negedge iRst_n) begin
  54. if(!iRst_n ) begin
  55. state <= state_IDLE;
  56. end else if(!en) begin
  57. state <= state_IDLE;
  58. end else if(dclk[1] == 1 & dclk[2] == 0) begin
  59. state <= state_Read;
  60. end else if (dclk[1] == 0 & dclk[2] == 1) begin
  61. state <= state_Write;
  62. end else begin
  63. state <=state;
  64. end
  65. end
  66. //==================状态切换==================//
  67. //==================data串行转并行==================//
  68. reg [2:0] Data_a_in_temp,Data_b_in_temp;//保证7次采样有4次为1
  69. reg [11:0] Data_a_temp,Data_b_temp;
  70. always@(posedge iClk_200M or negedge iRst_n)
  71. begin
  72. if(!iRst_n ) begin
  73. Data_a_temp <= 12'd0;
  74. Data_b_temp <= 12'd0;
  75. Data_a_in_temp <= 3'd0;
  76. Data_b_in_temp <= 3'd0;
  77. end else if(sclk_cnt > 6'd16)begin
  78. Data_a_in_temp <= 3'd0;
  79. Data_b_in_temp <= 3'd0;
  80. Data_a_temp <= 12'd0;
  81. Data_b_temp <= 12'd0;
  82. end else if(sclk_cnt > 6'd3 ) begin
  83. if(state == state_Read && dclk[6] == 0 ) begin
  84. Data_a_in_temp <= Data_a_in_temp + iData_a_in;
  85. Data_b_in_temp <= Data_b_in_temp + iData_b_in;
  86. Data_a_temp <= Data_a_temp;
  87. Data_b_temp <= Data_b_temp;
  88. end else if(state == state_Write && dclk[0]!=dclk[1])begin
  89. Data_a_in_temp <= 3'd0;
  90. Data_b_in_temp <= 3'd0;
  91. Data_a_temp <= {Data_a_temp[10:0],Data_a_in_temp[2]};
  92. Data_b_temp <= {Data_b_temp[10:0],Data_b_in_temp[2]};
  93. end else begin
  94. Data_a_in_temp <= Data_a_in_temp;
  95. Data_b_in_temp <= Data_b_in_temp;
  96. Data_a_temp <= Data_a_temp;
  97. Data_b_temp <= Data_b_temp;
  98. end
  99. end else begin
  100. Data_a_in_temp <= Data_a_in_temp;
  101. Data_b_in_temp <= Data_b_in_temp;
  102. Data_a_temp <= Data_a_temp;
  103. Data_b_temp <= Data_b_temp;
  104. end
  105. end
  106. //==================data串行转并行==================//
  107. //==================oConv_down操作======================//
  108. assign oConv_down = (sclk_cnt > 6'd1) ? 0 : 1;
  109. //==================oConv_down操作======================//
  110. //==================数据按帧输出==================//
  111. always@(posedge iClk_200M or negedge iRst_n)
  112. begin
  113. if(!iRst_n )
  114. begin
  115. oData_a <= 12'd0;
  116. oData_b <= 12'd0;
  117. end
  118. else if( oConv_down == 1'd1)
  119. begin
  120. oData_a <= Data_a_temp;
  121. oData_b <= Data_b_temp;
  122. end
  123. else
  124. begin
  125. oData_a <= oData_a;
  126. oData_b <= oData_b;
  127. end
  128. end
  129. //==================数据按帧输出==================//
  130. endmodule

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

闽ICP备14008679号