Vivado使用技巧:时钟的约束方法

news2024/11/19 8:31:18

时钟的基础知识
        数字设计中,“时钟”表示在寄存器之间可靠地传输数据所需的参考时间;Vivado的时序引擎利用时钟特征来计算时序路径需求,通过计算时间裕量(Slack)的方法报告设计的时序空余;时钟必须被正确定义以最佳精度获得最大的时序路径覆盖范围,包含如下特性:

●定义在时钟树的驱动管脚或端口,通常称作根或源点;
●通过周期和波形属性来描述时钟边沿;
●周期(period)以ns为单位进行设定,与波形重复率相关;
●波形(waveform)以列表的形式给出,表中包含上升沿和下降沿在周期中的绝对时间,以ns为单位;第一个上升沿对应于第一个值,第一个下降沿对应第二个值;默认情况下,相位偏移从0ns开始,占空比为50%;

如下图给出了两个时钟Clk0: period=10, waveform={0 5}、Clk1: period=8, waveform = {2 8}; 

        上述给出的只是时钟的理想特征。当时钟进入了FPGA器件,通过时钟树传递时,时钟边沿会有延时,通常称作时钟网络延迟;噪声或硬件表现会导致时钟随时可能发生变化,通常称作时钟不确定性,包括时钟抖动(Clock jitter)、相位错位(Phase error)等等, Vivado在时序分析时会考虑这些非理想因素以得到精确的时序裕量;

        通常板子上有一个外部组件(如有源晶振)产生时钟信号,通过输入端口进入器件内部;外部时钟可以通过MMCM、PLL、BUFR等特殊原语生成其它时钟,也可以由LUT、寄存器等常规单元进行转换(通常称作门控时钟);接下来的部分将讲述如何由源时钟定义成其他类型的时钟;

主时钟Primary Clock
        主时钟通常由两个来源:(1)板级时钟通过输入端口进入设计;(2)GT收发器的输出管脚(如恢复时钟);

        主时钟必须与一个网表对象相连,该对象代表了所有时钟边沿的开始点,并且在时钟树中向下传递;也可以说,主时钟的源点定义了0时刻,Vivado靠此来计算时钟延迟和不确定性 ;vivado会忽略所有时钟树上从主时钟上游的单元到主时钟之间的延时!

        主时钟只能通过create_clock命令来定义,且必须放在约束的开始,这是因为其它时序约束几乎都要参考主时钟;下面给出几个主时钟的例子,第一个例子如下图所示,采用单端时钟输入:

         板级时钟通过sysclk端口进入FPGA,通过一个输入缓冲器和一个时钟缓冲器后到达寄存器,使用如下命令定义:

create_clock -period 10 [get_ports sysclk]  #10ns周期,50%占空比,无相移
create_clock -name devclk -period 10 -wavefor {2.5 5} [get_ports sysclk]  #板级时钟名称devclk,10ns周期,25%占空比,90°相移

第二个例子,时钟源由高速收发器gt0提供,如下图所示:

          通过sysclk端口进入FPGA,之后经过混合时钟管理单元MMCM生成其他时钟,以gt0发出的时钟为主时钟,其他生成时钟都有一个共同的时钟源,使用如下命令定义:

create_clock -name rxclk -period 3.33 [get_pins gt0/RXOUTCLK]

第三个例子如下图所示,采用差分时钟输入,这也是高速时钟的输入方式:

 

上图中差分时钟驱动一个PLL,定义主时钟时必须只创建差分缓冲器的正极输入;如果同时创建了正极、负极输入,将会导致错误的CDC路径;使用如下命令定义:

create_clock -name sysclk -period 3.33 [get_ports SYS_CLK_clk_p]

 虚拟时钟Virtual Clock
虚拟时钟通常用于设定对输入和输出的延迟约束,之所以称为“虚拟”,是因为这种时钟在物理上没有与设计中的任何网表对象相连;定义时使用create_clock命令,但无需指定源对象 ,在下列情况需要用到虚拟时钟:

所有的设计时钟都不是外部器件I/O的参考时钟;
FPGA的I/O路径与一个内部生成的时钟相关,但是该时钟不能合适地通过对板级时钟计时来生成(如两个周期的比不是整数);
希望为与I/O延迟约束相关的时钟设定不同的抖动和延迟,但是不希望修改内部时钟的特征 ;
比如时钟clk_virt的周期为10ns,且不与任何网表对象相连,可以这样定义“create_clock -name clk_virt –period 10”,没有指定objects参数;注意,虚拟时钟必须在使用之前便定义好 ;

生成时钟Generated Clock
 生成时钟是指在设计内部由特殊单元(如MMCM、PLL)或用户逻辑驱动的时钟;生成时钟与一个上级时钟(注:官方称作master clock,为与primary clock作区分,这里称作上级时钟)相关,其属性也是直接由上级时钟派生而来;上级时钟可以是一个主时钟,也可以是另一个生成时钟;

生成时钟使用create_generated_clock命令定义,该命令不是设定周期或波形,而是描述时钟电路如何对上级时钟进行转换。这种转换可以是下面的关系:

Vivado计算生成时钟的延迟时,会追踪生成时钟的源管脚与上级时钟的源管脚之间的所有组合和时序路径。某些情况下可能只希望考虑组合逻辑路径,在命令行后添加-combinational选项即可;

这里先解释一下本文甚至本系列大量使用的两个词,端口(Port)和管脚(Pin)。端口通常用get_ports命令获取,管脚使用get_pins命令获取。二者的含义是不同的,但管脚的范围更广泛,比如设计中用到的一个寄存器都有3个管脚:clk、D和Q;下面给出几个定义生成时钟的例子:

简单的频率分频
简单的频率倍频
频率倍频与分频的组合,获得一个非整数的比例,通常由MMCM或PLL完成
相移或波形反相
占空比改变
上述所有关系的组合
1.简单的2分频

 可以采用如下两种方法对生成时钟进行约束:

#定义主时钟,周期10ns,50%占空比

create_clock -name clkin -period 10 [get_ports clkin]
#约束方法1,主时钟作为源点
create_generated_clock -name clkdiv2 -source [get_ports clkin] -divide_by 2 [get_pins REGA/Q] 
#约束方法2,REGA的始终管脚作为源点
create_generated_clock -name clkdiv2 -source [get_pins REGA/C] -divide_by 2 [get_pins REGA/Q]

        约束命令中使用**-source选项来设定上级时钟,但如上所示,该选项只能设定为一个端口或管脚类型的网表对象,不能直接设置为时钟类型对象。上面约束使用-divide_by选项设置分频系数,此外还可以使用-edges**选项,如下所示:

#该约束与上面等效
create_generated_clock -name clkdiv2 -source [get_pins REGA/C] -eedges {1 3 5} [get_pins REGA/Q]

 #1 3 5 分别为生成时钟一个周期的三个沿对应master clock的上升沿的位置
 -edges的参数为一个列表,该列表通过主时钟的边沿来描述生成时钟的波形;列表中的值为主时钟边沿的序号(注意观察上图),由时钟上升沿开始,定义了生成时钟边沿的时间点;

 2.改变占空比与相移

 如果仅需要改变时钟的相移,使用**-edge_shift**选项可以正向或反向设定每一个生成时钟波形的相移量;注意,-edge_shift选项不能与-devide_by、-multiply_by、-invert选项同时使用;下图中上级时钟为clkin,进入mmcm0单元,产生一个25%占空比、相移90°的时钟:

 

        可以采用如下方法对生成时钟进行约束:使用上级时钟的1、2、3标号边沿(即0ns、5ns、10ns)定义生成时钟,为了得到预期波形,1和3标号边沿要分别移动2.5ns,得到2.5ns、5ns、12.5ns的波形: 

#定义主时钟,周期10ns,50%占空比
create_clock -name clkin -period 10 [get_ports clkin]
#定义生成时钟,周期10ns,25%占空比,90°相移
create_generated_clock -name clkshift -source [get_pins mmcm0/CLKIN] -edges {1 2 3} \
-edge_shift {2.5 0 2.5} [get_pins mmcm0/CLKOUT]

3.同时倍频与分频

 这种情况通常用于定义MMCM或PLL的输出,一般使用这些IP核时会自动创建相应约束;考虑上例中的图,假设MMCM将上级时钟倍频到4/3倍,无法直接倍频,需要同时使用-divede_by和-multiply_by选项来实现:

create_generated_clock -name clk43 -source [get_pins mmcm0/CLKIN] -multiply_by 4 \
-divide_by 3 [get_pins mmcm0/CLKOUT]
4.仅通过组合路径追踪上级时钟

前面简单介绍了-combinational选项的使用,为了更好理解,这里举一个具体例子;下图中,上级时钟同时传递到寄存器和多路选择器中,寄存器对时钟进行2分频,多路选择器从寄存器的2分频时钟和上级时钟中选择一个作为生成时钟输出 :

 显而易见,从上级时钟到生成时钟有两条路径,一条为时序路径,一条为组合路径;如果我们只希望考虑组合路径上的延迟时,定义生成时钟时就需要使用-combinational选项 :

create_generated_clock -name clkout -source [get_pins mmcm0/CLKIN] -combinational
[get_pins MUX/O]

自动生成时钟 Automatically Derived Clocks
 
 这种类型时钟算是生成时钟的一种特例,“自动”是指在已经定义了上级时钟的情况下,Vivado会自动为时钟管理单元CMBs(Clock Modifying Blocks)的输出管脚创建约束,官方称作Automatically Derived Clocks或Auto-generated Clock;

如果约束中已经存在用户在某一网表对象上定义的时钟,则不会创建相同对象上的自动生成时钟;

下面给出一个具体例子,下图中上级时钟clkin驱动clkip/mmcm0单元的CLKIN输入,该单元是一个MMCME2资源的实例,则自动生成时钟的定义源点为clkip/mmcm0/CLKOUT,顶层与此源点连接的网络名为clkip/cpuClk,自动生成时钟的名字便是cpuClk:

         如上所述,Vivado会自动创建自动生成时钟的名称(Name),如果两个名称发生冲突也会自动添加后缀,如usrclk、usrclk_1等等;

 时钟组Clock Group

 默认情况下,Vivado会测量设计中所有时钟之间的路径时序,添加如下两种约束可以控制该功能:

划分时钟组通常有两个依据:

(1)原理图或时钟网络报告中的时钟树拓扑图,判断哪些时钟不应该放在一起做时序分析;

(2)时钟交互报告查看两个时钟间存在的约束,判断它们是否有共享的主时钟(代表是否有已知的相位关系)或者是否有公共周期 ;

但要明白,我们设定时钟组的目的还是为了保证设计在硬件中能正常工作,因此我们必须确保这些忽略了时序分析的路径有合适的再同步电路或异步数据传输协议;

set_clock_groups:建立时钟组,Vivado不会对不同时钟组的时钟之间进行时序分析;
set_false_path:将两个时钟之间的路径设置为false path后,不会对该路径进行任何时序分析;
 根据时钟间的关系,可以做如下分类:

同步时钟:即两个时钟间有可预知的相对相位,通常它们的时钟树源自网表中的同一个根,且有一个公共周期;
异步时钟:两个时钟间有无法预知的相对相位。比如两个独立的晶振信号通过两个输入端口进入FPGA中,生成两个时钟。由于两个主时钟没有明确的相位关系,两个生成时钟间便是异步的;
不可扩展时钟:官方称作Unexpandable Clocks,是指时序引擎在1000个周期内无法判断两个时钟是否有公共周期。这种情况通常发生在两个时钟周期比是一个特殊的分数,比如一个主时钟通过MMCM生成一个周期为5.125ns的时钟clk1和一个周期为6.666ns的时钟clk2,尽管它们在时钟树的根上有一个确定的相位关系,但是在1000个周期内时钟上升沿无法再次对齐;
 
1.异步时钟组 
同步时钟可以安全地进行时序分析,异步时钟和不可扩展时钟虽然通过时序分析也会得到一个裕量值,但这个值不可作为可靠结果;从这个角度出发,不可扩展时钟也可以视作一种特殊的异步时钟;这就需要通过设置时钟组来忽略异步时钟的时序路径上的时序分析 ;

这里举个例子,一个主时钟clk0通过MMCM生成两个时钟usrclk和itfclk;另一个主时钟clk1通过另一个MMCM生成两个时钟clkrx和clktx,用如下命令创建异步时钟组: 

set_clock_groups -name async_clk0_clk1 -asynchronous -group {clk0 usrclk itfclk} \
-group {clk1 gtclkrx gtclktx}
 
#如果时钟名称事先不知道,可以用如下写法
set_clock_groups -name async_clk0_clk1 -asynchronous -group [get_clocks -include_generated_clocks clk0] -group [get_clocks -include_generated_clocks clk1]

2.互斥时钟组 Exclusive Clock Groups
        下面再介绍另一种会用到时钟组的情况:某些设计会有几个操作模式,不同操作模式使用不同的时钟,这些时钟通常由专用的时钟选择器进行选择,如BUFGMUX和BUFGCTRL,最好不要用LUT作时钟选择器;

这些单元都是组合逻辑单元,Vivado会将所有输入传递到输出;在Vivado IDE中,几个时序时钟可以同时存在时钟树上,方便地同时报告所有操作模式,但是在硬件中这是不可能的,它们之间是互斥的,这些时钟便称作互斥时钟;

举个例子,一个MMCM实例生成的两个时钟clk0和clk1,与一BUFGMUX实例clkmux相连,clkmux的输出驱动设计时钟树;默认情况下,虽然clk0和clk1共享同一时钟树,且不能同时存在,Vivado还是会分析clk0和clk1之间的路径,这个问题要通过设置互斥时钟组来解决,达到禁止分析这两个时钟间路径 的目的。约束如下:

set_clock_groups -name exclusive_clk0_clk1 -physically_exclusive \
-group clk0 -group clk1

在ASIC工艺中使用-physically_exclusive和-logically_exclusive代表不同的信号完整性分析模式,但对于Xilinx FPGA而言,二者是等价的,都可以使用; 

时钟延迟、抖动与不确定性
 本文的上述约束可以说都是对时钟的理想特征进行约束,为了更精确地进行时序分析,设计者还必须设定一些与运行环境相关的可预测变量和随机变量,这部分也称作时钟的不确定性特征;

 1.时钟延迟latency
经过板子上和FPGA器件内部的传输,时钟边沿到达目的地后会有一个确定的延迟,这个延迟可以分为两个部分看待:

网络延迟:也称作插入延迟,指在FPGA内部传输带来的延迟;Vivado会自动分析计算该延迟,布线过程前只是一个粗略的估计,布线后便可以得到一个精确的值;对于生成时钟,包含其本身的网络延迟和上级时钟的网络延迟两部分;
源端延迟:通常指FPGA器件外,时钟进入源点前的传输延迟,这部分延迟与PCB设计相关,需要用set_clock_latency命令进行约束;
下面给出一个约束源端时钟延迟的例子:

# Minimum source latency value for clock sysClk (for both Slow and Fast corners)
set_clock_latency -source -early 0.2 [get_clocks sysClk]
# Maximum source latency value for clock sysClk (for both Slow and Fast corners)
set_clock_latency -source -late 0.5 [get_clocks sysClk]

2.时钟抖动jitter 
        对于ASIC器件来说,时钟抖动通常代表了时钟不确定性特征;但对于Xilinx FPGA而言,抖动属性被当作可预测变量看待;抖动有的需要单独设置,有的在时序分析过程中自动计算,抖动分为两种:

输入抖动:指实际时钟边沿与理想时钟边沿到达时刻之间的差值,使用set_iput_jitter命令为每个主时钟单独设置输入抖动;但是不能直接为生成时钟设置输入抖动,这部分由工具自动计算,如果(1).生成时钟由一个组合或时序单元创建,生成时钟的抖动与上级时钟相同;(2).生成时钟由 MMCM或PLL驱动,生成时钟的抖动为一个自动计算的值;

系统抖动:指电源噪声、板级噪声或其它原因引起的整体的抖动,对于整个设计,使用set_system_jitter命令设置一个值即可,会应用到所有时钟;

下面给出一个约束输入抖动的例子:

#主时钟传输过程中有±100ps的抖动
set_input_jitter [get_clocks -of_objects [get_clocks sysclk]] 0.1

        不过,时钟抖动对整个时钟不确定性计算的影响不是太大。计算时钟不确定性时对每条路径都是独立的,且主要依赖于时钟拓扑结构、路径上的时钟对、时钟树上是否存在MMCM/PLL单元等其它因素;

3.附加的时钟不确定性 Additional Clock Uncertainty
使用set_clock_uncertainty命令可以根据需要为特定的时钟关系定义附加的时钟不确定性,这样在时序分析时,可以为设计中的某些部分增加额外裕量 

前面文章说过XDC约束带有顺序性,后面的约束会重写前面的约束。但在这里,时钟间的不确定性总是优先于单个时钟的不确定性,不管约束顺序如何;看下面的例子:

set_clock_uncertainty 2.0 -from [get_clocks clk1] -to [get_clocks clk2] 
set_clock_uncertainty 1.0 [get_clocks clk1]

        这里首先约束从clk1到clk2有一个2ns的时钟不确定性,接着又约束clk1有1ns的时钟不确定性,但是后面这条约束不会改动从clk1到clk2之间的关系;同时,要注意clk1到clk2有时钟间的不确定性,clk2到clk1也有时钟间的不确定性,所以要约束完整! 

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

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

相关文章

C++11 -- 入门基础知识

文章目录 C11简介列表初始化std::initializer_list 变量类型推导nullptr范围for循环STL中的一些变化 C11简介 在2003年C标准委员会曾经提交了一份技术勘误表(简称TC1),使得C03这个名字已经取代了C98称为C11之前的最新C标准名称。不过由于C03(TC1)主要是对C98标准中…

怎么在照片上添加logo

怎么在照片上添加logo?现在是全面自媒体的时代,很多旅行博主或者摄影爱好者喜欢将自己拍摄的照片发布到各大平台上,分享自己的摄影作品,不过互联网属于一个开放平台,所以盗取照片的事情时有发生,很多不法分…

LabVIEWCompactRIO 开发指南16 有效使用网络共享变量的技巧

LabVIEWCompactRIO 开发指南16 有效使用网络共享变量的技巧 在使用网络共享变量进行编程时,可以遵循三个技巧来最大化性能并避免任何不需要的行为。图4.11显示了包含每个技巧的初始化过程。 技巧1:初始化共享变量 在应用程序开始时将共享变量初始化为已知值。如…

全文检索-Elasticsearch-整合SpringBoot

文章目录 前言一、整合检索服务1.1 创建 gulimall-search 模块1.2 配置 Maven 依赖1.3 搜索服务注册到注册中心1.4 新增 es 配置类1.5 测试 RestHighLevelClient 组件 二、存储数据到 ES2.1 测试 ES 简单插入数据2.2 测试 ES 查询复杂语句2.3 读入数据 前言 前面记录了 Elasti…

如何修复d3dcompiler_47.dll缺失?多种解决方法分享

在使用Windows操作系统的过程中,有时候会遇到d3dcompiler_47.dll缺失的情况。这个问题可能会导致某些应用程序无法正常运行,因此需要及时解决。本文将介绍如何修复d3dcompiler_47.dll缺失的问题。 一.什么是d3dcompiler_47.dll D3dcompiler_47.dll是Di…

Kali-linux查看打开的端口

对一个大范围的网络或活跃的主机进行渗透测试,必须要了解这些主机上所打开的端口号。在Kali Linux中默认提供了Nmap和Zenmap两个扫描端口工具。为了访问目标系统中打开的TCP和UDP端口,本节将介绍Nmap和Zenmap工具的使用。 4.4.1 TCP端口扫描工具Nmap 使…

revit的附着顶部/底部工具使用及CAD图纸转柱

一、revit的附着顶部/底部工具的使用 生活上,有很多建筑是斜屋顶的房子,像是一些别墅的装修,斜屋顶往往比平屋顶更有装饰感,也更有利于排水。 那么在Revit中,绘制带有斜屋顶的往往会遇到这样一个问题,屋顶之…

OpenCL编程指南-3.2OpenCL上下文

OpenCL上下文 上下文是所有OpenCL应用的核心。上下文为关联的设备、内存对象(例如,缓冲区和图像)以及命令队列(在上下文和各设备之间提供一个接口)提供了一个容器。正是上下文驱动着应用程序与特定设备以及特定设备之…

算法训练Day53:​ 1143.最长公共子序列 1035.不相交的线 53.最大子序和 动态规划

文章目录 最长公共子序列题解 不相交的线题解 最大子数组和题解 最长公共子序列 CategoryDifficultyLikesDislikesContestSlugProblemIndexScorealgorithmsMedium (64.94%)13110--0 Tags Companies 给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子…

浏览csdn博客自动隐藏侧边栏并只看目录

背景 CSDN 总算做了点好事,能够隐藏大部分无关信息,只看博客内容本身。具体如图,还在测试版 以我的一篇博客为例,原始界面,花里胡哨一堆 点击隐藏侧栏后的清爽版 点击只看目录后的清爽版 前提提要 安装油猴脚本&…

使用VSCode创建Vue项目

Vue介绍 Vue.js是一个渐进式JavaScript框架,用于构建用户界面。它可以与其他库或现有项目集成,也可以作为单个组件使用。Vue.js的目标是提供一种简单、快速和灵活的方式来开发交互式Web应用程序。 Vue.js的核心特性包括: 响应式数据绑定&am…

http协议格式

HyperText Transfer Tansfer Protocol 超文本传输协议,是一种基于TCP的应用层协议,也是目前为止最为流行的应用层协议之一,可以说HTTP协议是万维网的基石。历经了0.9、HTTP/1.0、HTTP/1.1、HTTP/2几个版本(关于HTTP协议的历史,这里…

unity-物体rotation翻转180度后,OnPointerDown失效的问题

问题:今天碰到一个问题,就是把物体A进行水平翻转后,如下图,OnPointerDown 就失效了 》解决方案1(使用Scale X来替代Rotation Y): 使用Scale改为-1来翻转,这样 OnPointerDown 就正常…

双向链表刷题总结

剑指 Offer 36. 二叉搜索树与双向链表 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。 为了让您更好地理解问题,以下面的二叉搜索树为例: 我们希望将这…

分布式系统中的那些一致性(CAP、BASE、2PC、3PC、Paxos、ZAB、Raft)

本文介绍 CAP、BASE理论的正确理解、Paxos 算法如何保证一致性及死循环问题、ZAB 协议中原子广播及崩溃恢复以及 Raft 算法的动态演示。 下面还有投票,一起参与进来吧👍 文章目录 前言CAP理论理解误导正确的理解CAP理论的应用 BASE理论Paxos算法如何保证…

ASEMI代理LT6230CS6-10#TRPBF原装ADI车规级LT6230CS6-10#TRPBF

编辑:ll ASEMI代理LT6230CS6-10#TRPBF原装ADI车规级LT6230CS6-10#TRPBF 型号:LT6230CS6-10#TRPBF 品牌:ADI /亚德诺 封装:SOT-6 批号:2023 安装类型:表面贴装型 引脚数量:6 工作温度:-4…

sentinel介绍

介绍 官网地址 Sentinel 和 Hystrix 的原则是一致的: 当调用链路中某个资源出现不稳定,例如,表现为 timeout,异常比例升高的时候,则对这个资源的调用进行限制,并让请求快速失败,避免影响到其它的资源&…

阿里云争食币圈

阿里云的触手正在向币圈延伸。几天前,阿里云与Avalanche区块链和MUA DAO联合推出Cloudverse,为想要在链上部署元宇宙的企业提供一站式解决方案。 Avalanche是典型的币圈项目,链上的一切价值流转都以加密货币结算。此次合作释放出阿里云在Web…

apt 与 dpkg 命令详解

一. apt & dpkg 异同点 1. apt 与 dpkg 均为 ubuntu 下面的包管理工具。 2. dpkg 仅用于安装本地的软件包&#xff0c;安装时不会安装依赖包&#xff0c;不解决依赖问题。 sudo dpkg -i <package_name>.deb 3. apt 默认会从远程仓库搜索包的名字&#xff0c;下载并安…

多元线性回归——自相关(二)

自相关问题 文章目录 自相关问题(R)[toc]1 什么是自相关2 自相关产生的原因3 自相关的后果4 自相关检验5 自相关补救6 R语言操作 1 什么是自相关 经典普通最小二乘法估计的假设之一是扰动项不存在自相关&#xff0c;即对于 ∀ i ≠ j \forall i\ne j ∀ij,都有 C o v ( μ …