0,UDP层协议
源端口号:自身的端口号;
目的端口号:接受方的端口号;
UDP长度:UDP首部+数据的长度;
UDP校验和:与IP校验和算法一致;
1,工程编写(不包含巨帧数据传输)
udp层包含udp_rx,udp_tx,udp_module模块。
module _10g_udp_module
#(
parameter P_SOURCE_PORT = 16'h8080 ,
parameter P_TARGET_PORT = 16'h8080
)
(
input i_clk ,
input i_rst ,
/************** drp *********************/
input [ 15:0] i_dynamic_source_port ,
input i_dynamic_source_valid ,
input [ 15:0] i_dynamic_target_port ,
input i_dynamic_target_valid ,
/************** ip_interface *********************/
output [ 63:0] m_axis_udp2ip_data ,
output [ 55:0] m_axis_udp2ip_user ,//16len + 8type + 16ip + 3mflag + 13offset
output [ 7:0] m_axis_udp2ip_keep ,
output m_axis_udp2ip_last ,
output m_axis_udp2ip_valid ,
input [ 63:0] s_axis_ip2udp_data ,
input [ 55:0] s_axis_ip2udp_user ,//16len + 8type + 16ip + 3mflag + 13offset
input [ 7:0] s_axis_ip2udp_keep ,
input s_axis_ip2udp_last ,
input s_axis_ip2udp_valid ,
/************** user_interface *********************/
input [ 63:0] s_axis_user_data ,
input [ 31:0] s_axis_user_user ,//{16'data_len,16'axi_len} //包含两种len,一种时用于传输的len,一种适用于udp头部中的数据长度len
input [ 7:0] s_axis_user_keep ,
input s_axis_user_last ,
input s_axis_user_valid ,
output s_axis_user_ready ,
output [ 63:0] m_axis_user_data ,
output [ 31:0] m_axis_user_user ,//{16'data_len,16'axi_len} //包含两种len,一种时用于传输的len,一种适用于udp头部中的数据长度len
output [ 7:0] m_axis_user_keep ,
output m_axis_user_last ,
output m_axis_user_valid
);
包含于IP层相连接接的接口,以及于用户端相连接的端口。均使用axi接口实现。
其中在user接口这里, 设定了两种长度,data_len长度,axi_len长度。
- data_len:udp传输的数据的具体长度(以1byte划分);
- axi_len : axi接口数据的长度(以8byte划分),用于axi接口模块中的计数;
[ 31:0] s_axis_user_user ,//{16'data_len,16'axi_len} //包含两种len,一种时用于传输的len,一种适用于udp头部中的数据长度len
其转换如下: 其中last_keep为尾端keep,决定最后一个8byte中有多少数据有效。
assign data_len = last_keep == 8'b1111_1111 ? axi_len*8:
last_keep == 8'b1111_1110 ? (axi_len-1)*8 + 7:
last_keep == 8'b1111_1100 ? (axi_len-1)*8 + 6:
last_keep == 8'b1111_1000 ? (axi_len-1)*8 + 5:
last_keep == 8'b1111_0000 ? (axi_len-1)*8 + 4:
last_keep == 8'b1110_0000 ? (axi_len-1)*8 + 3:
last_keep == 8'b1100_0000 ? (axi_len-1)*8 + 2:
last_keep == 8'b1000_0000 ? (axi_len-1)*8 + 1:
axi_len*8 ;
1.1,udp_rx
接受IP层传递过来的报文 ,提取payload长度,提取payload数据。
传递给用户端口。
module _10g_udp_rx
#(
parameter P_SOURCE_PORT = 16'h8080 ,
parameter P_TARGET_PORT = 16'h8080
)
(
input i_clk ,
input i_rst ,
/************** drp *********************/
input [ 15:0] i_dynamic_source_port ,
input i_dynamic_source_valid ,
input [ 15:0] i_dynamic_target_port ,
input i_dynamic_target_valid ,
/************** ip_interface *********************/
input [ 63:0] s_axis_ip2udp_data ,
input [ 55:0] s_axis_ip2udp_user ,//16len + 8type + 16ip + 3mflag + 13offset
input [ 7:0] s_axis_ip2udp_keep ,
input s_axis_ip2udp_last ,
input s_axis_ip2udp_valid ,
/************** user_interface *********************/
output [ 63:0] m_axis_user_data ,
output [ 31:0] m_axis_user_user ,//{16'data_len,16'axi_len}
output [ 7:0] m_axis_user_keep ,
output m_axis_user_last ,
output m_axis_user_valid
);
仿真波形:
可以看到随着尾部keep的改变,data_len也进行了改变。
user_axi_len相对与ip_axi_len减少了个1,这是因为去除了一个8byte的udp报文头。
多组数据仿真:
测试用例:
#1000;
udp_user_data(16'd30 , 8'b1111_1111);
#100;
udp_user_data(16'd30 , 8'b1111_0000);
1.2,udp_tx
将用户传递的数据进行组帧,添加udp报头,发送给IP层。比较简单
module _10g_udp_tx
#(
parameter P_SOURCE_PORT = 16'h8080 ,
parameter P_TARGET_PORT = 16'h8080
)
(
input i_clk ,
input i_rst ,
/************** drp *********************/
input [ 15:0] i_dynamic_source_port ,
input i_dynamic_source_valid ,
input [ 15:0] i_dynamic_target_port ,
input i_dynamic_target_valid ,
/************** ip_interface *********************/
output [ 63:0] m_axis_udp2ip_data ,
output [ 55:0] m_axis_udp2ip_user ,//16len + 8type + 16ip + 3mflag + 13offset
output [ 7:0] m_axis_udp2ip_keep ,
output m_axis_udp2ip_last ,
output m_axis_udp2ip_valid ,
/************** user_interface *********************/
input [ 63:0] s_axis_user_data ,
input [ 31:0] s_axis_user_user ,//{16'data_len,16'axi_len} //包含两种len,一种时用于传输的len,一种适用于udp头部中的数据长度len
input [ 7:0] s_axis_user_keep ,
input s_axis_user_last ,
input s_axis_user_valid ,
output s_axis_user_ready
);
仿真波形:
ip_axi_len 相对user_axi_len与多了个1,这是因为添加了一个8byte的udp报文头。
多组测试也是没有问题的,数据长度正确
测试用例:
#1000;
udp_user_data(16'd30 , 8'b1111_1111);
#100;
udp_user_data(16'd30 , 8'b1111_0000);
#100;
udp_user_data(16'd40 , 8'b1000_0000);
#100;
udp_user_data(16'd50 , 8'b1100_0000);
1.3,仿真代码,
进行一个回环测试
`timescale 1ns/1ps
/***************** Information **************************/
// Creat_Time : 2024/12/17
// Engineer :
// Tool_Version : Vivado_2020.2
// Device : XCKU060_FFVA1156_2_i
// Function : tb_udp_module
// Edition :
/********************************************************/
module tb_udp_module();
localparam P_SOURCE_PORT = 16'h8080 ;
localparam P_TARGET_PORT = 16'h8080 ;
reg i_clk ;
reg i_rst ;
always begin
i_clk <= 'd0;
#10;
i_clk <= 'd1;
#10;
end
initial begin
i_rst <= 'd1;
#100;
@(posedge i_clk);
i_rst <= 'd0;
end
logic [ 63:0] m_axis_udp2ip_data ;
logic [ 55:0] m_axis_udp2ip_user ;
logic [ 7:0] m_axis_udp2ip_keep ;
logic m_axis_udp2ip_last ;
logic m_axis_udp2ip_valid;
logic [ 63:0] s_axis_ip2udp_data ;
logic [ 55:0] s_axis_ip2udp_user ;
logic [ 7:0] s_axis_ip2udp_keep ;
logic s_axis_ip2udp_last ;
logic s_axis_ip2udp_valid;
logic [ 63:0] s_axis_user_data ;
logic [ 31:0] s_axis_user_user ;
logic [ 7:0] s_axis_user_keep ;
logic s_axis_user_last ;
logic s_axis_user_valid ;
logic s_axis_user_ready ;
logic [ 63:0] m_axis_user_data ;
logic [ 31:0] m_axis_user_user ;
logic [ 7:0] m_axis_user_keep ;
logic m_axis_user_last ;
logic m_axis_user_valid ;
_10g_udp_module
#(
.P_SOURCE_PORT (P_SOURCE_PORT ),
.P_TARGET_PORT (P_TARGET_PORT )
)
_10g_udp_module_inst
(
.i_clk (i_clk ),
.i_rst (i_rst ),
/************** drp *********************/
.i_dynamic_source_port ( ),
.i_dynamic_source_valid ( ),
.i_dynamic_target_port ( ),
.i_dynamic_target_valid ( ),
/************** ip_interface *********************/
.m_axis_udp2ip_data (m_axis_udp2ip_data ),
.m_axis_udp2ip_user (m_axis_udp2ip_user ),//16len + 8type + 16ip + 3mflag + 13offset
.m_axis_udp2ip_keep (m_axis_udp2ip_keep ),
.m_axis_udp2ip_last (m_axis_udp2ip_last ),
.m_axis_udp2ip_valid (m_axis_udp2ip_valid ),
.s_axis_ip2udp_data (m_axis_udp2ip_data ),
.s_axis_ip2udp_user (m_axis_udp2ip_user ),//16len + 8type + 16ip + 3mflag + 13offset
.s_axis_ip2udp_keep (m_axis_udp2ip_keep ),
.s_axis_ip2udp_last (m_axis_udp2ip_last ),
.s_axis_ip2udp_valid (m_axis_udp2ip_valid ),
/************** user_interface *********************/
.s_axis_user_data (s_axis_user_data ),
.s_axis_user_user (s_axis_user_user ),
.s_axis_user_keep (s_axis_user_keep ),
.s_axis_user_last (s_axis_user_last ),
.s_axis_user_valid (s_axis_user_valid ),
.s_axis_user_ready (s_axis_user_ready ),
.m_axis_user_data (m_axis_user_data ),
.m_axis_user_user (m_axis_user_user ),
.m_axis_user_keep (m_axis_user_keep ),
.m_axis_user_last (m_axis_user_last ),
.m_axis_user_valid (m_axis_user_valid )
);
initial begin
s_axis_user_data <= 'd0;
s_axis_user_user <= 'd0;
s_axis_user_keep <= 'd0;
s_axis_user_last <= 'd0;
s_axis_user_valid <= 'd0;
#1000;
udp_user_data(16'd30 , 8'b1111_1111);
#100;
udp_user_data(16'd30 , 8'b1111_0000);
// #100;
// udp_user_data(16'd40 , 8'b1000_0000);
// #100;
// udp_user_data(16'd50 , 8'b1100_0000);
end
task udp_user_data(input [15:0] axi_len , input [7:0] last_keep);
begin:udp_user_data_task
integer i;
logic [15:0] data_len;
s_axis_user_data <= 'd0;
s_axis_user_user <= 'd0;
s_axis_user_keep <= 'd0;
s_axis_user_last <= 'd0;
s_axis_user_valid <= 'd0;
assign data_len = last_keep == 8'b1111_1111 ? axi_len*8:
last_keep == 8'b1111_1110 ? (axi_len-1)*8 + 7:
last_keep == 8'b1111_1100 ? (axi_len-1)*8 + 6:
last_keep == 8'b1111_1000 ? (axi_len-1)*8 + 5:
last_keep == 8'b1111_0000 ? (axi_len-1)*8 + 4:
last_keep == 8'b1110_0000 ? (axi_len-1)*8 + 3:
last_keep == 8'b1100_0000 ? (axi_len-1)*8 + 2:
last_keep == 8'b1000_0000 ? (axi_len-1)*8 + 1:
axi_len*8 ;
wait(s_axis_user_ready );
@(posedge i_clk);
for(i = 0; i < axi_len ; i = i + 1) begin
if(i == axi_len - 1) begin
s_axis_user_data <= s_axis_user_data + 1;
s_axis_user_user <= {data_len ,axi_len};
s_axis_user_keep <= last_keep;
s_axis_user_last <= 'd1;
s_axis_user_valid <= 'd1;
end
else begin
s_axis_user_data <= s_axis_user_data + 1;
s_axis_user_user <= {data_len ,axi_len};
s_axis_user_keep <= 8'b1111_1111;
s_axis_user_last <= 'd0;
s_axis_user_valid <= 'd1;
end
@(posedge i_clk);
end
s_axis_user_data <= s_axis_user_data ;
s_axis_user_user <= s_axis_user_user ;
s_axis_user_keep <= 8'b1111_1111 ;
s_axis_user_last <= 'd0;
s_axis_user_valid <= 'd0;
end
endtask
endmodule
2,工程编写(包含巨帧数据传输)
待施工。。。。