FPGA千兆网口数据传输MDIO接口——FPGA学习笔记3

这篇具有很好参考价值的文章主要介绍了FPGA千兆网口数据传输MDIO接口——FPGA学习笔记3。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、以太网简介

        是当今现有局域网采用的最通用的通信协议标准,它规定了包括物理层的连线、电子信号和介质访问层协议的内容。成本低,通信速率高,抗干扰能力强。

        1、分类

标准以太网:10Mbit/s

快速以太网:100Mbit/s

千兆以太网:1000Mbit/s

.........

以太网和千兆网口其实不完全相同。以太网是一种局域网技术标准,而千兆网口通常指的是支持1Gb/s(即千兆位每秒)速度的网络接口。

以太网是一种通用的局域网技术标准,定义了数据传输的规范和硬件设备之间的通信方式。而千兆网口是一种物理接口标准,用于连接计算机或其他网络设备到网络中,支持更高的数据传输速度。

因此,可以说千兆网口是以太网的一种实现方式,它提供了更快的数据传输速度,但并不等同于以太网。在实际应用中,通常会使用以太网技术,并通过千兆网口进行连接,以实现更快的网络通信速度。

        2、以太网接口

        以太网通信离不开连接端口的支持,网络数据连接的端口就是以太网接口。以太网接口类型有RJ45接口,RJ11接口(电话线接口),SC光纤接口等其中RJ45接口是我们现在最常见的网络设备接口(如:电脑网口)

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

3、6一对是为了向下兼容10/100M

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

上图为RGMII接口,时钟为双沿2.5MHz、25MHz、250MHz。位宽为4位。(节省引脚)

GMII接口,时钟为单沿1.25MHz、12.5MHz、125MHz。位宽为8位。

MAC侧完成对报文的封包和解包过程

PHY芯片:实现模数转换

ETH_RXC 接收端时钟
ETH_RXCTL 接收端数据使能(接受报文有效,该引脚拉高)
ETH_RXD[3:0] 接收数据
ETH_TXC 发送端时钟
ETH_TXCTL 发送端数据使能(发送报文有效,该引脚拉高)
ETH_TXD[3:0] 发送数据
ETH_RST_N 复位脚
ETH_MDC
ETH_MDIO

MDIO接口:(默认即可实现功能)

        3、UDP网络协议简介

UDP(User Datagram Protocol,用户数据报协议)是一种无连接的网络传输协议,位于OSI模型的传输层。以下是UDP网络协议的简介:

                (1)无连接性:UDP是一种无连接的协议,发送端在发送数据之前不需要与接收端建立连接,也不会维护连接状态。

                (2)面向数据报:UDP以数据报(Datagram)的形式传输数据,每个数据报都是独立的,互相之间没有关联。

                (3)不可靠性:UDP不提供数据可靠性保证,数据报可能会丢失、重复或无序到达。也不会进行数据校验和重传。

                (4)高效性:由于没有连接建立和维护的开销,以及简化的功能,UDP比TCP更轻量级,传输效率更高。

                (5)适用场景:UDP适用于对实时性要求高、数据传输完整性要求不高的应用场景,如音频、视频流媒体传输、在线游戏等。

                总的来说,UDP是一种简单、高效但不可靠的网络传输协议,适用于对实时性要求高、能容忍少量数据丢失的应用场景。

        4、数据链路

        数据通过FPGA进行数据协议的打包和MAC协议处理,通过RGMII总线协议传输将数据传送至PHY芯片,PHY芯片将数据进行处理后发送至RJ45接口进行数据发送。

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

        物理层(RJ45网口接口)、数据链路层(PHY芯片和MAC协议)、网络层(在FPGA中处理的MAC协议)、传输层(在FPGA中处理的数据协议打包,用UDP或者TCP协议就是说的这一层)

二、以太网PHY芯片简介RTL8211

        1、PHY芯片:物理层芯片(物理接口收发器)

                自动协商通信速率,或自行配置

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

        2、BMCI寄存器配置(RTL8211为例)

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

                BMCI寄存器addr为:0x00

                (1)0.15:软件复位,1复位,0工作。结束复位后,无需手动写0,结束复位会自动归0,基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

                (2)0.14:环回,主要用于检测,1使能,0失能。

                (3)0.13,0.6:Speed配置,配置不同速率(先失能自协商) 

                (4)0.12:自协商配置,默认使能,1使能,0失能。

                (5)0.11:掉电模式配置,1掉电模式,0正常工作模式。

                (6)0.10:隔离配置,RGMII接口隔离,引脚失能,只有MDIO,MDC配置有效

                (7)0.9:重新开始自协商配置。

                (8)0.8:双工模式配置

                (9)0.7:冲突测试

                (10)0.5:单向使能:1双方建立连接成功后通信,0直接通信

        3、BMSR寄存器配置

                BMCI寄存器addr为:0x01

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

                        (1)1.5:自协商完成

                        (2)1.2:是否连接OK

        4、PHYSR寄存器配置

                BMCI寄存器addr为:0x11

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

                (1)17.15:14  :连接速率(前提link ok,自协商完成)

三、以太网PHY芯片简介YT8531

        1、PHY芯片

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

网线差分模拟信号转换数字信号,FPGA数字信号转换网线差分模拟信号。

        2、引脚复用

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

        3、硬件原理图(正点原子达芬奇开发板)

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

22R电阻做阻抗匹配。

        4、PHY地址接口

一定会响应0x00!!

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

        5、基本控制寄存器配置

寄存器地址0x00

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

                (1) 15:软复位,带自清0,默认为0 。0工作,1复位。

                (2) 14:内部环回,默认为0。0失能,1使能。

                (3) 13:速率配置低位,关闭自协商才可以使用,bit6,13进行配置。

                (4) 12:自协商使能,默认支持。1使能,0失能。

                (5) 11:掉电模式,1掉电,0正常。

                (6) 10:隔离模式,一般为0正常模式

                (7) 9:重新自协商,自带置1。

                (8) 8:配置双工,关闭自协商才可以使用,1双工,0半双工。

        6、基本状态寄存器配置 

寄存器地址0x01

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

                (1) 13:双工模式检测。        0:半双工,         1:全双工。

                (2) 15~14:传输速度等级检测。10:1000M      01:100M       00:10M

                (3) 2:连接状态。      1:连接已建立,        0:链接未建立。

                (4) 3:自协商能力,    1具有,      0不具备。

                (5) 4:远端错误指示位:读取后自动清0         0:远端设备正常    1:远端设备异常

                (6) 5:自协商完成标志,软复位后自动清0       1:完成自协商      0:未完成自协商。

                (7) 6:前导码模式,1:不检测前导码直接接受        0:检测前导码

                (8) 7:单项传输能力:0:当检测到建立有效连接才开始传输     1:直接开始传输。

        7、特定状态寄存器

寄存器地址0x11

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

四、MDIO接口时序

        MDIO: Management Data Input/Output

        也被称为SMI ( Serial Management Interface ) ,即串行管理接口。

        MAC和 PHY芯片有一个配置接口,即MDIO接口,可以配置 PHY芯片的工作模式以及获取 PHY芯片的若干状态信息。 

        1、MDIO接口连接图

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

        2、PHY帧格式

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

        管理接口通过MDC和MDIO引脚提供对内部寄存器的访问,如IEEE802.3u第22节所述。MDC信号由MAC提供,是MDIO信号的管理数据时钟参考。MDIO是管理数据的输入/输出,是一个双向信号,与MDC同步运行。MDIO引脚需要一个1.5k欧姆的上拉电阻,以在空闲和周转期间保持MDIO高电平。

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

前置抑制为RTL8211E/RTL8211EG上电后的默认设置。然而,在操作之间仍然必须至少有一个空闲位。RTL8211E/RTL8211EG可以共享同一条MDIO线。在交换机/路由器应用程序中,每个端口应该在硬件复位序列中分配一个唯一的地址,并且只能通过该唯一的PHY地址进行寻址。有关RTL8211E/RTL8211EG管理寄存器的详细信息,请参见第30页第8节寄存器描述。

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

写状态下,一直由FPGA输出数据给到PHY芯片;读状态下,在TA位切换方向

                (1)Preamble:前导码,32个逻辑1,同时给出时钟。

                (2)ST:帧开始。固定01

                (3)OP:操作码,指示当前读写

                (4)PHYAD:PHY地址

                (5)REGAD:寄存器地址

                (6)TA:2bit宽度,时间间隔,切换FPGA数据线方向。Z为高阻状态,0为应答。

                (7)DATA:数据 

        3、PHY读写传输时序

                        上升沿采集数据,下降沿更新数据;MDC的最小周期为80ns对应时钟最大为12.5MHz 

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

 基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

五、MDIO读写测试实验

        PHY芯片不进行配置也可以使用 

        1、系统框图

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

        2、模块原理图

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

u_mdio_dri模块:

op_addr:读写地址

op_exec:触发信号↓↓↓↓↓↓↓↓↓↓↓

op_rh_wl:读写标志信号    1读    0写

op_wr_data:具体写入数据

op_done:读写结束后,拉高该信号

op_rd_ack:读应答信号    0应答     1未应答(帧格式里面的AT)

op_rd_data:读出的信号

dri_clk:驱动时钟

 当op_exec信号拉高标志一次读写操作开始,根据op_rh_wl状态判断读写操作,同时给出读写操作地址op_addr(如果是写操作要对应给出op_wr_data),读写操作结束后,拉高op_done信号,表示当前读写操作完成,控制模块可以发起下一次操作(如果是写读操作,在op_done为高期间,如果是0表示应答,如果是1表示未应答)(如果读操作,在op_done为高期间,会返回读到的数据)。

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

        3、状态机

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

        4、用户接口时序

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

        5、程序设计

                (1)mdio_dri模块

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

module mdio_dri #(
    parameter  PHY_ADDR = 5'b00100,//PHY地址
    parameter  CLK_DIV  = 6'd10    //分频系数
   )

    (
    input                clk       , //时钟信号
    input                rst_n     , //复位信号,低电平有效
    input                op_exec   , //触发开始信号
    input                op_rh_wl  , //低电平写,高电平读
    input        [4:0]   op_addr   , //寄存器地址
    input        [15:0]  op_wr_data, //写入寄存器的数据
    output  reg          op_done   , //读写完成
    output  reg  [15:0]  op_rd_data, //读出的数据
    output  reg          op_rd_ack , //读应答信号 0:应答 1:未应答
    output  reg          dri_clk   , //驱动时钟
    
    output  reg          eth_mdc   , //PHY管理接口的时钟信号 
    inout                eth_mdio    //PHY管理接口的双向数据信号
    );

//parameter define
localparam st_idle    = 6'b00_0001;  //空闲状态
localparam st_pre     = 6'b00_0010;  //发送PRE(前导码)
localparam st_start   = 6'b00_0100;  //开始状态,发送ST(开始)+OP(操作码)
localparam st_addr    = 6'b00_1000;  //写地址,发送PHY地址+寄存器地址
localparam st_wr_data = 6'b01_0000;  //TA+写数据
localparam st_rd_data = 6'b10_0000;  //TA+读数据

//reg define
reg    [5:0]  cur_state ;
reg    [5:0]  next_state;

reg    [5:0]  clk_cnt   ;  //分频计数                      
reg   [15:0]  wr_data_t ;  //缓存写寄存器的数据
reg    [4:0]  addr_t    ;  //缓存寄存器地址
reg    [6:0]  cnt       ;  //计数器
reg           st_done   ;  //状态开始跳转信号
reg    [1:0]  op_code   ;  //操作码  2'b01(写)  2'b10(读)                  
reg           mdio_dir  ;  //MDIO数据(SDA)方向控制
reg           mdio_out  ;  //MDIO输出信号
reg   [15:0]  rd_data_t ;  //缓存读寄存器数据

//wire define
wire          mdio_in    ; //MDIO数据输入
wire   [5:0]  clk_divide ; //PHY_CLK的分频系数

assign eth_mdio = mdio_dir ? mdio_out : 1'bz; //控制双向io方向
assign mdio_in = eth_mdio;                    //MDIO数据输入
//将PHY_CLK的分频系数除以2,得到dri_clk的分频系数,方便对MDC和MDIO信号操作
assign clk_divide = CLK_DIV >> 1;

//分频得到dri_clk时钟
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        dri_clk <=  1'b0;
        clk_cnt <= 1'b0;
    end
    else if(clk_cnt == clk_divide[5:1] - 1'd1) begin
        clk_cnt <= 1'b0;
        dri_clk <= ~dri_clk;
    end
    else
        clk_cnt <= clk_cnt + 1'b1;
end

//产生PHY_MDC时钟
always @(posedge dri_clk or negedge rst_n) begin
    if(!rst_n)
        eth_mdc <= 1'b1;
    else if(cnt[0] == 1'b0)
        eth_mdc <= 1'b1;
    else    
        eth_mdc <= 1'b0;  
end

//(三段式状态机)同步时序描述状态转移
always @(posedge dri_clk or negedge rst_n) begin
    if(!rst_n)
        cur_state <= st_idle;
    else
        cur_state <= next_state;
end  

//组合逻辑判断状态转移条件
always @(*) begin
    next_state = st_idle;
    case(cur_state)
        st_idle : begin
            if(op_exec)
                next_state = st_pre;
            else 
                next_state = st_idle;   
        end  
        st_pre : begin
            if(st_done)
                next_state = st_start;
            else
                next_state = st_pre;
        end
        st_start : begin
            if(st_done)
                next_state = st_addr;
            else
                next_state = st_start;
        end
        st_addr : begin
            if(st_done) begin
                if(op_code == 2'b01)                //MDIO接口写操作  
                    next_state = st_wr_data;
                else
                    next_state = st_rd_data;        //MDIO接口读操作  
            end
            else
                next_state = st_addr;
        end
        st_wr_data : begin
            if(st_done)
                next_state = st_idle;
            else
                next_state = st_wr_data;
        end        
        st_rd_data : begin
            if(st_done)
                next_state = st_idle;
            else
                next_state = st_rd_data;
        end                                                                          
        default : next_state = st_idle;
    endcase
  end

//时序电路描述状态输出
always @(posedge dri_clk or negedge rst_n) begin
    if(!rst_n) begin
        cnt <= 5'd0;
        op_code <= 1'b0;
        addr_t <= 1'b0;
        wr_data_t <= 1'b0;
        rd_data_t <= 1'b0;
        op_done <= 1'b0;
        st_done <= 1'b0; 
        op_rd_data <= 1'b0;
        op_rd_ack <= 1'b1;
        mdio_dir <= 1'b0;
        mdio_out <= 1'b1;
    end
    else begin
        st_done <= 1'b0 ;                            
        cnt     <= cnt +1'b1 ;          
        case(cur_state)
            st_idle : begin
                mdio_out <= 1'b1;                     
                mdio_dir <= 1'b0;                     
                op_done <= 1'b0;                     
                cnt <= 7'b0;  
                if(op_exec) begin
                    op_code <= {op_rh_wl,~op_rh_wl}; //OP_CODE: 2'b01(写)  2'b10(读) 
                    addr_t <= op_addr;
                    wr_data_t <= op_wr_data;
                    op_rd_ack <= 1'b1;
                end     
            end 
            st_pre : begin                          //发送前导码:32个1bit 
                mdio_dir <= 1'b1;                   //切换MDIO引脚方向:输出
                mdio_out <= 1'b1;                   //MDIO引脚输出高电平
                if(cnt == 7'd62) 
                    st_done <= 1'b1;
                else if(cnt == 7'd63)
                    cnt <= 7'b0;
            end            
            st_start  : begin
                case(cnt)
                    7'd1 : mdio_out <= 1'b0;        //发送开始信号 2'b01
                    7'd3 : mdio_out <= 1'b1; 
                    7'd5 : mdio_out <= op_code[1];  //发送操作码
                    7'd6 : st_done <= 1'b1;
                    7'd7 : begin
                               mdio_out <= op_code[0];
                               cnt <= 7'b0;  
                           end    
                    default : ;
                endcase
            end    
            st_addr : begin
                case(cnt)
                    7'd1 : mdio_out <= PHY_ADDR[4]; //发送PHY地址
                    7'd3 : mdio_out <= PHY_ADDR[3];
                    7'd5 : mdio_out <= PHY_ADDR[2];
                    7'd7 : mdio_out <= PHY_ADDR[1];  
                    7'd9 : mdio_out <= PHY_ADDR[0];
                    7'd11: mdio_out <= addr_t[4];  //发送寄存器地址
                    7'd13: mdio_out <= addr_t[3];
                    7'd15: mdio_out <= addr_t[2];
                    7'd17: mdio_out <= addr_t[1];  
                    7'd18: st_done <= 1'b1;
                    7'd19: begin
                               mdio_out <= addr_t[0]; 
                               cnt <= 7'd0;
                           end    
                    default : ;
                endcase                
            end    
            st_wr_data : begin
                case(cnt)
                    7'd1 : mdio_out <= 1'b1;         //发送TA,写操作(2'b10)
                    7'd3 : mdio_out <= 1'b0;
                    7'd5 : mdio_out <= wr_data_t[15];//发送写寄存器数据
                    7'd7 : mdio_out <= wr_data_t[14];
                    7'd9 : mdio_out <= wr_data_t[13];
                    7'd11: mdio_out <= wr_data_t[12];
                    7'd13: mdio_out <= wr_data_t[11];
                    7'd15: mdio_out <= wr_data_t[10];
                    7'd17: mdio_out <= wr_data_t[9];
                    7'd19: mdio_out <= wr_data_t[8];
                    7'd21: mdio_out <= wr_data_t[7];
                    7'd23: mdio_out <= wr_data_t[6];
                    7'd25: mdio_out <= wr_data_t[5];
                    7'd27: mdio_out <= wr_data_t[4];
                    7'd29: mdio_out <= wr_data_t[3];
                    7'd31: mdio_out <= wr_data_t[2];
                    7'd33: mdio_out <= wr_data_t[1];
                    7'd35: mdio_out <= wr_data_t[0];
                    7'd37: begin
                        mdio_dir <= 1'b0;
                        mdio_out <= 1'b1;
                    end
                    7'd39: st_done <= 1'b1;           
                    7'd40: begin
                               cnt <= 7'b0;
                               op_done <= 1'b1;      //写操作完成,拉高op_done信号 
                           end    
                    default : ;
                endcase    
            end
            st_rd_data : begin
                case(cnt)
                    7'd1 : begin
                        mdio_dir <= 1'b0;            //MDIO引脚切换至输入状态
                        mdio_out <= 1'b1;
                    end
                    7'd2 : ;                         //TA[1]位,该位为高阻状态,不操作             
                    7'd4 : op_rd_ack <= mdio_in;     //TA[0]位,0(应答) 1(未应答)
                    7'd6 : rd_data_t[15] <= mdio_in; //接收寄存器数据
                    7'd8 : rd_data_t[14] <= mdio_in;
                    7'd10: rd_data_t[13] <= mdio_in;
                    7'd12: rd_data_t[12] <= mdio_in;
                    7'd14: rd_data_t[11] <= mdio_in;
                    7'd16: rd_data_t[10] <= mdio_in;
                    7'd18: rd_data_t[9] <= mdio_in;
                    7'd20: rd_data_t[8] <= mdio_in;
                    7'd22: rd_data_t[7] <= mdio_in;
                    7'd24: rd_data_t[6] <= mdio_in;
                    7'd26: rd_data_t[5] <= mdio_in;
                    7'd28: rd_data_t[4] <= mdio_in;
                    7'd30: rd_data_t[3] <= mdio_in;
                    7'd32: rd_data_t[2] <= mdio_in;
                    7'd34: rd_data_t[1] <= mdio_in;
                    7'd36: rd_data_t[0] <= mdio_in;
                    7'd39: st_done <= 1'b1;
                    7'd40: begin
                        op_done <= 1'b1;             //读操作完成,拉高op_done信号          
                        op_rd_data <= rd_data_t;
                        rd_data_t <= 16'd0;
                        cnt <= 7'd0;
                    end
                    default : ;
                endcase   
            end                
            default : ;
        endcase               
    end
end                    

endmodule
                        ①控制双向io方向

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

                        ②分频得到dri_clk时钟

                 基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

                首先对CLK_DIV进行除2,目的是得到2倍的CLK_DIV时钟分频,再利用clk_cnt计数器产生dri_clk时钟。clk_divide[5:1] - 1'd1     取clk_divide的第5到第1位(实际作用除2取整,记满进行信号反转),再减掉1位作为计数器最大值、dri_clk信号跳转标志。(对时钟信号进行二分频)

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

                        ③产生PHY_MDC时钟

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

               cnt计数器最低位,实际只在0.1互相切换, 实际是对dri_clk进行二分频。(也就是dri_clk是MDC的两倍,此时eth_mdc是时钟频率四分频)

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

                        ④状态机——状态转移
//parameter define
localparam st_idle    = 6'b00_0001;  //空闲状态
localparam st_pre     = 6'b00_0010;  //发送PRE(前导码)
localparam st_start   = 6'b00_0100;  //开始状态,发送ST(开始)+OP(操作码)
localparam st_addr    = 6'b00_1000;  //写地址,发送PHY地址+寄存器地址
localparam st_wr_data = 6'b01_0000;  //TA+写数据
localparam st_rd_data = 6'b10_0000;  //TA+读数据
//(三段式状态机)同步时序描述状态转移
always @(posedge dri_clk or negedge rst_n) begin
    if(!rst_n)
        cur_state <= st_idle;
    else
        cur_state <= next_state;
end  

                状态转移,当前状态等于下一状态

                        ⑤状态机——状态转移条件
//组合逻辑判断状态转移条件
always @(*) begin
    next_state = st_idle;
    case(cur_state)
        st_idle : begin
            if(op_exec)
                next_state = st_pre;
            else 
                next_state = st_idle;   
        end  
        st_pre : begin
            if(st_done)
                next_state = st_start;
            else
                next_state = st_pre;
        end
        st_start : begin
            if(st_done)
                next_state = st_addr;
            else
                next_state = st_start;
        end
        st_addr : begin
            if(st_done) begin
                if(op_code == 2'b01)                //MDIO接口写操作  
                    next_state = st_wr_data;
                else
                    next_state = st_rd_data;        //MDIO接口读操作  
            end
            else
                next_state = st_addr;
        end
        st_wr_data : begin
            if(st_done)
                next_state = st_idle;
            else
                next_state = st_wr_data;
        end        
        st_rd_data : begin
            if(st_done)
                next_state = st_idle;
            else
                next_state = st_rd_data;
        end                                                                          
        default : next_state = st_idle;
    endcase
  end

        在 st_idle(空闲状态)模式下:op_exec(触发开始信号)拉高,下一状态进入st_pre,否则保持。

        在st_pre(发送PRE(前导码))模式下:st_done(状态开始跳转信号)拉高,下一状态进入st_start,否则保持

        在st_start(开始状态,发送ST(开始)+OP(操作码))模式下:st_done(状态开始跳转信号)拉高,下一状态进入st_addr,否则保持

        在st_addr(写地址,发送PHY地址+寄存器地址)模式下:如果op_code (操作码)== 2'b01,下一状态进入st_wr_data,否则进入st_rd_data

        在st_wr_data(TA+写数据)模式下:st_done(状态开始跳转信号)拉高,下一状态进入st_idle,否则保持

        在st_rd_data(TA+读数据)模式下:st_done(状态开始跳转信号)拉高,下一状态进入st_idle,否则保持

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

                        ⑥状态机——状态输出
//时序电路描述状态输出
always @(posedge dri_clk or negedge rst_n) begin
    if(!rst_n) begin
        cnt <= 5'd0;
        op_code <= 1'b0;
        addr_t <= 1'b0;
        wr_data_t <= 1'b0;
        rd_data_t <= 1'b0;
        op_done <= 1'b0;
        st_done <= 1'b0; 
        op_rd_data <= 1'b0;
        op_rd_ack <= 1'b1;
        mdio_dir <= 1'b0;
        mdio_out <= 1'b1;
    end
    else begin
        st_done <= 1'b0 ;                            
        cnt     <= cnt +1'b1 ;          
        case(cur_state)
            st_idle : begin
                mdio_out <= 1'b1;                     
                mdio_dir <= 1'b0;                     
                op_done <= 1'b0;                     
                cnt <= 7'b0;  
                if(op_exec) begin
                    op_code <= {op_rh_wl,~op_rh_wl}; //OP_CODE: 2'b01(写)  2'b10(读) 
                    addr_t <= op_addr;
                    wr_data_t <= op_wr_data;
                    op_rd_ack <= 1'b1;
                end     
            end 
            st_pre : begin                          //发送前导码:32个1bit 
                mdio_dir <= 1'b1;                   //切换MDIO引脚方向:输出
                mdio_out <= 1'b1;                   //MDIO引脚输出高电平
                if(cnt == 7'd62) 
                    st_done <= 1'b1;
                else if(cnt == 7'd63)
                    cnt <= 7'b0;
            end            
            st_start  : begin
                case(cnt)
                    7'd1 : mdio_out <= 1'b0;        //发送开始信号 2'b01
                    7'd3 : mdio_out <= 1'b1; 
                    7'd5 : mdio_out <= op_code[1];  //发送操作码
                    7'd6 : st_done <= 1'b1;
                    7'd7 : begin
                               mdio_out <= op_code[0];
                               cnt <= 7'b0;  
                           end    
                    default : ;
                endcase
            end    
            st_addr : begin
                case(cnt)
                    7'd1 : mdio_out <= PHY_ADDR[4]; //发送PHY地址
                    7'd3 : mdio_out <= PHY_ADDR[3];
                    7'd5 : mdio_out <= PHY_ADDR[2];
                    7'd7 : mdio_out <= PHY_ADDR[1];  
                    7'd9 : mdio_out <= PHY_ADDR[0];
                    7'd11: mdio_out <= addr_t[4];  //发送寄存器地址
                    7'd13: mdio_out <= addr_t[3];
                    7'd15: mdio_out <= addr_t[2];
                    7'd17: mdio_out <= addr_t[1];  
                    7'd18: st_done <= 1'b1;
                    7'd19: begin
                               mdio_out <= addr_t[0]; 
                               cnt <= 7'd0;
                           end    
                    default : ;
                endcase                
            end    
            st_wr_data : begin
                case(cnt)
                    7'd1 : mdio_out <= 1'b1;         //发送TA,写操作(2'b10)
                    7'd3 : mdio_out <= 1'b0;
                    7'd5 : mdio_out <= wr_data_t[15];//发送写寄存器数据
                    7'd7 : mdio_out <= wr_data_t[14];
                    7'd9 : mdio_out <= wr_data_t[13];
                    7'd11: mdio_out <= wr_data_t[12];
                    7'd13: mdio_out <= wr_data_t[11];
                    7'd15: mdio_out <= wr_data_t[10];
                    7'd17: mdio_out <= wr_data_t[9];
                    7'd19: mdio_out <= wr_data_t[8];
                    7'd21: mdio_out <= wr_data_t[7];
                    7'd23: mdio_out <= wr_data_t[6];
                    7'd25: mdio_out <= wr_data_t[5];
                    7'd27: mdio_out <= wr_data_t[4];
                    7'd29: mdio_out <= wr_data_t[3];
                    7'd31: mdio_out <= wr_data_t[2];
                    7'd33: mdio_out <= wr_data_t[1];
                    7'd35: mdio_out <= wr_data_t[0];
                    7'd37: begin
                        mdio_dir <= 1'b0;
                        mdio_out <= 1'b1;
                    end
                    7'd39: st_done <= 1'b1;           
                    7'd40: begin
                               cnt <= 7'b0;
                               op_done <= 1'b1;      //写操作完成,拉高op_done信号 
                           end    
                    default : ;
                endcase    
            end
            st_rd_data : begin
                case(cnt)
                    7'd1 : begin
                        mdio_dir <= 1'b0;            //MDIO引脚切换至输入状态
                        mdio_out <= 1'b1;
                    end
                    7'd2 : ;                         //TA[1]位,该位为高阻状态,不操作             
                    7'd4 : op_rd_ack <= mdio_in;     //TA[0]位,0(应答) 1(未应答)
                    7'd6 : rd_data_t[15] <= mdio_in; //接收寄存器数据
                    7'd8 : rd_data_t[14] <= mdio_in;
                    7'd10: rd_data_t[13] <= mdio_in;
                    7'd12: rd_data_t[12] <= mdio_in;
                    7'd14: rd_data_t[11] <= mdio_in;
                    7'd16: rd_data_t[10] <= mdio_in;
                    7'd18: rd_data_t[9] <= mdio_in;
                    7'd20: rd_data_t[8] <= mdio_in;
                    7'd22: rd_data_t[7] <= mdio_in;
                    7'd24: rd_data_t[6] <= mdio_in;
                    7'd26: rd_data_t[5] <= mdio_in;
                    7'd28: rd_data_t[4] <= mdio_in;
                    7'd30: rd_data_t[3] <= mdio_in;
                    7'd32: rd_data_t[2] <= mdio_in;
                    7'd34: rd_data_t[1] <= mdio_in;
                    7'd36: rd_data_t[0] <= mdio_in;
                    7'd39: st_done <= 1'b1;
                    7'd40: begin
                        op_done <= 1'b1;             //读操作完成,拉高op_done信号          
                        op_rd_data <= rd_data_t;
                        rd_data_t <= 16'd0;
                        cnt <= 7'd0;
                    end
                    default : ;
                endcase   
            end                
            default : ;
        endcase               
    end
end                    

endmodule

                复位后:cnt(计数器)、op_code(操作码  2'b01(写)  2'b10(读))、addr_t(缓存寄存器地址)、wr_data_t(缓存写寄存器的数据)、rd_data_t(缓存读寄存器数据)、op_done(读写完成)、st_done(状态开始跳转信号)、op_rd_data(读出的数据)、mdio_dir(MDIO数据(SDA)方向控制)清零。op_rd_ack(读应答信号 0:应答 1:未应答)、mdio_out(MDIO输出信号)置1。

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

        mdio_out(MDIO输出信号)置1、mdio_dir(MDIO数据(SDA)方向控制):输入、op_done(读写完成)置0。

        如果op_exec(触发信号)拉高,对op_code进行为拼接赋值,op_addr、op_wr_data进行寄存,op_rd_ack(读应答信号 0:应答 1:未应答)置1。

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

        dri_clk下计数63个上升沿,对应MDC时钟31个上升沿,即为发送32个前导码1。记满cnt清零

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

        发送起始信号ST01,发送读写操作码低电平写,op_code[1],op_code[0]低电平写,高电平读。st_done(状态开始跳转信号)置为1。        

        为什么cnt计数为奇数时改变数据:dri_clk为MDC的2倍,奇数刚好在MDC下降沿改变数据。

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

        依次发送PHY地址、寄存器地址,期间st_done(状态开始跳转信号)置为1

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

        发送TA写指令后,开始发送写入数据。之后将mdio_dir(MDIO数据(SDA)方向控制)置0释放总线进入高阻,mdio_out(MDIO输出信号)置1,op_done(读写完成)拉高标志一次读写造作结束。

 基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

         发送TA读指令后,TA[1]位无需操作保持高阻状态,由PHY侧控制总线。检测TA[0]位,如有应答,PHY侧会拉低mdio_in引脚,作为应答信号。依次接受16位读出数据寄存到rd_data_t下。之后op_done(读写完成)拉高标志一次读写造作结束,op_rd_data <= rd_data_t;进行输出其他新信号清零。

                (2)mdio_ctrl模块

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

module mdio_ctrl(
    input                clk           ,
    input                rst_n         ,
    input                soft_rst_trig , //软复位触发信号
    input                op_done       , //读写完成
    input        [15:0]  op_rd_data    , //读出的数据
    input                op_rd_ack     , //读应答信号 0:应答 1:未应答
    output  reg          op_exec       , //触发开始信号
    output  reg          op_rh_wl      , //低电平写,高电平读
    output  reg  [4:0]   op_addr       , //寄存器地址
    output  reg  [15:0]  op_wr_data    , //写入寄存器的数据
    output       [1:0]   led             //LED灯指示以太网连接状态
    );

//reg define
reg          rst_trig_d0;    
reg          rst_trig_d1;    
reg          rst_trig_flag;   //soft_rst_trig信号触发标志
reg  [23:0]  timer_cnt;       //定时计数器 
reg          timer_done;      //定时完成信号
reg          start_next;      //开始读下一个寄存器标致
reg          read_next;       //处于读下一个寄存器的过程
reg          link_error;      //链路断开或者自协商未完成
reg  [2:0]   flow_cnt;        //流程控制计数器 
reg  [1:0]   speed_status;    //连接速率 

//wire define
wire         pos_rst_trig;    //soft_rst_trig信号上升沿

//采soft_rst_trig信号上升沿
assign pos_rst_trig = ~rst_trig_d1 & rst_trig_d0;
//未连接或连接失败时led赋值00
// 01:10Mbps  10:100Mbps  11:1000Mbps 00:其他情况
assign led = link_error ? 2'b00: speed_status;
//对soft_rst_trig信号延时打拍
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        rst_trig_d0 <= 1'b0;
        rst_trig_d1 <= 1'b0;
    end
    else begin
        rst_trig_d0 <= soft_rst_trig;
        rst_trig_d1 <= rst_trig_d0;
    end
end

//定时计数
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        timer_cnt <= 1'b0;
        timer_done <= 1'b0;
    end
    else begin
        if(timer_cnt == 24'd1_000_000 - 1'b1) begin
            timer_done <= 1'b1;
            timer_cnt <= 1'b0;
        end
        else begin
            timer_done <= 1'b0;
            timer_cnt <= timer_cnt + 1'b1;
        end
    end
end    

//根据软复位信号对MDIO接口进行软复位,并定时读取以太网的连接状态
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        flow_cnt <= 3'd0;
        rst_trig_flag <= 1'b0;
        speed_status <= 2'b00;
        op_exec <= 1'b0; 
        op_rh_wl <= 1'b0; 
        op_addr <= 1'b0;       
        op_wr_data <= 1'b0; 
        start_next <= 1'b0; 
        read_next <= 1'b0; 
        link_error <= 1'b0;
    end
    else begin
        op_exec <= 1'b0; 
        if(pos_rst_trig)                      
            rst_trig_flag <= 1'b1;             //拉高软复位触发标志
        case(flow_cnt)
            2'd0 : begin
                if(rst_trig_flag) begin        //开始对MDIO接口进行软复位
                    op_exec <= 1'b1; 
                    op_rh_wl <= 1'b0; 
                    op_addr <= 5'h00; 
                    op_wr_data <= 16'h9140;    //Bit[15]=1'b1,表示软复位
                    flow_cnt <= 3'd1;
                end
                else if(timer_done) begin      //定时完成,获取以太网连接状态
                    op_exec <= 1'b1; 
                    op_rh_wl <= 1'b1; 
                    op_addr <= 5'h01; 
                    flow_cnt <= 3'd2;
                end
                else if(start_next) begin       //开始读下一个寄存器,获取以太网通信速度
                    op_exec <= 1'b1; 
                    op_rh_wl <= 1'b1; 
                    op_addr <= 5'h11;
                    flow_cnt <= 3'd2;
                    start_next <= 1'b0; 
                    read_next <= 1'b1; 
                end
            end    
            2'd1 : begin
                if(op_done) begin              //MDIO接口软复位完成
                    flow_cnt <= 3'd0;
                    rst_trig_flag <= 1'b0;
                end
            end
            2'd2 : begin                       
                if(op_done) begin              //MDIO接口读操作完成
                    if(op_rd_ack == 1'b0 && read_next == 1'b0) //读第一个寄存器,接口成功应答,
                        flow_cnt <= 3'd3;                      //读第下一个寄存器,接口成功应答
                    else if(op_rd_ack == 1'b0 && read_next == 1'b1)begin 
                        read_next <= 1'b0;
                        flow_cnt <= 3'd4;
                    end
                    else begin
                        flow_cnt <= 3'd0;
                     end
                end    
            end
            2'd3 : begin                     
                flow_cnt <= 3'd0;          //链路正常并且自协商完成
                if(op_rd_data[5] == 1'b1 && op_rd_data[2] == 1'b1)begin
                    start_next <= 1;
                    link_error <= 0;
                end
                else begin
                    link_error <= 1'b1;  
               end           
            end
            3'd4: begin
                flow_cnt <= 3'd0;
                if(op_rd_data[15:14] == 2'b10)
                    speed_status <= 2'b11; //1000Mbps
                else if(op_rd_data[15:14] == 2'b01) 
                    speed_status <= 2'b10; //100Mbps 
                else if(op_rd_data[15:14] == 2'b00) 
                    speed_status <= 2'b01; //10Mbps
                else
                    speed_status <= 2'b00; //其他情况  
            end
        endcase
    end    
end    

endmodule
                        ① 对soft_rst_trig信号延时打两拍

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

        对soft_rst_trig 软复位触发信号进行打两拍,抓取soft_rst_trig上升沿信号

                         ②定时计数

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

                         ③流程控制

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

         如果检测到soft_rst_trig 上升沿,将rst_trig_flag信号拉高

         不拉高op_exec原因:触摸按键按下实践不确定,如果在读写期间按下,拉高op_exec没有意义,无法达到复位效果。

        0状态:

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

        如果rst_trig_flag信号拉高,进行软复位,op_exec(触发开始信号)置1,op_rh_wl(低电平写,高电平读)置0。op_addr(寄存器地址)给出寄存器地址0x00,op_wr_data(写入寄存器的数据)对PHY芯片寄存器给出配置。flow_cnt下一状态进入1状态。

                16'h9140   =    2'b1001_0001_0100_0000‬

回看0x00寄存器,

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

                如果复位没有按下,则会等待计数器记满后,读取当前通信速率。op_exec(触发开始信号)置1,op_rh_wl(低电平写,高电平读)置1,op_addr(寄存器地址)给出寄存器地址0x01。flow_cnt下一状态进入2状态。

                16'h9140   =    2'b1001_0001_0100_0000‬

                如果计数器没有记满,start_next拉高时,op_exec(触发开始信号)置1,op_rh_wl(低电平写,高电平读)置1,op_addr(寄存器地址)给出寄存器地址0x11。flow_cnt下一状态进入2状态。start_next <= 1'b0;read_next <= 1'b1; 

        1状态:

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

        等待op_done读写结束标志拉高,下一状态为0状态,rst_trig_flag标志位拉低。

        2状态:

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

        如果应答信号op_rd_ack为0,read_next(寄存器读取标志)为0,跳转到3状态。

        如果read_next(寄存器读取标志)为1,重置read_next为0,下一状态为4状态。

        如果没有应答信号op_rd_ack为1时,下一状态进入0状态。

        3状态:

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

下一状态进入0状态。读出0x01寄存器的第5位和第2位,进行判断。符合条件(远端连接成功)start_next拉高。

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

         4状态:

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

        下一状态进入0状态,读取寄存器0x11的15、14位,的出对应的通信速率,赋值给speed_status。

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记

        利用三目运算为led进行赋值。

                (3)mdio_rw_test顶层

module mdio_rw_test(
    input          sys_clk  ,
    input          sys_rst_n,
    //MDIO接口
    output         eth_mdc  , //PHY管理接口的时钟信号
    inout          eth_mdio , //PHY管理接口的双向数据信号
    output         eth_rst_n, //以太网复位信号
    
    input          touch_key, //触摸按键
    output  [1:0]  led        //LED连接速率指示
    );
    
//wire define
wire          op_exec    ;  //触发开始信号
wire          op_rh_wl   ;  //低电平写,高电平读
wire  [4:0]   op_addr    ;  //寄存器地址
wire  [15:0]  op_wr_data ;  //写入寄存器的数据
wire          op_done    ;  //读写完成
wire  [15:0]  op_rd_data ;  //读出的数据
wire          op_rd_ack  ;  //读应答信号 0:应答   1:未应答
wire          dri_clk    ;  //驱动时钟

//硬件复位
assign eth_rst_n = sys_rst_n;

//MDIO接口驱动
mdio_dri #(
    .PHY_ADDR    (5'h04),   //PHY地址
    .CLK_DIV     (6'd10)    //分频系数
    )
    u_mdio_dri(
    .clk        (sys_clk),
    .rst_n      (sys_rst_n),
    .op_exec    (op_exec   ),
    .op_rh_wl   (op_rh_wl  ),   
    .op_addr    (op_addr   ),   
    .op_wr_data (op_wr_data),   
    .op_done    (op_done   ),   
    .op_rd_data (op_rd_data),   
    .op_rd_ack  (op_rd_ack ),   
    .dri_clk    (dri_clk   ),  
                 
    .eth_mdc    (eth_mdc   ),   
    .eth_mdio   (eth_mdio  )   
);      

//MDIO接口读写控制    
mdio_ctrl  u_mdio_ctrl(
    .clk           (dri_clk),  
    .rst_n         (sys_rst_n ),  
    .soft_rst_trig (touch_key ),  
    .op_done       (op_done   ),  
    .op_rd_data    (op_rd_data),  
    .op_rd_ack     (op_rd_ack ),  
    .op_exec       (op_exec   ),  
    .op_rh_wl      (op_rh_wl  ),  
    .op_addr       (op_addr   ),  
    .op_wr_data    (op_wr_data),  
    .led           (led       )
);      

endmodule

六、下载验证

基于fpga的rtl8211fd以太网接收程序,FPGA学习笔记,fpga开发,学习,笔记文章来源地址https://www.toymoban.com/news/detail-842838.html

到了这里,关于FPGA千兆网口数据传输MDIO接口——FPGA学习笔记3的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 千兆以太网(二)——MDIO接口协议

      MAC和PHY芯片有一个配置接口,即MDIO接口。可以配置PHY芯片的工作模式以及获取PHY芯片的状态信息。PHY芯片内部有一系列寄存器。用户通过配置寄存器来配置PHY芯片的工作模式。   FPGA通过MDIO接口对PHY芯片的内部寄存器进行配置。通常情况下芯片在默认情况下也可以工作

    2024年01月20日
    浏览(55)
  • FPGA学习笔记:数据采集传输系统设计(三):AD采集驱动ADC128S052

    ADC128S052为 12 位、8通道 的模数转换器 (ADC),转换速度高达 10 MSPS,采用SPI串行通信。 (1)工作时序图 应注意DIN中配置好的通道地址ADD在下一次采样时才生效 。 从时序图中可得出,ADC芯片在上升沿时采样,读取DIN数据;DOUT在下降沿时改变数据。 (2)串行时序图 片选信号在

    2024年02月07日
    浏览(56)
  • E9—TEMAC IP实现千兆网口UDP传输2023-08-28

    Tri Mode Ethernet MAC是收费IP,打开IP后,当左下角显示Bought IP license available则IP可用。 应用搭建的场景是,上位机发送数据,首先发起arp请求,随后下位机给出arp应答响应,上位机get到下位机的mac地址之后,将发送框中的数据打包成udp数据包下发到下位机中,下位机收到udp包,将

    2024年02月10日
    浏览(41)
  • FPGA(Verilog)实现uart传输协议传输数据(含仿真)

    目录 实现功能: 1.接收uart串行数据,输出并行数据(1byte)。 2.输入并行数据(1byte),输出uart串行数据。 3.完成uart传输的1次环回。 uart协议的1帧数据传输 模块封装-port设置 Verilog代码实现 1.uart接收模块:接收串行数据,输出并行数据和其有效标志。 仿真结果: 2.uart发送模块:接收

    2024年04月16日
    浏览(45)
  • FPGA 20个例程篇:13.千兆网口实现ARP通信协议(下)

            完成了RGMII接口和GMII接口转换的代码设计,接下来我们来设计以太网帧的报文解析模块,为了兼顾下一个例程中ICMP和UDP报文的解析,我们把ARP报文解析分成以太网首部解析和ARP数据解析两部分,这样以太网首部解析模块还可以再用到下一个例程当中提高了代码的复用

    2024年02月13日
    浏览(49)
  • FPGA 20个例程篇:14.千兆网口实现ICMP、UDP通信协议(上)

           UDP是一种面向无连接的传输层协议,属于TCP/IP协议族的一种,UDP具有消耗资源少、通信效率高等优点,一般性地用来传输音频或者视频等对实时性要求高的场合。         ICMP是TCP/IP协议族的一个IP层子协议,包含在IP数据报里,主要用于IP主机、路由器之间传递控制消

    2024年02月03日
    浏览(45)
  • FPGA 高速数据采集传输毕业论文【附仿真】

    以 FIFO IP 核以及 Verilog 编程设计的数字逻辑模块对JESD204B IP 核输出数据完成接收,处理成驱动设备可读取的数据格式后,送入设计的数字逻辑缓存部分中,通过AXI 总线送入DDR3 SDRAM 中缓存,并由传输部分数字逻辑模块完成缓存深度配置。  介绍设计的具体实现。在数字采集功

    2024年04月25日
    浏览(46)
  • FPGA中光纤,ddr3,srio数据传输速率、带宽分析

    需求分析:FPGA通过光纤接收数据,将接受的数据写入ddr中,再通过srio将数据传递给dsp。光纤传输的数据量为17万个32bit数据。 光纤速率分析:由于在光纤IP核中设置的速率为3.125G,单位bit。数据位宽为16bit。又由于光纤传输数据会进行8b/10b编码。因此单根光纤本地的传输速率

    2024年02月13日
    浏览(39)
  • SpringBoot案例 调用第三方接口传输数据

    最近再写调用三方接口传输数据的项目,这篇博客记录项目完成的过程,方便后续再碰到类似的项目可以快速上手 项目结构: 这里主要介绍HttpClient发送POST请求工具类和定时器的使用,mvc三层架构编码不做探究 pom.xml application-dev.yml Constast utils scheduled 该定时任务每10秒执行一

    2024年02月12日
    浏览(60)
  • 基于FPGA的EMAC模块与FIFO模块:高速数据传输与存储

    基于FPGA的EMAC模块与FIFO模块:高速数据传输与存储 在现代社会,高速数据传输和存储是信息技术领域的关键问题之一。而基于FPGA的EMAC模块与FIFO模块则成为了解决这些问题的重要途径。本文将介绍这两个模块的原理、实现方法以及如何在FPGA中应用它们。 EMAC模块是以太网MA

    2024年02月03日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包