当前位置:   article > 正文

【FPGA开发】关于如何使用FPGA配置AD9528

ad9528

这次工作中接触到了AD9528这个亚诺半导体的时钟发生芯片,可以产生多路同步的时钟。这个时钟使用spi接口进行相应的配置。后面记录自己如何针对这个过程进行相应FPGA代码编写。

AD9528 基本介绍:

 

具体的配置参数及方法:

具体我们在项目中使用了,五路时钟,我们的配置要求如下所示:

官网中有相应的可以下载的上位机软件,可以进行相应的配置,配置之后就可以知道相应的需要配置的寄存器参数是什么。

这个是咨询厂家之后的基本配置方法,具体的配置原理,要详细的阅读datasheet,具体的就是OUT1 OUT2两个时钟需要使用从PLL2 divider中产生的时钟

具体需要配置的寄存器如下:

代码编写及AD9528的spi时序图:

AD9528 原理图:

AD9528时序图:

针对这个时序图,我们就开始展开代码编写了:

Verilog代码实现SPI配置寄存器:

  1. // -----------------------------------------------------------------------------
  2. // Copyright (c) 2014-2023 All rights reserved
  3. // -----------------------------------------------------------------------------
  4. // Author : xibo wu (Gatsby)
  5. // File : spi.v
  6. // Create : 2023-10-25 16:16:08
  7. // Revise : 2023-10-27 13:46:23
  8. // Editor : sublime text3, tab size (4)
  9. // -----------------------------------------------------------------------------
  10. module spi_module
  11. (
  12. input i_clk , // 全局时钟100MHz
  13. input i_rst_n , // 复位信号,低电平有效
  14. // 四线标准SPI信号定义
  15. input i_spi_miso , // SPI串行输入,用来接收从机的数据
  16. output o_spi_sck , // SPI时钟
  17. output o_spi_cs , // SPI片选信号
  18. output o_spi_mosi // SPI输出,用来给从机发送数据
  19. );
  20. //-------parameter--------//
  21. parameter TX_IDLE = 4'b0001;
  22. parameter TX_HEADER = 4'b0010;
  23. parameter TX_PAYLOAD = 4'b0100;
  24. parameter TX_END = 4'b1000;
  25. //-----parameter_reg-------//
  26. //---form “addr_data”------//
  27. parameter REG_1 = 24'h0104_01;
  28. parameter REG_2 = 24'h0100_01;
  29. parameter REG_3 = 24'h0102_01;
  30. parameter REG_4 = 24'h0204_01;
  31. parameter REG_5 = 24'h0201_14;
  32. parameter REG_6 = 24'h010A_02;
  33. parameter REG_7 = 24'h0208_13;
  34. parameter REG_8 = 24'h0501_E0;
  35. parameter REG_9 = 24'h0502_3F;
  36. parameter REG_10 = 24'h0302_11;
  37. parameter REG_11 = 24'h030E_23;
  38. parameter REG_12 = 24'h0303_00;
  39. parameter REG_13 = 24'h0305_05;
  40. parameter REG_14 = 24'h0308_05;
  41. //---------regs-----------//
  42. reg [4:0] tx_bit_sel;
  43. reg wr_en;
  44. reg [3:0] clk_cnt;
  45. reg cs_n_t;
  46. reg sck_t = 1'b0;
  47. reg [4:0] reg_cnt = 5'd14; //此处还不明确后续需要更改
  48. reg mosi_t;
  49. reg [23:0] reg_cfg; //可变的寄存器写入配置数值
  50. //--------debug-----------//
  51. reg [23:0] reg_debug;
  52. reg [3:0] cur_state;
  53. reg [3:0] nxt_state;
  54. reg skip_en;
  55. //-------assign----------//
  56. assign o_spi_sck = sck_t;
  57. assign o_spi_cs = cs_n_t;
  58. assign o_spi_mosi = mosi_t;
  59. //---------debug-----------//
  60. always @(posedge i_clk or negedge i_rst_n) begin
  61. if (i_rst_n == 1'b0) begin
  62. reg_debug <= 24'b0;
  63. end else if(cs_n_t == 1'b0 && clk_cnt == 'd1) begin
  64. reg_debug <= {reg_debug[22:0],mosi_t};
  65. end else begin
  66. reg_debug <= reg_debug;
  67. end
  68. end
  69. //---------main------------//
  70. always @(posedge i_clk or negedge i_rst_n) begin
  71. if (i_rst_n == 1'b0) begin
  72. clk_cnt <= 4'b0;
  73. end else if(clk_cnt == 'd3) begin
  74. clk_cnt <= 'd0;
  75. end else begin
  76. clk_cnt <= clk_cnt + 4'd1;
  77. end
  78. end
  79. //要在sck上升沿之前把数据准备好
  80. always @(posedge i_clk or negedge i_rst_n) begin
  81. if (i_rst_n == 1'b0) begin
  82. wr_en <= 1'b0;
  83. end else if(clk_cnt == 'd2) begin
  84. wr_en <= 1'b1;
  85. end else begin
  86. wr_en <= 1'b0;
  87. end
  88. end
  89. always @(posedge i_clk or negedge i_rst_n) begin
  90. if (i_rst_n == 1'b0) begin
  91. sck_t <= 1'b0;
  92. end else if(clk_cnt == 'd1 && cs_n_t == 1'b0) begin
  93. sck_t <= 1'b1;
  94. end else if(clk_cnt == 'd3 && cs_n_t == 1'b0) begin
  95. sck_t <= 1'b0;
  96. end else begin
  97. sck_t <= sck_t;
  98. end
  99. end
  100. // 寄存器数据配置单元 j
  101. always @(posedge i_clk or posedge i_rst_n) begin
  102. if (i_rst_n == 1'b0) begin
  103. reg_cfg <= REG_1;
  104. end else begin
  105. case(reg_cnt)
  106. 5'd14 : reg_cfg <= REG_1 ;
  107. //中间后续填充相应的寄存器数值
  108. 5'd13 : reg_cfg <= REG_2 ;
  109. 5'd12 : reg_cfg <= REG_3 ;
  110. 5'd11 : reg_cfg <= REG_4 ;
  111. 5'd10 : reg_cfg <= REG_5 ;
  112. 5'd9 : reg_cfg <= REG_6 ;
  113. 5'd8 : reg_cfg <= REG_7 ;
  114. 5'd7 : reg_cfg <= REG_8 ;
  115. 5'd6 : reg_cfg <= REG_9 ;
  116. 5'd5 : reg_cfg <= REG_10;
  117. 5'd4 : reg_cfg <= REG_11;
  118. 5'd3 : reg_cfg <= REG_12;
  119. 5'd2 : reg_cfg <= REG_13;
  120. 5'd1 : reg_cfg <= REG_14;
  121. default:;
  122. endcase
  123. end
  124. end
  125. always @(posedge i_clk or negedge i_rst_n) begin
  126. if (i_rst_n == 1'b0) begin
  127. cur_state <= TX_IDLE;
  128. end else begin
  129. cur_state <= nxt_state;
  130. end
  131. end
  132. always @(*) begin
  133. nxt_state = TX_IDLE;
  134. case (cur_state)
  135. TX_IDLE : begin
  136. if (skip_en) begin
  137. nxt_state = TX_HEADER;
  138. end else begin
  139. nxt_state = TX_IDLE;
  140. end
  141. end
  142. TX_HEADER : begin
  143. if (skip_en) begin
  144. nxt_state = TX_PAYLOAD;
  145. end else begin
  146. nxt_state = TX_HEADER;
  147. end
  148. end
  149. TX_PAYLOAD : begin
  150. if (skip_en) begin
  151. nxt_state = TX_END;
  152. end else begin
  153. nxt_state = TX_PAYLOAD;
  154. end
  155. end
  156. TX_END : begin
  157. if (skip_en) begin
  158. nxt_state = TX_IDLE;
  159. end else begin
  160. nxt_state = TX_END;
  161. end
  162. end
  163. default : nxt_state = TX_IDLE;
  164. endcase
  165. end
  166. always @(posedge i_clk or negedge i_rst_n) begin
  167. if (i_rst_n == 1'b0) begin
  168. skip_en <= 1'b0;
  169. cs_n_t <= 1'b1;
  170. tx_bit_sel <= 5'd0;
  171. end else begin
  172. skip_en <= 1'b0;
  173. case (nxt_state)
  174. TX_IDLE : begin
  175. if(reg_cnt != 'd0) begin
  176. skip_en <= 1'b1;
  177. end else begin
  178. cs_n_t <= 1'b1;
  179. end
  180. end
  181. TX_HEADER : begin
  182. cs_n_t <= 1'b0;
  183. if (wr_en == 1'b1) begin
  184. tx_bit_sel <= tx_bit_sel + 'd1;
  185. cs_n_t <= 1'b0;
  186. case(tx_bit_sel)
  187. 5'd0 : mosi_t <= reg_cfg[23]; //读写位
  188. 5'd1 : mosi_t <= reg_cfg[22]; //空
  189. 5'd2 : mosi_t <= reg_cfg[21]; //空
  190. 5'd3 : mosi_t <= reg_cfg[20]; //addr[12]
  191. 5'd4 : mosi_t <= reg_cfg[19]; //addr[11]
  192. 5'd5 : mosi_t <= reg_cfg[18]; //addr[10]
  193. 5'd6 : mosi_t <= reg_cfg[17]; //addr[9]
  194. 5'd7 : mosi_t <= reg_cfg[16]; //addr[8]
  195. 5'd8 : mosi_t <= reg_cfg[15]; //addr[7]
  196. 5'd9 : mosi_t <= reg_cfg[14]; //addr[6]
  197. 5'd10 : mosi_t <= reg_cfg[13]; //addr[5]
  198. 5'd11 : mosi_t <= reg_cfg[12]; //addr[4]
  199. 5'd12 : mosi_t <= reg_cfg[11]; //addr[3]
  200. 5'd13 : mosi_t <= reg_cfg[10]; //addr[2]
  201. 5'd14 : mosi_t <= reg_cfg[9]; //addr[1]
  202. 5'd15 : begin
  203. mosi_t <= reg_cfg[8]; //addr[0]
  204. tx_bit_sel <= 'd0;
  205. skip_en <= 1'b1;
  206. end
  207. endcase
  208. end
  209. end
  210. TX_PAYLOAD : begin
  211. cs_n_t <= 1'b0;
  212. if (wr_en == 1'b1) begin
  213. tx_bit_sel <= tx_bit_sel + 'd1;
  214. case(tx_bit_sel)
  215. 5'd0 : mosi_t <= reg_cfg[7]; //data[7]
  216. 5'd1 : mosi_t <= reg_cfg[6]; //data[6]
  217. 5'd2 : mosi_t <= reg_cfg[5]; //data[5]
  218. 5'd3 : mosi_t <= reg_cfg[4]; //data[4]
  219. 5'd4 : mosi_t <= reg_cfg[3]; //data[3]
  220. 5'd5 : mosi_t <= reg_cfg[2]; //data[2]
  221. 5'd6 : mosi_t <= reg_cfg[1]; //data[1]
  222. 5'd7 : begin
  223. mosi_t <= reg_cfg[0]; //data[0]
  224. tx_bit_sel <= 'd0;
  225. skip_en <= 1'b1;
  226. end
  227. endcase
  228. end
  229. end
  230. TX_END : begin
  231. if(reg_cnt != 'd0) begin
  232. reg_cnt <= reg_cnt - 1'd1;
  233. skip_en <= 1'b1;
  234. end
  235. end
  236. default :;
  237. endcase
  238. end
  239. end
  240. endmodule

仿真结果如下:

该文章仅用来交流,有错误欢迎各位指正。

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

闽ICP备14008679号