基于FPGA的UDP 通信(六)

news2024/10/6 18:34:21



引言

前文链接:

基于FPGA的UDP 通信(一)

基于FPGA的UDP 通信(二)

基于FPGA的UDP 通信(三)

基于FPGA的UDP 通信(四)

基于FPGA的UDP 通信(五)

本文基于FPGA和MATLAB对千兆以太网通信模块UDP数据发送(FPGA发送)进行联合调试。

设计条件

FPGA芯片:xc7a35tfgg484-2

网络芯片(PHY):RTL8211(支持1000M/100M/10M)

MAC与PHY接口:GMII

接口类型:RJ-45

Vivado版本:2018.3

Matlab版本:R2022a

电脑:小新Pro16 2022 酷睿版 笔记本

转接口:绿联USB转千兆以太网 转接器



联调思路

模式0:纯接收模式

模式1:纯发送模式

模式2:回环测试

MATLAB发送数据至FPGA,FPGA收到后将数据发至MATLAB测试数据的完整性和准确性。

模式3:测速模式

FPGA一直向电脑发送UDP数据,查看实际通信速率。

模式切换由FPGA开发板的开关控制。

设计源码

数据生成模块

// | ===================================================---------------------------===================================================
// | ---------------------------------------------------   UDP 发送数据产生模块	   ---------------------------------------------------
// | ===================================================---------------------------===================================================
// | 创建时间 : 2022-01-13
// | 完成时间 : 2022-01-13
// | 作    者 :Xu Y. B.(CSDN 用户名:在路上,正出发)
// | 功能说明 :
// |			-1- 长生UDP发送模块需要的规律数据
// |			-2- 可用于通信速率测试(连续发送:帧间隔为 0 )
// |			-3- 最大帧间隔支持 1024 个时钟周期
// |			-4- 规律数从零开始
// |
// | ================================= 		模块修改历史纪录 	  =================================
// | 修改日期:
// | 修改作者:
// | 修改注解:






`timescale 1ns / 1ps

module UDP_TX_DATA_GEN_MDL(
// | ==================================== 模块输入输出端口声明 ====================================
// 时钟、复位
input 															I_CLK_125M,
input 															I_SYS_RSTN,
// 测试使能
input 															I_TEST_EN,
// 发送 握手信号
output  reg														O_TX_EN,//脉冲信号
input		 													I_TX_DONE,

// 数据
output reg 				[7:0]									O_TX_DATA,
input															I_DATA_REQ,

// 数据帧间隔
input 					[9:0]									I_FRAME_GAP,
output reg														O_GEN_FINISH
    );

// | ====================================   模块内部参数声明   ====================================
// 状态编码
localparam 				LP_ST_IDLE				=				5'b0_0001;
localparam 				LP_ST_TX_EN				=				5'b0_0010;
localparam 				LP_ST_GEN_DATA			=				5'b0_0100;
localparam 				LP_ST_WAIT_DONE			=				5'b0_1000;
localparam 				LP_ST_IFG 				=				5'b1_0000;

// | ====================================   模块内部信号声明   ====================================
// 状态信号
reg 					[4:0]									R_STATE;
reg 					[9:0]									R_IFG_CNT;

reg 															R_DATA_REQ;

// | ====================================   模块内部逻辑设计   ====================================
always @ (posedge I_CLK_125M)
begin
	if(~I_SYS_RSTN)
	begin
		R_DATA_REQ <= 1'b0;
	end
	else
	begin
		R_DATA_REQ <= I_DATA_REQ;
	end
end
always @ (posedge I_CLK_125M)
begin
	if(~I_SYS_RSTN)
	begin
		R_STATE <= LP_ST_IDLE;

		O_TX_EN <= 1'b0;
		O_TX_DATA <= 8'd0;
		O_GEN_FINISH <= 1'b0;
		R_IFG_CNT <= 10'd0;
	end
	else
	begin
		case(R_STATE)
			LP_ST_IDLE:
			begin
				O_TX_EN <= 1'b0;
				O_TX_DATA <= 8'd0;
				O_GEN_FINISH <= 1'b0;
				R_IFG_CNT <= 10'd0;
				if(I_TEST_EN)
				begin
					R_STATE <= LP_ST_TX_EN;
				end
				else
				begin
					R_STATE <= LP_ST_IDLE;
				end
			end		
			LP_ST_TX_EN:
			begin
				O_TX_EN <= 1'b1;
				O_TX_DATA <= 8'd0;
				O_GEN_FINISH <= 1'b0;
				R_IFG_CNT <= 10'd0;
				R_STATE <= LP_ST_GEN_DATA;
			end		
			LP_ST_GEN_DATA:
			begin
				O_TX_EN <= 1'b0;

				if(~I_DATA_REQ & R_DATA_REQ)
				begin
					R_STATE <= LP_ST_WAIT_DONE;
				end
				else
				begin
					R_STATE <= LP_ST_GEN_DATA;
				end

				if(I_DATA_REQ)
				begin
					O_TX_DATA <= O_TX_DATA + 1;
				end
				else
				begin
					O_TX_DATA <= 8'd0;
				end
			end	
			LP_ST_WAIT_DONE:
			begin
				if(I_TX_DONE)
				begin
					R_STATE <= LP_ST_IFG;
				end
				else
				begin
					R_STATE <= LP_ST_WAIT_DONE;
				end
			end	
			LP_ST_IFG:
			begin
				if(I_FRAME_GAP != 10'd0)
				begin
					if(R_IFG_CNT == (I_FRAME_GAP-1))
					begin
						R_IFG_CNT <= 10'd0;
						O_GEN_FINISH <= 1'b1;
						if(I_TEST_EN)
						begin
							R_STATE <= LP_ST_TX_EN;
						end
						else
						begin
							R_STATE <= LP_ST_IDLE;
						end
					end
					else
					begin
						R_IFG_CNT <= R_IFG_CNT + 1;
					end
				end
				else
				begin
					R_IFG_CNT <= 10'd0;
					O_GEN_FINISH <= 1'b1;
					
					if(I_TEST_EN)
					begin
						R_STATE <= LP_ST_TX_EN;
					end
					else
					begin
						R_STATE <= LP_ST_IDLE;
					end
				end
			end
			default:
			begin
				R_STATE <= LP_ST_IDLE;
			end		
		endcase
	end
end

endmodule

测试模式控制模块

// | ===================================================---------------------------===================================================
// | --------------------------------------------------- 	  UDP 测试模式控制 	   ---------------------------------------------------
// | ===================================================---------------------------===================================================
// | 创建时间 : 2022-01-16
// | 完成时间 : 2022-01-16
// | 作    者 :Xu Y. B.(CSDN 用户名:在路上,正出发)
// | 功能说明 :
// |			-1- 模式说明
// |				00:纯接收模式
// |				01:纯发送模式
// |				02:回环模式
// |				03:测速模式
// |			-2- 
// |			-3- 
// |			-4- 
// |			-5- 
// |
// | ================================= 		模块修改历史纪录 	  =================================
// | 修改日期:
// | 修改作者:
// | 修改注解:

`timescale 1ns / 1ps
module UDP_TEST_MODE_CTRL(
// | ==================================== 模块输入输出端口声明 ====================================
// 系统复位
input 															I_SYS_RSTN,
// 模式控制
input 				[1:0]										I_UDP_TEST_MODE,
input 															I_TX_ONCE,

// 接收
input 															I_RX_CLK,
input 															I_RX_VAL,
input 				[7:0]										I_RX_DATA,

// 发送
input 															I_TX_CLK,
output 															O_TX_EN,
input 															I_TX_DONE,
output reg 			[15:0]										O_TX_DATA_LEN,
input 															I_DATA_REQ,
output 				[7:0]										O_TX_DATA,
input 				[9:0]										I_FRAME_GAP


    );
// | ====================================   模块内部参数声明   ====================================
localparam 			LP_MODE_RX_ONLY				=				2'b00;
localparam 			LP_MODE_TX_ONLY				=				2'b01;
localparam 			LP_MODE_LOOP_BACK			=				2'b10;
localparam 			LP_MODE_TEST_SPEED			=				2'b11;

// | ====================================   模块内部信号声明   ====================================
wire															W_RX_RSTN;//系统复位 同步至 RX时钟域
// FIFO
wire 															W_FIFO_EMPTY;
wire 															W_WR_RST_BUSY;
wire 															W_RD_RST_BUSY;
wire 				[7:0]										W_FIFO_RD_DATA;
// 数据产生模块
reg 															R_GEN_TEST_EN;
wire 				[7:0]										W_GEN_TX_DATA;
wire 															W_GEN_TX_EN;
wire 															W_GEN_FINISH;
reg 				[1:0]										R_TX_ONCE;
// 数据接收
reg 				[15:0]										R_ETH_RCV_CNT;
reg 				[1:0]										R_TX_DONE;
reg					[1:0]										R_RX_VAL;
// | ====================================   模块内部逻辑设计   ====================================
always @ (posedge I_TX_CLK)
begin
	if(~I_SYS_RSTN)
	begin
		R_TX_ONCE <= 2'b00;
	end
	else
	begin
		R_TX_ONCE <= {R_TX_ONCE[0],I_TX_ONCE};
	end
end
always @ (posedge I_RX_CLK)
begin
	if(~W_RX_RSTN)
	begin
		R_TX_DONE <= 2'b00;
	end
	else
	begin
		R_TX_DONE <= {R_TX_DONE[0],I_TX_DONE};
	end
end
always @ (posedge I_RX_CLK)
begin
	if(~W_RX_RSTN)
	begin
		R_ETH_RCV_CNT <= 16'd0;
	end
	else if(R_TX_DONE[1])
	begin
		R_ETH_RCV_CNT <= 16'd0;
	end
	else if(I_RX_VAL)
	begin
		R_ETH_RCV_CNT <= R_ETH_RCV_CNT + 1;
	end
end
always @ (posedge I_TX_CLK)
begin
	if(~W_RX_RSTN)
	begin
		R_RX_VAL <= 2'b00;
	end
	else
	begin
		R_RX_VAL <= {R_RX_VAL[0],I_RX_VAL};
	end
end

always @ (posedge I_TX_CLK)
begin
	if(~I_SYS_RSTN)
	begin
		R_GEN_TEST_EN <= 1'b0;
		O_TX_DATA_LEN <= 16'd0;
	end
	else
	begin
		case(I_UDP_TEST_MODE)
			LP_MODE_RX_ONLY:
			begin
				if(I_TX_DONE)
				begin
					R_GEN_TEST_EN <= 1'b0;
					O_TX_DATA_LEN <= 16'd0;
				end
			end		
			LP_MODE_TX_ONLY:
			begin
				R_GEN_TEST_EN <= R_TX_ONCE[0] ^ R_TX_ONCE[1];
				if(I_TX_DONE | O_TX_EN)
				begin
					O_TX_DATA_LEN <= 16'd50;
				end
			end		
			LP_MODE_LOOP_BACK:
			begin
				R_GEN_TEST_EN <= ~R_RX_VAL[0] & R_RX_VAL[1];
				if(I_TX_DONE | O_TX_EN)
				begin
					O_TX_DATA_LEN <= R_ETH_RCV_CNT;
				end
			end	
			LP_MODE_TEST_SPEED:
			begin
				R_GEN_TEST_EN <= 1'b1;
				if(I_TX_DONE | O_TX_EN)
				begin
					O_TX_DATA_LEN <= 16'd1470;
				end
			end
			default:
			begin
				R_GEN_TEST_EN <= 1'b0;
				O_TX_DATA_LEN <= 16'd0;
			end		
		endcase
	end
end

assign O_TX_DATA = ((I_UDP_TEST_MODE == LP_MODE_TEST_SPEED) || (I_UDP_TEST_MODE == LP_MODE_TX_ONLY)) ? W_GEN_TX_DATA : W_FIFO_RD_DATA;

// | ====================================   模块内部模块例化   ====================================

RESET_SYNC_MDL #(
		.P_INPUT_RESET_ACTIVE_LEVEL (1'b0),
		.P_OUTPUT_RESET_ACTIVE_LEVEL(1'b0),
		.P_SYNC_DEPTH               (32'd2)
	) INST_RESET_SYNC_MDL (
		.I_SYNC_CLK (I_RX_CLK),
		.I_RESET    (I_SYS_RSTN),
		.O_RESET    (W_RX_RSTN)
	);

UDP_TX_DATA_GEN_MDL INST_UDP_TX_DATA_GEN_MDL
	(
		.I_CLK_125M   (I_TX_CLK),
		.I_SYS_RSTN   (I_SYS_RSTN),
		.I_TEST_EN    (R_GEN_TEST_EN),
		.O_TX_EN      (O_TX_EN),
		.I_TX_DONE    (I_TX_DONE),
		.O_TX_DATA    (W_GEN_TX_DATA),
		.I_DATA_REQ   (I_DATA_REQ),
		.I_FRAME_GAP  (I_FRAME_GAP),
		.O_GEN_FINISH (W_GEN_FINISH)
	);
ASYNC_FIFO_64X8 INST_ASYNC_FIFO_64X8 (
  		.rst(~I_SYS_RSTN),                    // input wire rst
  		.wr_clk(I_RX_CLK),            	      // input wire wr_clk
  		.rd_clk(I_TX_CLK),           		  // input wire rd_clk
  		.din(I_RX_DATA),                      // input wire [7 : 0] din
  		.wr_en(I_RX_VAL),           		  // input wire wr_en
  		.rd_en(~W_FIFO_EMPTY & I_DATA_REQ),   // input wire rd_en
  		.dout(W_FIFO_RD_DATA),                // output wire [7 : 0] dout
  		.full(),                			  // output wire full
  		.empty(W_FIFO_EMPTY),              	  // output wire empty
  		.wr_rst_busy(W_WR_RST_BUSY),  		  // output wire wr_rst_busy
  		.rd_rst_busy(W_RD_RST_BUSY)  		  // output wire rd_rst_busy
);
endmodule

 

UDP收发顶层封装

// | ===================================================---------------------------===================================================
// | --------------------------------------------------- 	  	UDP 通信模块 	   ---------------------------------------------------
// | ===================================================---------------------------===================================================
// | 创建时间 : 2022-01-15
// | 完成时间 : 2022-01-15
// | 作    者 :Xu Y. B.(CSDN 用户名:在路上,正出发)
// | 功能说明 :
// |			-1- 
// |			-2- 
// |			-3- 
// |			-4- 
// |
// | ================================= 		模块修改历史纪录 	  =================================
// | 修改日期:
// | 修改作者:
// | 修改注解:






`timescale 1ns / 1ps

module TOP_UDP_TR_MDL#(
// | ====================================  模块可配置参数声明  ==================================== 
parameter 			P_FPGA_MAC_ADDR				=				48'h00_00_00_00_00_00,   // FPGA侧 MAC地址
parameter 			P_FPGA_IP_ADDR				=				{8'd0,8'd0,8'd0,8'd0},   // FPGA侧 IP地址
parameter 			P_FPGA_UDP_PORT				=				16'd0, 				     // FPGA侧 UDP端口号

parameter 			P_DST_MAC_ADDR				=				48'h00_00_00_00_00_00,   // 目的侧 MAC地址
parameter 			P_DST_IP_ADDR				=				{8'd0,8'd0,8'd0,8'd0},   // 目的侧 IP地址
parameter 			P_DST_UDP_PORT				=				16'd0 				     // 目的侧 UDP端口号
)(
// | ==================================== 模块输入输出端口声明 ====================================
// ==== 系统复位
input 															I_SYS_RSTN,
// ==== PHY复位
output 															O_PHY_RSTB,
// UDP 发送
// 时钟、复位
input 															I_CLK_125M,
// 发送 握手信号
input 															I_TX_EN,//脉冲信号
output      													O_TX_DONE,
// 数据长度
input 				[15:0]										I_TX_DATA_LEN,   //一直有效至下一次传输开始,
																				 // 最小数据为 1 最大为 1472(最大值前提是 IP首部长度 20)
// ==== 数据
input 				[7:0]										I_TX_DATA,
output 															O_DATA_REQ,
// GMII接口
output 															O_GMII_TX_CLK,
output      		[7:0]										O_GMII_TXD,   //插入I/O缓冲,提高驱动
output 	    													O_GMII_TX_EN, //插入I/O缓冲

// ==== UDP 接收
// PHY芯片接口
input 															I_PHY_RX_CLK,
input 															I_PHY_RXDV,
input 				[7:0]										I_PHY_RXD,
input 															I_PHY_RXER,
// 用户数据
output  														O_ETH_USR_DATA_VAL,
output  			[7:0]										O_ETH_USR_DATA
    );
// | ====================================   模块内部逻辑设计   ====================================
assign O_PHY_RSTB = 1'b1;
// | ====================================   模块内部模块例化   ====================================
// UDP 发
UDP_TX_MDL #(
		.P_FPGA_MAC_ADDR(P_FPGA_MAC_ADDR),
		.P_FPGA_IP_ADDR (P_FPGA_IP_ADDR),
		.P_FPGA_UDP_PORT(P_FPGA_UDP_PORT),
		.P_DST_MAC_ADDR (P_DST_MAC_ADDR),
		.P_DST_IP_ADDR  (P_DST_IP_ADDR),
		.P_DST_UDP_PORT (P_DST_UDP_PORT)
	) INST_UDP_TX_MDL (
		.I_CLK_125M    (I_CLK_125M),
		.I_SYS_RSTN    (I_SYS_RSTN),
		.I_TX_EN       (I_TX_EN),
		.O_TX_DONE     (O_TX_DONE),
		.I_TX_DATA_LEN (I_TX_DATA_LEN),
		.I_TX_DATA     (I_TX_DATA),
		.O_DATA_REQ    (O_DATA_REQ),
		.O_GMII_TX_CLK (O_GMII_TX_CLK),
		.O_GMII_TXD    (O_GMII_TXD),
		.O_GMII_TX_EN  (O_GMII_TX_EN)
	);
// UDP 收
UDP_RX_MDL #(
		.P_FPGA_MAC_ADDR (P_FPGA_MAC_ADDR),
		.P_FPGA_IP_ADDR  (P_FPGA_IP_ADDR)
	) INST_UDP_RX_MDL (
		.I_SYS_RSTN         (I_SYS_RSTN),
		.I_PHY_RX_CLK       (I_PHY_RX_CLK),
		.I_PHY_RXDV         (I_PHY_RXDV),
		.I_PHY_RXD          (I_PHY_RXD),
		.I_PHY_RXER         (I_PHY_RXER),
		.O_ETH_USR_DATA_VAL (O_ETH_USR_DATA_VAL),
		.O_ETH_USR_DATA     (O_ETH_USR_DATA)
	);

endmodule

UDP数据环回设计

UDP收发时钟异步,因此为保证回环数据安全,使用异步FIFO进行跨时钟域数据传输。

异步FIFO配置

回环测试时,一次性写入数据不要超过64个。

测试顶层

顶层例化的部分代码:

// UDP 数据收发
`ifdef UDP_TEST
	TOP_UDP_TR_MDL #(
			.P_FPGA_MAC_ADDR (P_FPGA_MAC_ADDR),
			.P_FPGA_IP_ADDR  (P_FPGA_IP_ADDR),
			.P_FPGA_UDP_PORT (P_FPGA_UDP_PORT),
			.P_DST_MAC_ADDR  (P_DST_MAC_ADDR),
			.P_DST_IP_ADDR   (P_DST_IP_ADDR),
			.P_DST_UDP_PORT  (P_DST_UDP_PORT)
		) INST_TOP_UDP_TR_MDL (
			.I_SYS_RSTN         (W_MMCM_LOCKED),
			.O_PHY_RSTB         (O_PHY_RSTB),
	
			.I_CLK_125M         (W_CLK_125M),
			.I_TX_EN            (W_TX_EN),
			.O_TX_DONE          (W_TX_DONE),
			.I_TX_DATA_LEN      (W_TX_DATA_LEN),
			.I_TX_DATA          (W_TX_DATA),
			.O_DATA_REQ         (W_DATA_REQ),
			.O_GMII_TX_CLK      (O_GMII_TX_CLK),
			.O_GMII_TXD         (O_GMII_TXD),
			.O_GMII_TX_EN       (O_GMII_TX_EN),
	
			.I_PHY_RX_CLK       (I_PHY_RX_CLK),
			.I_PHY_RXDV         (I_PHY_RXDV),
			.I_PHY_RXD          (I_PHY_RXD),
			.I_PHY_RXER         (I_PHY_RXER),
			.O_ETH_USR_DATA_VAL (W_ETH_USR_DATA_VAL),
			.O_ETH_USR_DATA     (W_ETH_USR_DATA)
		);
	UDP_TEST_MODE_CTRL INST_UDP_TEST_MODE_CTRL
		(
			.I_SYS_RSTN      (W_MMCM_LOCKED),

			.I_UDP_TEST_MODE (I_UDP_TEST_MODE),
			.I_TX_ONCE       (I_TX_ONCE),

			.I_RX_CLK        (I_PHY_RX_CLK),
			.I_RX_VAL        (W_ETH_USR_DATA_VAL),
			.I_RX_DATA       (W_ETH_USR_DATA),

			.I_TX_CLK        (W_CLK_125M),
			.O_TX_EN         (W_TX_EN),
			.I_TX_DONE       (W_TX_DONE),
			.O_TX_DATA_LEN   (W_TX_DATA_LEN),
			.I_DATA_REQ      (W_DATA_REQ),
			.O_TX_DATA       (W_TX_DATA),
			.I_FRAME_GAP     (10'd0)
		);
	assign O_TEST_LED[0] = I_UDP_TEST_MODE == 2'd0;
	assign O_TEST_LED[1] = I_UDP_TEST_MODE == 2'd1;
	assign O_TEST_LED[2] = I_UDP_TEST_MODE == 2'd2;
	assign O_TEST_LED[3] = I_UDP_TEST_MODE == 2'd3;
`endif

功能仿真

将数据产生模块与数据发送模块作联合仿真,验证数据发送的功能。

UDP发送模块的源码在上篇博文。

TEST BENCH

// | ===================================================---------------------------===================================================
// | ---------------------------------------------------   UDP 数据发送模块测试    ---------------------------------------------------
// | ===================================================---------------------------===================================================
// | 创建时间 : 2022-01-15
// | 完成时间 : 2022-01-15
// | 作    者 :Xu Y. B.(CSDN 用户名:在路上,正出发)
// | 功能说明 :
// | 			-1- 
// | 			-2- 
// |
// | ================================= 		模块修改历史纪录 	  =================================
// | 修改日期:
// | 修改作者:
// | 修改注解:

`timescale 1ns / 1ps

module TB_UDP_TX_GEN();
// | ====================================  模块可配置参数声明  ==================================== 
parameter 			P_FPGA_MAC_ADDR				=				48'h00_0a_35_01_fe_c0;   // FPGA侧 MAC地址
parameter 			P_FPGA_IP_ADDR				=				{8'd192,8'd168,8'd8,8'd3};   // FPGA侧 IP地址
parameter 			P_FPGA_UDP_PORT				=				16'd6001; 				     // FPGA侧 UDP端口号

parameter 			P_DST_MAC_ADDR				=				48'hC8_5B_76_DD_0B_38;   // 目的侧 MAC地址
parameter 			P_DST_IP_ADDR				=				{8'd192,8'd168,8'd8,8'd2};   // 目的侧 IP地址
parameter 			P_DST_UDP_PORT				=				16'd6002; 				     // 目的侧 UDP端口号

// | ==================================== 模块输入输出端口声明 ====================================
// 时钟、复位
reg 															I_CLK_125M;
reg 															I_SYS_RSTN;
// 发送 握手信号
wire 															I_TX_EN;//脉冲信号
wire        													O_TX_DONE;
// 数据长度
reg 				[15:0]										I_TX_DATA_LEN;   //一直有效至下一次传输开始,
																				 // 最小数据为 1 最大为 1472(最大值前提是 IP首部长度 20)
// 数据
wire 				[7:0]										I_TX_DATA;
wire    														O_DATA_REQ;
// GMII接口
wire 															O_GMII_TX_CLK;
(*IOB = "TRUE"*)
wire     		    [7:0]										O_GMII_TXD; //插入I/O缓冲,提高驱动
(*IOB = "TRUE"*)
wire     													    O_GMII_TX_EN; //插入I/O缓冲

reg 				[9:0]										I_FRAME_GAP;
reg 															I_TEST_EN;
wire 															O_GEN_FINISH;
// | ====================================     产生测试激励 	   ====================================
initial I_CLK_125M = 1'b0;
always #4 I_CLK_125M = ~I_CLK_125M;

initial
begin
	I_SYS_RSTN = 0;
	I_TX_DATA_LEN = 16'd0;
	I_FRAME_GAP = 10'd0;
	I_TEST_EN = 1'b0;

	#124;
	I_SYS_RSTN = 1;

	@(posedge I_CLK_125M)
	I_TEST_EN <= 1'b1;
	I_TX_DATA_LEN = 16'd200;
	I_FRAME_GAP = 10'd100;

	#109;
	@(posedge I_CLK_125M)
	I_TEST_EN <= 1'b0;

	@(posedge O_GEN_FINISH);
	#309;
	@(posedge I_CLK_125M)
	I_TEST_EN <= 1'b1;
	I_TX_DATA_LEN = 16'd10;
	I_FRAME_GAP = 10'd0;

	@(posedge O_GEN_FINISH);
	@(posedge O_GEN_FINISH);
	@(posedge O_GEN_FINISH);

	#109;
	@(posedge I_CLK_125M)
	I_TEST_EN <= 1'b0;

	#1090;
	$finish;
end
UDP_TX_MDL #(
		.P_FPGA_MAC_ADDR (P_FPGA_MAC_ADDR),
		.P_FPGA_IP_ADDR  (P_FPGA_IP_ADDR),
		.P_FPGA_UDP_PORT (P_FPGA_UDP_PORT),
		.P_DST_MAC_ADDR  (P_DST_MAC_ADDR),
		.P_DST_IP_ADDR   (P_DST_IP_ADDR),
		.P_DST_UDP_PORT  (P_DST_UDP_PORT)
	) INST_UDP_TX_MDL (
		.I_CLK_125M    (I_CLK_125M),
		.I_SYS_RSTN    (I_SYS_RSTN),
		.I_TX_EN       (I_TX_EN),
		.O_TX_DONE     (O_TX_DONE),
		.I_TX_DATA_LEN (I_TX_DATA_LEN),
		.I_TX_DATA     (I_TX_DATA),
		.O_DATA_REQ    (O_DATA_REQ),
		.O_GMII_TX_CLK (O_GMII_TX_CLK),
		.O_GMII_TXD    (O_GMII_TXD),
		.O_GMII_TX_EN  (O_GMII_TX_EN)
	);
UDP_TX_DATA_GEN_MDL INST_UDP_TX_DATA_GEN_MDL
	(
		.I_CLK_125M  (I_CLK_125M),
		.I_SYS_RSTN  (I_SYS_RSTN),
		.I_TEST_EN   (I_TEST_EN),
		.O_TX_EN     (I_TX_EN),
		.I_TX_DONE   (O_TX_DONE),
		.O_TX_DATA   (I_TX_DATA),
		.I_DATA_REQ  (O_DATA_REQ),
		.I_FRAME_GAP (I_FRAME_GAP),
		.O_GEN_FINISH(O_GEN_FINISH)
	);


endmodule

仿真结果

板级联调

MATLAB源码

clc;
clearvars;

% UDP 参数设置
LocalHost = "192.168.8.1";
LocalPort = 6002;
Timeout = 60;
% 创建UDP端口对象
U_UDP_PORT_OBJ = udpport("ByteOrder","little-endian","LocalHost",LocalHost,"LocalPort",LocalPort,"Timeout",Timeout);

% 写数据
DstHost = "192.168.8.2";
DstPort = 6001;
WR_DATA = 1:10;
write(U_UDP_PORT_OBJ,WR_DATA,"uint8",DstHost,DstPort);

% 等待数据
while(U_UDP_PORT_OBJ.NumBytesAvailable == 0)
    U_UDP_PORT_OBJ.NumBytesAvailable 
end
% 读数据
DATA_READ = read(U_UDP_PORT_OBJ,length(WR_DATA),"uint8")
% 清除缓存
flush(U_UDP_PORT_OBJ);

clear U_UDP_PORT_OBJ

FPGA侧以太网参数设置

 其中目的 MAC地址需要通过以下方式获取:

1、cmd命令提示符内输入并执行(Enter键):

ipconfig -all

2、找到所连接的以太网名称,找到对应的 MAC地址 ,即为 FPGA发送端的目的MAC地址。 

测速结果

模式3下,FPGA侧一直发送UDP数据,发送数据1470字节,帧间距设置0,测速结果:

演示视频

感兴趣可以看看,主要包含了四种测试模式的实际调试。

C站:基于FPGA的 千兆以太网收发 板级调试演示视频

B站:基于FPGA的 千兆以太网收发 板级调试演示视频

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/168451.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Spring6源码・AOP】AOP源码解析

上一篇《【Spring6源码・AOP】代理对象的创建》&#xff0c;我们知道了代理是如何创建的&#xff0c;那么它又是如何工作的呢&#xff1f; 创建完代理对象之后&#xff0c;最终&#xff0c;会真正的执行我们的目标方法&#xff0c;但是步入该方法&#xff0c;会进入cglib代理类…

ET框架关于opCode的理解

因为所有的网络消息在发送时候格式都是这样 对于用Protobuf定义的每一消息类型class&#xff0c;都需要定义一个对应消息头code在发送的时候&#xff0c;先将消息体进行序列化&#xff0c;再将code进行序列化&#xff0c;进行组装发送 //这个代码没有进行过优化&#xff0c;会产…

大衣哥给儿媳买回来烟花,是准备加入河南炮击山东大战吗

自从取得抗疫阶段性胜利后&#xff0c;国人就再也难以按捺激动的心情&#xff0c;都想通过放烟花以示庆祝。河南山东属于搭界的两个省&#xff0c;最近就因为放烟花&#xff0c;闹出来不小的笑话&#xff0c;有人甚至戏称炮击事件。 事情的起因是这样的&#xff0c;河南因为地处…

maven的build节点配置

虽然一直在使用maven&#xff0c;但是对于maven的配置还没有深入的了解过。本文以build节点为切入点&#xff0c;主要解释相关maven打包使用到的一些基础配置。 文章目录build节点常用插件spring-boot-maven-pluginmaven-jar-pluginmaven-dependency-plugin注意事项build节点 …

基于javaweb的会议管理系统源码+数据库,javaEE会议管理系统源码

guihaiyidao_git 介绍 javaEE工程 普通的javaEE工程&#xff0c;用idea打开工程即可运行 服务器用的是Tomcat 8.5.722 数据库用的Oracle xe版 数据库可视化工具使用的是PLSQL 相关软件 需要可从百度网盘中获取 链接&#xff1a;https://pan.baidu.com/s/1ZrmfsvQEA4dIP0GF_p…

CSS 布局 - 水平 垂直对齐

CSS 布局 - 水平 & 垂直对齐 那么怎样设置居中对齐呢? 我们可以用margin: auto来设置水平居中对其元素。auto可以防止 元素的宽高溢出&#xff0c;而且也可以平均分配两边的空白。 举例说明: .center {padding: 23px;border: 5px solid red;width: 41%;margin: auto; }那…

【数据结构】单向链表的原理及实现

1.什么是单链表 链表里的数据是以节点的方式表示的&#xff0c;每一个结点的组成是由&#xff1a;元素指针来组成的&#xff0c;元素就是存储数据里的存储单元&#xff0c;指针就是用来连接每一个结点的地址数据。这个以结点的序列来表示线性表被称作为单链表。 单链表是一种…

牛客寒假算法集训营1 补题

标题迷惑大赏 A、World Final? World Cup! 题目描述 众所周知&#xff0c;2022年是四年一度的世界杯年&#xff0c;那么当然要整点足球题。本题需要你模拟一次点球大战。 假设对战双方为A和B&#xff0c;则点球大战中双方会按照ABABABABAB方式来罚点球&#xff0c;即两队交…

【闪电侠学netty】第7章 数据载体ByteBuf的介绍

1. 内容概要 1.1 总结 1.1.1 内存管理 Netty 使用的是堆外内存&#xff0c;需要手动释放&#xff0c;使用引用计数的方式管理内存&#xff0c;当引用计数 0&#xff0c;回收ByteBuf 底层内存 原则&#xff1a;谁使用retain() , 谁释放release() 1.1.2 创建ByteBuf的方式 B…

ASCII码,字符,字符串三者之间的关系

程序调试中遇到问题&#xff1a;在使用sprintf 函数&#xff0c;在转换字符串时&#xff0c;如果遇到0时&#xff0c;会自动认为是结束标志&#xff0c;0以后的内容不会被添加进来。复习一下字符串&#xff1a;一. ASCII码是什么&#xff1f;ASCII 全称为 ( American Standard …

【2023更新】通过硬件触发信号实现OAK多相机之间的同步拍摄

编辑&#xff1a;OAK中国 首发&#xff1a;oakchina.cn 喜欢的话&#xff0c;请多多&#x1f44d;⭐️✍ 内容可能会不定期更新&#xff0c;官网内容都是最新的&#xff0c;请查看首发地址链接。 ▌前言 Hello&#xff0c;大家好&#xff0c;这里是OAK中国&#xff0c;我是助手…

经典文献阅读之--NeRF-SLAM(单目稠密重建)

0. 简介 最近几年随着深度学习的发展&#xff0c;现在通过深度学习去预估出景深的做法已经日渐成熟&#xff0c;所以随之而来的是本文的出现《Real-Time Dense Monocular SLAM with Neural Radiance Fields》。这篇文章是一个结合单目稠密SLAM和层次化体素神经辐射场的3D场景重…

【自学Docker 】Docker管理命令大全(下)

文章目录Docker kill命令Docker kill命令概述Docker kill命令语法Docker kill命令参数案例使用容器 ID 杀掉容器使用容器名杀掉容器Docker kill命令总结Docker rm命令Docker rm命令概述Docker rm命令语法Docker rm命令参数案例删除已停止的容器删除正在运行的容器Docker rm命令…

13.拷贝控制

文章目录拷贝控制13.1拷贝、赋值与销毁13.1.1拷贝构造函数合成拷贝构造函数拷贝初始化参数和返回值编译器可以绕过拷贝构造函数13.1.2拷贝赋值运算符重载赋值运算符合成拷贝赋值运算符13.1.3析构函数析构函数完成什么工作什么时候会调用析构函数合成析构函数13.1.4三/五法则需要…

寒假题练——day(4)

题目 1 一个数组中只有两个数字是出现一次&#xff0c;其他所有数字都出现了两次。 编写一个函数找出这两个只出现一次的数字。 #include<stdio.h> int main() {int arr[] { 1, 3, 8, 1, 3, 8, 4, 6 };int num 0;int sz sizeof(arr) / sizeof(arr[0]);int i 0;int…

【Linux】六、Linux 基础IO(二)|重定向|如何理解 Linux一切皆文件|缓冲区

目录 五、重定向 5.1 什么是重定向 5.2 系统调用 dup2 5.3 三种重定向测试 5.3.1 输出重定向(>) 5.3.2 追加重定向(>>) 5.3.3 输入重定向(<) 5.4 父子进程拷贝问题 六、如何理解 Linux一切皆文件 七、缓冲区 7.1 认识缓冲区 7.2 缓冲区的刷新策略 …

连续系统PID的Simulink仿真-2

仍以二阶线性传递函数为被控对象&#xff0c;进行模拟PID 控制。被控对象形式为,其中b为在[103,163]范围内随机变化&#xff0c;a为在[15,35]范围内随机变化&#xff0c;则被控对象的描述方式可转换为&#xff1a;S函数是Simulink一项重要的功能&#xff0c;采用S函数可实现在S…

Pandas 数据清洗

Pandas 数据清洗数据清洗是对一些没有用的数据进行处理的过程。很多数据集存在数据缺失、数据格式错误、错误数据或重复数据的情况&#xff0c;如果要对使数据分析更加准确&#xff0c;就需要对这些没有用的数据进行处理。在这个教程中&#xff0c;我们将利用 Pandas包来进行数…

微软ATP带你看| 爆火的ChatGPT是什么?

&#xff08;本文阅读时间&#xff1a;7分钟&#xff09;OpenAI最新聊天机器人ChatGPT火爆全网&#xff01;能写代码、编剧本&#xff0c;马斯克都盛赞它“好得吓人”&#xff01;ChatGPT是什么GPT(Generative Pre-trained Transformer)系列是由OpenAI提出的非常强大的预训练语…

MaxCompute SQL示例解析

MaxCompute SQL示例解析 介绍MaxCompute SQL常见使用场景&#xff0c;掌握SQL的写法。 准备数据集 本文以emp表和dept表为示例数据集。您可以自行在MaxCompute项目上创建表并上传数据。 emp.csv中数据如下 7369,SMITH,CLERK,7902,1980-12-17 00:00:00,800,20 7499,ALLEN,SALES…