当从应用层得到数据时, eth_udp_tx.v 模块将在应用层发送过来数据的基础上,附加上udp 源port, udp 目的port , udp 长度, udp 的checksum 信息。 打成一个完整的udp包,送给ip层。在这个模块中,UDP_TX_CHECKSUM_EN 参数用来控制是否在udp 数据上加载checksum信息,如果不加载checksum 信息, 在checksum 的位置上填写0; 如果加载checksum,就需要计算 udp 头和整体的udp 数据,生成真实的checksum。

图1

图2
本节内容关心的一些关键信号,以时序图的方式呈现,如图3所示:

图3
udp_tx_st和udp_chk_st两个状态机的示意如图4(注意省略了状态转移条件不满足时,停留在当前状态的箭头)所示。

图4 udp_tx_st和udp_chk_st状态机示意图
udp_tx_st 状态机逻辑:
状态机0:初始化相关的数据,UDP_TX_DRAM的子地址指向 1023,跳转到状态机1。
状态机1:等待1个时钟周期,跳转到状态机2。
状态机2:当buffer 目前为空,跳转到状态机3。
状态机3:在地址0 的位置上填写udp 源port,跳转到状态机4。
状态机4:在地址1 的位置上填写udp 目的port,跳转到状态机5。
状态机5:先是在地址3 的位置上填写udp checksum 为 0,跳转到状态机6。
状态机6:将应用层的数据(byte)写入到buffer中去,跳转到状态机7。
状态机7:将应用层的数据(byte)写入到buffer中去,跳转到状态机8,如果没有数据,跳转到状态9。
状态机8:将应用层的数据(byte)写入到buffer中去,跳转到状态机7,如果没有数据,跳转到状态9。
状态机9:正常的数据包结束,在地址2 的位置上填写udp 的长度,如果需要计算checksum,跳转到状态10; 如果不需要checksum, 跳转到状态13。
状态机10:在udp头上填写udp 的checksum,跳转到状态13。
状态机13:对UDP_TX_DRAM的buffer进行封包,跳转到状态14。
状态机14:跳转到状态15。
状态机15:UDP_TX_DRAM的buffer 加一,跳转到状态0。
udp_chk_st 伴随状态机:
状态0: 初始化 udp_chk_sum = 16’h0011, 跳转状态 1。
状态1: 计算udp 数据的checksum, 当udp数据写入结束后,跳转状态 2。
状态2: 再计算一次udp length的checksum,跳转状态 3。
状态3: 计算源ip 地址checksum,跳转状态 4。
状态4: 计算源ip 地址checksum,跳转状态 5。
状态5: 计算目的ip 地址checksum,跳转状态 6。
状态6: 计算目的ip 地址checksum,跳转状态 7。
状态7: 计算完整的udp的checksum,标识udp checksum 计算结束,跳转状态 8。
状态8: 等待当前包封包结束,跳转状态 0。
eth_udp_tx.v 代码:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 |
`timescale 1ns / 1ps module eth_udp_tx # ( parameter [31:0] TX_IP_SRC = 32'hc0a8003d, parameter [31:0] TX_IP_DES = 32'hc0a800ff, parameter [15:0] UDP_TX_SRC_PORT = 16'hffff, parameter [15:0] UDP_TX_DES_PORT = 16'hffff, parameter UDP_TX_CHECKSUM_EN = 0, parameter IP_BUF_SIZE = 10, parameter IP_IDX_BIT = 1 ) ( input sys_clk, input [7:0] udp_din, input udp_din_vld, output reg udp_din_rdy = 0, output reg udp_tx_wea = 0, output [IP_BUF_SIZE + IP_IDX_BIT - 1:0] udp_tx_addra, output reg [15:0] udp_tx_dina = 0, input [15:0] udp_tx_douta, input reset ); //========================================================================= reg [IP_BUF_SIZE - 1:0] udp_tx_addra_sub = 0; reg [IP_IDX_BIT - 1:0] udp_tx_ida = 0; assign udp_tx_addra = {udp_tx_ida, udp_tx_addra_sub}; //======================================================================= reg [31:0] udp_chk_sum = 16'h0011; //UDP protocol reg udp_chk_end = 0; reg udp_chk_vld = 0; reg [15:0] udp_tx_cnt = 0; reg [3:0] udp_tx_st = 0; always @ (posedge sys_clk) if(reset) begin udp_din_rdy <= 0; udp_tx_ida <= 0; udp_tx_wea <= 0; udp_tx_st <= 0; end else case (udp_tx_st) 0: begin udp_chk_end <= 0; udp_tx_cnt <= 8; //count the UDP header udp_tx_wea <= 0; udp_tx_addra_sub <= {IP_BUF_SIZE{1'b1}}; udp_tx_st <= 1; end 1: begin udp_tx_wea <= 0; udp_tx_addra_sub <= {IP_BUF_SIZE{1'b1}}; udp_tx_st <= 2; end 2: begin if(udp_tx_douta[15] == 0) begin udp_tx_st <= 3; end end 3: begin udp_tx_addra_sub <= udp_tx_addra_sub + 1; //addr 0 udp_tx_dina <= UDP_TX_SRC_PORT[15:0]; udp_tx_wea <= 1; udp_tx_st <= 4; end 4: begin udp_tx_addra_sub <= udp_tx_addra_sub + 1; //addr 1 udp_tx_dina <= UDP_TX_DES_PORT[15:0]; udp_tx_wea <= 1; udp_tx_st <= 5; end 5: begin udp_tx_addra_sub <= 3; // checksum udp_tx_dina <= 16'h0000; udp_tx_wea <= 1; udp_din_rdy <= 1; udp_tx_st <= 6; end 6: //state 6-7 together write 2 bytes, using 2 clocks to fill 16 bits data into A/B Buffer begin udp_tx_wea <= 0; if(udp_din_vld & udp_din_rdy) begin udp_tx_addra_sub <= udp_tx_addra_sub + 1; udp_tx_dina <= {udp_din, 8'h00}; //odd udp_tx_cnt <= udp_tx_cnt + 1; udp_tx_st <= 7; end end 7: //state 7-8 together write 2 bytes, using 2 clocks to fill 16 bits data into A/B Buffer begin udp_tx_wea <= 1; if(udp_din_vld & udp_din_rdy) begin udp_tx_dina[7:0] <= udp_din; // even udp_tx_cnt <= udp_tx_cnt + 1; if(udp_tx_cnt == 1471) // 1518 - 4 (crc) - 20 - 14 - 8 udp_din_rdy <= 0; udp_tx_st <= 8; end else begin udp_din_rdy <= 0; udp_tx_st <= 9; end end 8: begin udp_tx_wea <= 0; if(udp_din_vld & udp_din_rdy) begin udp_tx_addra_sub <= udp_tx_addra_sub + 1; udp_tx_dina <= {udp_din, 8'h00}; udp_tx_cnt <= udp_tx_cnt + 1; if(udp_tx_cnt == 1471) // 1518 -4 (crc) - 20 - 14 - 8 udp_din_rdy <= 0; udp_tx_st <= 7; end else begin udp_din_rdy <= 0; udp_tx_st <= 9; end end 9: begin udp_tx_addra_sub <= 2; udp_tx_dina <= udp_tx_cnt[15:0]; udp_tx_wea <= 1; udp_chk_end <= 1; if(UDP_TX_CHECKSUM_EN) udp_tx_st <= 10; else udp_tx_st <= 13; end 10: begin udp_tx_wea <= 0; if(udp_chk_vld) begin udp_tx_addra_sub <= 3; // checksum udp_tx_dina <= udp_chk_sum[15:0]; udp_tx_wea <= 1; udp_tx_st <= 13; end end 13: begin udp_tx_addra_sub <= {IP_BUF_SIZE{1'b1}}; udp_tx_dina <= {4'b1000, udp_tx_cnt[11:0]}; udp_tx_wea <= 1; udp_tx_st <= 14; end 14: begin udp_chk_end <= 0; udp_tx_wea <= 0; udp_tx_st <= 15; end 15: // normal finished begin udp_tx_ida <= udp_tx_ida + 1; udp_tx_wea <= 0; udp_tx_st <= 0; end default: udp_tx_st <= 0; endcase reg [3:0] udp_chk_st = 0; always @ (posedge sys_clk) if(reset) begin udp_chk_vld <= 0; udp_chk_st <= 0; udp_chk_sum <= 16'h0011; end else case (udp_chk_st) 0: begin udp_chk_vld <= 0; udp_chk_sum <= 16'h0011; udp_chk_st <= 1; end 1: begin if(udp_tx_wea) udp_chk_sum <= udp_chk_sum + udp_tx_dina; if(udp_chk_end) udp_chk_st <= 2; end 2: //add UDP length again begin udp_chk_sum <= udp_chk_sum + udp_tx_dina; udp_chk_st <= 3; end 3: begin udp_chk_sum <= udp_chk_sum + TX_IP_SRC[31:16]; udp_chk_st <= 4; end 4: begin udp_chk_sum <= udp_chk_sum + TX_IP_SRC[15:00]; udp_chk_st <= 5; end 5: begin udp_chk_sum <= udp_chk_sum + TX_IP_DES[31:16]; udp_chk_st <= 6; end 6: begin udp_chk_sum <= udp_chk_sum + TX_IP_DES[15:00]; udp_chk_st <= 7; end 7: begin if(|udp_chk_sum[31:16]) udp_chk_sum <= udp_chk_sum[15:0] + udp_chk_sum[31:16]; else begin udp_chk_sum[15:0] <= ~udp_chk_sum[15:0]; udp_chk_vld <= 1; udp_chk_st <= 8; end end 8: begin udp_chk_vld <= 0; if(udp_chk_end == 0) udp_chk_st <= 0; end default: udp_chk_st <= 0; endcase //========================================================================= endmodule |
更多详细内容请参考相关视频。