基于FPAG的UDP数据包的收发
Posted fpga&matlab
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于FPAG的UDP数据包的收发相关的知识,希望对你有一定的参考价值。
收
`timescale 1ns / 1ps
//
// Module name : udp_rcv
// Project name :
// Target device:
// Author : lixiongxiong
// Create Date :
// Tool version :
// Description :
// IP datagram header format
//
// 0 4 8 16 19 24 31
// --------------------------------------------------------------------------------------------
// | src port | dst port |
// | | |
// --------------------------------------------------------------------------------------------
// | UDP length | checksum |
// | | |
// --------------------------------------------------------------------------------------------
// | Data |
// | |
// --------------------------------------------------------------------------------------------
// | .... |
// | |
// --------------------------------------------------------------------------------------------
//
// * - in 32 bit words
// All rights reserved,Software Technology Co., Ltd Wuhan
//
module udp_rcv
(
input tx_clk ,
input reset ,
input [31:0] ip_rcv_src_ip_addr ,
input [7 :0] udp_rcv_data ,
input udp_rcv_vld ,
output reg [15:0] udp_rcv_data_length ,
output reg [15:0] udp_rcv_src_port ,
output reg [15:0] udp_rcv_dst_port ,
output reg [31:0] udp_rcv_src_ip_addr ,
output reg [7 :0] udp_rcv_pdata ,
output reg udp_rcv_pvld ,
output reg [15:0] udp_rcv_pkt_cnt
);
reg [11:0] byte_counter ;
/*****************************************************************************************
******************************************************************************************/
always @(posedge tx_clk or negedge reset)
begin
if(reset == 1'b0)
byte_counter <= 12'd0;
else if(udp_rcv_vld == 1'b1)
byte_counter <= byte_counter + 1'b1;
else
byte_counter <= 12'd0;
end
/*****************************************************************************************
******************************************************************************************/
always @(posedge tx_clk or negedge reset)
begin
if(reset == 1'b0)
begin
udp_rcv_data_length<= 16'd0;
udp_rcv_src_port <= 16'd0;
udp_rcv_dst_port <= 32'd0;
udp_rcv_pdata <= 8'd0;
udp_rcv_pvld <= 1'b0;
udp_rcv_src_ip_addr <= 32'd0;
end
else if(udp_rcv_vld == 1'b1)
begin
case(byte_counter)
12'd0: begin
udp_rcv_src_port[15:8] <= udp_rcv_data;
udp_rcv_src_ip_addr <= ip_rcv_src_ip_addr;
end
12'd1: udp_rcv_src_port[7:0] <= udp_rcv_data;
12'd2: udp_rcv_dst_port[15:8] <= udp_rcv_data;
12'd3: udp_rcv_dst_port[7:0] <= udp_rcv_data;
12'd4: udp_rcv_data_length[15:8] <= udp_rcv_data;
12'd5: udp_rcv_data_length[7:0] <= udp_rcv_data;
12'd6: ;
12'd7: ;
default:
begin
udp_rcv_pdata <= udp_rcv_data;
udp_rcv_pvld <= 1'b1;
end
endcase
end
else
begin
udp_rcv_pdata <= 8'd0;
udp_rcv_pvld <= 1'b0;
end
end
/*****************************************************************************************
status calc
******************************************************************************************/
reg udp_rcv_vld_dly ;
always @(posedge tx_clk or negedge reset)
begin
if(reset == 1'b0)
udp_rcv_vld_dly <= 1'd0;
else
udp_rcv_vld_dly <= udp_rcv_vld;
end
always @(posedge tx_clk or negedge reset)
begin
if(reset == 1'b0)
udp_rcv_pkt_cnt <= 16'd0;
else if((udp_rcv_vld == 1'b1)&&(udp_rcv_vld_dly == 1'b0))
udp_rcv_pkt_cnt <= udp_rcv_pkt_cnt + 1'b1;
end
endmodule
发
`timescale 1ns / 1ps
//
// Module name : udp_send
// Project name :
// Target device:
// Author : lixiongxiong
// Create Date :
// Tool version :
// Description :
// IP datagram header format
//
// 0 4 8 16 19 24 31
// --------------------------------------------------------------------------------------------
// | src port | dst port |
// | | |
// --------------------------------------------------------------------------------------------
// | UDP length | checksum |
// | | |
// --------------------------------------------------------------------------------------------
// | Data |
// | |
// --------------------------------------------------------------------------------------------
// | .... |
// | |
// --------------------------------------------------------------------------------------------
//
// * - in 32 bit words
// All rights reserved,Software Technology Co., Ltd Wuhan
//
module udp_send
(
input tx_clk ,
input reset ,
input [7 :0] udp_send_pdata ,
input udp_send_pvld ,
output udp_send_ready ,
input [15:0] udp_send_src_port ,
input [15:0] udp_send_dst_port ,
input [31:0] udp_send_dst_ip_addr,
input [31:0] our_ip_address ,
output udp_nwk_req ,
output [15:0] udp_send_data_length,
output reg [31:0] udp_send_dst_ip_addr_r,
output reg [7 :0] udp_send_data ,
output reg udp_send_vld ,
output reg [15:0] udp_send_drop_pkt_cnt,
output reg [15:0] udp_send_pkt_cnt
);
reg [2 :0] udp_tx_state ;
reg [2 :0] nxt_udp_tx_state ;
reg [1 :0] udp_send_pvld_dly ;
reg [7 :0] udp_send_pdata_dly1 ;
reg [7 :0] udp_send_pdata_dly2 ;
wire rcv_start ;
wire rcv_end ;
wire udp_send_end ;
reg [10:0] byte_counter ;
reg [10:0] udp_send_pdata_length;
wire [15:0] udp_send_data_length1;
wire [15:0] udp_send_data_length2;
wire ram_wren ;
reg [15:0] checksum1 ;
wire [15:0] checksum_send ;
reg [3 :0] gen_checksum_cnt ;
wire gen_checksum_end ;
reg [15:0] udp_send_src_port_r ;
reg [15:0] udp_send_dst_port_r ;
reg [10:0] udp_reply_cnt ;
reg [10:0] rdaddress ;
wire [7 :0] ram_rdata ;
wire udp_send_drop ;
localparam IDLE = 3'd0;
localparam RECEIVE = 3'd1;
localparam GEN_CHECKSUM = 3'd2;
localparam SEND = 3'd3;
/*****************************************************************************************
******************************************************************************************/
always @(posedge tx_clk or negedge reset)
begin
if(reset == 1'b0)
begin
udp_send_src_port_r<= 16'd0;
udp_send_dst_port_r<= 16'd0;
udp_send_dst_ip_addr_r<= 32'd0;
end
else if(rcv_start == 1'b1)
begin
udp_send_src_port_r <= udp_send_src_port;
udp_send_dst_port_r <= udp_send_dst_port;
udp_send_dst_ip_addr_r <= udp_send_dst_ip_addr;
end
end
always @(posedge tx_clk or negedge reset)
begin
if(reset == 1'b0)
begin
udp_send_pvld_dly <= 2'd0;
udp_send_pdata_dly1<= 8'd0;
udp_send_pdata_dly2<= 8'd0;
end
else
begin
udp_send_pvld_dly <= {udp_send_pvld_dly[0],udp_send_pvld};
udp_send_pdata_dly1<= udp_send_pdata;
udp_send_pdata_dly2<= udp_send_pdata_dly1;
end
end
assign rcv_start = ((udp_send_pvld == 1'b1)&&(udp_send_pvld_dly[0] == 1'b0)) ? 1'b1 : 1'b0;
assign rcv_end = ((udp_send_pvld_dly[0] == 1'b0)&&(udp_send_pvld_dly[1] == 1'b1)) ? 1'b1 : 1'b0;
assign gen_checksum_end = ((udp_tx_state == GEN_CHECKSUM)&&(gen_checksum_cnt == 4'd9)) ? 1'b1 : 1'b0;
always @(posedge tx_clk or negedge reset)
begin
if(reset == 1'b0)
byte_counter <= 11'd0;
else if((udp_send_pvld_dly[0] == 1'b1)&&(udp_tx_state == RECEIVE))
byte_counter <= byte_counter + 1'b1;
else
byte_counter <= 11'd0;
end
always @(posedge tx_clk or negedge reset)
begin
if(reset == 1'b0)
gen_checksum_cnt <= 4'd0;
else if(udp_tx_state == GEN_CHECKSUM)
gen_checksum_cnt <= gen_checksum_cnt + 1'b1;
else
gen_checksum_cnt <= 4'd0;
end
always @(posedge tx_clk or negedge reset)
begin
if(reset == 1'b0)
udp_send_pdata_length <= 10'd0;
else if((udp_send_pvld_dly[0] == 1'b0)&&(udp_send_pvld_dly[1] == 1'b1))
udp_send_pdata_length <= byte_counter;
end
assign udp_send_data_length1 = {5'd0,udp_send_pdata_length}+16'd8;
assign udp_send_data_length2 = {5'd0,udp_send_pdata_length}+16'd8 + 16'd20;
assign udp_send_data_length = udp_send_data_length2;
/*****************************************************************************************
******************************************************************************************/
always @(posedge tx_clk or negedge reset)
begin
if(reset == 1'b0)
udp_tx_state <= IDLE;
else
udp_tx_state <= nxt_udp_tx_state;
end
always@(*)
begin
case(udp_tx_state)
IDLE:
begin
if(rcv_start == 1'b1)
nxt_udp_tx_state = RECEIVE;
else
nxt_udp_tx_state = IDLE;
end
RECEIVE:
begin
if(rcv_end == 1'b1)
nxt_udp_tx_state = GEN_CHECKSUM;
else
nxt_udp_tx_state = RECEIVE;
end
GEN_CHECKSUM:
begin
if(gen_checksum_end == 1'b1)
nxt_udp_tx_state = SEND;
else
nxt_udp_tx_state = GEN_CHECKSUM;
end
SEND:
begin
if(udp_send_end == 1'b1)
nxt_udp_tx_state = IDLE;
else
nxt_udp_tx_state = SEND;
end
default:
nxt_udp_tx_state <= IDLE;
endcase
end
/*****************************************************************************************
******************************************************************************************/
assign ram_wren = ((udp_tx_state == RECEIVE)&&(udp_send_pvld_dly[0] == 1'b1)) ? 1'b1 : 1'b0;
dpram_8d_10a u_dpram_8d_10a (
.clock ( tx_clk ),
.data ( udp_send_pdata_dly1 ),
.rdaddress ( rdaddress ),
.wraddress ( byte_counter ),
.wren ( ram_wren ),
.q ( ram_rdata )
);
always @(posedge tx_clk or negedge reset)
begin
if(reset == 1'b0)
rdaddress <= 11'd0;
else if((udp_tx_state == SEND)&&(udp_reply_cnt >= 11'd41))
rdaddress <= udp_reply_cnt-11'd41;
else
rdaddress <= 11'd0;
end
/*****************************************************************************************
******************************************************************************************/
always @(posedge tx_clk or negedge reset)
begin
if(reset == 1'b0)
checksum1 <= 16'd0;
else
begin
case(udp_tx_state)
IDLE: checksum1 <= 16'd0;
RECEIVE:
begin
if((udp_send_pvld_dly[0] == 1'b0)&&(udp_send_pvld_dly[1] == 1'b1)
&&(byte_counter[0] == 1'b1))
checksum1 <= complement({udp_send_pdata_dly2,8'h00},checksum1);
else if((udp_send_pvld_dly[0] == 1'b1)&&(byte_counter[0] == 1'b1))
checksum1 <= complement({udp_send_pdata_dly2,udp_send_pdata_dly1},checksum1);
else
checksum1 <= checksum1;
end
GEN_CHECKSUM:
begin
case(gen_checksum_cnt)
4'd0: checksum1 <= complement(our_ip_address[31:16],checksum1);
4'd1: checksum1 <= complement(our_ip_address[15:0],checksum1);
4'd2: checksum1 <= complement(udp_send_dst_ip_addr[31:16],checksum1);
4'd3: checksum1 <= complement(udp_send_dst_ip_addr[15:0],checksum1);
4'd4: checksum1 <= complement({8'd0,8'd17},checksum1);
4'd5: checksum1 <= complement(udp_send_data_length1,checksum1);
4'd6: checksum1 <= complement(udp_send_src_port_r,checksum1);
4'd7: checksum1 <= complement(udp_send_dst_port_r,checksum1);
4'd8: checksum1 <= complement(udp_send_data_length1,checksum1);
4'd9: checksum1 <= complement(16'd0,checksum1);
default:;
endcase
end
SEND: checksum1 <= checksum1;
default: checksum1 <= checksum1;
endcase
end
end
assign checksum_send = ~checksum1;
function [15:0] complement
(
input [15:0] dataina,
input [15:0] datainb
);
reg [16:0] temp ;
begin
temp = dataina + datainb;
complement = temp[15:0]+temp[16];
end
endfunction
/*****************************************************************************************
******************************************************************************************/
assign udp_nwk_req = gen_checksum_end;
assign udp_send_ready = (udp_tx_state == IDLE) ? 1'b1 : 1'b0;
always @(posedge tx_clk or negedge reset)
begin
if(reset == 1'b0)
udp_reply_cnt <= 11'd0;
else if(udp_tx_state == SEND)
udp_reply_cnt <= udp_reply_cnt + 1'b1;
else
udp_reply_cnt <= 11'd0;
end
assign udp_send_end = ((udp_reply_cnt == udp_send_pdata_length+8+20+14-1)&&(udp_tx_state == SEND)) ? 1'b1 : 1'b0;
//8-->udp header length
//20-->ip header length
//14-->ETH header length
always @(*)
begin
if(udp_reply_cnt < 11'd35)
udp_send_data = 8'd0;
else if(udp_reply_cnt == 11'd35)
udp_send_data = udp_send_src_port_r[15:8];
else if(udp_reply_cnt == 11'd36)
udp_send_data = udp_send_src_port_r[7:0];
else if(udp_reply_cnt == 11'd37)
udp_send_data = udp_send_dst_port_r[15:8];
else if(udp_reply_cnt == 11'd38)
udp_send_data = udp_send_dst_port_r[7:0];
else if(udp_reply_cnt == 11'd39)
udp_send_data = udp_send_data_length1[15:8];
else if(udp_reply_cnt == 11'd40)
udp_send_data = udp_send_data_length1[7:0];
else if(udp_reply_cnt == 11'd41)
udp_send_data = checksum_send[15:8];
else if(udp_reply_cnt == 11'd42)
udp_send_data = checksum_send[7:0];
else
udp_send_data = ram_rdata;
end
always @(posedge tx_clk or negedge reset)
begin
if(reset == 1'b0)
udp_send_vld <= 1'd0;
else if(udp_tx_state == SEND)
udp_send_vld <= 1'b1;
else
udp_send_vld <= 1'd0;
end
/*****************************************************************************************
status calc
******************************************************************************************/
assign udp_send_drop = ((rcv_start == 1'b1)&&(udp_send_ready == 1'b0)) ? 1'b1 : 1'b0;
always @(posedge tx_clk or negedge reset)
begin
if(reset == 1'b0)
udp_send_drop_pkt_cnt <= 16'd0;
else if(udp_send_drop == 1'b1)
udp_send_drop_pkt_cnt <= udp_send_drop_pkt_cnt + 1'b1;
end
always @(posedge tx_clk or negedge reset)
begin
if(reset == 1'b0)
udp_send_pkt_cnt <= 16'd0;
else if(rcv_start == 1'b1)
udp_send_pkt_cnt <= udp_send_pkt_cnt + 1'b1;
end
endmodule
以上是关于基于FPAG的UDP数据包的收发的主要内容,如果未能解决你的问题,请参考以下文章