主题中讨论的其他器件: DP83869、 DP83867IS
大家好、
我 正在尝试在 PHY 中设置 MII 级环回以确认 MAC<->PHY 之间的通信。 通过 MAC 和 PCS 级别(均在 MAC 内部)、而不是 MII 级别(MAC 外部)的测试、我能够成功执行环回测试。 我正在寻找一些建议或线索、以了解可能缺失/出错的原因。
我们的硬件:
- Intel Cyclone 10 GX FPGA
- NIOS II 工艺(软内核、在 FPGA 结构中实例化)
- TI DP83869HM PHY
我们的软件/工具:
- Quartus Prime Pro 19.4.
- 用于 Eclipse 的 NIOS II 软件构建工具19.4
- 英特尔以太网数据包生成器/以太网数据包监控器19.4 IP
- Intel 三速以太网19.4 IP
我们的设置/设置:
- SGMII->Copper 模式(OP_MODE_DE解码= 0x0046)
- 千兆位速度
- 自动协商被禁用(文档建议针对回送禁用此功能)
- 全双工
我们的文档:
- 三速以太网 Intel FPGA IP 用户指南(UG-01008 - 2021.10.04)
- DP83869HM 数据表- 2018年12月修订
- Intel Cyclone 10 LP FPGA 三速以太网和 Intel 板载 PHY 芯片参考设计
- 第4页、图1提供了系统的基本图。 但是、我们还有一个额外的多路复用器、可在连接到链路伙伴时允许"正常"流量流动
- 如何配置 DP838xx 进行以太网合规性测试
我们尝试使其正常工作的东西
- 我们已确认能够通过 从寄存器读回数据/观察示波器上的数据来对 MAC/PCS/PHY 中的所有寄存器(包括扩展寄存器)进行 R/W 检查
- 我们已确认所有 MAC/PCS/PHY 设置在速度、双工和自动协商方面相互匹配
- 我们已确认 MAC 和 PC 级环回工作正常。 可以在以太网数据包监控寄存器和 MAC 寄存器中查看统计信息
- 我们已确认、我们准确遵循"英特尔 Cyclone 10 LP FPGA 三速以太网和英特尔板载 PHY 芯片参考设计"软件包中的 PHY 回路设置步骤
- 在.zip 中包含的.TCL 脚本中可以找到详细步骤本身
- 已尝试将专有0xC6寄存器设置为0x10。
- 该寄存器对它的功能没有任何说明。 但在"如何为以太网合规性测试配置 DP838xx "文档第13页中、这是一个必要的步骤。 不清楚是否需要将其设置为环回
- 已尝试将 LOOPCR (0xFE)设置为0xE720。
- 该寄存器没有关于其功能的说明、仅在"DP83869HM 数据表"的第27页中简要介绍。 不清楚是否需要为 MII 回送设置此参数。
- 尝试通过在 PHY_CONTROL (0x10)寄存器中设置"FORCE_LINK_STSACH"来强制 BMSR (0x01)寄存器中的 LINK_STS1启动。
- 注意:当我们尝试数字回送(不起作用)时、LINK_STS1为高电平。 对于 MII 回送、该位是否应为高电平?
在这个帖子中 、用户说"我们将 寄存器0x00的位14设置 为1、并 将0x0004写入寄存器0x16。 测试结果成功"。 在下一个回复中、TI 员工表示"MII 和模拟/数字回路的配置正确。" 我们尝试了这些设置、并确认它们在我们的案例中不起作用。 这些步骤中是否还有其他未完成的步骤?
下面是我们当前的实施方案:
#include <stdio.h>#include <system.h>#include <io.h>#include <altera_eth_tse_regs.h>
typedef volatile struct tse_pcs_struct{ unsigned int control; unsigned int status; unsigned int phy_id1; unsigned int phy_id2; unsigned int dev_ability; unsigned int partner_ability; unsigned int an_expansion; unsigned int device_next_page; unsigned int partner_next_page; unsigned int master_slave_cntl; unsigned int master_slave_stat; unsigned int reserved1; unsigned int reserved2; unsigned int reserved3; unsigned int reserved4; unsigned int extended_status; unsigned int scratch; unsigned int rev; unsigned int link_timer1; unsigned int link_timer2; unsigned int if_mode;} tse_pcs;
// Offsets from MAC Base#define MAC_REV 0x00#define MAC_SCRATCH 0x01#define MAC_CMD_CFG 0x02#define MAC_MAC_0 0x03#define MAC_MAC_1 0x04#define MAC_FRM_LEN 0x05#define MAC_PAUSE_QUANT 0x06#define MAC_RX_SEC_EMPTY 0x07#define MAC_RX_SEC_FULL 0x08#define MAC_TX_SEC_EMPTY 0x09#define MAC_TX_SEC_FULL 0x0A#define MAC_RX_ALMOST_EMPTY 0x0B#define MAC_RX_ALMOST_FULL 0x0C#define MAC_TX_ALMOST_EMPTY 0x0D#define MAC_TX_ALMOST_FULL 0x0E#define MAC_MDIO_ADDR0 0x0F#define MAC_MDIO_ADDR1 0x10#define MAC_HOLDOFF_QUANT 0x11#define MAC_TX_IPG_LENGTH 0x17#define MAC_TX_CMD_STAT 0x3A#define MAC_RX_CMD_STAT 0x3B
// Offsets from Packet Gen Base#define PKT_GEN_NUM_PKT 0x00#define PKT_GEN_CONFIG_REG 0x01#define PKT_GEN_RAND_SEED0 0x02#define PKT_GEN_RAND_SEED1 0x03#define PKT_GEN_SRC_ADDR0 0x04#define PKT_GEN_SRC_ADDR1 0x05#define PKT_GEN_DEST_ADDR0 0x06#define PKT_GEN_DEST_ADDR1 0x07#define PKT_GEN_OPERATION 0x08#define PKT_GEN_PKT_TX_CNT 0x09
// Offsets from Packet Monitor Base#define PKT_MON_NUM_PKT 0x00#define PKT_MON_RX_OK 0x01#define PKT_MON_RX_ERROR 0x02#define PKT_MON_BYTE_RX_CNT0 0x03#define PKT_MON_BYTE_RX_CNT1 0x04#define PKT_MON_CYCLE_RX_CNT0 0x05#define PKT_MON_CYCLE_RX_CNT1 0x06#define RX_CTRL_STATUS 0x07
// Offsets for PCS Registers#define ETH_PCS_BASE 0x10002200#define PCS_CTRL_REG 0x00#define PCS_IF_MODE_REG 0x14
// Offsets for PHY Registers#define ETH_PHY_BASE 0x10002280#define PHY_BMCR 0x00#define PHY_BMSR 0x01#define PHY_REGCR 0x0D#define PHY_ADDAR 0x0E#define PHY_CONTROL 0x10#define PHY_STATUS 0x11#define PHY_BIST 0x16#define PHY_GEN_CTRL 0x1F#define PHY_LOOPCR 0xFE#define OP_MODE_DECODE 0x1DF
#define NUM_PKTS_TX_RX 1000
np_tse_mac *mac_registers = ((void*) ETH_TSE_0_BASE);tse_pcs *pcs_registers = ((void*) ETH_PCS_BASE);
int main(){ alt_u32 selector = 0;
// Step 1a - Configure MAC IOWR(ETH_TSE_0_BASE, MAC_CMD_CFG, 0x003B); // tx/rx enable, gigE, promiscuous mode IOWR(ETH_TSE_0_BASE, MAC_MAC_0, 0x17231C00); // Set upper portion of MAC address IOWR(ETH_TSE_0_BASE, MAC_MAC_1, 0x0000CB4A); // Set lower portion of MAC address IOWR(ETH_TSE_0_BASE, MAC_FRM_LEN, 1518); // Set dframe length IOWR(ETH_TSE_0_BASE, MAC_PAUSE_QUANT, 0xFFFF); // Set pause quant to max IOWR(ETH_TSE_0_BASE, MAC_RX_SEC_EMPTY, 4080); IOWR(ETH_TSE_0_BASE, MAC_RX_SEC_FULL, 16); IOWR(ETH_TSE_0_BASE, MAC_TX_SEC_EMPTY, 4080); IOWR(ETH_TSE_0_BASE, MAC_TX_SEC_FULL, 16); IOWR(ETH_TSE_0_BASE, MAC_RX_ALMOST_EMPTY, 8); IOWR(ETH_TSE_0_BASE, MAC_RX_ALMOST_FULL, 8); IOWR(ETH_TSE_0_BASE, MAC_TX_ALMOST_EMPTY, 8); IOWR(ETH_TSE_0_BASE, MAC_TX_ALMOST_FULL, 3); IOWR(ETH_TSE_0_BASE, MAC_MDIO_ADDR0, 0); IOWR(ETH_TSE_0_BASE, MAC_MDIO_ADDR1, 0); IOWR(ETH_TSE_0_BASE, MAC_TX_IPG_LENGTH, 12); IOWR(ETH_TSE_0_BASE, MAC_TX_CMD_STAT, 0); // OMIT_CRC = 0, TX_SHIFT16 = 0 IOWR(ETH_TSE_0_BASE, MAC_RX_CMD_STAT, 0); // RX_SHIFT16 = 0
IOWR(ETH_TSE_0_BASE, MAC_CMD_CFG, 0x203B); // Reset MAC using same values as above while ( (IORD(ETH_TSE_0_BASE, MAC_CMD_CFG) & 0x2000) == 0x2000) { // do nothing. Wait for MAC reset to complete } IOWR(ETH_TSE_0_BASE, MAC_CMD_CFG, 0x003B); // re-enable Tx/Rx lines (reset disables these)
// Step 1b - Configure PCS ------------------------------------------------ IOWR(ETH_PCS_BASE, PCS_CTRL_REG, 0x0140); // disable AN, gigE IOWR(ETH_PCS_BASE, PCS_IF_MODE_REG, 0x0009); // disable SGMII AN, gigE, full duplex
// Step 1c - Configure PHY ------------------------------------------------ IOWR(ETH_TSE_0_BASE, MAC_MDIO_ADDR1, 0); // set mdio address 1 to PHY 0
IOWR(ETH_PHY_BASE, PHY_REGCR, 0x001F); // Set OP_MODE_DECODE IOWR(ETH_PHY_BASE, PHY_ADDAR, OP_MODE_DECODE); IOWR(ETH_PHY_BASE, PHY_REGCR, 0x401F); IOWR(ETH_PHY_BASE, PHY_ADDAR, 0x0046);
IOWR(ETH_PHY_BASE, PHY_REGCR, 0x001F); // set LOOPCR - Data sheet says this needs to be done. No description on what it does IOWR(ETH_PHY_BASE, PHY_ADDAR, PHY_LOOPCR); IOWR(ETH_PHY_BASE, PHY_REGCR, 0x401F); IOWR(ETH_PHY_BASE, PHY_ADDAR, 0xE720);
IOWR(ETH_PHY_BASE, PHY_BMCR, 0x0140); // Set BMCR - AN disabled, gigE (need to turn off AN before enabling MII Loopback mode) IOWR(ETH_PHY_BASE, PHY_CONTROL, 0x5008); // Set MDI Mode - 0x5028 = MDI-X, 0x5008 = MDI (need to turn off Auto MDI-x before enabling MII Loopback mode) IOWR(ETH_PHY_BASE, PHY_BMCR, 0x4140); // Enable MII Loopback IOWR(ETH_PHY_BASE, PHY_GEN_CTRL, 0x4000); // SW Reset - preserves register values
// Step 2 - Configure packet generator ------------------------------------ IOWR(ETH_GEN_DW_0_BASE, PKT_GEN_NUM_PKT, NUM_PKTS_TX_RX); // set number of pkts to be sent IOWR(ETH_GEN_DW_0_BASE, PKT_GEN_CONFIG_REG, 0x0BB8); // Set # pkts, fixed pkt length of 1500, incremental pattern IOWR(ETH_GEN_DW_0_BASE, PKT_GEN_RAND_SEED0, 0x12345678); // Set random seed lower (can be anything, chose value from .tcl script) IOWR(ETH_GEN_DW_0_BASE, PKT_GEN_RAND_SEED1, 0x00009ABC); // Set random seed upper (can be anything, chose value from .tcl script) IOWR(ETH_GEN_DW_0_BASE, PKT_GEN_SRC_ADDR0, 0x17231C00); // Set src mac address lower (pulled MAC address from TI docs) IOWR(ETH_GEN_DW_0_BASE, PKT_GEN_SRC_ADDR1, 0x0000CB4A); // Set src mac address upper (pulled MAC address from TI docs) IOWR(ETH_GEN_DW_0_BASE, PKT_GEN_DEST_ADDR0, 0x17231C00); // Set dest mac address lower (pulled MAC address from TI docs) IOWR(ETH_GEN_DW_0_BASE, PKT_GEN_DEST_ADDR1, 0x0000CB4A); // Set dest mac address upper (pulled MAC address from TI docs)
// Step 3 - Configure packet monitor -------------------------------------- IOWR(ETH_MON_DW_0_BASE, PKT_MON_NUM_PKT, NUM_PKTS_TX_RX); // set number of pkts to be received
// Step 4 - Configure muxers ---------------------------------------------- IOWR(ST_MUX_2_TO_1_DW_0_BASE, 0, 0x01); // Set mux 0 to a 1 (data coming in from mux 1) IOWR(ST_MUX_2_TO_1_DW_1_BASE, 0, 0x00); // Set mux 1 to a 0 (data coming in from pkt generator)
// Step 5 - Turn on packet monitor ---------------------------------------- IOWR(ETH_MON_DW_0_BASE, RX_CTRL_STATUS, 0x01);
// Step 6 - Turn on packet generator -------------------------------------- IOWR(ETH_GEN_DW_0_BASE, PKT_GEN_OPERATION, 0x01);
while(!selector) { // do nothing until we pause and change selector to 1 }
alt_u32 rx_OK = IORD(ETH_MON_DW_0_BASE, PKT_MON_RX_OK); alt_u32 tx_ERROR = IORD(ETH_MON_DW_0_BASE, PKT_MON_RX_ERROR); alt_u32 last_bmcr = IORD(ETH_PHY_BASE, PHY_BMCR); alt_u32 last_bmsr = IORD(ETH_PHY_BASE, PHY_BMSR); last_bmsr = IORD(ETH_PHY_BASE, PHY_BMSR); // need to be read 2x for valid link up read alt_u32 last_phy_ctrl = IORD(ETH_PHY_BASE, PHY_CONTROL); alt_u32 last_phy_sts = IORD(ETH_PHY_BASE, PHY_STATUS);
while(1) { // do nothing }
return 0;}
请参阅上述代码、了解我们为启用 MII 级环回所采取的确切步骤。 通过检查 MAC 统计寄存器、我们可以看到所有数据包都正常发送、但 MAC 不接收任何本应环回的帧。 这向我们表明、数据并未像我们预期的那样在 PHY 中环回。
总的来说、我们感觉缺少了一些步骤/知识来使其正常工作。 我们的设置是否缺少任何内容? 欢迎并感谢您提供任何帮助或建议!