基于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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: FPGA是可编程逻辑器件,可以根据需要自定义其功能。UART是通用异步收发传输接口的缩写。FPGA可以通过UART与外界进行通信,而数据包则是UART通信中用来传输数据的核心。 在FPGA中,通常会使用串口通信模块来实现与外部设备的通信,这包括与计算机、单片机等的通信。而UART通信中,数据包则是按照一定的格式传输数据的。数据包通常包括起始位、数据位、校验位、停止位等。在接收端,通过识别数据包中的这些信息,可以正确解读出发送端发送的数据。 在FPGA中实现UART通信和数据包传输,需要编写相应的Verilog或VHDL代码。其中,串口通信模块需要实现串口波特率设置、发送数据和接收数据等功能,而数据包传输则需要对数据采集、帧同步、CRC校验等进行处理。 总之,FPGA UART数据包是在FPGA中实现串口通信和数据传输的重要组成部分,通过合理的设计和编程可以实现高效、稳定和可靠的通信。 ### 回答2: FPGA UART数据包是在FPGA板上使用通用异步收发器传输数据的一种方式。通用异步收发器(UART)是一种常见的串行通信协议,通常用于在微处理器和外部设备之间进行数据传输。UART传输数据的方式是将数据分割成小的数据包(数据帧),然后添加一些控制信息,例如起始位、停止位、校验位等等,以确保数据的准确性和完整性。FPGA可以通过使用UART协议来与其他外设进行数据传输,例如电脑、传感器等。 在FPGA中,使用UART数据包的主要步骤包括:首先,设置串口通信的波特率,数据位数和校验方式等参数。然后,根据协议规定,将数据分割为帧,并在其前后添加控制位,以确保数据传输的正确。在传输数据时,FPGA通过将数据帧转换成串行数据流来发送给外设,然后接收外设发送的数据并进行解析和处理。 总之,FPGA使用UART数据包是FPGA与外设进行通信的一种可靠方式,可以用于传输各种类型的数据。通过使用UART协议,FPGA可以与许多不同的设备进行通信,并且在数据传输中具有高度可靠性和准确性。 ### 回答3: FPGA UART数据包是指使用FPGA实现通用异步收发传输器(UART)协议的数据包。UART是一种串行通信协议,常用于嵌入式系统中,可实现单向或双向通信。FPGA作为可编程逻辑器件,可以实现复杂的逻辑功能,因此可以用来实现UART协议。FPGA UART数据包通常包括起始位、数据位、校验位和停止位等几部分。起始位表示传输数据的开始,通常为逻辑0电平;数据位为实际传输的数据位数,可选5、6、7、8位之一;校验位用于确保数据传输的准确性,可选奇偶校验或无校验;停止位用于表示数据传输的结束,通常为逻辑1电平。FPGA UART数据包的组合和解析过程需要编写相应的Verilog或VHDL代码,其中包括时序控制、数据缓存、校验等基本模块。FPGA UART数据包的优点在于实现灵活、速度快、可扩展性强等方面,通常被应用于高性能的通信领域。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fpga和matlab

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值