• ZYNQ多通道数据采集与LWIP传输系统


    Zynq数据采集系统

    • 一、系统设计

    系统结构如图所示。

    PS将网络传输进来的参数通过BRAM传递到PL;

    PL将AD采样数据通过DMA传输到PS,PS收到中断后通过LWIP发送到上位机。

    PL驱动8路ADS8681进行数据采样,每路AD可独立配置采样率以及是否使能。

    采样模式有连续采样、触发采样;触发方式有内触发、外触发;触发延时有正延时、负延时可设。

    8路数据传输采用依次轮训的方式,按包长度大小将每路数据分别发送。

    • 二、Block Design

    • 三、PL端设计

    • 1.conv模块实现采样率配置,根据上位机配置下来的频率控制字生成相应频率的转换信号,来控制AD的采样。

    1. // conv.v
    2. `timescale 1ns / 1ps
    3. //
    4. //
    5. //
    6. module conv (
    7. input rst_n ,
    8. input clk_200M_in ,
    9. input [31:0] fre_word_i ,
    10. input fre_word_valid_i,
    11. output ad_conv_o
    12. );
    13. reg [31:0] fre_word_ff ;
    14. reg [32:0] fre_word_add_ff ;
    15. wire fre_add_cout ;
    16. reg high_fre_ff ;
    17. reg high_fre_ff_d1 ;
    18. wire high_fre_up ;
    19. reg ad_conv_ff ;
    20. reg [7:0] ad_conv_div_cnt ;
    21. assign ad_conv_o = ad_conv_ff ;
    22. always @ ( posedge clk_200M_in or negedge rst_n ) begin
    23. if(!rst_n) begin
    24. fre_word_ff <= 32'hFFFFFFFF; //默认1MHz采样率
    25. end
    26. else if(fre_word_valid_i) begin
    27. fre_word_ff <= fre_word_i[31:0]; //采样率参数计算公式=4294.96*freq(Hz)
    28. end
    29. else begin
    30. fre_word_ff <= fre_word_ff ;
    31. end
    32. end
    33. always @ (posedge clk_200M_in or negedge rst_n) begin//loop add
    34. if(!rst_n) begin
    35. fre_word_add_ff <= 33'h1ffffffff;
    36. end
    37. else begin
    38. fre_word_add_ff <= fre_word_ff[31:0] + fre_word_add_ff[31:0];
    39. end
    40. end
    41. assign fre_add_cout = fre_word_add_ff[32];//cout
    42. always @ (posedge clk_200M_in or negedge rst_n) begin//2_div
    43. if(!rst_n) begin
    44. high_fre_ff <= 1'b0;
    45. end
    46. else if(fre_add_cout) begin
    47. high_fre_ff <= !high_fre_ff;
    48. end
    49. else begin
    50. high_fre_ff <= high_fre_ff;
    51. end
    52. end
    53. //div 100/
    54. always @ (posedge clk_200M_in ) begin
    55. high_fre_ff_d1 <= high_fre_ff;
    56. end
    57. assign high_fre_up = high_fre_ff & ! high_fre_ff_d1;
    58. always @ (posedge clk_200M_in or negedge rst_n) begin
    59. if(!rst_n) begin
    60. ad_conv_ff <= 1'b0;
    61. ad_conv_div_cnt <= 8'd0;
    62. end
    63. else if(high_fre_up) begin
    64. if(ad_conv_div_cnt == 8'd19) begin//100
    65. ad_conv_div_cnt <= 8'd0;
    66. ad_conv_ff <= !ad_conv_ff;
    67. end
    68. else begin
    69. ad_conv_div_cnt <= ad_conv_div_cnt + 1'b1;
    70. ad_conv_ff <= ad_conv_ff;
    71. end
    72. end
    73. else begin
    74. ad_conv_div_cnt <= ad_conv_div_cnt;
    75. ad_conv_ff <= ad_conv_ff;
    76. end
    77. end
    78. endmodule
    • 2.Tx_data_gen模块实现8路数据的轮训,依次判断第1路到第8路AD是否完成包长度的采样,并将完成的数据写入DMA控制器,发送到PS。

    1. `timescale 1ns/1ps
    2. module tx_data_gen#(
    3. parameter TCP_TX_LENTH = 16'd1024
    4. )(
    5. input clk_i ,
    6. input rst_n ,
    7. input ch1_tx_start_i ,
    8. input [15:0] ch1_tx_data_i ,
    9. input ch1_tx_dvalid_i ,
    10. output reg ch1_rd_req_o ,
    11. input ch2_tx_start_i ,
    12. input [15:0] ch2_tx_data_i ,
    13. input ch2_tx_dvalid_i ,
    14. output reg ch2_rd_req_o ,
    15. input ch3_tx_start_i ,
    16. input [15:0] ch3_tx_data_i ,
    17. input ch3_tx_dvalid_i ,
    18. output reg ch3_rd_req_o ,
    19. input ch4_tx_start_i ,
    20. input [15:0] ch4_tx_data_i ,
    21. input ch4_tx_dvalid_i ,
    22. output reg ch4_rd_req_o ,
    23. input ch5_tx_start_i ,
    24. input [15:0] ch5_tx_data_i ,
    25. input ch5_tx_dvalid_i ,
    26. output reg ch5_rd_req_o ,
    27. input ch6_tx_start_i ,
    28. input [15:0] ch6_tx_data_i ,
    29. input ch6_tx_dvalid_i ,
    30. output reg ch6_rd_req_o ,
    31. input ch7_tx_start_i ,
    32. input [15:0] ch7_tx_data_i ,
    33. input ch7_tx_dvalid_i ,
    34. output reg ch7_rd_req_o ,
    35. input ch8_tx_start_i ,
    36. input [15:0] ch8_tx_data_i ,
    37. input ch8_tx_dvalid_i ,
    38. output reg ch8_rd_req_o ,
    39. input tcp_tx_busy_i ,
    40. output reg[15:0] tx_data_o ,
    41. output reg tx_dvalid_o
    42. );
    43. localparam TX_IDLE = 0 ,
    44. TX_CH1 = 1 ,
    45. TX_CH1_D = 2 ,
    46. TX_CH2 = 3 ,
    47. TX_CH2_D = 4 ,
    48. TX_CH3 = 5 ,
    49. TX_CH3_D = 6 ,
    50. TX_CH4 = 7 ,
    51. TX_CH4_D = 8 ,
    52. TX_CH5 = 9 ,
    53. TX_CH5_D = 10 ,
    54. TX_CH6 = 11 ,
    55. TX_CH6_D = 12 ,
    56. TX_CH7 = 13 ,
    57. TX_CH7_D = 14 ,
    58. TX_CH8 = 15 ,
    59. TX_CH8_D = 16 ,
    60. TX_DONE = 17 ;
    61. reg [17:0] cur_s ;
    62. reg [17:0] next_s ;
    63. reg ch1_tx_en ;
    64. reg ch2_tx_en ;
    65. reg ch3_tx_en ;
    66. reg ch4_tx_en ;
    67. reg ch5_tx_en ;
    68. reg ch6_tx_en ;
    69. reg ch7_tx_en ;
    70. reg ch8_tx_en ;
    71. reg tx_data_done;
    72. reg [15:0] tx_data_cnt ;
    73. always @ (posedge clk_i) begin
    74. if (!rst_n) begin
    75. ch1_tx_en <= 1'b0 ;
    76. end
    77. else if (ch1_tx_start_i == 1'b1) begin
    78. ch1_tx_en <= 1'b1 ;
    79. end
    80. else if (cur_s[TX_CH1_D]) begin
    81. ch1_tx_en <= 1'b0 ;
    82. end
    83. end
    84. always @ (posedge clk_i) begin
    85. if (!rst_n) begin
    86. ch2_tx_en <= 1'b0 ;
    87. end
    88. else if (ch2_tx_start_i == 1'b1) begin
    89. ch2_tx_en <= 1'b1 ;
    90. end
    91. else if (cur_s[TX_CH2_D]) begin
    92. ch2_tx_en <= 1'b0 ;
    93. end
    94. end
    95. always @ (posedge clk_i) begin
    96. if (!rst_n) begin
    97. ch3_tx_en <= 1'b0 ;
    98. end
    99. else if (ch3_tx_start_i == 1'b1) begin
    100. ch3_tx_en <= 1'b1 ;
    101. end
    102. else if (cur_s[TX_CH3_D]) begin
    103. ch3_tx_en <= 1'b0 ;
    104. end
    105. end
    106. always @ (posedge clk_i) begin
    107. if (!rst_n) begin
    108. ch4_tx_en <= 1'b0 ;
    109. end
    110. else if (ch4_tx_start_i == 1'b1) begin
    111. ch4_tx_en <= 1'b1 ;
    112. end
    113. else if (cur_s[TX_CH4_D]) begin
    114. ch4_tx_en <= 1'b0 ;
    115. end
    116. end
    117. always @ (posedge clk_i) begin
    118. if (!rst_n) begin
    119. ch5_tx_en <= 1'b0 ;
    120. end
    121. else if (ch5_tx_start_i == 1'b1) begin
    122. ch5_tx_en <= 1'b1 ;
    123. end
    124. else if (cur_s[TX_CH5_D]) begin
    125. ch5_tx_en <= 1'b0 ;
    126. end
    127. end
    128. always @ (posedge clk_i) begin
    129. if (!rst_n) begin
    130. ch6_tx_en <= 1'b0 ;
    131. end
    132. else if (ch6_tx_start_i == 1'b1) begin
    133. ch6_tx_en <= 1'b1 ;
    134. end
    135. else if (cur_s[TX_CH6_D]) begin
    136. ch6_tx_en <= 1'b0 ;
    137. end
    138. end
    139. always @ (posedge clk_i) begin
    140. if (!rst_n) begin
    141. ch7_tx_en <= 1'b0 ;
    142. end
    143. else if (ch7_tx_start_i == 1'b1) begin
    144. ch7_tx_en <= 1'b1 ;
    145. end
    146. else if (cur_s[TX_CH7_D]) begin
    147. ch7_tx_en <= 1'b0 ;
    148. end
    149. end
    150. always @ (posedge clk_i) begin
    151. if (!rst_n) begin
    152. ch8_tx_en <= 1'b0 ;
    153. end
    154. else if (ch8_tx_start_i == 1'b1) begin
    155. ch8_tx_en <= 1'b1 ;
    156. end
    157. else if (cur_s[TX_CH8_D]) begin
    158. ch8_tx_en <= 1'b0 ;
    159. end
    160. end
    161. always @ (posedge clk_i) begin
    162. if (!rst_n) begin
    163. cur_s <= 'd0 ;
    164. cur_s[TX_IDLE] <= 1'b1 ;
    165. end
    166. else begin
    167. cur_s <= next_s ;
    168. end
    169. end
    170. always @ ( * ) begin
    171. next_s = 'd0 ;
    172. case(1'b1)
    173. cur_s[TX_IDLE] : begin
    174. if (!tcp_tx_busy_i) begin
    175. next_s[TX_CH1] = 1'b1 ;
    176. end
    177. else begin
    178. next_s[TX_IDLE] = 1'b1 ;
    179. end
    180. end
    181. cur_s[TX_CH1] : begin
    182. if ((!tcp_tx_busy_i) && (ch1_tx_en == 1'b1)) begin
    183. next_s[TX_CH1_D] = 1'b1 ;
    184. end
    185. else if ((!tcp_tx_busy_i) && (ch1_tx_en == 1'b0)) begin
    186. next_s[TX_CH2] = 1'b1 ;
    187. end
    188. else begin
    189. next_s[TX_CH1] = 1'b1 ;
    190. end
    191. end
    192. cur_s[TX_CH1_D] : begin
    193. if (tx_data_done) begin
    194. next_s[TX_CH2] = 1'b1 ;
    195. end
    196. else begin
    197. next_s[TX_CH1_D] = 1'b1 ;
    198. end
    199. end
    200. cur_s[TX_CH2] : begin
    201. if ((!tcp_tx_busy_i) && (ch2_tx_en == 1'b1)) begin
    202. next_s[TX_CH2_D] = 1'b1 ;
    203. end
    204. else if ((!tcp_tx_busy_i) && (ch2_tx_en == 1'b0)) begin
    205. next_s[TX_CH3] = 1'b1 ;
    206. end
    207. else begin
    208. next_s[TX_CH2] = 1'b1 ;
    209. end
    210. end
    211. cur_s[TX_CH2_D] : begin
    212. if (tx_data_done) begin
    213. next_s[TX_CH3] = 1'b1 ;
    214. end
    215. else begin
    216. next_s[TX_CH2_D] = 1'b1 ;
    217. end
    218. end
    219. cur_s[TX_CH3] : begin
    220. if ((!tcp_tx_busy_i) && (ch3_tx_en == 1'b1)) begin
    221. next_s[TX_CH3_D] = 1'b1 ;
    222. end
    223. else if ((!tcp_tx_busy_i) && (ch3_tx_en == 1'b0)) begin
    224. next_s[TX_CH4] = 1'b1 ;
    225. end
    226. else begin
    227. next_s[TX_CH3] = 1'b1 ;
    228. end
    229. end
    230. cur_s[TX_CH3_D] : begin
    231. if (tx_data_done) begin
    232. next_s[TX_CH4] = 1'b1 ;
    233. end
    234. else begin
    235. next_s[TX_CH3_D] = 1'b1 ;
    236. end
    237. end
    238. cur_s[TX_CH4] : begin
    239. if ((!tcp_tx_busy_i) && (ch4_tx_en == 1'b1)) begin
    240. next_s[TX_CH4_D] = 1'b1 ;
    241. end
    242. else if ((!tcp_tx_busy_i) && (ch4_tx_en == 1'b0)) begin
    243. next_s[TX_CH5] = 1'b1 ;
    244. end
    245. else begin
    246. next_s[TX_CH4] = 1'b1 ;
    247. end
    248. end
    249. cur_s[TX_CH4_D] : begin
    250. if (tx_data_done) begin
    251. next_s[TX_CH5] = 1'b1 ;
    252. end
    253. else begin
    254. next_s[TX_CH4_D] = 1'b1 ;
    255. end
    256. end
    257. cur_s[TX_CH5] : begin
    258. if ((!tcp_tx_busy_i) && (ch5_tx_en == 1'b1)) begin
    259. next_s[TX_CH5_D] = 1'b1 ;
    260. end
    261. else if ((!tcp_tx_busy_i) && (ch5_tx_en == 1'b0)) begin
    262. next_s[TX_CH6] = 1'b1 ;
    263. end
    264. else begin
    265. next_s[TX_CH5] = 1'b1 ;
    266. end
    267. end
    268. cur_s[TX_CH5_D] : begin
    269. if (tx_data_done) begin
    270. next_s[TX_CH6] = 1'b1 ;
    271. end
    272. else begin
    273. next_s[TX_CH5_D] = 1'b1 ;
    274. end
    275. end
    276. cur_s[TX_CH6] : begin
    277. if ((!tcp_tx_busy_i) && (ch6_tx_en == 1'b1)) begin
    278. next_s[TX_CH6_D] = 1'b1 ;
    279. end
    280. else if ((!tcp_tx_busy_i) && (ch6_tx_en == 1'b0)) begin
    281. next_s[TX_CH7] = 1'b1 ;
    282. end
    283. else begin
    284. next_s[TX_CH6] = 1'b1 ;
    285. end
    286. end
    287. cur_s[TX_CH6_D] : begin
    288. if (tx_data_done) begin
    289. next_s[TX_CH7] = 1'b1 ;
    290. end
    291. else begin
    292. next_s[TX_CH6_D] = 1'b1 ;
    293. end
    294. end
    295. cur_s[TX_CH7] : begin
    296. if ((!tcp_tx_busy_i) && (ch7_tx_en == 1'b1)) begin
    297. next_s[TX_CH7_D] = 1'b1 ;
    298. end
    299. else if ((!tcp_tx_busy_i) && (ch7_tx_en == 1'b0)) begin
    300. next_s[TX_CH8] = 1'b1 ;
    301. end
    302. else begin
    303. next_s[TX_CH7] = 1'b1 ;
    304. end
    305. end
    306. cur_s[TX_CH7_D] : begin
    307. if (tx_data_done) begin
    308. next_s[TX_CH8] = 1'b1 ;
    309. end
    310. else begin
    311. next_s[TX_CH7_D] = 1'b1 ;
    312. end
    313. end
    314. cur_s[TX_CH8] : begin
    315. if ((!tcp_tx_busy_i) && (ch8_tx_en == 1'b1)) begin
    316. next_s[TX_CH8_D] = 1'b1 ;
    317. end
    318. else if ((!tcp_tx_busy_i) && (ch8_tx_en == 1'b0)) begin
    319. next_s[TX_DONE] = 1'b1 ;
    320. end
    321. else begin
    322. next_s[TX_CH8] = 1'b1 ;
    323. end
    324. end
    325. cur_s[TX_CH8_D] : begin
    326. if (tx_data_done) begin
    327. next_s[TX_DONE] = 1'b1 ;
    328. end
    329. else begin
    330. next_s[TX_CH8_D] = 1'b1 ;
    331. end
    332. end
    333. cur_s[TX_DONE] : begin
    334. if (!tcp_tx_busy_i) begin
    335. next_s[TX_IDLE] = 1'b1 ;
    336. end
    337. else begin
    338. next_s[TX_DONE] = 1'b1 ;
    339. end
    340. end
    341. default : next_s[TX_IDLE] = 1'b1 ;
    342. endcase
    343. end
    344. always @ (posedge clk_i) begin
    345. if (!rst_n) begin
    346. tx_data_cnt <= 16'd0 ;
    347. end
    348. else begin
    349. ch1_rd_req_o <= 1'b0 ;
    350. ch2_rd_req_o <= 1'b0 ;
    351. ch3_rd_req_o <= 1'b0 ;
    352. ch4_rd_req_o <= 1'b0 ;
    353. ch5_rd_req_o <= 1'b0 ;
    354. ch6_rd_req_o <= 1'b0 ;
    355. ch7_rd_req_o <= 1'b0 ;
    356. ch8_rd_req_o <= 1'b0 ;
    357. case(1'b1)
    358. next_s[TX_CH1_D] : begin
    359. if (tx_data_cnt < TCP_TX_LENTH - 1 ) begin
    360. if (ch1_tx_dvalid_i) begin
    361. tx_data_cnt <= tx_data_cnt + 1'b1 ;
    362. end
    363. else begin
    364. tx_data_cnt <= tx_data_cnt ;
    365. end
    366. ch1_rd_req_o <= 1'b1 ;
    367. end
    368. else begin
    369. tx_data_cnt <= tx_data_cnt ;
    370. end
    371. end
    372. next_s[TX_CH2_D] : begin
    373. if (tx_data_cnt < TCP_TX_LENTH - 1 ) begin
    374. if (ch2_tx_dvalid_i) begin
    375. tx_data_cnt <= tx_data_cnt + 1'b1 ;
    376. end
    377. else begin
    378. tx_data_cnt <= tx_data_cnt ;
    379. end
    380. ch2_rd_req_o <= 1'b1 ;
    381. end
    382. else begin
    383. tx_data_cnt <= tx_data_cnt ;
    384. end
    385. end
    386. next_s[TX_CH3_D] : begin
    387. if (tx_data_cnt < TCP_TX_LENTH - 1 ) begin
    388. if (ch3_tx_dvalid_i) begin
    389. tx_data_cnt <= tx_data_cnt + 1'b1 ;
    390. end
    391. else begin
    392. tx_data_cnt <= tx_data_cnt ;
    393. end
    394. ch3_rd_req_o <= 1'b1 ;
    395. end
    396. else begin
    397. tx_data_cnt <= tx_data_cnt ;
    398. end
    399. end
    400. next_s[TX_CH4_D] : begin
    401. if (tx_data_cnt < TCP_TX_LENTH - 1 ) begin
    402. if (ch4_tx_dvalid_i) begin
    403. tx_data_cnt <= tx_data_cnt + 1'b1 ;
    404. end
    405. else begin
    406. tx_data_cnt <= tx_data_cnt ;
    407. end
    408. ch4_rd_req_o <= 1'b1 ;
    409. end
    410. else begin
    411. tx_data_cnt <= tx_data_cnt ;
    412. end
    413. end
    414. next_s[TX_CH5_D] : begin
    415. if (tx_data_cnt < TCP_TX_LENTH - 1 ) begin
    416. if (ch5_tx_dvalid_i) begin
    417. tx_data_cnt <= tx_data_cnt + 1'b1 ;
    418. end
    419. else begin
    420. tx_data_cnt <= tx_data_cnt ;
    421. end
    422. ch5_rd_req_o <= 1'b1 ;
    423. end
    424. else begin
    425. tx_data_cnt <= tx_data_cnt ;
    426. end
    427. end
    428. next_s[TX_CH6_D] : begin
    429. if (tx_data_cnt < TCP_TX_LENTH - 1 ) begin
    430. if (ch6_tx_dvalid_i) begin
    431. tx_data_cnt <= tx_data_cnt + 1'b1 ;
    432. end
    433. else begin
    434. tx_data_cnt <= tx_data_cnt ;
    435. end
    436. ch6_rd_req_o <= 1'b1 ;
    437. end
    438. else begin
    439. tx_data_cnt <= tx_data_cnt ;
    440. end
    441. end
    442. next_s[TX_CH7_D] : begin
    443. if (tx_data_cnt < TCP_TX_LENTH - 1 ) begin
    444. if (ch7_tx_dvalid_i) begin
    445. tx_data_cnt <= tx_data_cnt + 1'b1 ;
    446. end
    447. else begin
    448. tx_data_cnt <= tx_data_cnt ;
    449. end
    450. ch7_rd_req_o <= 1'b1 ;
    451. end
    452. else begin
    453. tx_data_cnt <= tx_data_cnt ;
    454. end
    455. end
    456. next_s[TX_CH8_D] : begin
    457. if (tx_data_cnt < TCP_TX_LENTH - 1 ) begin
    458. if (ch8_tx_dvalid_i) begin
    459. tx_data_cnt <= tx_data_cnt + 1'b1 ;
    460. end
    461. else begin
    462. tx_data_cnt <= tx_data_cnt ;
    463. end
    464. ch8_rd_req_o <= 1'b1 ;
    465. end
    466. else begin
    467. tx_data_cnt <= tx_data_cnt ;
    468. end
    469. end
    470. default : tx_data_cnt <= 16'd0 ;
    471. endcase
    472. end
    473. end
    474. always @ (posedge clk_i) begin
    475. if (!rst_n) begin
    476. tx_data_done <= 1'b0 ;
    477. end
    478. else if (tx_data_cnt == TCP_TX_LENTH - 1) begin
    479. tx_data_done <= 1'b1 ;
    480. end
    481. else begin
    482. tx_data_done <= 1'b0 ;
    483. end
    484. end
    485. always @ (posedge clk_i) begin
    486. if (!rst_n) begin
    487. tx_data_o <= 16'd0 ;
    488. tx_dvalid_o <= 1'b0 ;
    489. end
    490. else if (cur_s[TX_CH1_D]) begin
    491. tx_data_o <= ch1_tx_data_i ;
    492. tx_dvalid_o <= ch1_tx_dvalid_i ;
    493. end
    494. else if (cur_s[TX_CH2_D]) begin
    495. tx_data_o <= ch2_tx_data_i ;
    496. tx_dvalid_o <= ch2_tx_dvalid_i ;
    497. end
    498. else if (cur_s[TX_CH3_D]) begin
    499. tx_data_o <= ch3_tx_data_i ;
    500. tx_dvalid_o <= ch3_tx_dvalid_i ;
    501. end
    502. else if (cur_s[TX_CH4_D]) begin
    503. tx_data_o <= ch4_tx_data_i ;
    504. tx_dvalid_o <= ch4_tx_dvalid_i ;
    505. end
    506. else if (cur_s[TX_CH5_D]) begin
    507. tx_data_o <= ch5_tx_data_i ;
    508. tx_dvalid_o <= ch5_tx_dvalid_i ;
    509. end
    510. else if (cur_s[TX_CH6_D]) begin
    511. tx_data_o <= ch6_tx_data_i ;
    512. tx_dvalid_o <= ch6_tx_dvalid_i ;
    513. end
    514. else if (cur_s[TX_CH7_D]) begin
    515. tx_data_o <= ch7_tx_data_i ;
    516. tx_dvalid_o <= ch7_tx_dvalid_i ;
    517. end
    518. else if (cur_s[TX_CH8_D]) begin
    519. tx_data_o <= ch8_tx_data_i ;
    520. tx_dvalid_o <= ch8_tx_dvalid_i ;
    521. end
    522. else begin
    523. tx_data_o <= 16'd0 ;
    524. tx_dvalid_o <= 1'b0 ;
    525. end
    526. end
    527. endmodule
    • 3.Dma_data_gen模块实现控制DMA的数据写入。

    1. `timescale 1ns / 1ps
    2. //
    3. // Company:
    4. // Engineer:
    5. //
    6. // Create Date: 2023/03/10 11:25:16
    7. // Design Name:
    8. // Module Name: data_gen
    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 dma_data_gen(
    22. input pl_clk ,
    23. input ps_clk ,
    24. input rst_n ,
    25. input gpio_en ,
    26. input dma_fifo_wr_en ,
    27. input [15:0] dma_fifo_din ,
    28. output dma_fifo_afull ,
    29. input S_AXIS_tready ,
    30. output S_AXIS_tvalid ,
    31. output S_AXIS_tlast ,
    32. output [15:0] S_AXIS_tdata ,
    33. output [1:0] S_AXIS_tkeep ,
    34. output [1:0] debug_state
    35. );
    36. reg S_AXIS_tvalid ;
    37. reg S_AXIS_tlast ;
    38. reg [15:0] S_AXIS_tdata ;
    39. reg [2:0] state ;
    40. reg dma_fifo_rd_en ;
    41. wire [15:0] dma_fifo_dout ;
    42. wire dma_fifo_dvalid ;
    43. wire dma_fifo_full ;
    44. wire dma_fifo_empty ;
    45. wire dma_fifo_pfull ;
    46. reg [15:0] dma_data_cnt ;
    47. reg rst_n_ff1 ;
    48. reg rst_n_ff2 ;
    49. reg rst_n_ff3 ;
    50. assign S_AXIS_tkeep = 2'b11;
    51. assign debug_state = state[1:0] ;
    52. dma_fifo udma_fifo (
    53. .rst (!rst_n ),// input wire rst
    54. .wr_clk (pl_clk ),// input wire wr_clk
    55. .rd_clk (ps_clk ),// input wire rd_clk
    56. .din (dma_fifo_din ),// input wire [15 : 0] din
    57. .wr_en (dma_fifo_wr_en ),// input wire wr_en
    58. .rd_en (dma_fifo_rd_en ),// input wire rd_en
    59. .dout (dma_fifo_dout ),// output wire [15 : 0] dout
    60. .full (dma_fifo_full ),// output wire full
    61. .almost_full(dma_fifo_afull ),// output wire almost_full
    62. .empty (dma_fifo_empty ),// output wire empty
    63. .valid (dma_fifo_dvalid),// output wire valid
    64. .prog_full (dma_fifo_pfull ) // output wire prog_full
    65. );
    66. always @ (posedge ps_clk) begin
    67. rst_n_ff1 <= rst_n ;
    68. rst_n_ff2 <= rst_n_ff1 ;
    69. rst_n_ff3 <= rst_n_ff2 ;
    70. end
    71. always@(posedge ps_clk) begin
    72. if(!rst_n_ff3) begin
    73. S_AXIS_tvalid <= 1'b0 ;
    74. S_AXIS_tlast <= 1'b0 ;
    75. S_AXIS_tdata <= 16'd0;
    76. dma_fifo_rd_en <= 1'b0 ;
    77. dma_data_cnt <= 16'd0;
    78. state <= 0;
    79. end
    80. else begin
    81. case(state) //状态机
    82. 0: begin
    83. if (gpio_en) begin
    84. state <= 1;
    85. end
    86. else begin
    87. state <= 0 ;
    88. end
    89. end
    90. 1: begin
    91. if(dma_fifo_pfull&&S_AXIS_tready) begin //启动信号到来且FIFO可写
    92. dma_fifo_rd_en <= 1'b1; //设置读DMA FIFO有效
    93. state <= 2;
    94. end
    95. else begin
    96. dma_fifo_rd_en <= 1'b0;
    97. state <= 1;
    98. end
    99. end
    100. 2:begin
    101. if(S_AXIS_tready) begin //FIFO可写
    102. if (dma_fifo_dvalid) begin
    103. dma_data_cnt <= dma_data_cnt + 1'b1 ;
    104. S_AXIS_tvalid <= 1'b1;
    105. S_AXIS_tdata <= dma_fifo_dout;
    106. end
    107. if (dma_data_cnt <= 16'd509) begin
    108. dma_fifo_rd_en <= 1'b1 ; //设置读DMA FIFO有效
    109. end
    110. else begin
    111. dma_fifo_rd_en <= 1'b0 ; //设置读DMA FIFO有效
    112. end
    113. if (dma_data_cnt == 16'd511) begin
    114. state <= 3;
    115. S_AXIS_tlast <= 1'b1;//发送最后一个数据
    116. end
    117. else begin
    118. state <= 2;
    119. S_AXIS_tlast <= 1'b0;
    120. end
    121. end
    122. else begin//等待FIFO可写
    123. dma_fifo_rd_en <= 1'b0;
    124. S_AXIS_tdata <= S_AXIS_tdata;
    125. state <= 2;
    126. end
    127. end
    128. 3:begin
    129. dma_fifo_rd_en <= 1'b0;
    130. dma_data_cnt <= 16'd0 ;
    131. if(!S_AXIS_tready) begin //FIFO满则等待
    132. S_AXIS_tvalid <= 1'b1;
    133. S_AXIS_tlast <= 1'b1;
    134. S_AXIS_tdata <= dma_fifo_dout;
    135. state <= 3;
    136. end
    137. else begin //写入结束
    138. S_AXIS_tvalid <= 1'b0;
    139. S_AXIS_tlast <= 1'b0;
    140. S_AXIS_tdata <= 16'd0;
    141. state <= 0;
    142. end
    143. end
    144. default: state <=0;
    145. endcase
    146. end
    147. end
    148. endmodule
    • 四、PS端设计

    1.DMA数据发送

    PS 的 dma 数据接收采用了乒乓操作的模式,两个缓冲区交替进行数据接收。XAxiDma_SimpleTransfer 函数中 Length,以字节为单位,每次发起 dma 时,设置的 Length 的值必须大于或等于 PL 实际传输的数据长度,否则会出现错误。本例程中设置的长度 为 1024字节。first_trans_start 是为了进行第一次先进行一次 DMA 中断传输,这样完成后设置 first_trans_start 为 0。以 后每次完成网络传输后,再启动 DMA 接受。TCP 数据包的发送主要依赖于 tcp_write 和 tcp_output 两个函数,tcp_write 将所需要发送的数 据写入 tcp 发送缓冲区等待发送,tcp_output 函数则将缓存区内数据包发送出去。在发送 TCP 数据包时,这两个函数往往要同时配合使用。

    1. void send_dma_data()
    2. {
    3. #if __arm__
    4. int copy = 3;
    5. #else
    6. int copy = 0;
    7. #endif
    8. err_t err;
    9. int Status;
    10. struct tcp_pcb *tpcb = connected_pcb;
    11. /*initial the first axdma transmission, only excuse once*/
    12. if(!first_trans_start)
    13. {
    14. Status = XAxiDma_SimpleTransfer(&AxiDma, (u32)RxBufferPtr[0],
    15. (u32)(PAKET_LENGTH), XAXIDMA_DEVICE_TO_DMA);
    16. if (Status != XST_SUCCESS)
    17. {
    18. xil_printf("axi dma failed! 0 %d\r\n", Status);
    19. return;
    20. }
    21. first_trans_start = 1;
    22. }
    23. /*if the last axidma transmission is done, the interrupt triggered, then start TCP transmission*/
    24. if(packet_trans_done)
    25. {
    26. if (!connected_pcb)
    27. return;
    28. if (tcp_sndbuf(tpcb) > SEND_SIZE)
    29. {
    30. err = tcp_write(tpcb, RxBufferPtr[packet_index & 1], SEND_SIZE, copy);
    31. if (err != ERR_OK) {
    32. xil_printf("txperf: Error on tcp_write: %d\r\n", err);
    33. connected_pcb = NULL;
    34. return;
    35. }
    36. err = tcp_output(tpcb);
    37. if (err != ERR_OK) {
    38. xil_printf("txperf: Error on tcp_output: %d\r\n",err);
    39. return;
    40. }
    41. Xil_DCacheFlushRange((u32)RxBufferPtr[(packet_index)&1], (u32)(PAKET_LENGTH));   //刷新Data Cache
    42. packet_index++;
    43. packet_trans_done = 0;
    44. Status = XAxiDma_SimpleTransfer(&AxiDma, (u32)RxBufferPtr[(packet_index)&1],
    45. (u32)(PAKET_LENGTH), XAXIDMA_DEVICE_TO_DMA);
    46. if (Status != XST_SUCCESS)
    47. {
    48. xil_printf("axi dma %d failed! %d \r\n", (packet_index), Status);
    49. return;
    50. }
    51. }
    52. }
    53. }

    2.main 函数的主要流程:

    1):初始化并配置 PL 侧的 AXI GPIO

    2):初始化并配置 PL 侧的 AXI DMA

    3):初始化并配置 PS 的中断控制器

    4):初始化 lwip 协议栈和 PS 的以太网控制器

    5):配置 TCP 传输所需的相关参数,并与服务器建立 TCP 连接

    6)接收上位机下发的参数,写入BRAM,通知PL读取BRAM数据进行参数解析

    7):通过 AXI GPIO 启动 PL 进行数据生成和传输

    8):通过 AXI DMA 接收 PL 传输的数据,通过 TCP 发送至 PC 机,并不断循环该过程

    • 五、TCP连接

    • 本系统中ZYNQ 作为客户端,PC 作为服务器。由zynq 向PC 主动发起 TCP 连接请求,通过tcp_connect 函数便可以完成这个过程。该函数的参数包含了一个回调函数指针tcp_connected_fn,该回调函数将在TCP 连接请求三次握手完成后被自动调用。该回调函数被调用时代表客户端和服务器之间的TCP 连接建立完 成。在本例程中,该回调函数被定义为 tcp_connected_callback,在该函数中,拉高连接建立完成信号 tcp_client_connected,并通过tcp_sent 函数配置另一个TCP 发送完成的回调函数。该回调函数在每个 TCP 包发送完成后会被自动调用,代表 TCP 包发送完成。该回调函数在本例程中被定义为tcp_sent_callback, 仅作发送完成数据包的计数。

  • 相关阅读:
    Python循环语句实战练习和循环嵌套详解
    知识图谱实体对齐1:基于平移(translation)嵌入的方法
    leetcode48. 旋转图像
    ubuntu18.04安装pcl1.9.1
    Linux如何设置开机自启
    chrome F12 network 保留之前请求信息
    在众多编程语言中,我为什么要学Python?
    Java由浅入深理解线程池设计和原理
    做自媒体影视短视频剪辑号,在哪儿下载素材?
    Java Integer.toHexString()具有什么功能呢?
  • 原文地址:https://blog.csdn.net/Xionq/article/details/132627788