米联客udp_stack以太网协议栈使用教程

实验室有一块米联客出的Kintex-7的板子,被我用来做毕业设计,其中使用到了千兆以太网的外设,于是打算使用米联客自己教程中所使用的协议栈来开发千兆以太网通信,接着就接触到了米联客的教程udp_stack.dcp。
//如果帮到你,一定要点赞收藏哦!//

0 使用背景

博主在很多设计部分参考了官方资料的udp_tx_speed工程,包括tri-mode ethernet IP, async/package FIFO的设置都与此同步,在此默认哥老倌们都已经配置好了。

1 协议栈介绍

1.1 结构拓扑

下图为udp_stack.dcp的结构,事实上博主只使用了数据发送回路。本来想把receive_buffer这一部分去掉的,后来发现,这部分用来接收反馈数据/反馈信号的,如果去掉,udp_stack.dcp就没法正常工作。
图1 2

1.2 接口描述

下图中是udp_stack.dcp的接口定义
在这里插入图片描述

在这里插入图片描述
在这些接口的连接中,除了app_tx_XXX博主是引出来自己写控制逻辑外,其余的都参照tx_speed教程中的连接方式了。

1.3 逻辑控制

下图是米联客给的时序图,所以主要任务即为控制app层的app_tx_XXX信号,让协议栈为我们打工!实现千兆以太网通信。
在这里插入图片描述
说到这儿,有人就要问了:“合着逻辑控制都是用嘴吹的,没法白嫖是吧?”
在这里插入图片描述
这就奉上自己写的代码,里面用了三段式Moore状态机来控制,已经过验证,该逻辑控制可行。

module TOP_CTRL(
	input clk_15_625,
	input clk_25,
	input clk_200,
	
	input rst_n,
	input udp_tx_ready,
	input app_tx_ack,
	input locked,
	input dst_ip_unreachable,
	
	output phy_rst_o,
	output reg app_tx_request,
	output reg app_tx_data_valid,
	output reg [63:0] app_tx_data,
	output reg [7:0] app_tx_data_keep,
	output reg app_tx_data_last,
	// output reg [15:0] package_length,
	output reg [3:0] state
    );
//reg definition
reg [15:0] delay_cnt;
reg [3:0] send_counter = 0;
// reg [3:0] state;
reg [4:0] next_state;
//wire definition

//parameter definition
parameter idle_state = 0;
parameter request_state = 1;
parameter transmit_state = 2;
parameter delay_state = 3;
//phy_rst_o output defintion
assign  phy_rst_o = (delay_cnt == 10'd100)? 1'b1 : 1'b0;

always @(posedge clk_25) begin
   if(!locked) 
         delay_cnt <= 10'd0;
   else begin
		 if(delay_cnt == 10'd100)
			delay_cnt <= delay_cnt;
		 else
		    delay_cnt <= delay_cnt + 1'b1;
   end
end

//The first stage of the state machine
always@(posedge clk_15_625 or negedge rst_n)
begin
    if(!rst_n)
        state <= idle_state;
    else
        state <=  next_state;
end

//The second stage of state machine
always@(negedge clk_15_625 or negedge rst_n)
begin
    if(!rst_n)
        begin
        next_state <= idle_state;
        end
    else
        begin
        case(state)
        
            idle_state:
                begin
                if(udp_tx_ready)
                 next_state <= request_state;
                else
                 next_state <= idle_state;
                end
                
            request_state:
                begin
                    if(app_tx_ack)
                    next_state <= transmit_state;
                    else if(dst_ip_unreachable)
                    next_state <= idle_state;
                    else
                    next_state <= next_state;
                end
            
            transmit_state:
                begin
                if(send_counter < 8)
                next_state <= next_state;
                else
                next_state <= delay_state;
                end
            
            delay_state:
                begin
                //Delay logic
                    next_state <= idle_state;
//                    else
//                    next_state <= delay_state;
                end
        
            default:
            next_state <= idle_state; 
        endcase
        end
end

//The third stage of state machine
always@(posedge clk_15_625 or negedge rst_n)
    begin
        if(!rst_n)
            begin			
            app_tx_data_valid <= 1'b0;			
			app_tx_request  <= 1'b0;            
			app_tx_data <= 64'd0;
            app_tx_data_last <= 1'b0;
            app_tx_data_keep <= 8'hff;
            send_counter <= 4'd0;
			// package_length <= 16'd8;
            end
        else
            begin
            case(state)
                idle_state:      
                    begin
                    app_tx_data = 64'h0;
					app_tx_request <= 1'b0;
					app_tx_data_valid <= 1'b0;
                    end
                
                request_state:      
                    begin
                    app_tx_data_valid <= 1'b0;
                    app_tx_request <= 1'b1;
                    end
                
                transmit_state:     
                    begin
                    app_tx_request <= 1'b0;
                    app_tx_data_valid <= 1'b1;
                    app_tx_data <= 64'h1122334455667788; 
                    if(send_counter == 4'd7)
                        begin
                        app_tx_data_keep <= 8'hff;
                         app_tx_data_last <= 1'b1;
                        end
                    else
                        begin
                        app_tx_data_keep <= 8'hff;
                        end
                    send_counter <= send_counter + 1'b1;
                    end
                
                delay_state:
                    begin
                    app_tx_data_valid <= 1'b0;
                    app_tx_data <= 64'h0; 
                    app_tx_data_keep <= 8'hff;
                    send_counter <= 4'd0;
                    app_tx_data_last <= 1'b0;
                    end 
                
                default:          
                    begin
                    app_tx_data <= 64'h0;
                    end
                
            endcase
            end
end

endmodule
白嫖的时候要记得点赞收藏,不然以后找不到回来的路。(阅完即删^V^

2 调试工具

博主在开发过程中使用了两个工具:
1.Vivado自带的Behavior simulation
2.烧写到板子,然后用chipscope/ila观察波形,值得一提的是,在仿真过程中udp_stack.dcp不能参与仿真,必须得要udp_stack.v! 那咋办嘛?难道要劳资花钱买源代码???
在这里插入图片描述
不用担心,博主给出了解决方案:
米联客含协议栈.dcp的工程仿真教程
在这里插入图片描述

注意:
0# 实际implementation 的时候又需要删除udp_stack.v
1# 起初调试过程中,发现udp_stack的发送回路和接受回路都可以通,但是无论如何udp_tx_ack也不能拉高,我勒个去,排查了几天,最后把自己写的三段式状态机替换了才知道原来问题出在时钟源,我的状态机控制那里是整个工程的,包括了千兆网口和其余的一些模块,因而使用的是默认的200MHz时钟源clk_200,但实际上udp_stack中控制关键引脚时应该使用的时钟时clk_15_625。

3 总结

值得一提的是,米联客推出千兆以太网解决方案,总体来说还是比较好的,但是目前时序约束貌似还没有改进,即使是官方例程也是不满足时序要求的
在这里插入图片描述
如果有没描述清楚的问题,欢迎大家留言讨论;
//如果帮到你,一定要点赞收藏哦!//

参考资料
[1] 03米联客2020版FPGA课程(UDP以太网通信篇).pdf
[2] 01_udp_rgmii_1g\02_udp_txspeed_rgmii参考工程

评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值