当前位置: 首页 > news >正文

64B/66B GT Transceiver 配置

一、前言

前一篇文章已经讲述了64B/66B的编码原理,此篇文章来配置一下7系列GT的64B/66B编码。并讲述所对应的例子工程的架构,以及部分代码的含义。

二、IP核配置

1、打开7 Series FPGAs Transceiver Wizards,选择将共享逻辑放置在example design中

 2、线速率、参考时钟选择

(1)协议选择从0开始

(2)线速率选择10G,参考时钟选择156.25M

(3)PLL选择:当线速率大于6.6G,自动选择为QPLL

(4)Transceiver选择:保持默认就可以,在布局布线的时候,软件会根据管脚绑定自动选择Transceiver。

3、编码和时钟选择

(1)选择TX、RX外部数据带宽为64bit,选择编码方式为64B/66B with Ext Seq Ctr,内部数据带宽为32bit,DRP时钟为100M

这里的64B/66B with Ext Seq Ctr表示使用64B/66B编码,并使用外部计数器。关于这方面的知识可以去参考UG476中的Gearbox的章节,或者参考此篇文章:详解GearBox设计原理

(2)这里的选项几乎都是有关8B/10B编码的,不需要勾选

(3)这里使用弹性Buffer去做跨时钟域,选择TXUSERCLK的源为TXOUTCLK,TXOUTCLK的源为参考时钟。

(4)这里的选项大多关于PCS、PMA复位或者QPLL、CPLL掉电的,也不需要勾选

 4、逗号对齐和均衡

(1)这里的选项全部都是8B/10B所用到的,所以不能选择

(2)均衡方式这里选择DFE,接收端的阈值电压设置为800mv

(3)这里将TX极性转换、幅值控制、前加重、后加重选上,RX端将RX极性转换选上。

5、这是是使用PCIe或者SATA所用的选项,这里只将loopback勾选

6、通道绑定和时钟矫正

在这里使用序列长度为2的时钟矫正序列,并设置为BC507、总结,关注以下内部带宽、外部带宽,参考时钟频率、TXUSERCLK2就好

 三、例子工程

工程架构:

 Frame_gen模块:用来产生数据帧;

Scrambler模块:用来对所发送的数据进行加扰;

Descrambler模块:用来对接收的模块进行解扰;

Block_syn模块:用于进行块同步。

Frame_chck:用于检测接收到的数据正确性

四、加扰、解扰模块

64B/66B自同步扰码实现随机化,编码所使用的扰码器为: X58+X39+1

扰码的数学原理使用了多项式,多项式的选择通常是基于扰码的特性,包括生成数据的随机度,以及打乱连0和连1的能力。一个简单的扰码器包含一组排列好的触发器,用于移位数据流。大部分的触发器只需要简单地输出下一个比特流即可,但是在复杂的扰码电路中,触发器需要与数据流中的历史比特进行逻辑运算(与和或运算)。

例子工程中加扰、解扰模块是按照如下的示意图进行的:

加扰、解扰程序如下 

//加扰模块
module gtwizard_0_SCRAMBLER #
( parameter TX_DATA_WIDTH = 32
)
(// User Interfaceinput  wire  [(TX_DATA_WIDTH-1):0] UNSCRAMBLED_DATA_IN,input  wire                        DATA_VALID_IN,output reg   [(TX_DATA_WIDTH-1):0] SCRAMBLED_DATA_OUT,// System Interfaceinput  wire          USER_CLK,input  wire          SYSTEM_RESET
);//***************************Internal Register Declarations******************** integer                        i;reg     [57:0]                 poly;reg     [(TX_DATA_WIDTH-1):0]  scrambled_data_i;reg     [57:0]                 scrambler;reg     [(TX_DATA_WIDTH-1):0]  tempData;reg                            xorBit;//*********************************Main Body of Code***************************always @(scrambler,UNSCRAMBLED_DATA_IN)beginpoly = scrambler;for (i=0;i<=(TX_DATA_WIDTH-1);i=i+1)beginxorBit = UNSCRAMBLED_DATA_IN[i] ^ poly[38] ^ poly[57];poly = {poly[56:0],xorBit};tempData[i] = xorBit;endend  //________________ Scrambled Data assignment to output port _______________    always @(posedge USER_CLK)beginif (SYSTEM_RESET)beginSCRAMBLED_DATA_OUT <= `DLY  'h0;scrambler          <= `DLY  58'h155_5555_5555_5555;endelse if (DATA_VALID_IN)beginSCRAMBLED_DATA_OUT <= `DLY  tempData;scrambler          <= `DLY  poly;endendendmodule
//解扰模块
module gtwizard_0_DESCRAMBLER #
( parameter RX_DATA_WIDTH = 32
)
(// User Interfaceinput  wire [(RX_DATA_WIDTH-1):0] SCRAMBLED_DATA_IN,input  wire                       DATA_VALID_IN,output reg  [(RX_DATA_WIDTH-1):0] UNSCRAMBLED_DATA_OUT,// System Interface
input  wire         USER_CLK,
input  wire         SYSTEM_RESET
);//***************************Internal Register Declarations******************** reg     [57:0]                 descrambler;integer                        i;reg     [57:0]                 poly;reg     [(RX_DATA_WIDTH-1):0]  tempData;reg     [(RX_DATA_WIDTH-1):0]  unscrambled_data_i;reg                            xorBit;//*********************************Main Body of Code***************************always @(descrambler,SCRAMBLED_DATA_IN)beginpoly = descrambler;for (i=0;i<=(RX_DATA_WIDTH-1);i=i+1)beginxorBit = SCRAMBLED_DATA_IN[i] ^ poly[38] ^ poly[57];poly = {poly[56:0],SCRAMBLED_DATA_IN[i]};tempData[i] = xorBit;endend//________________ Scrambled Data assignment to output port _______________    always @(posedge USER_CLK)beginif (SYSTEM_RESET)beginUNSCRAMBLED_DATA_OUT <= `DLY  'h0;descrambler          <= `DLY  58'h155_5555_5555_5555;endelse if (DATA_VALID_IN)beginUNSCRAMBLED_DATA_OUT <= `DLY  tempData;descrambler          <= `DLY  poly;endendendmodule

五、块对齐

64B/66B和64B/67B协议依赖于块同步来确定它们的块边界。块同步是必需的,因为在实现块锁定之前,所有传入的数据都未对齐。其目标是通过更改数据对齐方式来搜索有效的同步标头。RXGEARBOXSLIP输入端口用于改变Gearbox数据对齐,以便可以在正常模式下检查所有可能的对齐。RXGEARBOXSLIP输入端口用于改变变速箱数据对齐,以便可以在正常模式下检查所有可能的对齐。这个滑移和测试同步头的过程重复,直到实现块锁定。使用RXGearbox时,FPGA逻辑中需要块同步状态机。

整个过程按照如下的状态机进行:

例子工程的代码如下,将一些关键条件进行注释:

`timescale 1ns / 1ps
`define DLY #1module gtwizard_0_BLOCK_SYNC_SM #
(parameter SH_CNT_MAX         = 64,parameter SH_INVALID_CNT_MAX = 16 
)
(// User Interfaceoutput reg          BLOCKSYNC_OUT,output reg          RXGEARBOXSLIP_OUT,input  wire [2:0]   RXHEADER_IN,input  wire         RXHEADERVALID_IN,// System Interfaceinput  wire         USER_CLK,input  wire         SYSTEM_RESET
);//**************************** Wire Declarations ******************************wire           slip_pulse_i;    wire           next_begin_c;wire           next_sh_invalid_c;    wire           next_sh_valid_c;    wire           next_slip_c;    wire           next_sync_done_c;    wire           next_test_sh_c;    wire           sh_count_equals_max_i;    wire           sh_invalid_cnt_equals_max_i;    wire           sh_invalid_cnt_equals_zero_i;    wire           slip_done_i;    wire           sync_found_i;    //***************************External Register Declarations*************************** reg            begin_r;reg            sh_invalid_r;    reg            sh_valid_r;    reg    [31:0]  slip_count_i; reg            slip_r;    reg            sync_done_r;    reg    [9:0]   sync_header_count_i; reg    [9:0]   sync_header_invalid_count_i;   reg            test_sh_r;    //**************************** Main Body of Code *******************************// assign sync_found_i   = (RXHEADER_IN[1:0] == 2'b01) || (RXHEADER_IN[1:0] == 2'b10);//寻找到数据头//________________________________ State machine __________________________    // State registersalways @(posedge USER_CLK)if(SYSTEM_RESET){begin_r,test_sh_r,sh_valid_r,sh_invalid_r,slip_r,sync_done_r}  <=  `DLY    6'b100000;elsebeginbegin_r          <=  `DLY    next_begin_c;test_sh_r        <=  `DLY    next_test_sh_c;sh_valid_r       <=  `DLY    next_sh_valid_c;sh_invalid_r     <=  `DLY    next_sh_invalid_c;slip_r           <=  `DLY    next_slip_c;sync_done_r      <=  `DLY    next_sync_done_c;end// Next state logic//begin信号相当于一个复位信号,当同步 或者 滑动计数器已满 或者 同步计数器已经达到最大值但是无效同步计数器有值 或者 同步头无效,同步头的数量到达最大值 都要将计数器清0assign  next_begin_c     =   sync_done_r                                                                                    //已经同步| (slip_r && slip_done_i)                                                                      //slip的滑动计数器已满| (sh_valid_r && sh_count_equals_max_i && !sh_invalid_cnt_equals_max_i)                        //同步头有效,同步头的数量到达最大值,无效同步头的数量也没有达到最大值| (sh_invalid_r && sh_count_equals_max_i && !sh_invalid_cnt_equals_max_i && BLOCKSYNC_OUT);    //同步头无效,同步头的数量到达最大值,无效同步头的数量也没有达到最大值 快同步继续进行assign  next_test_sh_c    =  begin_r                                                                                         //开始| (test_sh_r && !RXHEADERVALID_IN)                                                              //正在检测同步头,并且没有有效的同步头输入,则下一个时钟周期继续检测头部| (sh_valid_r && !sh_count_equals_max_i)                                                        //同步头有效,但是有效同步头的数量没有达到最大值| (sh_invalid_r && !sh_count_equals_max_i && !sh_invalid_cnt_equals_max_i && BLOCKSYNC_OUT);    //同步头无效、同步头的数量没有到达最大值、无效同步头的数量也没有达到最大值、快同步继续进行assign  next_sh_valid_c   =  (test_sh_r && RXHEADERVALID_IN && sync_found_i);                                                //同步头已经找到,并且输入头有效,并且正在处于查找输入头的状态assign  next_sh_invalid_c =  (test_sh_r && RXHEADERVALID_IN && !sync_found_i);                                               //正在处于查找输入头的状态,输入头有效,但是同步头没有找到,assign  next_slip_c       = (sh_invalid_r && (sh_invalid_cnt_equals_max_i || !BLOCKSYNC_OUT))                                                            //下一次滑动的条件:同步头无效,无效同步头计数达到最大值 或者 块同步输出为0| (sh_valid_r && sh_count_equals_max_i && ! sh_invalid_cnt_equals_zero_i && (sh_invalid_cnt_equals_max_i || !BLOCKSYNC_OUT)) //同步头有效并且有效同步头计数器已达到最大值,但是无效同步计数器不为0,并且此时的无效同步计数器达到最大值或者块同步没有输出| (slip_r && !slip_done_i);                                                                                                  //滑动信号有效并且滑动计数器没有计满assign  next_sync_done_c  =  (sh_valid_r && sh_count_equals_max_i && sh_invalid_cnt_equals_zero_i);                          //同步标志:输入的同步头有效并且有效同步头计数器达到最大值并且无效同步器计数为0//________________ Counter keep track of sync headers counted _____________    always @(posedge USER_CLK)if(begin_r)  beginsync_header_count_i   <=  `DLY    10'd0;endelse if (sh_valid_r || sh_invalid_r)                                                                                  //同步计数器在有效同步头和无效同步头的时候都会加1beginsync_header_count_i  <=  `DLY    sync_header_count_i + 10'd1;endassign sh_count_equals_max_i = (sync_header_count_i==SH_CNT_MAX);//________________ Counter keep track of invalid sync headers  ____________    always @(posedge USER_CLK)if(begin_r)  beginsync_header_invalid_count_i   <=  `DLY    10'd0;endelse if (sh_invalid_r)                                                                                              //记录无效同步头的数量beginsync_header_invalid_count_i  <=  `DLY    sync_header_invalid_count_i + 10'd1;end// signal to indicate max number of invalid sync headers has been reachedassign sh_invalid_cnt_equals_max_i  = (sync_header_invalid_count_i==SH_INVALID_CNT_MAX);// signal to indicate no invalid sync headersassign sh_invalid_cnt_equals_zero_i = (sync_header_invalid_count_i==0);//_______ Counter wait for 16 cycles to ensure that slip is complete _______    assign slip_pulse_i = next_slip_c && !slip_r;                                                                           //滑动信号输出always @(posedge USER_CLK)RXGEARBOXSLIP_OUT   <=  slip_pulse_i;//_____________ Ouput assignment to indicate block sync complete  _________     always @(posedge USER_CLK)if(!slip_r) slip_count_i   <=  `DLY    32'h00000000;else        slip_count_i   <=  `DLY    {slip_count_i[30:0],RXGEARBOXSLIP_OUT};                                      //滑动计数器assign slip_done_i = slip_count_i[31];//_____________ Pulse GEARBOXSLIP port to slip the data by 1 bit  _________    always @(posedge USER_CLK)if(SYSTEM_RESET || slip_r)  BLOCKSYNC_OUT   <=  `DLY    1'b0;else if (sync_done_r)       BLOCKSYNC_OUT   <=  `DLY    1'b1;                                                       //当同步时,证明块同步已完成endmodule

六、总结

具体的块对齐过程可以结合仿真看一下,由于过程比较复杂,这里就不细说了

相关文章:

64B/66B GT Transceiver 配置

一、前言 前一篇文章已经讲述了64B/66B的编码原理&#xff0c;此篇文章来配置一下7系列GT的64B/66B编码。并讲述所对应的例子工程的架构&#xff0c;以及部分代码的含义。 二、IP核配置 1、打开7 Series FPGAs Transceiver Wizards&#xff0c;选择将共享逻辑放置在example …...

ES6: promise对象与回调地狱

ES6&#xff1a; promise对象与回调地狱 一、回调地狱二、Promise概述三、Promise的组成四、用函数封装Promise读取文件操作 一、回调地狱 在js中大量使用回调函数进行异步操作&#xff0c;而异步操作什么时候返回结果是不可控的&#xff0c;所以希望一段程序按我们制定的顺序执…...

Qt事件处理机制2-事件函数的传播

所有继承自QObject的类都有event函数&#xff0c;该函数用来处理自身的事件&#xff0c;函数定义如下&#xff1a; virtual bool QObject::event(QEvent *e)&#xff1b;Qt帮助文档&#xff1a; This virtual function receives events to an object and should return true i…...

【PDF.js】PDF文件预览

【PDF.js】PDF文件预览 一、PDF.js二、PDF.js 下载1、下载PDF.js2、在项目中引入3、屏蔽跨域错误 三、项目中使用四、说明五、实现效果 使用PDFJS实现pdf文件的预览&#xff0c;支持预览指定页、关键词搜索、缩略图、页面尺寸调整等等。 一、PDF.js 官方地址 文档地址 二、PD…...

从建表语句带你学习doris_表索引

1、doris建表概述 1.1、doris建表模板 CREATE [EXTERNAL] TABLE [IF NOT EXISTS] [DATABASE.]table_name (column_definition1[,column_deinition2,......][,index_definition1,[,index_definition2,]] ) [ENGINE [olap|mysql|broker|hive]] [key_desc] [COMMENT "tabl…...

Linux CentOS 安装 MySQL 服务教程

Linux CentOS 安装 MySQL 服务教程 1. 查看系统和GNU C库(glibc)版本信息 1.1 查询机器 glibc 版本信息 glibc&#xff0c;全名GNU C Library&#xff0c;是大多数Linux发行版中使用的C库&#xff0c;为系统和应用程序提供核心的API接口。在Linux系统中&#xff0c;特别是在…...

MSSQL 命令行操作说明 sql server 2022 命令行下进行配置管理

说明&#xff1a;本文的内容是因为我在导入Access2019的 *.accdb 格式的数据时&#xff0c;总是出错的背景下&#xff0c;不得已搜索和整理了一下&#xff0c;如何用命令行进行sql server 数据库和用户管理的方法&#xff0c;作为从Access2019 直接导出数据到sql server 数据库…...

【系统分析师】系统安全分析与设计

文章目录 1、安全基础技术1.1 密码相关1.1.1对称加密1.1.2非对称加密1.1.3信息摘要1.1.4数字签名1.1.5数字信封 1.2 PKI公钥体系 2、信息系统安全2.1 保障层次2.2 网络安全2.2.1WIFI2.2.2 网络威胁与攻击2.2.3 安全保护等级 2.3计算机病毒与木马2.4安全防范体系 1、安全基础技术…...

ActiveMQ 07 集群配置

Active MQ 07 集群配置 官方文档 http://activemq.apache.org/clustering 主备集群 http://activemq.apache.org/masterslave.html Master Slave TypeRequirementsProsConsShared File System Master SlaveA shared file system such as a SANRun as many slaves as requ…...

Redis(哨兵模式)

什么是哨兵机制 问题: redis 主从复制模式下, 一旦主节点由于故障不能提供服务, 需要人工进行主从切换, 同时大量客户端需要被通知切换到新的主节点上, 对于有一定规模的应用来说, 对于人力的资源消耗会很大.解决: 通过哨兵对主从结构进行监控, 一旦出现主节点挂了的情况, 自动…...

一种基于镜像指示位办法的RingBuffer实现,解决Mirror和2的幂个数限制

简介 在嵌入式开发中&#xff0c;经常有需要用到RingBuffer的概念&#xff0c;在RingBuffer中经常遇到一个Buffer满和Buffer空的判断的问题&#xff0c;一般的做法是留一个单位的buffer不用&#xff0c;这样做最省事&#xff0c;但是当RingBuffer单位是一个结构体时&#xff0…...

【Java开发指南 | 第十一篇】Java运算符

读者可订阅专栏&#xff1a;Java开发指南 |【CSDN秋说】 文章目录 算术运算符关系运算符位运算符逻辑运算符赋值运算符条件运算符&#xff08;?:&#xff09;instanceof 运算符Java运算符优先级 Java运算符包括&#xff1a;算术运算符、关系运算符、位运算符、逻辑运算符、赋值…...

【IC前端虚拟项目】验证环境方案思路和文档组织

【IC前端虚拟项目】数据搬运指令处理模块前端实现虚拟项目说明-CSDN博客 对于mvu的验证环境,从功能角度就可以分析出需要搭建哪些部分,再看一下mvu的周围环境哈: 很明显验证环境必然要包括几个部分: 1.模拟idu发送指令; 2.模拟ram/ddr读写数据; 3.rm模拟mvu的行为; …...

程序设计|C语言教学——C语言基础1:C语言的引入和入门

一、程序的执行 1.定义 解释&#xff1a;借助一个程序&#xff0c;那个程序能够试图理解你的程序&#xff0c;然后按照你的要求执行。下次执行的时候还需要从零开始解释。 编译&#xff1a;借助一个程序&#xff0c;能够像翻译官一样&#xff0c;把你的程序翻译成机器语言&a…...

初学python记录:力扣928. 尽量减少恶意软件的传播 II

题目&#xff1a; 给定一个由 n 个节点组成的网络&#xff0c;用 n x n 个邻接矩阵 graph 表示。在节点网络中&#xff0c;只有当 graph[i][j] 1 时&#xff0c;节点 i 能够直接连接到另一个节点 j。 一些节点 initial 最初被恶意软件感染。只要两个节点直接连接&#xff0c…...

LlamaIndex 组件 - Storing

文章目录 一、储存概览1、概念2、使用模式3、模块 二、Vector Stores1、简单向量存储2、矢量存储选项和功能支持3、Example Notebooks 三、文件存储1、简单文档存储2、MongoDB 文档存储3、Redis 文档存储4、Firestore 文档存储 四、索引存储1、简单索引存储2、MongoDB 索引存储…...

在Linux系统中设定延迟任务

一、在系统中设定延迟任务要求如下&#xff1a; 要求&#xff1a; 在系统中建立easylee用户&#xff0c;设定其密码为easylee 延迟任务由root用户建立 要求在5小时后备份系统中的用户信息文件到/backup中 确保延迟任务是使用非交互模式建立 确保系统中只有root用户和easylee用户…...

JVM之方法区的详细解析

方法区 方法区&#xff1a;是各个线程共享的内存区域&#xff0c;用于存储已被虚拟机加载的类信息、常量、即时编译器编译后的代码等数据&#xff0c;虽然 Java 虚拟机规范把方法区描述为堆的一个逻辑部分&#xff0c;但是也叫 Non-Heap&#xff08;非堆&#xff09; 设置方法…...

Go 使用ObjectID

ObjectID介绍 MongoDB中的ObjectId是一种特殊的12字节 BSON 类型数据&#xff0c;用于为主文档提供唯一的标识符&#xff0c;默认情况下作为 _id 字段的默认值出现在每一个MongoDB集合中的文档中。以下是ObjectId的具体组成&#xff1a; 1. 时间戳&#xff08;Timestamp&…...

基于SpringBoot+Vue的疾病防控系统设计与实现(源码+文档+包运行)

一.系统概述 在如今社会上&#xff0c;关于信息上面的处理&#xff0c;没有任何一个企业或者个人会忽视&#xff0c;如何让信息急速传递&#xff0c;并且归档储存查询&#xff0c;采用之前的纸张记录模式已经不符合当前使用要求了。所以&#xff0c;对疾病防控信息管理的提升&a…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

腾讯云V3签名

想要接入腾讯云的Api&#xff0c;必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口&#xff0c;但总是卡在签名这一步&#xff0c;最后放弃选择SDK&#xff0c;这次终于自己代码实现。 可能腾讯云翻新了接口文档&#xff0c;现在阅读起来&#xff0c;清晰了很多&…...

深入理解Optional:处理空指针异常

1. 使用Optional处理可能为空的集合 在Java开发中&#xff0c;集合判空是一个常见但容易出错的场景。传统方式虽然可行&#xff0c;但存在一些潜在问题&#xff1a; // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...