本帖最后由 FPGA课程 于 2024-8-9 19:55 编辑
软件版本:Anlogic -TD5.9.1-DR1_ES1.1 操作系统:WIN10 64bit 硬件平台:适用安路(Anlogic)FPGA 实验平台:米联客-MLK-L1-CZ06-DR1M90G开发板 3.5 UDP层该层实现用户数据和UDP报文的互转,相比于其它层次的设计,该层的逻辑相对简单。 3.5.1 UDP接收模块通过计数器将UDP报文头部信息拆解,提取出端口号和长度信息。通过提取的长度对有效数据进行计数,从而得到有效数据并发送给用户端。 - always@(posedge I_R_udp_clk or posedge I_reset) begin
- if(I_reset) begin
- cnt <= 4'd0;
- O_R_udp_valid <= 1'b0;
- O_R_udp_data <= 8'd0;
- O_R_udp_len <= 16'd0;
- udp_src_port <= 16'd0;
- udp_dest_port <= 16'd0;
- udp_pkg_len <= 16'd0;
- udp_data_cnt <= 16'd0;
- end
- else if(I_udp_ip_rvalid) begin
- udp_data_cnt <= udp_data_cnt + 1'b1;
- case(cnt)
- 0 :begin udp_src_port[15:8] <= I_udp_ip_rdata; cnt <= cnt + 1'b1;end //UDP接收源端口(远程主机端口)
- 1 :begin udp_src_port[7:0] <= I_udp_ip_rdata; cnt <= cnt + 1'b1;end //UDP接收源端口(远程主机端口)
- 2 :begin udp_dest_port[15:8] <= I_udp_ip_rdata; cnt <= cnt + 1'b1;end //UDP接收目的端口(本地主机端口)
- 3 :begin udp_dest_port[7:0] <= I_udp_ip_rdata; cnt <= cnt + 1'b1;end //UDP接收目的端口(本地主机端口)
- 4 :begin udp_pkg_len[15:8] <= I_udp_ip_rdata; cnt <= cnt + 1'b1;end //UDP数据包长度
- 5 :begin udp_pkg_len[7:0] <= I_udp_ip_rdata; cnt <= cnt + 1'b1;end //UDP数据包长度
- 6 :begin cnt <= cnt + 1'b1;end //跳过检验和
- 7 :begin cnt <= cnt + 1'b1;end //跳过校验和
- 8 :begin
- O_R_udp_valid <= 1'b1; //UDP接收数据有效
- O_R_udp_data <= I_udp_ip_rdata;
- O_R_udp_len <= udp_pkg_len - 16'd8;
- cnt <= cnt + 1'b1;
- end
- 9 :begin
- if(udp_pkg_len < 16'd26) begin
- if(udp_data_cnt == udp_pkg_len) begin
- O_R_udp_valid <= 1'b0;
- O_R_udp_data <= 8'd0;
- cnt <= cnt + 1'b1;
- end
- else begin
- O_R_udp_valid <= 1'b1;
- O_R_udp_data <= I_udp_ip_rdata;
- cnt <= cnt;
- end
- end
- else begin
- O_R_udp_valid <= 1'b1;
- O_R_udp_data <= I_udp_ip_rdata;
- cnt <= cnt;
- end
- end
- 10 :begin
- O_R_udp_valid <= 1'b0;
- O_R_udp_data <= 8'd0;
- cnt <= cnt;
- end
- default: cnt <= 4'd0;
- endcase
- end
- else if(!I_udp_ip_rvalid) begin
- udp_pkg_len <= 16'd0;
- udp_src_port <= 16'd0;
- udp_dest_port <= 16'd0;
- udp_data_cnt <= 16'd0;
- O_R_udp_len <= 16'd0;
- O_R_udp_data <= 8'd0;
- O_R_udp_valid <= 1'b0;
- cnt <= 4'd0;
- end
- end
复制代码
3.5.2 UDP发送模块状态机转换图如下: IDLE:当用户端发送写请求,且uiip_tx模块不忙时,进入WAIT_ACK状态。 WAIT_ACK:等待uiip_tx模块将udp_ip_tbusy信号拉高,完成握手,进入SEND_UDP_HEADER状态,开始发送UDP报文头部。 SEND_UDP_HEADER:将8个字节的UDP报文头部添加在有效数据之前,头部数据发送完成后,进入SEND_UDP_PACKET状态。 SEND_UDP_PACKET:将经过shift_ram移位8位的数据拼接在包头之后,通过计数器判断发送数据的数量,待数据发送完成后,回到IDLE状态,等待下一次发送请求。 - always@(posedge I_W_udp_clk or posedge I_reset) begin
- if(I_reset) begin
- cnt <= 4'd0;
- O_udp_ip_tvalid <= 1'b0;
- O_udp_ip_tdata <= 8'd0;
- O_udp_ip_tpkg_len <= 16'd0;
- trans_data_cnt <= 16'd0;
- STATE <= IDLE;
- end
- else begin
- case(STATE)
- IDLE:begin
- if(I_W_udp_req & (~I_udp_ip_tbusy)) //当有写UDP请求,并且ip_tx模块不忙(当I_udp_ip_tbusy=1代表正在ip层正在传输数据)
- STATE <= WAIT_ACK; //进入WAIT_ACK
- else
- STATE <= IDLE;
- end
- WAIT_ACK:begin
- if(I_udp_ip_tbusy) //如果ip_tx模块准备好,代表udp_layer可以发送数据
- STATE <= SEND_UDP_HEADER;
- else
- STATE <= WAIT_ACK;
- end
- SEND_UDP_HEADER:begin
- case(cnt)
- 0 :begin
- if(I_W_udp_valid) begin
- O_udp_ip_tvalid <= 1'b1; //udp包数据有效
- O_udp_ip_tdata <= I_udp_local_port[15:8]; //UDP报文源端口
- O_udp_ip_tpkg_len <= I_W_udp_len + 16'h0008; //UDP报文长度,其中8bytes为udp首部
-
- cnt <= cnt + 1'b1;
- end
- else
- cnt <= 0;
- end
- 1 :begin
- O_udp_ip_tdata <= I_udp_local_port[7:0]; //UDP报文源端口
- cnt <= cnt + 1'b1;
- end
- 2 :begin
- O_udp_ip_tdata <= I_udp_dest_port[15:8]; //UDP报文目的端口
- cnt <= cnt + 1'b1;
- end
- 3 :begin
- O_udp_ip_tdata <= I_udp_dest_port[7:0]; //UDP报文目的端口
- cnt <= cnt + 1'b1;
- end
- 4 :begin
- O_udp_ip_tdata <= O_udp_ip_tpkg_len[15:8];//UDP报文长度
- cnt <= cnt + 1'b1;
- end
- 5 :begin
- O_udp_ip_tdata <= O_udp_ip_tpkg_len[7:0]; //UDP报文长度
- cnt <= cnt + 1'b1;
- end
- 6 :begin
- O_udp_ip_tdata <= CHECKSUM[7:0]; //校验和
- cnt <= cnt + 1'b1;
- end
- 7 :begin
- O_udp_ip_tdata <= CHECKSUM [7:0]; //校验和
- cnt <= 0;
- STATE <= SEND_UDP_PACKET;
- end
- default: cnt <= 0;
- endcase
- end
- SEND_UDP_PACKET:begin
- if(trans_data_cnt != (O_udp_ip_tpkg_len - 16'd8)) begin
- O_udp_ip_tvalid <= 1'b1;
- O_udp_ip_tdata <= shift_data_out;
- trans_data_cnt <= trans_data_cnt + 1'b1;
- STATE <= SEND_UDP_PACKET;
- end
- else begin
- trans_data_cnt <= 16'd0;
- O_udp_ip_tdata <= 8'd0;
- O_udp_ip_tvalid <= 1'b0;
- O_udp_ip_tpkg_len <= 16'd0;
- cnt <= 0;
- STATE <= IDLE;
- end
- end
- default: STATE <= IDLE;
- endcase
- end
- end
复制代码
|