八、基于FPGA的以太网协议介绍(三)

第一文中介绍了以太网的各层协议;链接:https://blog.csdn.net/weixin_41838250/article/details/114686428?spm=1001.2014.3001.5502

第二文中对使用的10Gbase-R和MAC使用做了简单描述;链接:https://blog.csdn.net/weixin_41838250/article/details/114691373

这里做一个简单的千兆网络设计,使用RGMII接口。

1,架构设计

2 发送端

UDP发送模块,完成UDP数据报,IP数据报,MAC帧组装;代码如下

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2020/08/28 13:37:07
// Design Name: 
// Module Name: network_tx_design
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//

module network_tx_design #(
	parameter [15:0] src_port = 16'h5000,
	parameter [15:0] dest_port = 16'h6000,
	parameter [31:0] src_ip = 32'h01010101,
	parameter [31:0] dest_ip = 32'h05050505,
	parameter [47:0] src_mac_addr = 48'hAAAABBBBCC,
	parameter [47:0] dest_mac_addr = 48'hDDDDEEEEFFFF
)(
	input          sys_clk,
	input          sys_rst,
	
	input          udp_tx_sof,
	input          udp_tx_en,
	input  [7:0]   udp_tx_data,
	input  [15:0]  udp_tx_byte_num,
	output         udp_tx_ready,
	output         udp_tx_ok,

	input          mac_enable,
	output         mac_tx_sof,
	output         mac_tx_eof,
	output         mac_tx_en,
	output [7:0]   mac_tx_data,
	input          mac_tx_ready
);
	
	
	localparam [15:0] total_length = 14+20+8; //mac_header_length + ip_header_length + udp_header_length;
	//ip header
	localparam [15:0] ver_len_tos = 16'h4500;
	localparam [15:0] logo_flag = 16'd0;
	localparam [15:0] mf_offest = 16'd0;
	localparam [7:0] ip_protocol = 8'd17;
	localparam [7:0] ttl_time = 8'd0;
	
	//mac header 
	localparam [15:0] mac_type = 16'h0800;	
	//state
	localparam [3:0] idle_state   = 4'd0;
	localparam [3:0] sof_state    = 4'd1;
	localparam [3:0] header_state = 4'd2;
	localparam [3:0] data_state   = 4'd3;
	localparam [3:0] end_state    = 4'd4;

	
	wire [19:0] ip_check_num;
	wire [15:0] ip_check_sum;
	
	reg         fifo_wr_en = 0;
	reg  [7:0]  fifo_wr_data = 0;
	wire        fifo_wr_ready;
	reg         fifo_rd_en = 0;
	wire [7:0]  fifo_rd_data;
	wire        fifo_rd_ready;
	
	reg [15:0] rx_data_cnt = 0;
	reg [15:0] tx_header_cnt = 0;
	reg [15:0] tx_data_cnt = 0;
	
	reg        tx_sof = 0;
	reg        tx_eof = 0;
	reg        tx_ok = 0;
	reg        tx_en = 0;
	reg [7:0]  tx_data = 0;
	wire [15:0] ip_total_num;
	wire [15:0] udp_total_num;

	reg [3:0]  tx_current_state = idle_state;
	reg [3:0]  tx_next_state = idle_state;
	
	assign udp_total_num = udp_tx_byte_num + 8;
	assign ip_total_num = udp_tx_byte_num + 28;
	assign ip_check_num = ver_len_tos + {ttl_time,ip_protocol} + (udp_tx_byte_num + 28) + src_ip[31:16] + src_ip[15:0] + dest_ip[31:16] + dest_ip[15:0];
	assign ip_check_sum = ~(ip_check_num[19:16] + ip_check_num[15:0]);
	
//----------------------------rx data----------------------------------------------------
	always @ (posedge sys_clk) begin 
		if(sys_rst) 
			rx_data_cnt <= 0;	
		else if(udp_tx_sof && udp_tx_en)
			rx_data_cnt <= 1;
		else if(udp_tx_en)
			rx_data_cnt <= rx_data_cnt + 1;	
		else 
			rx_data_cnt <= rx_data_cnt;		
	end 

	always @ (posedge sys_clk) begin //写FIFO
		if(sys_rst) begin 
			fifo_wr_en <= 0;
			fifo_wr_data <= 0;
			end 
		else begin 
			fifo_wr_en <= udp_tx_en;
			fifo_wr_data <= udp_tx_data;
			end 
	end 
	
	data_fifo udp_data_fifo(
		.s_aclk         (sys_clk      ),
		.s_aresetn      (!sys_rst     ),
		.wr_rst_busy    ( ),
		.rd_rst_busy    ( ),
		.s_axis_tready  (fifo_wr_ready),
		.s_axis_tvalid  (fifo_wr_en   ),		
		.s_axis_tdata   (fifo_wr_data ),
		.m_axis_tready  (fifo_rd_en   ),
		.m_axis_tdata   (fifo_rd_data ),
		.m_axis_tvalid  (fifo_rd_ready)
	);
	
//----------------------------tx  data state-------------------------------------------

	always @ (posedge sys_clk) begin 
		if(sys_rst)
			tx_current_state <= idle_state;
		else 
			tx_current_state <= tx_next_state;
	end 
   
	always @ (*) begin 
		if(sys_rst)
			tx_next_state = idle_state;
		else case(tx_current_state) 
			idle_state : if(udp_tx_sof) tx_next_state = sof_state;
							else tx_next_state = idle_state;
							
			sof_state  : tx_next_state = header_state;	
							
			header_state : if(tx_header_cnt >= total_length) tx_next_state = data_state; 
							else tx_next_state = header_state; 
							
			data_state : if(tx_data_cnt >= udp_tx_byte_num) tx_next_state = end_state;
							else tx_next_state = data_state;
							
			end_state : tx_next_state = idle_state;
			
			default : tx_next_state = idle_state;
			endcase 
	end 

	always @ (posedge sys_clk) begin 
		if(sys_rst) begin 
			tx_sof <= 0;
			tx_eof <= 0;
			tx_ok <= 0;
			tx_en <= 0;
			tx_data <= 0;
			tx_data_cnt <= 0;
			tx_header_cnt <= 0;
			fifo_rd_en <= 0;
			end
		else case(tx_current_state)
			idle_state : begin 
							tx_sof <= 0;
							tx_eof <= 0;
							tx_ok <= 0;
							tx_en <= 0;
							tx_data <= 0;
							tx_header_cnt <= 0;
							tx_data_cnt <= 0;
							fifo_rd_en <= 0;
						end 

			sof_state : begin 
							tx_sof <= 1;
							tx_eof <= 0;
							tx_ok <= 0;
							tx_en <= 1;
							tx_data <= dest_mac_addr[47:40];
							tx_header_cnt <= 1;
							tx_data_cnt <= 0;
							fifo_rd_en <= 0;							
						end 
							
			header_state : if(mac_tx_ready) begin 
								tx_sof <= 0;
								tx_header_cnt <= tx_header_cnt + 1;
								case(tx_header_cnt)
									//MAC
									0 : begin tx_en <= 1; tx_data <= dest_mac_addr[47:40]; end 
                                    1 : begin tx_en <= 1; tx_data <= dest_mac_addr[39:32]; end 
                                    2 : begin tx_en <= 1; tx_data <= dest_mac_addr[31:24]; end 
                                    3 : begin tx_en <= 1; tx_data <= dest_mac_addr[23:16]; end
                                    4 : begin tx_en <= 1; tx_data <= dest_mac_addr[15:8];  end
                                    5 : begin tx_en <= 1; tx_data <= dest_mac_addr[7:0];   end
                                    6 : begin tx_en <= 1; tx_data <= src_mac_addr[47:40];  end
                                    7 : begin tx_en <= 1; tx_data <= src_mac_addr[39:32];  end
                                    8 : begin tx_en <= 1; tx_data <= src_mac_addr[31:24];  end
                                    9 : begin tx_en <= 1; tx_data <= src_mac_addr[23:16];  end
                                    10: begin tx_en <= 1; tx_data <= src_mac_addr[15:8];   end
                                    11: begin tx_en <= 1; tx_data <= src_mac_addr[7:0];    end
                                    12: begin tx_en <= 1; tx_data <= mac_type[15:8];       end
                                    13: begin tx_en <= 1; tx_data <= mac_type[7:0];        end
									
									//IP
									14: begin tx_en <= 1; tx_data <= ver_len_tos[15:8];    end
									15: begin tx_en <= 1; tx_data <= ver_len_tos[7:0];     end
									16: begin tx_en <= 1; tx_data <= ip_total_num[15:8];   end
									17: begin tx_en <= 1; tx_data <= ip_total_num[7:0];    end
									18: begin tx_en <= 1; tx_data <= logo_flag[15:8];      end
									19: begin tx_en <= 1; tx_data <= logo_flag[7:0];       end
									20: begin tx_en <= 1; tx_data <= mf_offest[15:8];      end
									21: begin tx_en <= 1; tx_data <= mf_offest[7:0];       end
									22: begin tx_en <= 1; tx_data <= ttl_time;             end
									23: begin tx_en <= 1; tx_data <= ip_protocol;          end
									24: begin tx_en <= 1; tx_data <= ip_check_sum[15:8];   end
									25: begin tx_en <= 1; tx_data <= ip_check_sum[7:0];    end
									26: begin tx_en <= 1; tx_data <= src_ip[31:24];        end
									27: begin tx_en <= 1; tx_data <= src_ip[23:16];        end
									28: begin tx_en <= 1; tx_data <= src_ip[15:8];         end
									29: begin tx_en <= 1; tx_data <= src_ip[7:0];          end
									30: begin tx_en <= 1; tx_data <= dest_ip[31:24];       end
									31: begin tx_en <= 1; tx_data <= dest_ip[23:16];       end
									32: begin tx_en <= 1; tx_data <= dest_ip[15:8];        end
									33: begin tx_en <= 1; tx_data <= dest_ip[7:0];         end
									
									//UDP
									34: begin tx_en <= 1; tx_data <= src_port[15:8];       end
									35: begin tx_en <= 1; tx_data <= src_port[7:0];        end
									36: begin tx_en <= 1; tx_data <= dest_port[15:8];      end
									37: begin tx_en <= 1; tx_data <= dest_port[7:0];       end
									38: begin tx_en <= 1; tx_data <= udp_total_num[15:8];  end
									39: begin tx_en <= 1; tx_data <= udp_total_num[7:0];   end
									40: begin tx_en <= 1; tx_data <= 8'd0;                 end
									41: begin tx_en <= 1; tx_data <= 8'd0;                 end
									42: begin tx_en <= 0; end 
								endcase 
								end
							else begin 
								tx_sof <= tx_sof;
								tx_en <= tx_en;
								tx_header_cnt <= tx_header_cnt;
								end 
			data_state :begin
							if(fifo_rd_ready == 1 && tx_data_cnt < udp_tx_byte_num && mac_tx_ready)
								fifo_rd_en <= 1;
							else  
								fifo_rd_en <= 0;

							if(fifo_rd_en && fifo_rd_ready && tx_data_cnt == udp_tx_byte_num - 1) begin 
							    tx_eof <= 1;
							    tx_en <= 1;
								tx_data_cnt <= tx_data_cnt + 1;
								tx_data <= fifo_rd_data;
							    end 
							else if(fifo_rd_en && fifo_rd_ready) begin 
								tx_eof <= 0;
								tx_en <= 1;
								tx_data_cnt <= tx_data_cnt + 1;
								tx_data <= fifo_rd_data;
								end
							else begin 
							    tx_eof <= 0;
								tx_en <= 0;
								tx_data_cnt <= tx_data_cnt;
								tx_data <= 0;
								end   
						end

			end_state : begin 
							tx_sof <= 0;
							tx_eof <= 0;
							tx_ok <= 1;
							tx_en <= 0;
							tx_data <= 0;
							tx_header_cnt <= 0;
							tx_data_cnt <= 0;	
							fifo_rd_en <= 0;
						end 
			endcase 
	end 
	
	assign mac_tx_sof = tx_sof;
    assign mac_tx_eof = tx_eof;
    assign mac_tx_en = tx_en;
    assign mac_tx_data = tx_data;
    assign udp_tx_ok = tx_ok;
    assign udp_tx_ready = fifo_wr_ready;//&& mac_enable;
    
endmodule 

2.2  接收端

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2020/09/01 10:29:44
// Design Name: 
// Module Name: network_rx_design
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module network_rx_design#(
	parameter [15:0] src_port = 16'h5000,
	parameter [15:0] dest_port = 16'h6000,
	parameter [31:0] src_ip = 32'h01010101,
	parameter [31:0] dest_ip = 32'h05050505,
	parameter [47:0] src_mac_addr = 48'hAAAABBBBCC,
	parameter [47:0] dest_mac_addr = 48'hDDDDEEEEFFFF
)(
	input         sys_clk,
	input         sys_rst,

	input         mac_enable,
	input         mac_rx_en,
	input         mac_rx_eof,
	input  [7:0]  mac_rx_data,

	output        udp_rx_error,
	output        udp_rx_sof,
	output        udp_rx_eof,
	output        udp_rx_en,
	output [7:0]  udp_rx_data,
	output [15:0] udp_byte_num
);


	//state
	localparam [3:0] idle_state   = 4'd0;
	localparam [3:0] header_state = 4'd1;
	localparam [3:0] data_state   = 4'd2;
	localparam [3:0] end_state    = 4'd3;

	reg  [3:0]  rx_current_state = idle_state;
	reg  [3:0]  rx_next_state = idle_state;

	reg  rx_en = 0;
	reg  rx_sof = 0;
	reg  rx_eof = 0;
	reg  [7:0]  rx_data = 0;
	reg  [15:0] rx_data_cnt = 0;
	reg  [7:0]  rx_header_cnt = 0;
	reg  rx_error = 0;

	//mac
	reg  [47:0] rx_dest_mac_addr = 0;
	reg  [47:0] rx_src_mac_addr = 0;
	//ip
	reg  [15:0] rx_ip_total_length = 0;
	reg  [7:0]  rx_ip_protocol = 0;
	reg  [15:0] rx_ip_check_sum = 0;
	reg  [31:0] rx_src_ip = 0;
	reg  [31:0] rx_dest_ip = 0;
	//udp
	reg  [15:0] rx_dest_port = 0;
	reg  [15:0] rx_src_port = 0;
	reg  [15:0] rx_udp_total_length = 0;


//---------------------------------------------------------------------------------------
	always @ (posedge sys_clk) begin 
		if(sys_rst)
			rx_current_state <= idle_state;
		else 
			rx_current_state <= rx_next_state;
   end 

	always @ (*) begin 
		if(sys_rst)
			rx_next_state = idle_state;
		else case(rx_current_state) 
			idle_state : if(mac_enable) rx_next_state = header_state;
						else rx_next_state = idle_state;
						
			header_state  : if(mac_rx_en && rx_header_cnt == 41) rx_next_state = data_state;
						else rx_next_state = header_state;

			data_state : if(mac_rx_en && mac_rx_eof) rx_next_state = end_state; 
						else rx_next_state = data_state; 

			end_state : rx_next_state = idle_state;

			default : rx_next_state = idle_state;
		endcase 
	end 

	always @ (posedge sys_clk) begin
		if(sys_rst) begin 
			rx_en <= 0;
			rx_sof <= 0;
			rx_eof <= 0;
			rx_data <= 0;
			rx_data_cnt <= 0;	
			rx_error <= 0;
			rx_header_cnt <= 0;
			rx_dest_mac_addr <= 0;
			rx_src_mac_addr <= 0;
			rx_ip_total_length <= 0;
			rx_ip_protocol <= 0;
			rx_ip_check_sum <= 0;
			rx_src_ip <= 0;
			rx_dest_ip <= 0;
			rx_dest_port <= 0;
			rx_src_port <= 0;
			rx_udp_total_length <= 0;
			end 
		else case(rx_current_state)
			idle_state : begin 
						rx_en <= 0;
						rx_sof <= 0;
						rx_eof <= 0;
						rx_data <= 0;
						rx_data_cnt <= 0;	
						rx_header_cnt <= 0;
						rx_error <= 0;
						rx_dest_mac_addr <= 0;
						rx_src_mac_addr <= 0;
						rx_ip_total_length <= 0;
						rx_ip_protocol <= 0;
						rx_ip_check_sum <= 0;
						rx_src_ip <= 0;
						rx_dest_ip <= 0;
						rx_src_port <= 0;
						rx_dest_port <= 0;
						rx_udp_total_length <= 0;
					end 

			header_state : begin 
						if(mac_rx_en) begin
							rx_header_cnt <= rx_header_cnt + 1;
							case(rx_header_cnt)
								0  : rx_dest_mac_addr[47:40] <=  mac_rx_data;
								1  : rx_dest_mac_addr[39:32] <=  mac_rx_data;
								2  : rx_dest_mac_addr[31:24] <=  mac_rx_data;
								3  : rx_dest_mac_addr[23:16] <=  mac_rx_data;
								4  : rx_dest_mac_addr[15:8]  <=  mac_rx_data;
								5  : rx_dest_mac_addr[7:0]   <=  mac_rx_data;
								6  : rx_src_mac_addr[47:40]  <=  mac_rx_data;
								7  : rx_src_mac_addr[39:32]  <=  mac_rx_data;
								8  : rx_src_mac_addr[31:24]  <=  mac_rx_data;
								9  : rx_src_mac_addr[23:16]  <=  mac_rx_data;
								10 : rx_src_mac_addr[15:8]   <=  mac_rx_data;
								11 : rx_src_mac_addr[7:0]    <=  mac_rx_data;

								16 : rx_ip_total_length[15:8] <= mac_rx_data;
								17 : rx_ip_total_length[7:0]  <= mac_rx_data;
								23 : rx_ip_protocol        <= mac_rx_data;
								24 : rx_ip_check_sum[15:8] <= mac_rx_data;
								25 : rx_ip_check_sum[7:0]  <= mac_rx_data;
								26 : rx_src_ip[31:24]  <= mac_rx_data;
								27 : rx_src_ip[23:16]  <= mac_rx_data;
								28 : rx_src_ip[15:8]   <= mac_rx_data;
								29 : rx_src_ip[7:0]    <= mac_rx_data;
								30 : rx_dest_ip[31:24] <= mac_rx_data;
								31 : rx_dest_ip[23:16] <= mac_rx_data;
								32 : rx_dest_ip[15:8]  <= mac_rx_data;
								33 : rx_dest_ip[7:0]   <= mac_rx_data;

								34 : rx_src_port[15:8]  <= mac_rx_data;
								35 : rx_src_port[7:0]   <= mac_rx_data;
								36 : rx_dest_port[15:8] <= mac_rx_data;
								37 : rx_dest_port[7:0]  <= mac_rx_data;
								38 : rx_udp_total_length[15:8]  <= mac_rx_data;
								39 : rx_udp_total_length[7:0]   <= mac_rx_data;

								default : ;
								endcase 
							end
						else begin 
							rx_header_cnt <= rx_header_cnt;
							end 
					end 

			data_state : begin 
						if(mac_rx_en && mac_rx_eof) begin  
							rx_en <= 1;
							rx_sof <= 0;
							rx_eof <= 1;
							rx_data <= mac_rx_data;
							rx_data_cnt <= rx_data_cnt + 1;
							end
						else if(mac_rx_en && rx_data_cnt == 0) begin 
							rx_en <= 1;
							rx_sof <= 1;
							rx_eof <= 0;
							rx_data <= mac_rx_data;
							rx_data_cnt <= rx_data_cnt + 1;	
							end 
						else if(mac_rx_en) begin 
							rx_en <= 1;
							rx_sof <= 0;
							rx_eof <= 0;
							rx_data <= mac_rx_data;
							rx_data_cnt <= rx_data_cnt + 1;	
							end 
						else begin 
							rx_en <= 0;
							rx_sof <= 0;
							rx_eof <= 0;
							rx_data <= mac_rx_data;
							rx_data_cnt <= rx_data_cnt;	
							end 
					end 

			end_state : begin 
						rx_en <= 0;
						rx_sof <= 0;
						rx_eof <= 0;
						rx_data <= 0;
						rx_data_cnt <= 0;
						if(rx_data_cnt != rx_udp_total_length - 8)
							rx_error <= 1;
						else 
							rx_error <= 0;
					end 
					
			endcase 
	end

	assign udp_rx_sof = rx_sof;
	assign udp_rx_eof = rx_eof;
	assign udp_rx_en  = rx_en;
	assign udp_rx_data = rx_data;
	assign udp_byte_num = rx_udp_total_length - 8;
	assign udp_rx_error = rx_error;

endmodule

 

 

 

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值