FPGA 37 ,FPGA千兆以太网设计实战:RGMII接口时序实现全解析( RGMII接口时序设计,RGMII~GMII,GMII~RGMII 接口转换 )
目录
前言
一、设计流程
1.1 需求理解
1.2 模块划分
1.3 测试验证
二、模块分工
2.1 RGMII→GMII(接收方向,rgmii_rx 模块)
2.2 GMII→RGMII(发送方向,rgmii_tx 模块)
三、代码实现
3.1 顶层模块 rgmii_to_gmii
3.2 接收模块 rgmii_rx
3.3 发送模块 rgmii_tx
3.4 测试平台模块 tb
四、逻辑分析
4.1 双向转换的关键逻辑实现
4.2 双向转换逻辑的逻辑验证
五、注意事项
5.1 时钟处理
5.2 数据转换
5.3 测试验证
六、本文总结
七、更多操作

前言
在现代网络通信系统中,为了减少引脚数量并提高传输速率,RGMII 被广泛应用。在 FPGA 开发中,RGMII 和 GMII 是常见的网络接口标准。RGMII 接口具有信号线少、传输效率高的特点,而 GMII 接口则相对更易于理解和处理。在实际应用中,如与传统设备兼容时,常常需要在这两种接口之间进行数据转换。这里将详细介绍 RGMII 到 GMII 接口转换的设计流程、代码实现以及注意事项。
RGMII(Reduced Gigabit Media Independent Interface):简化的千兆媒体独立接口
GMII(Gigabit Media Independent Interface):千兆介质专用接口
更多 GMII RGMII 解析,请看
FPGA 32 ,以太网TCP/IP四层模型:从MII到RGMII的深度解析
https://blog.csdn.net/weixin_65793170/article/details/146006143?spm=1001.2014.3001.5501
一、设计流程
1.1 需求理解
在进行接口转换设计之前,需要明确 RGMII 和 GMII 接口的特点和差异。RGMII 接口采用双沿数据传输,而 GMII 接口采用单沿数据传输。因此,设计的核心是实现双沿数据和单沿数据之间的转换。
1.2 模块划分
根据功能需求,将整个设计划分为三个主要模块:
- 顶层模块
rgmii_to_gmii - 接收模块
rgmii_rx - 发送模块
rgmii_tx
顶层模块负责连接各个子模块,接收模块将 RGMII 的双沿数据转换为 GMII 的单沿数据,发送模块将 GMII 的单沿数据转换为 RGMII 的双沿数据。
1.3 测试验证
设计完成后,需要编写测试平台对整个系统进行功能验证,确保接口转换的正确性。最后,通过tb(Test Bench)模块,对设计模块(如 rgmii_to_gmii)进行功能验证,确保接口转换的逻辑正确性。

二、模块分工
各模块核心作用:
| 模块 | 转换方向 | 核心功能 |
|---|---|---|
rgmii_to_gmii | 双向(RGMII↔GMII) | 顶层整合模块,实例化 rgmii_rx 和 rgmii_tx,实现 RGMII 与 GMII 接口的双向转换:- 连接 RGMII 侧(PHY)与 GMII 侧(MAC)的时钟、数据、控制信号 - 传递接收方向(RGMII→GMII)和发送方向(GMII→RGMII)的数据流 - 统一管理时钟同步(如将 GMII 时钟映射为 RGMII 发送时钟) |
rgmii_rx | RGMII → GMII(接收) | 将 RGMII 的双沿数据(4 位,上下沿各 2 位)和控制信号转换为 GMII 的单沿数据(8 位,仅上升沿有效): - 利用 IDDR 原语提取时钟双沿的信号- 时钟处理( BUFIO/BUFG)确保 GMII 时钟质量- 控制信号转换(双沿有效 → 单沿使能) |
rgmii_tx | GMII → RGMII(发送) | 将 GMII 的单沿数据(8 位,仅上升沿有效)和控制信号转换为 RGMII 的双沿数据(4 位,上下沿各 2 位): - 利用 ODDR 原语生成双沿数据和控制信号- 时钟同步(直接复用 GMII 时钟作为 RGMII 发送时钟) |
tb(Test Bench) | 无(测试验证) | 测试平台模块,不参与实际接口转换,仅用于仿真验证: - 生成时钟激励(125MHz,50% 占空比) - 驱动输入信号(RGMII 接收数据、GMII 发送数据)递增变化 - 验证输出信号是否符合双向转换逻辑(如双沿数据拼接 / 拆分的正确性) |
双向转换的核心模块:
| 模块 | 转换方向 | 核心功能 |
|---|---|---|
rgmii_rx | RGMII → GMII(接收) | 将 RGMII 的双沿数据(4 位,上下沿各 2 位)和控制信号转换为 GMII 的单沿数据(8 位,仅上升沿有效)。 |
rgmii_tx | GMII → RGMII(发送) | 将 GMII 的单沿数据(8 位,仅上升沿有效)和控制信号转换为 RGMII 的双沿数据(4 位,上下沿各 2 位)。 |
2.1 RGMII→GMII(接收方向,rgmii_rx 模块)
- 输入(RGMII 侧):
- 时钟
rgmii_rxc(PHY 提供,双沿同步) - 双沿数据
rgmii_rxd[3:0](上升沿传高 2 位[3:2],下降沿传低 2 位[1:0]) - 控制信号
rgmii_rx_ctrl(RXDV 和 RXER 的异或,双沿有效)
- 时钟
- 输出(GMII 侧):
- 时钟
gmii_rxc(经时钟缓冲处理,供 GMII 使用) - 单沿数据
gmii_rxd[7:0](rgmii_rxd双沿数据拼接:上升沿数据放低 4 位,下降沿数据放高 4 位?需结合代码逻辑,实际代码中IDDR的 Q1 对应上升沿,Q2 对应下降沿,拼接为[i]和[4+i],即 0-3 位为上升沿采样,4-7 位为下降沿采样) - 使能信号
gmii_rx_en(由双沿控制信号相与生成,确保数据有效时持续高电平)
- 时钟
2.2 GMII→RGMII(发送方向,rgmii_tx 模块)
- 输入(GMII 侧):
- 时钟
gmii_txc(FPGA 内部时钟,125MHz,单沿驱动) - 单沿数据
gmii_tx_data[7:0](仅上升沿有效,高 4 位和低 4 位分别对应 RGMII 双沿的上下沿) - 使能信号
gmii_tx_en(单沿有效,控制数据发送)
- 时钟
- 输出(RGMII 侧):
- 时钟
rgmii_txc(与gmii_txc同频,供 PHY 使用) - 双沿数据
rgmii_data[3:0](gmii_tx_data高 4 位[7:4]对应上升沿,低 4 位[3:0]对应下降沿,通过ODDR双沿输出) - 控制信号
rgmii_tx_ctrl(由gmii_tx_en双沿驱动,确保上下沿数据均有效)
- 时钟
125M的时钟,一个时钟8ns,4ns反转一次就可以。
三、代码实现
3.1 顶层模块 rgmii_to_gmii
`timescale 1ns / 1ps
module rgmii_to_gmii(//rgmii接口input wire rgmii_rxc ,//由phy提供的时钟input wire rgmii_rx_ctrl ,//由en和error的异或值组成input wire [3:0] rgmii_rxd ,//由phy芯片提供的双沿数据output wire rgmii_txc ,//发送给phy芯片的时钟output wire rgmii_tx_ctrl ,//由en、error的异或值组成output wire [3:0] rgmii_data ,//双沿数据//gmii接口output wire gmii_txc ,//fpga的时钟,125Mhz,可以用phy提供的时钟,需要做约束处理input wire gmii_tx_en ,//使能---高有效input wire [7:0] gmii_tx_data ,//单沿数据output wire gmii_rxc ,//经过buf处理后的时钟output wire gmii_rx_en ,//使能信号output wire [7:0] gmii_rxd //经过单双沿源语处理后的单沿数据);// 将gmii_txc赋值为gmii_rxcassign gmii_txc = gmii_rxc;// 实例化接收模块rgmii_rx rgmii_rx_u(. rgmii_rxc (rgmii_rxc ) ,//由phy提供的时钟. rgmii_rx_ctrl(rgmii_rx_ctrl) ,//由en和error的异或值组成. rgmii_rxd (rgmii_rxd ) ,//由phy芯片提供的双沿数据. gmii_rxc (gmii_rxc ) ,//经过buf处理后的时钟. gmii_rx_en (gmii_rx_en ) ,//使能信号. gmii_rxd (gmii_rxd ) //经过单双沿源语处理后的单沿数据);// 实例化发送模块rgmii_tx rgmii_tx_u(. gmii_txc (gmii_txc ),//fpga的时钟,125Mhz,可以用phy提供的时钟,需要做约束处理. gmii_tx_en (gmii_tx_en ),//使能---高有效. gmii_tx_data (gmii_tx_data ),//单沿数据. rgmii_txc (rgmii_txc ),//发送给phy芯片的时钟. rgmii_tx_ctrl(rgmii_tx_ctrl),//由en、error的异或值组成. rgmii_data (rgmii_data ) //双沿数据);
endmodule
逻辑实现流程:
- 首先将
gmii_txc赋值为gmii_rxc,确保两者时钟一致。 - 实例化
rgmii_rx模块,将 RGMII 接口的接收数据传递给该模块进行处理。 - 实例化
rgmii_tx模块,将 GMII 接口的发送数据传递给该模块进行处理。
此模块负责整合接收和发送功能。
3.2 接收模块 rgmii_rx
`timescale 1ns / 1ps
//gmii to rgmii----双沿转单沿数据
module rgmii_rx(input wire rgmii_rxc ,//由phy提供的时钟input wire rgmii_rx_ctrl ,//由en和error的异或值组成input wire [3:0] rgmii_rxd ,//由phy芯片提供的双沿数据output wire gmii_rxc ,//经过buf处理后的时钟output wire gmii_rx_en ,//使能信号output wire [7:0] gmii_rxd //经过单双沿源语处理后的单沿数据);wire [1:0] gmii_rx_ctrl;//寄存rgmii_rx_ctrl双沿的数据//----------时钟处理wire rgmii_rxc_bufio;//经过io时钟资源的输入时钟wire rgmii_rxc_bufg ;//经过全局时钟网络资源的输入时钟// 将gmii_rxc赋值为经过全局时钟网络资源处理后的时钟assign gmii_rxc = rgmii_rxc_bufg;// 使用BUFIO原语处理输入时钟BUFIO BUFIO_inst (.O(rgmii_rxc_bufio), // 1-bit output: Clock output (connect to I/O clock loads)..I(rgmii_rxc) // 1-bit input: Clock input (connect to an IBUF or BUFMR).);// 使用BUFG原语处理输入时钟BUFG BUFG_inst (.O(rgmii_rxc_bufg), // 1-bit output: Clock output.I(rgmii_rxc) // 1-bit input: Clock input);//--------ctrl的双单沿转换// 将gmii_rx_en赋值为gmii_rx_ctrl的两个位相与的结果assign gmii_rx_en = gmii_rx_ctrl [0] & gmii_rx_ctrl[1];// 使用IDDR原语进行控制信号的双单沿转换IDDR #(.DDR_CLK_EDGE("SAME_EDGE_PIPELINED"), // "OPPOSITE_EDGE", "SAME_EDGE" // or "SAME_EDGE_PIPELINED" .INIT_Q1(1'b0), // Initial value of Q1: 1'b0 or 1'b1.INIT_Q2(1'b0), // Initial value of Q2: 1'b0 or 1'b1.SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC" ) IDDR_inst_rx_ctrl (.Q1(gmii_rx_ctrl[0]), // 1-bit output for positive edge of clock.Q2(gmii_rx_ctrl[1]), // 1-bit output for negative edge of clock.C(rgmii_rxc_bufio), // 1-bit clock input.CE(1'b1), // 1-bit clock enable input.D(rgmii_rx_ctrl), // 1-bit DDR data input.R(1'b0), // 1-bit reset.S(1'b0) // 1-bit set);//----------数据的双单沿转换genvar i;// 使用generate语句进行数据的双单沿转换generatefor (i = 0;i < 4 ;i = i + 1 ) begin:iddr_rxdIDDR #(.DDR_CLK_EDGE("SAME_EDGE_PIPELINED"), // "OPPOSITE_EDGE", "SAME_EDGE" // or "SAME_EDGE_PIPELINED" .INIT_Q1(1'b0), // Initial value of Q1: 1'b0 or 1'b1.INIT_Q2(1'b0), // Initial value of Q2: 1'b0 or 1'b1.SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC" ) IDDR_inst_rxd (.Q1(gmii_rxd[i]), // 1-bit output for positive edge of clock.Q2(gmii_rxd[4 + i]), // 1-bit output for negative edge of clock.C(rgmii_rxc_bufio), // 1-bit clock input.CE(1'b1), // 1-bit clock enable input.D(rgmii_rxd[i]), // 1-bit DDR data input.R(1'b0), // 1-bit reset.S(1'b0) // 1-bit set); endendgenerate
endmodule
逻辑实现流程:
- 时钟处理:使用
BUFIO和BUFG原语对输入时钟rgmii_rxc进行处理,确保时钟信号的质量,并将处理后的时钟输出给gmii_rxc。 - 控制信号转换:使用
IDDR原语在时钟的上升沿和下降沿分别采集rgmii_rx_ctrl的值,将这两个值存储在gmii_rx_ctrl中,然后将gmii_rx_ctrl的两个位相与得到gmii_rx_en。 - 数据转换:使用
generate语句和IDDR原语将rgmii_rxd的双沿数据转换为gmii_rxd的单沿数据。
3.3 发送模块 rgmii_tx
`timescale 1ns / 1ps
//GMII to RGMII---单沿转双沿数据
module rgmii_tx(input wire gmii_txc ,//fpga的时钟,125Mhz,可以用phy提供的时钟,需要做约束处理input wire gmii_tx_en ,//使能---高有效input wire [7:0] gmii_tx_data ,//单沿数据output wire rgmii_txc ,//发送给phy芯片的时钟output wire rgmii_tx_ctrl,//由en、error的异或值组成output wire [3:0] rgmii_data //双沿数据);// 将rgmii_txc赋值为gmii_txcassign rgmii_txc = gmii_txc;//--------ctrl的单双沿转换// 使用ODDR原语进行控制信号的单双沿转换ODDR #(.DDR_CLK_EDGE("SAME_EDGE"), // "OPPOSITE_EDGE" or "SAME_EDGE" .INIT(1'b0), // Initial value of Q: 1'b0 or 1'b1.SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC" ) ODDR_tx_ctrl (.Q(rgmii_tx_ctrl), // 1-bit DDR output.C(gmii_txc), // 1-bit clock input.CE(1'b1), // 1-bit clock enable input.D1(gmii_tx_en), // 1-bit data input (positive edge).D2(gmii_tx_en), // 1-bit data input (negative edge).R(1'b0), // 1-bit reset.S(1'b0) // 1-bit set);//--------数据的单双沿转换genvar i;//定义循环变量,只能在generate这个循环语句中使用// 使用generate语句进行数据的单双沿转换generatefor (i = 0;i < 4 ;i = i + 1 ) begin:gmii_txd //定义标签,作为generate循环语句中的实例名称ODDR #(.DDR_CLK_EDGE("SAME_EDGE"), // "OPPOSITE_EDGE" or "SAME_EDGE" .INIT(1'b0), // Initial value of Q: 1'b0 or 1'b1.SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC" ) ODDR_tx_data (.Q(rgmii_data[i]), // 1-bit DDR output.C(gmii_txc), // 1-bit clock input.CE(1'b1), // 1-bit clock enable input.D1(gmii_tx_data[i]), // 1-bit data input (positive edge).D2(gmii_tx_data[4 + i]), // 1-bit data input (negative edge).R(1'b0), // 1-bit reset.S(1'b0) // 1-bit set); endendgenerate
endmodule
逻辑实现流程:
- 将
rgmii_txc赋值为gmii_txc,确保发送时钟一致。 - 控制信号转换:使用
ODDR原语将单沿的gmii_tx_en转换为双沿的rgmii_tx_ctrl。 - 数据转换:使用
generate语句和ODDR原语将单沿的gmii_tx_data转换为双沿的rgmii_data。
3.4 测试平台模块 tb
`timescale 1ns / 1ps
module tb();// Parameters// Portsreg rgmii_rxc = 0;reg rgmii_rx_ctrl = 0;reg [3:0] rgmii_rxd;wire rgmii_txc;wire rgmii_tx_ctrl;wire [3:0] rgmii_data;wire gmii_txc;reg gmii_tx_en = 0;reg [7:0] gmii_tx_data;wire gmii_rxc;wire gmii_rx_en;wire [7:0] gmii_rxd;// 实例化顶层模块rgmii_to_gmii rgmii_to_gmii_dut (.rgmii_rxc (rgmii_rxc ),.rgmii_rx_ctrl (rgmii_rx_ctrl ),.rgmii_rxd (rgmii_rxd ),.rgmii_txc (rgmii_txc ),.rgmii_tx_ctrl (rgmii_tx_ctrl ),.rgmii_data (rgmii_data ),.gmii_txc (gmii_txc ),.gmii_tx_en (gmii_tx_en ),.gmii_tx_data (gmii_tx_data ),.gmii_rxc (gmii_rxc ),.gmii_rx_en (gmii_rx_en ),.gmii_rxd ( gmii_rxd));initial begin// 初始化输入信号rgmii_rxc = 0 ;rgmii_rx_ctrl = 1 ;rgmii_rxd = 0 ;gmii_tx_en = 1 ;gmii_tx_data = 0 ;end// 生成时钟信号always #4 rgmii_rxc = ~rgmii_rxc;// 当gmii_rx_en有效时,rgmii_rxd在时钟的上升沿和下降沿加1always@(posedge rgmii_rxc or negedge rgmii_rxc)beginif(gmii_rx_en)beginrgmii_rxd <= rgmii_rxd + 1;endend// 当gmii_rx_en有效时,gmii_tx_data在时钟的上升沿加1always@(posedge rgmii_rxc )beginif(gmii_rx_en)begingmii_tx_data <= gmii_tx_data + 1;endendendmodule
逻辑实现流程:
- 初始化输入信号,包括时钟信号、控制信号和数据信号。
- 生成时钟信号
rgmii_rxc,周期为 8ns。 - 当
gmii_rx_en有效时,rgmii_rxd在时钟的上升沿和下降沿加 1。 - 当
gmii_rx_en有效时,gmii_tx_data在时钟的上升沿加 1。
四、逻辑分析
4.1 双向转换的关键逻辑实现
① 双沿数据与单沿数据的映射关系
-
RGMII→GMII(接收方向):
- 数据转换:每个 RGMII 时钟周期传输 4 位(上下沿各 2 位),通过
IDDR原语在上升沿采样高 2 位(存入gmii_rxd[i]),下降沿采样低 2 位(存入gmii_rxd[4+i]),最终拼接为 8 位单沿数据(如rgmii_rxd[3:2]→gmii_rxd[0:1],rgmii_rxd[1:0]→gmii_rxd[4:5]?需注意代码中i的索引,实际代码中i从 0 到 3,Q1对应gmii_rxd[i],Q2对应gmii_rxd[4+i],即 0-3 位为上升沿采样,4-7 位为下降沿采样)。 - 控制信号:
rgmii_rx_ctrl在上下沿分别采样,通过IDDR得到两位信号,相与后作为 GMII 的使能信号gmii_rx_en(确保双沿数据均有效时才输出高电平)。
- 数据转换:每个 RGMII 时钟周期传输 4 位(上下沿各 2 位),通过
-
GMII→RGMII(发送方向):
- 数据转换:GMII 的 8 位单沿数据需拆分为 RGMII 的 4 位双沿数据,其中
gmii_tx_data[3:0]对应下降沿数据(存入rgmii_data[i]的下降沿输入D2),gmii_tx_data[7:4]对应上升沿数据(存入rgmii_data[i]的上升沿输入D1),通过ODDR原语在时钟上下沿分别输出。 - 控制信号:
gmii_tx_en单沿信号通过ODDR转换为双沿信号rgmii_tx_ctrl,确保 RGMII 侧上下沿数据均被使能。
- 数据转换:GMII 的 8 位单沿数据需拆分为 RGMII 的 4 位双沿数据,其中
② 时钟处理与同步
- 接收方向(RGMII→GMII):
- RGMII 时钟
rgmii_rxc由 PHY 提供,通过BUFIO和BUFG原语优化时钟路径,确保 GMII 侧时钟gmii_rxc的低抖动和低延迟,满足 GMII 接口的时序要求。
- RGMII 时钟
- 发送方向(GMII→RGMII):
- FPGA 内部时钟
gmii_txc直接作为 RGMII 时钟rgmii_txc,需通过时序约束(如时钟频率、占空比)确保与 PHY 的兼容性(通常为 125MHz,50% 占空比)。
- FPGA 内部时钟
4.2 双向转换逻辑的逻辑验证
双向转换的验证逻辑,也就是tb 模块。测试平台通过以下方式验证双向转换的正确性:
- 时钟激励:生成 125MHz 时钟(周期 8ns),模拟 RGMII 和 GMII 的同步时钟。
- 数据递增:
- 当
gmii_rx_en有效时,RGMII 接收数据rgmii_rxd在上下沿递增(模拟 PHY 发送的双沿数据),验证 GMII 输出gmii_rxd是否正确拼接为 8 位单沿数据(如rgmii_rxd=0x5(二进制0101)时,上升沿01对应gmii_rxd[1:0]=01,下降沿01对应gmii_rxd[5:4]=01,最终gmii_rxd=0x15?需根据实际索引确认)。 - GMII 发送数据
gmii_tx_data在上升沿递增,验证 RGMII 输出rgmii_data是否正确拆分为双沿数据(如gmii_tx_data=0xA(二进制1010)时,上升沿数据10对应rgmii_data[3:2]=10,下降沿数据10对应rgmii_data[1:0]=10,最终rgmii_data=0xA)。
- 当
- 控制信号联动:确保
gmii_rx_en和rgmii_tx_ctrl在数据有效时保持高电平,无数据时拉低,避免无效数据传输。
五、注意事项
5.1 时钟处理
在进行接口转换时,时钟的处理非常重要。使用 BUFIO 和 BUFG 原语可以确保时钟信号的质量,避免时钟抖动和延迟对数据传输的影响。
5.2 数据转换
在进行双沿数据和单沿数据转换时,需要注意数据的对齐和时序关系。使用 IDDR 和 ODDR 原语时,要正确设置参数,确保数据的正确转换。
5.3 测试验证
在设计完成后,一定要进行充分的测试验证。可以使用仿真工具对测试平台进行仿真,观察各个信号的波形,确保接口转换的正确性。同时,还可以进行硬件测试,将设计下载到 FPGA 开发板上进行实际测试。
六、本文总结
本文围绕 FPGA 中 RGMII 与 GMII 接口的转换设计,详细阐述了从需求分析到代码实现的完整流程,重点解决了双沿数据与单沿数据之间的转换问题。通过模块化设计,将功能划分为顶层模块、接收模块(RGMII 转 GMII)和发送模块(GMII 转 RGMII),并利用 FPGA 的 IDDR/ODDR 原语实现双沿数据的采样与生成,确保了接口时序的严格对齐。
在接收模块中,通过 BUFIO 和 BUFG 原语优化时钟路径,使用 IDDR 提取时钟双沿的控制信号和数据,最终拼接为 GMII 所需的 8 位单沿数据;发送模块则通过 ODDR 将 GMII 的单沿数据映射到 RGMII 的双沿信号,实现高效的数据传输。测试平台通过时钟激励和数据递增逻辑,验证了接口转换的功能正确性。
设计中需特别注意时钟质量优化、双沿数据的时序对齐以及跨时钟域处理(如需),确保满足 IEEE 标准和硬件时序约束。该方案为 FPGA 网络接口设计提供了可复用的模板,适用于千兆以太网等高速数据传输场景,具有较强的工程实践价值。通过合理的模块划分和原语应用,可有效简化开发流程,提升系统稳定性。实际部署建议结合Xilinx的UltraScale Architecture PCB Design Guide进行板级优化,并通过Tcl脚本实现自动化时序检查。
七、更多操作
完整FPGA系列,请看
FPGA系列,文章目录
https://blog.csdn.net/weixin_65793170/article/details/144185217

相关文章:
FPGA 37 ,FPGA千兆以太网设计实战:RGMII接口时序实现全解析( RGMII接口时序设计,RGMII~GMII,GMII~RGMII 接口转换 )
目录 前言 一、设计流程 1.1 需求理解 1.2 模块划分 1.3 测试验证 二、模块分工 2.1 RGMII→GMII(接收方向,rgmii_rx 模块) 2.2 GMII→RGMII(发送方向,rgmii_tx 模块) 三、代码实现 3.1 顶层模块 …...
上篇:《排序算法的奇妙世界:如何让数据井然有序?》
个人主页:strive-debug 排序算法精讲:从理论到实践 一、排序概念及应用 1.1 基本概念 **排序**:将一组记录按照特定关键字(如数值大小)进行递增或递减排列的操作。 1.2 常见排序算法分类 - **简单低效型**ÿ…...
红宝书第三十四讲:零基础学会单元测试框架:Jest、Mocha、QUnit
红宝书第三十四讲:零基础学会单元测试框架:Jest、Mocha、QUnit 资料取自《JavaScript高级程序设计(第5版)》。 查看总目录:红宝书学习大纲 一、单元测试是什么? 就像给代码做“体检”,帮你检查…...
【JDBC-54.1】MySQL JDBC连接字符串常用参数详解
在Java应用程序中连接MySQL数据库时,JDBC连接字符串是建立连接的关键。一个配置得当的连接字符串不仅能确保连接成功,还能优化性能、增强安全性并处理各种连接场景。本文将深入探讨MySQL JDBC连接字符串的常用参数及其最佳实践。 1. 基本连接字符串格式…...
swagger 注释说明
一、接口注释核心字段 在 Go 的路由处理函数(Handler)上方添加注释,支持以下常用注解: 注解名称用途说明示例格式Summary接口简要描述Summary 创建用户Description接口详细说明Description 通过用户名和邮箱创建新用户Tags接口分…...
CST1019.基于Spring Boot+Vue智能洗车管理系统
计算机/JAVA毕业设计 【CST1019.基于Spring BootVue智能洗车管理系统】 【项目介绍】 智能洗车管理系统,基于 Spring Boot Vue 实现,功能丰富、界面精美 【业务模块】 系统共有三类用户,分别是:管理员用户、普通用户、工人用户&…...
【前端网络请求】XHR封装,支持文件上传、进度监控、混合字段传输
网络请求介绍 XMLHttpRequest(XHR)是前端开发中用于发起网络请求的基础技术。虽然现代开发中常用fetch或axios,但掌握XHR的封装技巧仍能让你更灵活地应对复杂需求。本文将通过一个可复用、功能全面的XHR封装工具,教你实现以下功能: 📤 文件上传(单个/多个文件)📊 实…...
# Shell脚本参数设计规范(DeepSeek指导)
Shell脚本参数设计规范(DeepSeek指导) 文章目录 Shell脚本参数设计规范(DeepSeek指导)A 我问:Q DeepSeek回答:**命令行参数表示规范****标准化表示示例**情况1:必选选项参数值情况2:…...
学习SqlSugar的跨库查询基本用法
使用SqlSugar操作数据库通常都是单库操作,跨库查询的情况要么是单个系统数据不完整,需要其它系统的关联业务数据支撑,要么就是需要整合汇总多个系统的数据进行数据数据分析、处理、展示。遇到上述情况,可以要求另外的系统提供查询…...
HTTP:五.WEB服务器
web服务器 定义:实现提供资源或应答的提供者都可以谓之为服务器!web服务器工作内容 接受建立连接请求 接受请求 处理请求 访问报文中指定的资源 构建响应 发送响应 记录事务处理过程 Web应用开发用到的一般技术元素 静态元素:html, img,js,Css,SWF,MP4 动态元素:PHP,…...
5.3 GitHub订阅系统核心架构解密:高并发设计与SQLite优化实战
GitHub Sentinel 分析报告功能实现:订阅管理核心逻辑解析 关键词:GitHub API 订阅管理, SQLite 数据库设计, RESTful API 开发, 原子操作封装, 异常处理机制 1. 订阅管理功能架构设计 订阅管理模块采用分层架构设计,通过清晰的接口隔离实现高内聚低耦合: #mermaid-svg-bW…...
CSI-PVController-volumeWorker
volumeWorker() 与claim worker流程一样,从volumeQueue中取数据,也就是取出的都是PV,如果informer中有这个pv,就进入update流程。 定义workFunc:首先,定义了一个匿名函数workFunc,这个函数是实…...
0基础 | 硬件滤波 C、RC、LC、π型
一、滤波概念 (一)滤波定义 滤波是将信号中特定波段频率滤除的操作,是抑制和防止干扰的重要措施。通过滤波器实现对特定频率成分的筛选,确保目标信号的纯净度,提升系统稳定性。 (二)滤波器分…...
图论基础理论
在我看来,想要掌握图的基础应用,仅需要三步走。 什么是图(基本概念)、图的构造(打地基)、图的遍历方式(应用的基础) 只要能OK的掌握这三步、就算图论入门了!࿰…...
leaflet 之 获取中国某个行政区的经纬度边界(latLngBounds)
思路 在json文件中获取下面的四个点 组成东北,西南两组 { “southwest”: { “lat”: 35.950, “lng”: 120.000 },//西南方 “northeast”: { “lat”: 36.200, “lng”: 120.300 }//东北方 } 最西点经度(minLng) 最东点经度(maxLng&#x…...
企业级低代码平台的架构范式转型研究
在快速迭代的数字时代,低代码平台如同一股清流,悄然成为开发者们的新宠。 它利用直观易用的拖拽式界面和丰富的预制组件,将应用程序的开发过程简化到了前所未有的程度。通过封装复杂的编程逻辑和提供强大的集成能力,低代码平台让…...
怎么免费下载GLTF/GLB格式模型文件,还可以在线编辑修改
现在非常流行glb格式模型,和gltf格式文件,可是之类模型网站非常非常少 1,咱们先直接打开http://glbxz.com 官方glb下载网站 glbxz.com 2 可以搜索,自己想要的模型关键词 3,到自己想下载素材页面 4,…...
MyBatis 中 Mapper 传递参数的多种方法
# MyBatis Mapper 传递参数的多种方法及其优势 在使用 MyBatis 进行数据库操作时,Mapper 接口的参数传递是一个非常基础但又十分重要的部分。不同的参数传递方式适用于不同的场景,合理选择可以大大提高代码的可读性和维护性。本文将详细介绍几种常见的 …...
大模型到底是怎么产生的?一文揭秘大模型诞生全过程
前言 大模型到底是怎么产生的呢? 本文将从最基础的概念开始,逐步深入,用通俗易懂的语言为大家揭开大模型的神秘面纱。 大家好,我是大 F,深耕AI算法十余年,互联网大厂核心技术岗。 知行合一,不写水文,喜欢可关注,分享AI算法干货、技术心得。 【专栏介绍】: 欢迎关注《…...
2025年3月 Scratch图形化三级 真题解析 中国电子学会全国青少年软件编程等级考试
2025年3月Scratch图形化编程等级考试三级真题试卷 一、选择题 第 1 题 默认小猫角色,scratch运行程序后,下列说法正确的是?( ) A.小猫的颜色、位置在一直变化 B.小猫在舞台中的位置在一直变化,颜色…...
判断两个 IP 地址是否在同一子网 C
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> // 将点分十进制的 IP 地址转换为 32 位无符号整数 unsigned int ip_to_uint(const char *ip) { struct in_addr addr; if (inet_pton(AF_INET, ip, &am…...
DHCP中继
前言: DHCP Relay即DHCP中继,它是为解决DHCP服务器和DHCP客户端不在同一个广播域而提出的 DHCP中继 DHCP协议依赖广播通信(如客户端发送DHCP Discover报文),但广播报文无法跨越子网,因为: 路由…...
02 - spring security基于配置文件及内存的账号密码
spring security基于配置的账号密码 文档 00 - spring security框架使用01 - spring security自定义登录页面 yml文件中配置账号密码 spring:security:user:name: adminpassword: 123456yml文件中配置账号密码后,控制台将不再输出临时密码 基于内存的账号密码 …...
【贪心之摆动序列】
题目: 分析: 这里我们使用题目中给的第二个实例来进行分析 题目中要求我们序列当中有多少个摆动序列,摆动序列满足一上一下,一下一上,这样是摆动序列,并且要输出摆动序列的最长长度 通过上面的图我们可以…...
Spring Boot 中应用的设计模式
Spring Boot 中应用的设计模式详解 Spring Boot 作为 Spring 框架的扩展,广泛使用了多种经典设计模式。以下是主要设计模式及其在 Spring Boot 中的具体应用: 一、创建型模式 1. 工厂模式 (Factory Pattern) 应用场景: BeanFactory 和 Ap…...
0x25广度优先搜索+0x26广搜变形
1.一般bfs AcWing 172. 立体推箱子 #include<bits/stdc.h> using namespace std; int n,m; char s[505][505]; int vis[3][505][505]; int df[3][4]{{1,1, 2,2},{0,0,1,1}, {0,0,2,2}}; int dx[3][4]{{0,0,1,-2},{0,0,1,-1},{2,-1,0,0}}; int dy[3][4]{{1,-2,0,0},{2,…...
java面向对象02:回顾方法
回顾方法及加深 定义方法 修饰符 返回类型 break:跳出switch和return的区别 方法名 参数列表 package com.oop.demo01;//Demo01类 public class Demo01 {//main方法public static void main(String[] args) {}/*修饰符 返回值类型 方法名(...){//方法体return…...
数据结构day05
一 栈的应用(括号匹配) 各位同学大家好,在之前的小结中,我们学习了栈和队列这两种数据结构,那从这个小节开始,我们要学习几种栈和队列的典型应用。这个小节中,我们来看一下括号匹配问题…...
windows中搭建Ubuntu子系统
windows中搭建虚拟环境 1.配置2.windows中搭建Ubuntu子系统2.1windows配置2.1.1 确认启用私有化2.1.2 将wsl2设置为默认版本2.1.3 确认开启相关配置2.1.4重启windows以加载更改配置 2.2 搭建Ubuntu子系统2.2.1 下载Ubuntu2.2.2 迁移位置 3.Ubuntu子系统搭建docker环境3.1安装do…...
ImgTool_0.8.0:图片漂白去底处理优化工具
ImgTool_0.8.0 是一款专为Windows设计的免费、绿色便携式图片处理工具,支持 Windows 7/8/10/11 系统。其核心功能为漂白去底,可高效去除扫描件或手机拍摄图片中的泛黄、灰底及阴影,同时提供智能纠偏、透视校正等辅助功能࿰…...
