IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> verilog实现UDP协议栈1:UDP打包部分的分析和编码 -> 正文阅读

[网络协议]verilog实现UDP协议栈1:UDP打包部分的分析和编码

参考1:IP包结构??ccIP报文格式详解_海阔天空sky的博客-CSDN博客_ip报文格式??????

我们看到UDP的头部很简单

?用C代码表示如下:

typedef struct _udp_hdr
{
unsigned short src_port; //远端口号
unsigned short dst_port; //目的端口号
unsigned short uhl;   //udp头部长度
unsigned short chk_sum; //16位udp检验和
}udp_hdr;

UDP的下一层是IP层,但是这个IP层也给多ICMP提供服务,所以IP专门做一个打包处理模块,所以这里UDP之按照UDP协议加上hdr就好。

这里我们要设计一个udp_tx_enframe模块,输入一个原始的数据包,输出一个打包好的udp数据包,但是不带ip包头。输入是:源端口,目的端口,字节流长度,以及字节流内容;输出为打包好的udp字节流。这里面因为牵扯了16位的chk_sum,我们要接收到所有的字节包后才能计算出来这个数值,因此我们必须有个缓存收完所有的字节流内容之后计算出来chk_sum之后再发出udp报头和报文。我们走的是以太网一个包大约1K-2K字节,我们选择一个2048字节的双口RAM做缓存。

我们还是按照流处理的一般规则,输入口做成slave输出口做成master。之后就写代码:




module udp_tx_pack (
		 input clk,rst,
		 input [31:0] src_ip,dst_ip;
		 input [15:0] src_port,dst_port, tx_len,
		 input tx_start,
		 output reg tx_busy ,
		 input [7:0] tx_dat,
		 
		 output [15:0]  udp_tx_len ,
		 output udp_tx_start,
		 input udp_tx_busy ,
		 output[7:0] udp_tx_dat ,
		 output reg  [31:0] udp_src_ip,udp_dst_ip
		 );
		 
		 
		 
		 reg [11:0] wr_addr,wr_addr_end ;
		 reg [7:0] wr_data;
		 reg wr_req;
		 
		 reg [11:0] rd_addr ;
		 reg [15:0]  st,st2 ; 
		 reg [11:0] wr_cntr ;
		 reg [15:0] src_port_reg ,dst_port_reg , tx_len_reg   ;
		 always @ (posedge clk) if (rst)   {src_port_reg ,dst_port_reg   }<=0;else if (st==100&tx_start) {src_port_reg ,dst_port_reg    } <={ src_port,dst_port };
		 always @ (posedge clk) if (rst)   wr_addr_end<=0; else if (st==100&tx_start) wr_addr_end <= tx_len + 4 ;
		 
		 always @(posedge clk) if (st=100&tx_start){udp_src_ip,udp_dst_ip}<={src_ip,dst_ip};
		 
		 always @ (posedge clk) if (rst)st<=0;else  case (st)
		 0:st<=100;
		 100: if (tx_start)st<= 200;
		 200: if (wr_addr == wr_addr_end ) st <= 300 ;
		 301,302,303,304,305,306,307:st<=st+1;
		 308: st<=400;// tell st2 can now pick this data
		 400: st<=500;
		 500: if (rd_addr==10 && st2==400) st<=600;
		 600: st<=100; // ok , free now 
		 default st<=0; 
		 endcase 
		 
		 reg [15:0] chksum = 0 ;
		 always @(posedge clk) if (rst) chksum<=0; else case (st)
		 0,100:		 chksum <= 0;
		 200,300,301,302,303,304,305,306,307: chksum<=chksum+wr_data ;
		 endcase 
		
		 always @(posedge clk) if (rst) tx_busy<=0;else case(st)200:busy<=1;600:busy<=0;endcase

		 always @(posedge clk)case (st)
			100:begin  wr_en<=1;wr_data<= tx_dat; wr_addr<= 4; end 
			200:begin  wr_en<=1;wr_data<= tx_dat; wr_addr<=wr_addr+1; end
			301:begin  wr_en<=1;wr_data<= src_port_reg[7:0]; wr_addr<=0 ; end
			300:begin  wr_en<=1;wr_data<= src_port_reg[15:8]; wr_addr<=1 ; end
			303:begin  wr_en<=1;wr_data<= dst_port_reg[7:0]; wr_addr<=2 ; end
			302:begin  wr_en<=1;wr_data<= dst_port_reg[15:8]; wr_addr<=3 ; end
			304:begin  wr_en<=1;wr_data<= 8; wr_addr<=4 ; end
			305:begin  wr_en<=1;wr_data<= 0; wr_addr<=5 ; end
			307:begin  wr_en<=1;wr_data<= chksum[7:0]; wr_addr<=6 ; end
			306:begin  wr_en<=1;wr_data<= chksum[15:8]; wr_addr<=7 ; end
			default begin  wr_en<=0;wr_data<=0 ; wr_addr<= 0; end
		endcase
		
		always@(posedge clk) if (rst)st2<=0;else case (st2)		
		0:st2<=100;
		100:if (st==400)st2<=200;
		200:if (udp_tx_busy==0) st2<=400;
		400:if (rd_addr == wr_addr_end) st2<=500 ;
		500:st2<=600;
		600:st2<=100;
		default st2<=0;
		endcase		
		
		always@(posedge clk) udp_tx_start<= st2==200 & udp_tx_busy!=0; 
		
		wire [7:0] rd_data ; assign  udp_tx_dat = rd_data;
 
		ram2port #( .DWIDTH(8),.AWIDTH(12))ram2port_i(.clk(clk),.wr_en(wr_en),.wr_addr(wr_addr) ,
			.rd_addr(rd_addr) ,.wr_data(wr_data),.rd_data(rd_data)  );

endmodule 
			

module ram2port
#(
    parameter DWIDTH=32,
    parameter AWIDTH=9
)
(
    input clk,
    input wr_en,
    input [AWIDTH-1:0] wr_addr ,
    input [AWIDTH-1:0] rd_addr ,
    input [DWIDTH-1:0] wr_data,
    output reg [DWIDTH-1:0] rd_data,
 );


reg [DWIDTH-1:0] ram [(1<<AWIDTH)-1:0];
integer 	    i;
initial begin
    for(i=0;i<(1<<AWIDTH);i=i+1)
        ram[i] <= {DWIDTH{1'b0}};
    rd_data <= 0;
end

always @ (posedge clk) if (wr_en) ram[wr_addr]<=wr_data;
always @ (posedge clk)  rd_data <= ram[rd_addr] ;
endmodule 



		 
		 
		 
		 
		 

上述代码粗略写写,代码还没有进行调试。有空继续。下一篇将写一些arp_cache。

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-12-04 13:46:48  更:2021-12-04 13:47:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年7日历 -2024/7/6 7:46:19-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码