系统结构如图所示。

PS将网络传输进来的参数通过BRAM传递到PL;
PL将AD采样数据通过DMA传输到PS,PS收到中断后通过LWIP发送到上位机。
PL驱动8路ADS8681进行数据采样,每路AD可独立配置采样率以及是否使能。
采样模式有连续采样、触发采样;触发方式有内触发、外触发;触发延时有正延时、负延时可设。
8路数据传输采用依次轮训的方式,按包长度大小将每路数据分别发送。


- // conv.v
- `timescale 1ns / 1ps
- //
-
- //
-
-
- //
-
- module conv (
- input rst_n ,
- input clk_200M_in ,
- input [31:0] fre_word_i ,
- input fre_word_valid_i,
-
- output ad_conv_o
- );
-
- reg [31:0] fre_word_ff ;
- reg [32:0] fre_word_add_ff ;
- wire fre_add_cout ;
- reg high_fre_ff ;
- reg high_fre_ff_d1 ;
- wire high_fre_up ;
- reg ad_conv_ff ;
- reg [7:0] ad_conv_div_cnt ;
-
- assign ad_conv_o = ad_conv_ff ;
-
- always @ ( posedge clk_200M_in or negedge rst_n ) begin
- if(!rst_n) begin
- fre_word_ff <= 32'hFFFFFFFF; //默认1MHz采样率
- end
- else if(fre_word_valid_i) begin
- fre_word_ff <= fre_word_i[31:0]; //采样率参数计算公式=4294.96*freq(Hz)
- end
- else begin
- fre_word_ff <= fre_word_ff ;
- end
- end
-
- always @ (posedge clk_200M_in or negedge rst_n) begin//loop add
- if(!rst_n) begin
- fre_word_add_ff <= 33'h1ffffffff;
- end
- else begin
- fre_word_add_ff <= fre_word_ff[31:0] + fre_word_add_ff[31:0];
- end
- end
-
- assign fre_add_cout = fre_word_add_ff[32];//cout
-
- always @ (posedge clk_200M_in or negedge rst_n) begin//2_div
- if(!rst_n) begin
- high_fre_ff <= 1'b0;
- end
- else if(fre_add_cout) begin
- high_fre_ff <= !high_fre_ff;
- end
- else begin
- high_fre_ff <= high_fre_ff;
- end
- end
- //div 100/
- always @ (posedge clk_200M_in ) begin
- high_fre_ff_d1 <= high_fre_ff;
- end
- assign high_fre_up = high_fre_ff & ! high_fre_ff_d1;
- always @ (posedge clk_200M_in or negedge rst_n) begin
- if(!rst_n) begin
- ad_conv_ff <= 1'b0;
- ad_conv_div_cnt <= 8'd0;
- end
- else if(high_fre_up) begin
- if(ad_conv_div_cnt == 8'd19) begin//100
- ad_conv_div_cnt <= 8'd0;
- ad_conv_ff <= !ad_conv_ff;
- end
- else begin
- ad_conv_div_cnt <= ad_conv_div_cnt + 1'b1;
- ad_conv_ff <= ad_conv_ff;
- end
- end
- else begin
- ad_conv_div_cnt <= ad_conv_div_cnt;
- ad_conv_ff <= ad_conv_ff;
- end
- end
-
- endmodule
-
-
- `timescale 1ns/1ps
- module tx_data_gen#(
- parameter TCP_TX_LENTH = 16'd1024
- )(
- input clk_i ,
- input rst_n ,
-
- input ch1_tx_start_i ,
- input [15:0] ch1_tx_data_i ,
- input ch1_tx_dvalid_i ,
- output reg ch1_rd_req_o ,
-
- input ch2_tx_start_i ,
- input [15:0] ch2_tx_data_i ,
- input ch2_tx_dvalid_i ,
- output reg ch2_rd_req_o ,
-
- input ch3_tx_start_i ,
- input [15:0] ch3_tx_data_i ,
- input ch3_tx_dvalid_i ,
- output reg ch3_rd_req_o ,
-
- input ch4_tx_start_i ,
- input [15:0] ch4_tx_data_i ,
- input ch4_tx_dvalid_i ,
- output reg ch4_rd_req_o ,
-
- input ch5_tx_start_i ,
- input [15:0] ch5_tx_data_i ,
- input ch5_tx_dvalid_i ,
- output reg ch5_rd_req_o ,
-
- input ch6_tx_start_i ,
- input [15:0] ch6_tx_data_i ,
- input ch6_tx_dvalid_i ,
- output reg ch6_rd_req_o ,
-
- input ch7_tx_start_i ,
- input [15:0] ch7_tx_data_i ,
- input ch7_tx_dvalid_i ,
- output reg ch7_rd_req_o ,
-
- input ch8_tx_start_i ,
- input [15:0] ch8_tx_data_i ,
- input ch8_tx_dvalid_i ,
- output reg ch8_rd_req_o ,
-
- input tcp_tx_busy_i ,
- output reg[15:0] tx_data_o ,
- output reg tx_dvalid_o
- );
- localparam TX_IDLE = 0 ,
- TX_CH1 = 1 ,
- TX_CH1_D = 2 ,
- TX_CH2 = 3 ,
- TX_CH2_D = 4 ,
- TX_CH3 = 5 ,
- TX_CH3_D = 6 ,
- TX_CH4 = 7 ,
- TX_CH4_D = 8 ,
- TX_CH5 = 9 ,
- TX_CH5_D = 10 ,
- TX_CH6 = 11 ,
- TX_CH6_D = 12 ,
- TX_CH7 = 13 ,
- TX_CH7_D = 14 ,
- TX_CH8 = 15 ,
- TX_CH8_D = 16 ,
- TX_DONE = 17 ;
-
- reg [17:0] cur_s ;
- reg [17:0] next_s ;
- reg ch1_tx_en ;
- reg ch2_tx_en ;
- reg ch3_tx_en ;
- reg ch4_tx_en ;
- reg ch5_tx_en ;
- reg ch6_tx_en ;
- reg ch7_tx_en ;
- reg ch8_tx_en ;
- reg tx_data_done;
- reg [15:0] tx_data_cnt ;
-
- always @ (posedge clk_i) begin
- if (!rst_n) begin
- ch1_tx_en <= 1'b0 ;
- end
- else if (ch1_tx_start_i == 1'b1) begin
- ch1_tx_en <= 1'b1 ;
- end
- else if (cur_s[TX_CH1_D]) begin
- ch1_tx_en <= 1'b0 ;
- end
- end
-
-
- always @ (posedge clk_i) begin
- if (!rst_n) begin
- ch2_tx_en <= 1'b0 ;
- end
- else if (ch2_tx_start_i == 1'b1) begin
- ch2_tx_en <= 1'b1 ;
- end
- else if (cur_s[TX_CH2_D]) begin
- ch2_tx_en <= 1'b0 ;
- end
- end
-
- always @ (posedge clk_i) begin
- if (!rst_n) begin
- ch3_tx_en <= 1'b0 ;
- end
- else if (ch3_tx_start_i == 1'b1) begin
- ch3_tx_en <= 1'b1 ;
- end
- else if (cur_s[TX_CH3_D]) begin
- ch3_tx_en <= 1'b0 ;
- end
- end
-
- always @ (posedge clk_i) begin
- if (!rst_n) begin
- ch4_tx_en <= 1'b0 ;
- end
- else if (ch4_tx_start_i == 1'b1) begin
- ch4_tx_en <= 1'b1 ;
- end
- else if (cur_s[TX_CH4_D]) begin
- ch4_tx_en <= 1'b0 ;
- end
- end
-
- always @ (posedge clk_i) begin
- if (!rst_n) begin
- ch5_tx_en <= 1'b0 ;
- end
- else if (ch5_tx_start_i == 1'b1) begin
- ch5_tx_en <= 1'b1 ;
- end
- else if (cur_s[TX_CH5_D]) begin
- ch5_tx_en <= 1'b0 ;
- end
- end
-
- always @ (posedge clk_i) begin
- if (!rst_n) begin
- ch6_tx_en <= 1'b0 ;
- end
- else if (ch6_tx_start_i == 1'b1) begin
- ch6_tx_en <= 1'b1 ;
- end
- else if (cur_s[TX_CH6_D]) begin
- ch6_tx_en <= 1'b0 ;
- end
- end
-
- always @ (posedge clk_i) begin
- if (!rst_n) begin
- ch7_tx_en <= 1'b0 ;
- end
- else if (ch7_tx_start_i == 1'b1) begin
- ch7_tx_en <= 1'b1 ;
- end
- else if (cur_s[TX_CH7_D]) begin
- ch7_tx_en <= 1'b0 ;
- end
- end
-
- always @ (posedge clk_i) begin
- if (!rst_n) begin
- ch8_tx_en <= 1'b0 ;
- end
- else if (ch8_tx_start_i == 1'b1) begin
- ch8_tx_en <= 1'b1 ;
- end
- else if (cur_s[TX_CH8_D]) begin
- ch8_tx_en <= 1'b0 ;
- end
- end
-
-
- always @ (posedge clk_i) begin
- if (!rst_n) begin
- cur_s <= 'd0 ;
- cur_s[TX_IDLE] <= 1'b1 ;
- end
- else begin
- cur_s <= next_s ;
- end
- end
-
- always @ ( * ) begin
- next_s = 'd0 ;
- case(1'b1)
- cur_s[TX_IDLE] : begin
- if (!tcp_tx_busy_i) begin
- next_s[TX_CH1] = 1'b1 ;
- end
- else begin
- next_s[TX_IDLE] = 1'b1 ;
- end
- end
- cur_s[TX_CH1] : begin
- if ((!tcp_tx_busy_i) && (ch1_tx_en == 1'b1)) begin
- next_s[TX_CH1_D] = 1'b1 ;
- end
- else if ((!tcp_tx_busy_i) && (ch1_tx_en == 1'b0)) begin
- next_s[TX_CH2] = 1'b1 ;
- end
- else begin
- next_s[TX_CH1] = 1'b1 ;
- end
- end
- cur_s[TX_CH1_D] : begin
- if (tx_data_done) begin
- next_s[TX_CH2] = 1'b1 ;
- end
- else begin
- next_s[TX_CH1_D] = 1'b1 ;
- end
- end
- cur_s[TX_CH2] : begin
- if ((!tcp_tx_busy_i) && (ch2_tx_en == 1'b1)) begin
- next_s[TX_CH2_D] = 1'b1 ;
- end
- else if ((!tcp_tx_busy_i) && (ch2_tx_en == 1'b0)) begin
- next_s[TX_CH3] = 1'b1 ;
- end
- else begin
- next_s[TX_CH2] = 1'b1 ;
- end
- end
- cur_s[TX_CH2_D] : begin
- if (tx_data_done) begin
- next_s[TX_CH3] = 1'b1 ;
- end
- else begin
- next_s[TX_CH2_D] = 1'b1 ;
- end
- end
- cur_s[TX_CH3] : begin
- if ((!tcp_tx_busy_i) && (ch3_tx_en == 1'b1)) begin
- next_s[TX_CH3_D] = 1'b1 ;
- end
- else if ((!tcp_tx_busy_i) && (ch3_tx_en == 1'b0)) begin
- next_s[TX_CH4] = 1'b1 ;
- end
- else begin
- next_s[TX_CH3] = 1'b1 ;
- end
- end
- cur_s[TX_CH3_D] : begin
- if (tx_data_done) begin
- next_s[TX_CH4] = 1'b1 ;
- end
- else begin
- next_s[TX_CH3_D] = 1'b1 ;
- end
- end
- cur_s[TX_CH4] : begin
- if ((!tcp_tx_busy_i) && (ch4_tx_en == 1'b1)) begin
- next_s[TX_CH4_D] = 1'b1 ;
- end
- else if ((!tcp_tx_busy_i) && (ch4_tx_en == 1'b0)) begin
- next_s[TX_CH5] = 1'b1 ;
- end
- else begin
- next_s[TX_CH4] = 1'b1 ;
- end
- end
- cur_s[TX_CH4_D] : begin
- if (tx_data_done) begin
- next_s[TX_CH5] = 1'b1 ;
- end
- else begin
- next_s[TX_CH4_D] = 1'b1 ;
- end
- end
- cur_s[TX_CH5] : begin
- if ((!tcp_tx_busy_i) && (ch5_tx_en == 1'b1)) begin
- next_s[TX_CH5_D] = 1'b1 ;
- end
- else if ((!tcp_tx_busy_i) && (ch5_tx_en == 1'b0)) begin
- next_s[TX_CH6] = 1'b1 ;
- end
- else begin
- next_s[TX_CH5] = 1'b1 ;
- end
- end
- cur_s[TX_CH5_D] : begin
- if (tx_data_done) begin
- next_s[TX_CH6] = 1'b1 ;
- end
- else begin
- next_s[TX_CH5_D] = 1'b1 ;
- end
- end
- cur_s[TX_CH6] : begin
- if ((!tcp_tx_busy_i) && (ch6_tx_en == 1'b1)) begin
- next_s[TX_CH6_D] = 1'b1 ;
- end
- else if ((!tcp_tx_busy_i) && (ch6_tx_en == 1'b0)) begin
- next_s[TX_CH7] = 1'b1 ;
- end
- else begin
- next_s[TX_CH6] = 1'b1 ;
- end
- end
- cur_s[TX_CH6_D] : begin
- if (tx_data_done) begin
- next_s[TX_CH7] = 1'b1 ;
- end
- else begin
- next_s[TX_CH6_D] = 1'b1 ;
- end
- end
- cur_s[TX_CH7] : begin
- if ((!tcp_tx_busy_i) && (ch7_tx_en == 1'b1)) begin
- next_s[TX_CH7_D] = 1'b1 ;
- end
- else if ((!tcp_tx_busy_i) && (ch7_tx_en == 1'b0)) begin
- next_s[TX_CH8] = 1'b1 ;
- end
- else begin
- next_s[TX_CH7] = 1'b1 ;
- end
- end
- cur_s[TX_CH7_D] : begin
- if (tx_data_done) begin
- next_s[TX_CH8] = 1'b1 ;
- end
- else begin
- next_s[TX_CH7_D] = 1'b1 ;
- end
- end
- cur_s[TX_CH8] : begin
- if ((!tcp_tx_busy_i) && (ch8_tx_en == 1'b1)) begin
- next_s[TX_CH8_D] = 1'b1 ;
- end
- else if ((!tcp_tx_busy_i) && (ch8_tx_en == 1'b0)) begin
- next_s[TX_DONE] = 1'b1 ;
- end
- else begin
- next_s[TX_CH8] = 1'b1 ;
- end
- end
- cur_s[TX_CH8_D] : begin
- if (tx_data_done) begin
- next_s[TX_DONE] = 1'b1 ;
- end
- else begin
- next_s[TX_CH8_D] = 1'b1 ;
- end
- end
- cur_s[TX_DONE] : begin
- if (!tcp_tx_busy_i) begin
- next_s[TX_IDLE] = 1'b1 ;
- end
- else begin
- next_s[TX_DONE] = 1'b1 ;
- end
- end
- default : next_s[TX_IDLE] = 1'b1 ;
- endcase
- end
-
- always @ (posedge clk_i) begin
- if (!rst_n) begin
- tx_data_cnt <= 16'd0 ;
- end
- else begin
- ch1_rd_req_o <= 1'b0 ;
- ch2_rd_req_o <= 1'b0 ;
- ch3_rd_req_o <= 1'b0 ;
- ch4_rd_req_o <= 1'b0 ;
- ch5_rd_req_o <= 1'b0 ;
- ch6_rd_req_o <= 1'b0 ;
- ch7_rd_req_o <= 1'b0 ;
- ch8_rd_req_o <= 1'b0 ;
- case(1'b1)
- next_s[TX_CH1_D] : begin
- if (tx_data_cnt < TCP_TX_LENTH - 1 ) begin
- if (ch1_tx_dvalid_i) begin
- tx_data_cnt <= tx_data_cnt + 1'b1 ;
- end
- else begin
- tx_data_cnt <= tx_data_cnt ;
- end
- ch1_rd_req_o <= 1'b1 ;
- end
- else begin
- tx_data_cnt <= tx_data_cnt ;
- end
- end
- next_s[TX_CH2_D] : begin
- if (tx_data_cnt < TCP_TX_LENTH - 1 ) begin
- if (ch2_tx_dvalid_i) begin
- tx_data_cnt <= tx_data_cnt + 1'b1 ;
- end
- else begin
- tx_data_cnt <= tx_data_cnt ;
- end
- ch2_rd_req_o <= 1'b1 ;
- end
- else begin
- tx_data_cnt <= tx_data_cnt ;
- end
- end
- next_s[TX_CH3_D] : begin
- if (tx_data_cnt < TCP_TX_LENTH - 1 ) begin
- if (ch3_tx_dvalid_i) begin
- tx_data_cnt <= tx_data_cnt + 1'b1 ;
- end
- else begin
- tx_data_cnt <= tx_data_cnt ;
- end
- ch3_rd_req_o <= 1'b1 ;
- end
- else begin
- tx_data_cnt <= tx_data_cnt ;
- end
- end
- next_s[TX_CH4_D] : begin
- if (tx_data_cnt < TCP_TX_LENTH - 1 ) begin
- if (ch4_tx_dvalid_i) begin
- tx_data_cnt <= tx_data_cnt + 1'b1 ;
- end
- else begin
- tx_data_cnt <= tx_data_cnt ;
- end
- ch4_rd_req_o <= 1'b1 ;
- end
- else begin
- tx_data_cnt <= tx_data_cnt ;
- end
- end
- next_s[TX_CH5_D] : begin
- if (tx_data_cnt < TCP_TX_LENTH - 1 ) begin
- if (ch5_tx_dvalid_i) begin
- tx_data_cnt <= tx_data_cnt + 1'b1 ;
- end
- else begin
- tx_data_cnt <= tx_data_cnt ;
- end
- ch5_rd_req_o <= 1'b1 ;
- end
- else begin
- tx_data_cnt <= tx_data_cnt ;
- end
- end
- next_s[TX_CH6_D] : begin
- if (tx_data_cnt < TCP_TX_LENTH - 1 ) begin
- if (ch6_tx_dvalid_i) begin
- tx_data_cnt <= tx_data_cnt + 1'b1 ;
- end
- else begin
- tx_data_cnt <= tx_data_cnt ;
- end
- ch6_rd_req_o <= 1'b1 ;
- end
- else begin
- tx_data_cnt <= tx_data_cnt ;
- end
- end
- next_s[TX_CH7_D] : begin
- if (tx_data_cnt < TCP_TX_LENTH - 1 ) begin
- if (ch7_tx_dvalid_i) begin
- tx_data_cnt <= tx_data_cnt + 1'b1 ;
- end
- else begin
- tx_data_cnt <= tx_data_cnt ;
- end
- ch7_rd_req_o <= 1'b1 ;
- end
- else begin
- tx_data_cnt <= tx_data_cnt ;
- end
- end
- next_s[TX_CH8_D] : begin
- if (tx_data_cnt < TCP_TX_LENTH - 1 ) begin
- if (ch8_tx_dvalid_i) begin
- tx_data_cnt <= tx_data_cnt + 1'b1 ;
- end
- else begin
- tx_data_cnt <= tx_data_cnt ;
- end
- ch8_rd_req_o <= 1'b1 ;
- end
- else begin
- tx_data_cnt <= tx_data_cnt ;
- end
- end
- default : tx_data_cnt <= 16'd0 ;
- endcase
- end
- end
-
- always @ (posedge clk_i) begin
- if (!rst_n) begin
- tx_data_done <= 1'b0 ;
- end
- else if (tx_data_cnt == TCP_TX_LENTH - 1) begin
- tx_data_done <= 1'b1 ;
- end
- else begin
- tx_data_done <= 1'b0 ;
- end
- end
-
- always @ (posedge clk_i) begin
- if (!rst_n) begin
- tx_data_o <= 16'd0 ;
- tx_dvalid_o <= 1'b0 ;
- end
- else if (cur_s[TX_CH1_D]) begin
- tx_data_o <= ch1_tx_data_i ;
- tx_dvalid_o <= ch1_tx_dvalid_i ;
- end
- else if (cur_s[TX_CH2_D]) begin
- tx_data_o <= ch2_tx_data_i ;
- tx_dvalid_o <= ch2_tx_dvalid_i ;
- end
- else if (cur_s[TX_CH3_D]) begin
- tx_data_o <= ch3_tx_data_i ;
- tx_dvalid_o <= ch3_tx_dvalid_i ;
- end
- else if (cur_s[TX_CH4_D]) begin
- tx_data_o <= ch4_tx_data_i ;
- tx_dvalid_o <= ch4_tx_dvalid_i ;
- end
- else if (cur_s[TX_CH5_D]) begin
- tx_data_o <= ch5_tx_data_i ;
- tx_dvalid_o <= ch5_tx_dvalid_i ;
- end
- else if (cur_s[TX_CH6_D]) begin
- tx_data_o <= ch6_tx_data_i ;
- tx_dvalid_o <= ch6_tx_dvalid_i ;
- end
- else if (cur_s[TX_CH7_D]) begin
- tx_data_o <= ch7_tx_data_i ;
- tx_dvalid_o <= ch7_tx_dvalid_i ;
- end
- else if (cur_s[TX_CH8_D]) begin
- tx_data_o <= ch8_tx_data_i ;
- tx_dvalid_o <= ch8_tx_dvalid_i ;
- end
- else begin
- tx_data_o <= 16'd0 ;
- tx_dvalid_o <= 1'b0 ;
- end
- end
-
-
-
- endmodule
- `timescale 1ns / 1ps
- //
- // Company:
- // Engineer:
- //
- // Create Date: 2023/03/10 11:25:16
- // Design Name:
- // Module Name: data_gen
- // Project Name:
- // Target Devices:
- // Tool Versions:
- // Description:
- //
- // Dependencies:
- //
- // Revision:
- // Revision 0.01 - File Created
- // Additional Comments:
- //
- //
-
-
- module dma_data_gen(
- input pl_clk ,
- input ps_clk ,
- input rst_n ,
- input gpio_en ,
- input dma_fifo_wr_en ,
- input [15:0] dma_fifo_din ,
- output dma_fifo_afull ,
-
- input S_AXIS_tready ,
- output S_AXIS_tvalid ,
- output S_AXIS_tlast ,
- output [15:0] S_AXIS_tdata ,
- output [1:0] S_AXIS_tkeep ,
- output [1:0] debug_state
- );
- reg S_AXIS_tvalid ;
- reg S_AXIS_tlast ;
- reg [15:0] S_AXIS_tdata ;
- reg [2:0] state ;
-
- reg dma_fifo_rd_en ;
- wire [15:0] dma_fifo_dout ;
- wire dma_fifo_dvalid ;
- wire dma_fifo_full ;
- wire dma_fifo_empty ;
- wire dma_fifo_pfull ;
- reg [15:0] dma_data_cnt ;
-
- reg rst_n_ff1 ;
- reg rst_n_ff2 ;
- reg rst_n_ff3 ;
-
- assign S_AXIS_tkeep = 2'b11;
- assign debug_state = state[1:0] ;
- dma_fifo udma_fifo (
- .rst (!rst_n ),// input wire rst
- .wr_clk (pl_clk ),// input wire wr_clk
- .rd_clk (ps_clk ),// input wire rd_clk
- .din (dma_fifo_din ),// input wire [15 : 0] din
- .wr_en (dma_fifo_wr_en ),// input wire wr_en
- .rd_en (dma_fifo_rd_en ),// input wire rd_en
- .dout (dma_fifo_dout ),// output wire [15 : 0] dout
- .full (dma_fifo_full ),// output wire full
- .almost_full(dma_fifo_afull ),// output wire almost_full
- .empty (dma_fifo_empty ),// output wire empty
- .valid (dma_fifo_dvalid),// output wire valid
- .prog_full (dma_fifo_pfull ) // output wire prog_full
- );
- always @ (posedge ps_clk) begin
- rst_n_ff1 <= rst_n ;
- rst_n_ff2 <= rst_n_ff1 ;
- rst_n_ff3 <= rst_n_ff2 ;
- end
- always@(posedge ps_clk) begin
- if(!rst_n_ff3) begin
- S_AXIS_tvalid <= 1'b0 ;
- S_AXIS_tlast <= 1'b0 ;
- S_AXIS_tdata <= 16'd0;
- dma_fifo_rd_en <= 1'b0 ;
- dma_data_cnt <= 16'd0;
- state <= 0;
- end
- else begin
- case(state) //状态机
- 0: begin
- if (gpio_en) begin
- state <= 1;
- end
- else begin
- state <= 0 ;
- end
- end
- 1: begin
- if(dma_fifo_pfull&&S_AXIS_tready) begin //启动信号到来且FIFO可写
- dma_fifo_rd_en <= 1'b1; //设置读DMA FIFO有效
- state <= 2;
- end
- else begin
- dma_fifo_rd_en <= 1'b0;
- state <= 1;
- end
- end
- 2:begin
- if(S_AXIS_tready) begin //FIFO可写
- if (dma_fifo_dvalid) begin
- dma_data_cnt <= dma_data_cnt + 1'b1 ;
- S_AXIS_tvalid <= 1'b1;
- S_AXIS_tdata <= dma_fifo_dout;
- end
-
- if (dma_data_cnt <= 16'd509) begin
- dma_fifo_rd_en <= 1'b1 ; //设置读DMA FIFO有效
- end
- else begin
- dma_fifo_rd_en <= 1'b0 ; //设置读DMA FIFO有效
- end
-
- if (dma_data_cnt == 16'd511) begin
- state <= 3;
- S_AXIS_tlast <= 1'b1;//发送最后一个数据
- end
- else begin
- state <= 2;
- S_AXIS_tlast <= 1'b0;
- end
- end
- else begin//等待FIFO可写
- dma_fifo_rd_en <= 1'b0;
- S_AXIS_tdata <= S_AXIS_tdata;
- state <= 2;
- end
- end
- 3:begin
- dma_fifo_rd_en <= 1'b0;
- dma_data_cnt <= 16'd0 ;
- if(!S_AXIS_tready) begin //FIFO满则等待
- S_AXIS_tvalid <= 1'b1;
- S_AXIS_tlast <= 1'b1;
- S_AXIS_tdata <= dma_fifo_dout;
- state <= 3;
- end
- else begin //写入结束
- S_AXIS_tvalid <= 1'b0;
- S_AXIS_tlast <= 1'b0;
- S_AXIS_tdata <= 16'd0;
- state <= 0;
- end
- end
- default: state <=0;
- endcase
- end
- end
-
-
- endmodule
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 数据包时,这两个函数往往要同时配合使用。
- void send_dma_data()
-
- {
-
- #if __arm__
-
- int copy = 3;
-
- #else
-
- int copy = 0;
-
- #endif
-
- err_t err;
-
- int Status;
-
- struct tcp_pcb *tpcb = connected_pcb;
-
-
-
-
-
-
-
-
-
- /*initial the first axdma transmission, only excuse once*/
-
- if(!first_trans_start)
-
- {
-
- Status = XAxiDma_SimpleTransfer(&AxiDma, (u32)RxBufferPtr[0],
-
- (u32)(PAKET_LENGTH), XAXIDMA_DEVICE_TO_DMA);
-
- if (Status != XST_SUCCESS)
-
- {
-
- xil_printf("axi dma failed! 0 %d\r\n", Status);
-
- return;
-
- }
-
-
-
- first_trans_start = 1;
-
- }
-
-
-
- /*if the last axidma transmission is done, the interrupt triggered, then start TCP transmission*/
-
- if(packet_trans_done)
-
- {
-
-
-
- if (!connected_pcb)
-
- return;
-
-
-
-
-
- if (tcp_sndbuf(tpcb) > SEND_SIZE)
-
- {
-
-
-
- err = tcp_write(tpcb, RxBufferPtr[packet_index & 1], SEND_SIZE, copy);
-
- if (err != ERR_OK) {
-
- xil_printf("txperf: Error on tcp_write: %d\r\n", err);
-
- connected_pcb = NULL;
-
- return;
-
- }
-
- err = tcp_output(tpcb);
-
- if (err != ERR_OK) {
-
- xil_printf("txperf: Error on tcp_output: %d\r\n",err);
-
- return;
-
- }
-
-
-
- Xil_DCacheFlushRange((u32)RxBufferPtr[(packet_index)&1], (u32)(PAKET_LENGTH)); //刷新Data Cache
-
-
-
- packet_index++;
-
-
-
- packet_trans_done = 0;
-
-
-
-
-
- Status = XAxiDma_SimpleTransfer(&AxiDma, (u32)RxBufferPtr[(packet_index)&1],
-
- (u32)(PAKET_LENGTH), XAXIDMA_DEVICE_TO_DMA);
-
- if (Status != XST_SUCCESS)
-
- {
-
- xil_printf("axi dma %d failed! %d \r\n", (packet_index), Status);
-
- return;
-
- }
-
-
-
-
-
- }
-
- }
-
- }
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 机,并不断循环该过程
本系统中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, 仅作发送完成数据包的计数。