系统结构如图所示。
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, 仅作发送完成数据包的计数。