FPGA模块——以太网芯片MDIO读写

FPGA模块——以太网MDIO读写

  • MDIO接口介绍
  • MDIO接口代码
    • (1)MDIO接口驱动代码
    • (2)使用MDIO驱动的代码

MDIO接口介绍

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

1.MDIO部分的接口结构
在这里插入图片描述

2.千兆以太网在接口上兼容百兆和十兆以太网。
在这里插入图片描述
在这里插入图片描述
3.YT8511 是一个千兆以太网物理层收发器,支持 1000/100/10Mbps 通信速率,该芯片内部的参数可以通过MDIO接口进行配置。
在这里插入图片描述

MDIO接口代码

MDIO接口主要是控制三根接口线,进行驱动和读写。
在这里插入图片描述

(1)MDIO接口驱动代码

mdio_dri文件:输入一些读写开始等等控制信号,输出读到的数据和控制芯片的时钟

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) beginif(!rst_n) begindri_clk <=  1'b0;clk_cnt <= 1'b0;endelse if(clk_cnt == clk_divide[5:1] - 1'd1) beginclk_cnt <= 1'b0;dri_clk <= ~dri_clk;endelseclk_cnt <= clk_cnt + 1'b1;
end//产生PHY_MDC时钟
always @(posedge dri_clk or negedge rst_n) beginif(!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) beginif(!rst_n)cur_state <= st_idle;elsecur_state <= next_state;
end  //组合逻辑判断状态转移条件
always @(*) beginnext_state = st_idle;case(cur_state)st_idle : beginif(op_exec)next_state = st_pre;else next_state = st_idle;   end  st_pre : beginif(st_done)next_state = st_start;elsenext_state = st_pre;endst_start : beginif(st_done)next_state = st_addr;elsenext_state = st_start;endst_addr : beginif(st_done) beginif(op_code == 2'b01)                //MDIO接口写操作  next_state = st_wr_data;elsenext_state = st_rd_data;        //MDIO接口读操作  endelsenext_state = st_addr;endst_wr_data : beginif(st_done)next_state = st_idle;elsenext_state = st_wr_data;end        st_rd_data : beginif(st_done)next_state = st_idle;elsenext_state = st_rd_data;end                                                                          default : next_state = st_idle;endcaseend//时序电路描述状态输出
always @(posedge dri_clk or negedge rst_n) beginif(!rst_n) begincnt <= 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;endelse beginst_done <= 1'b0 ;                            cnt     <= cnt +1'b1 ;          case(cur_state)st_idle : beginmdio_out <= 1'b1;                     mdio_dir <= 1'b0;                     op_done <= 1'b0;                     cnt <= 7'b0;  if(op_exec) beginop_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  : begincase(cnt)7'd1 : mdio_out <= 1'b0;        //发送开始信号 2'b017'd3 : mdio_out <= 1'b1; 7'd5 : mdio_out <= op_code[1];  //发送操作码7'd6 : st_done <= 1'b1;7'd7 : beginmdio_out <= op_code[0];cnt <= 7'b0;  end    default : ;endcaseend    st_addr : begincase(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: beginmdio_out <= addr_t[0]; cnt <= 7'd0;end    default : ;endcase                end    st_wr_data : begincase(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: beginmdio_dir <= 1'b0;mdio_out <= 1'b1;end7'd39: st_done <= 1'b1;           7'd40: begincnt <= 7'b0;op_done <= 1'b1;      //写操作完成,拉高op_done信号 end    default : ;endcase    endst_rd_data : begincase(cnt)7'd1 : beginmdio_dir <= 1'b0;            //MDIO引脚切换至输入状态mdio_out <= 1'b1;end7'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: beginop_done <= 1'b1;             //读操作完成,拉高op_done信号          op_rd_data <= rd_data_t;rd_data_t <= 16'd0;cnt <= 7'd0;enddefault : ;endcase   end                default : ;endcase               end
end                    endmodule

(2)使用MDIO驱动的代码

mdio_ctrl文件:对寄存器进行读写配置,主要还是读取状态,用于显示

1.基本控制寄存器地址:0x00
代码里面配置为16’h9140 即1001_0001_0100_0000
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.基本状态寄存器地址:0x01
用来读出转态信息
在这里插入图片描述
在这里插入图片描述

3.特定状态寄存器地址:0x11
在这里插入图片描述

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) beginif(!rst_n) beginrst_trig_d0 <= 1'b0;rst_trig_d1 <= 1'b0;endelse beginrst_trig_d0 <= soft_rst_trig;rst_trig_d1 <= rst_trig_d0;end
end//定时计数
always @(posedge clk or negedge rst_n) beginif(!rst_n) begintimer_cnt <= 1'b0;timer_done <= 1'b0;endelse beginif(timer_cnt == 24'd1_000_000 - 1'b1) begintimer_done <= 1'b1;timer_cnt <= 1'b0;endelse begintimer_done <= 1'b0;timer_cnt <= timer_cnt + 1'b1;endend
end    //根据软复位信号对MDIO接口进行软复位,并定时读取以太网的连接状态
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginflow_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;endelse beginop_exec <= 1'b0; if(pos_rst_trig)                      rst_trig_flag <= 1'b1;             //拉高软复位触发标志case(flow_cnt)2'd0 : beginif(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;endelse if(timer_done) begin      //定时完成,获取以太网连接状态op_exec <= 1'b1; op_rh_wl <= 1'b1; op_addr <= 5'h01; flow_cnt <= 3'd2;endelse 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; endend    2'd1 : beginif(op_done) begin              //MDIO接口软复位完成flow_cnt <= 3'd0;rst_trig_flag <= 1'b0;endend2'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;endelse beginflow_cnt <= 3'd0;endend    end2'd3 : begin                     flow_cnt <= 3'd0;          //链路正常并且自协商完成if(op_rd_data[5] == 1'b1 && op_rd_data[2] == 1'b1)beginstart_next <= 1;link_error <= 0;endelse beginlink_error <= 1'b1;  end           end3'd4: beginflow_cnt <= 3'd0;if(op_rd_data[15:14] == 2'b10)speed_status <= 2'b11; //1000Mbpselse 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; //10Mbpselsespeed_status <= 2'b00; //其他情况  endendcaseend    
end    endmodule

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/235491.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

读书笔记产品经理学习笔记1-忘掉技术,先看客户需求

技术到产品思维的转换 以前做技术的时候&#xff0c;扮演的角色是怎样多快好省的完成开发。现在做产品了&#xff0c;你得自己定产品方案&#xff0c;让别人来开发。最重要的是先弄清楚客户的需求是什么&#xff0c;要解决什么问题&#xff0c;再看产品怎么设计&#xff0c;然…

你想改win11系统中窗口、菜单等的字体? 微软不想让你改

如果你感觉win11系统中显示的字体不好看&#xff0c;想换。等一等&#xff0c;微软本不想让你改。 Windows 11 在默认情况下并没有提供直接修改系统默认字体的选项&#xff0c;而需要进行注册表或其他高级设置来更改系统字体。这可能是因为微软希望保持系统的一致性和稳定性&a…

[Realtek sdk-3.4.14b]RTL8197FH-VG+RTL8812F WiFi使用功率限制功能使用说明

sdk说明 ** Gateway/AP firmware v3.4.14b – Aug 26, 2019**  Wireless LAN driver changes as:  Refine WiFi Stability and Performance  Add 8812F MU-MIMO  Add 97G/8812F multiple mac-clone  Add 97G 2T3R antenna diversity  Fix 97G/8812F/8814B MP issu…

可狱可囚的爬虫系列课程 07:BeautifulSoup4(bs4)库的使用

前面一直在讲 Requests 模块如何使用&#xff0c;那都是在请求阶段要做的事情&#xff0c;相信很多网友都在等一个能够开始爬网站信息的教程&#xff0c;今天它来了&#xff0c;今天我要给大家讲一个很简单易懂的库&#xff1a;BeautifulSoup4。 一、概述&安装 Beautiful…

KylinV10 安装 MySQL 教程(可防踩雷)

KylinV10 安装 MySQL 教程&#xff08;可防踩雷&#xff09; 1、直接用 apt 快捷安装 MySQL $ sudo apt-get update #更新软件源 $ sudo apt-get install mysql-server #安装mysql然后你会发现&#xff0c;KylinV10 安装畅通无阻&#xff0c;并没有设置密码的场景&#xff0c…

你相信光吗?2D 后效与光照技术分享!

“ 很多朋友提到后效&#xff0c;就会想起那些 3D 游戏大作&#xff0c;但实际上&#xff0c;后效在 2D 游戏开发中的应用也是非常广泛的。恰当地使用后效&#xff0c;可以使一款 2D 游戏的画质提升好几个台阶。今天邀请到了社区大佬 wing&#xff0c;给大家分享一下 2D 后效框…

MyBatis ORM映射

MyBatis只能自动维护库表”列名“与”属性名“相同时的对应关系&#xff0c;二者不同时无法自动ORM 因此需要使用到ORM映射。 共有两种解决办法&#xff1a;1.列的别名 2.结果映射 1.列的别名 在SQL中使用 as 为查询字段添加列别名&#xff0c;以匹配属性名 public List<…

nodejs+vue+微信小程序+python+PHP高校成绩分析系统-计算机毕业设计推荐

综合购物商城管理经历和对网上信息归纳整理的结果&#xff0c;在实际应用中&#xff0c;将用户分为两种&#xff1a;管理员和高校成绩分析系统综合网络空间开发设计要求。目的是将高校成绩分析从传统管理方式转换为在网上管理&#xff0c;完成高校成绩分析管理的方便快捷、安全…

pyCharm 创建一个FastApi web项目,实现接口调用

FastApi和Django区别 我这边演示项目使用的fastApi作为web框架&#xff0c;当然主流一般都是使用Django做web框架&#xff0c;但是Django是一个重量级web框架他有很多组件&#xff0c;如授权&#xff0c;分流等全套web功能。我这边呢只需要有个接口可以被别人调用&#xff0c;…

【超详细前后端项目搭建】前端vue3+ts项目(引入ElementPlus、Axios)、后端springboot搭建(创建接口操作mysql数据库)实现前后端联调

目录 前言一、前端项目1、使用vue脚手架创建项目1.1检查vue版本1.2 使用vue脚手架创建项目 2、删除项目多余文件&#xff0c;修改配置项目2.1、删除以下文件2.1、在views下创建index文件2.2、修改router/index.ts路由文件&#xff1a;2.3、修改App.vue文件&#xff1a;2.4、初始…

气候变化与环境保护:全球研究与未来趋势

导言 气候变化和环境保护是当今社会亟待解决的全球性难题。本文将深入探讨这一主要流行研究方向的发展历程、遇到的问题、解决过程&#xff0c;以及未来的可用范围&#xff0c;着重分析在各国的应用和未来的研究趋势&#xff0c;以探讨在哪些方面能够取得胜利&#xff0c;以及在…

PySpark中DataFrame的join操作

内容导航 类别内容导航机器学习机器学习算法应用场景与评价指标机器学习算法—分类机器学习算法—回归机器学习算法—聚类机器学习算法—异常检测机器学习算法—时间序列数据可视化数据可视化—折线图数据可视化—箱线图数据可视化—柱状图数据可视化—饼图、环形图、雷达图统…

期货开平规则(期货交易开平规则解析)

什么是期货开平规则 期货开平规则&#xff0c;简单来说是指期货交易中的开仓和平仓所遵循的一系列规定。具体而言&#xff0c;开仓是指买入或卖出期货合约&#xff0c;建立一个新的持仓&#xff1b;平仓则是指买入或卖出相应数量的期货合约&#xff0c;用以解除原有持仓。开平…

什么是数据仪表板?数据可视化仪表盘怎么制作?

在数据经济时代&#xff0c;分析数据是每个企业做出最佳决策的关键。但是&#xff0c;手动分析和解释大量数据是不可行的。数据可视化对于分析数据中存在的各种有价值信息至关重要&#xff0c;包括可见趋势和隐藏趋势等。仪表盘显示可视化趋势和信息&#xff0c;例如 KPI、趋势…

简易实现 STL--list

实现 list 的主要思想及过程 首先&#xff0c;实现过程中的所有代码必须放在自己定义的命名空间中。 定义一个结点的结构体类模板&#xff0c;结点的数据类型就应该是模板类型 T&#xff0c;定义的 next指针和 prev指针都应该是模板指针类型&#xff0c;并且结构体类中药有构…

2017年第六届数学建模国际赛小美赛A题飓风与全球变暖解题全过程文档及程序

2017年第六届数学建模国际赛小美赛 A题 飓风与全球变暖 原题再现&#xff1a; 飓风&#xff08;也包括在西北太平洋被称为“台风”的风暴以及在印度洋和西南太平洋被称为“严重热带气旋”&#xff09;具有极大的破坏性&#xff0c;往往造成数百人甚至数千人死亡。   许多气…

UE4移动端最小包优化实践

移动端对于包大小有着严苛的要求,然而UE哪怕是一个空工程打出来也有90+M,本文以一个复杂的工程为例,探索怎么把包大小降低到最小。 一、工程简介 工程包含代码、插件、资源、iOS原生库工程。 二、按官方文档进行基础优化 官方文档 1、勾选Use Pak File和Create comp…

YOLOv5性能评估指标->mAP、Precision、Recall、FPS、Confienc (讲解论文关注的主要指标)

简介 这篇博客&#xff0c;主要给大家讲解我们在训练yolov5时生成的结果文件中各个图片及其中指标的含义&#xff0c;帮助大家更深入的理解&#xff0c;以及我们在评估模型时和发表论文时主要关注的参数有那些。本文通过举例训练过程中的某一时间的结果来帮助大家理解&#xf…

npm安装依赖报错ERESOLVE unable to resolve dependency tree(我是在taro项目中)(node、npm 版本问题)

换了电脑之后新电脑安装包出错 &#x1f447;&#x1f447;&#x1f447; npm install 安装包报错 ERESOLVE unable to resolve dependency tree 百度后尝试使用 npm install --force 还是报错 参考 有人说是 node 版本和 npm 版本的问题 参考 新电脑 node版本&#xff1a;16.1…

ros2机器人常规控制流程

The joint_state_publisher reads the robot_description parameter from the parameter server, finds all of the non-fixed joints and publishes a JointState message with all those joints defined.也就是说如果我们不需要控制机器人运动&#xff0c;只需要一个节点就可…