基于FPGA的函数信号发生器设计

本科时期的一个课设,现在将他分享出来,写了很详细的文章,可以直接拿去使用:设计采用波形查找表和相位累加器的方法实现DDS,查找表的数据位宽为8位,采样点数为4096。波形产生范围是100Hz-20MHz,最小频率间隔为1Hz,用8个数码管显示频率,可产生正弦波、方波、三角波,波形用两个led显示,select信号控制,全灭为正弦波,一亮一灭为方波,全亮为锯齿波。为了使频率和相位便于调节,用3个拨码开关控制步进,用8个led显示状态。

基于FPGA的函数信号发生器设计

目录

1 原理分析

1.1 DDS框图

1.2 DDS原理

1.2.1 DDS的工作原理

1.2.2 奈奎斯特采样定理

1.2.3 合成

1.2.4 调频

2 详细设计

2.1 频率与相位步进设计

2.1.1 频率步进精度

2.1.2 相位步进精度

2.1.3 涉及计算的主要公式

(1) 频率控制字

(2) 相位控制字

2.1.4 对参数文件进行详细解释

2.2 相位累加设计

3 仿真分析

3.1 仿真代码

3.2 仿真波形

4 实验总结

参考文献


摘要:本设计以EGO1开发板为核心部件,基于Xilinx Vivado平台,运用Verilog语言,采用波形查找表和相位累加器的方法实现了信号发生器的设计,总结概括了DDS(直接数字频率合成器)的原理、详细设计、仿真分析以及实验总结。DDS通过相位累加和波形数据查询实现信号合成,涉及奈奎斯特采样定理和调频原理。设计中考虑了频率与相位步进精度,利用高位相位累加器和正弦波采样点数实现高精度输出。仿真验证了设计的正确性,实验表明该DDS设计性能良好。

关键字:Vivado;Verilog;函数信号发生器;波形查找表;相位累加器

1 原理分析

DDS信号发生器采用直接数字频率合成(Direct Digital Synthesis,简称DDS)技术,把信号发生器的频率稳定度、准确度提高到与基准频率相同的水平,并且可以在很宽的频率范围内进行精细的频率调节。采用这种方法设计的信号源可工作于调制状态,可对输出电平进行调节,也可输出各种波形。DDS的设计思想完全是基于数值计算信号波形的抽样值来实现频率合成的。

DDS的工作原理是基于相位和幅度的对应关系,通过改变频率控制字来改变相位累加器的累加速度,然后在固定时钟的控制下取样,取样得到的相位值通过相位幅度转换得到与相位值对应的幅度序列,幅度序列通过数模转换得到模拟形式量化的正弦波输出。

1.1 DDS框图

DDS的结构主要由相位累加器、波形存储器、数模(D/A)转换器和低通滤波器等四个大的结构组成。其结构框图如下:

图1-1 DDS结构图

图1-1 DDS结构图

图中,相位累加器是由N位加法器与N位累加寄存器构成,它是DDS模块中一个极其重要的部分。在参考频率时钟的驱动下,DDS模块开始工作;当每来一个参考时钟时,累加器就把频率控制字FW与寄存器输出的值进行累加,将相加后的结果再输入到寄存器中,而累加寄存器就将在上一个参考时钟作用时产生的数据通过反馈的方式输送到累加器中。这样,在时钟的作用下,就可以不停的对频率控制字进行累加。此时,用相位累加器输出的数据作为地址在波形存储器中通过查找地址所对应的幅值表,就可以完成其从相位到幅值之间的转化。

1.2 DDS原理

1.2.1 DDS的工作原理

DDS技术是根据奈奎斯特取样定律,从连续信号的相位出发,将正弦信号取样,编码,量化,形成一个正弦函数表,储存在EPROM中,合成时,通过改变相位累加器的频率字来改变相位增量,也就是步长。相位增量的不同导致一个周期内取样点的不同,在时钟频率即采样频率不变的情况下,通过相位的改变来改变频率。

1.2.2 奈奎斯特采样定理

奈奎斯特采样定理讨论了对于频谱在信号的采样频率限制,所以也称为低通采样定理。假设存在一个最高频率为的带限信号,如果以不小于二倍于的采样频率对信号进行采样,即,得到,则原信号可以被采样数据串无失真的还原出来。

1.2.3 合成

合成,简单来说就是将我们的采样数据还原成模拟信号。还原的方式为:以一定的频率将采样数据依次输出。就可以还原波形。
假设,以100M的频率输出我们的1024个抽样数据,则将会得到一个频率为:

的正弦波。这就达到了最初的信号输出。

1.2.4 调频

调频的方案有两种:一种是改变时钟频率,将读取采样数据的速度变快或者变慢,这样就可以改变频率。这种方法对于当下很多开发板固定的晶振频率来说比较难以实现。

另一种方案就是减少输出的采样数据,输出的采样数据越少,频率便会越高。 在DDS模块中,输出频率的公式为:

输出信号的频率分辨率为:

从上两式可以看出,在参考信号与加法器或寄存器的位数给定时,信号最终的输出频率主要由频率控制字决定。故当频率控制字变化时,输出频率也跟着变化,从而可以实现调频的基本功能。

2 详细设计

图2-1 RTL视图

图2-1 RTL视图

RTL视图如上所示,本设计采用波形查找表和相位累加器的方法实现DDS,查找表的数据位宽为8位,采样点数为4096。波形产生范围是100Hz-20MHz,最小频率间隔为1Hz,用8个数码管显示频率,可产生正弦波、方波、三角波,波形用两个led显示,select信号控制,全灭为正弦波,一亮一灭为方波,全亮为锯齿波。 为了使频率和相位便于调节,用3个拨码开关控制步进,用8个led显示状态。对应关系如下表:

sw[2:0]频率步进相位步进led[7:0]
0001Hz1度0000_0001
00110Hz5度0000_0010
010100Hz10度0000_0100
0111KHz30度0000_1000
10010KHz50度0001_0000
101100KHz90度0010_0000
1101MHz100度0100_0000
11110MHz180度1000_0000

2.1 频率与相位步进设计

参数文件如下,其中包括计算相位控制字和频率控制字的公式。

//频率步进(下面是以时钟频率100M,相位控制字12位,频率控制字32位计算所得)
`define  Fword_step0  32'd43       //频率步进1HZ
`define  Fword_step1  32'd430       //频率步进10HZ
`define  Fword_step2  32'd4_295      //频率步进100HZ
`define  Fword_step3  32'd42_950      //频率步进1KHZ 
`define  Fword_step4  32'd429_497      //频率步进10KHZ
`define  Fword_step5  32'd4_294_967     //频率步进100KHZ
`define  Fword_step6  32'd42_949_673     //频率步进1MHZ
`define  Fword_step7  32'd429_496_730     //频率步进10MHZ
//相位步进                                  
`define  Pword_step0  12'd11    //相位步进1度
`define  Pword_step1  12'd57    //相位步进5度
`define  Pword_step2  12'd114             //相位步进10度
`define  Pword_step3  12'd341             //相位步进30度
`define  Pword_step4  12'd569             //相位步进50度
`define  Pword_step5  12'd1024         //相位步进90度
`define  Pword_step6  12'd1138         //相位步进100度
`define  Pword_step7  12'd2048         //相位步进180度 

//计算公式 
`define  SYS_CLK   33'd100_000_000 //系统时钟频率 
`define  MAX_FWORD  33'd4294967296  //2的WORD_WIDTH次方 
`define  ROM_DEP   32'd4096  //2的ADDR_WIDTH次方
                                  
`define  Fword_step0     integer(`MAX_FWORD/(`SYS_CLK/       1.000_000_000_0))  //频率步进1HZ
`define  Fword_step1  integer(`MAX_FWORD/(`SYS_CLK/      10.000_000_000_0))  //频率步进10HZ
`define  Fword_step2  integer(`MAX_FWORD/(`SYS_CLK/     100.000_000_000_0))  //频率步进100HZ
`define  Fword_step3  integer(`MAX_FWORD/(`SYS_CLK/    1000.000_000_000_0))  //频率步进1KHZ 
`define  Fword_step4  integer(`MAX_FWORD/(`SYS_CLK/   10000.000_000_000_0))  //频率步进10KHZ
`define  Fword_step5  integer(`MAX_FWORD/(`SYS_CLK/  100000.000_000_000_0))  //频率步进100KHZ
`define  Fword_step6  integer(`MAX_FWORD/(`SYS_CLK/ 1000000.000_000_000_0))  //频率步进1MHZ
`define  Fword_step7  integer(`MAX_FWORD/(`SYS_CLK/10000000.000_000_000_0))  //频率步进10MHZ

`define  Pword_step0  integer(`ROM_DEP/(360/  1.000_000_000_0))   //相位步进1度
`define  Pword_step1  integer(`ROM_DEP/(360/  5.000_000_000_0))   //相位步进5度
`define  Pword_step2  integer(`ROM_DEP/(360/ 10.000_000_000_0))         //相位步进10度
`define  Pword_step3  integer(`ROM_DEP/(360/ 30.000_000_000_0))   //相位步进30度
`define  Pword_step4  integer(`ROM_DEP/(360/ 50.000_000_000_0))   //相位步进50度
`define  Pword_step5  integer(`ROM_DEP/(360/ 90.000_000_000_0))   //相位步进90度
`define  Pword_step6  integer(`ROM_DEP/(360/100.000_000_000_0))   //相位步进100度
`define  Pword_step7  integer(`ROM_DEP/(360/180.000_000_000_0))   //相位步进180度 
 
`define  PWORD_WIDTH  4'd12        //相位控制字位宽
`define  FWORD_WIDTH  6'd32   //频率控制字位宽
`define  ADDR_WIDTH  4'd12   //ROM查找表深度位宽
`define  DA_WIDTH  4'd8   //DA位宽
//`define  KEY_CNT   21'd1_999_999 //按键计数值,实际
`define  KEY_CNT   21'd200    //按键计数值,仿真时
`define  Fword_START  integer(`Fword_step2) //输出最小频率所对应的频率控制字
`define  Fword_END  integer(`Fword_step7*2) //输出最大频率所对应的频率控制字
`define  Pword_START  integer(0)    //输出最小相位所对应的相位控制字
`define  Pword_END  integer(`Pword_step7*2) //输出最大相位所对应的相位控制字 

参数文件说明:其核心就是频率控制,相位控制和相位累加。主要参数有:频率步进精度、相位步进精度、DAC的位数以及滤波器的设计。

2.1.1 频率步进精度

频率步进精度就决定了程序中相位累加器的位数(一般都是取24-32位),同时也要取决于FPGA的时钟(这里以100MHz为例)。

也就是说采用32位的相位累加器,在参考时钟为100MHz时可以达到0.02328Hz的精度。

2.1.2 相位步进精度

相位步进主要是调解输出波形的相位。这里就还涉及到采样深度(也就是对正弦波的采样点数,这里以4096为例)

根据不同的相位精度,求出X即可得相位控制字。如:相位步进5度,计算得X=56.88888。

2.1.3 涉及计算的主要公式

(1) 频率控制字

M为频率控制字,改变M的值即可改变输出频率,N为相位累加器的位数。

由于采样定理,所产生信号的频率不能超过时钟频率的一半,在实际运用中为了保证输出信号的质量,输出频率不超过参考时钟频率的三分之一,以避免混叠或被谐波落入有用输出频带内。相位累加器输出位并不全部加到查询表,而要截断。相位截断减小了查询表长度,但并不影响频率分辨率,对最终输出仅增加一个很小的相位噪声。DAC分辨率一般比查询表长度小2-4位。

(2) 相位控制字

X为ROM查找表的采样深度,p为相位,a为相位控制字。将计算结果加在相位累加器上便可得到相应相位的波形。

2.1.4 对参数文件进行详细解释

为了增加代码的可移植性,特意将设计里面所用到的所有参数全部列入para.v文件里面,可以参照上述代码和注释加以理解。相位控制字和频率控制字的计算公式全部写成宏参数的形式,不需要自己去算相位和频率控制字,只需要按照实际需求修改相位累加器位宽、ROM查找表深度位宽、时钟频率等参数,编译器会计算出相应步进参数,复制到相位累加器模块里面去。

2.2 相位累加设计

`include"para.v"

module DDS_phase_acc(
    
    input                      clk   ,
    input                       rst_n  ,
    input                      EN   ,//信号使能
    input      [`FWORD_WIDTH-1:0]      Fword  ,//频率控制字
    input     [`PWORD_WIDTH-1:0]      Pword  ,//相位控制字
 
 output reg [`ADDR_WIDTH -1:0]  Rom_Addr
 );
 
 reg        [`FWORD_WIDTH-1:0]        Fre_acc  ;//相位累加器

 always @ (posedge clk or negedge rst_n) begin
    if (!rst_n)
        Fre_acc <= 0;
    else if(!EN)
        Fre_acc <= 0;
    else 
        Fre_acc <= Fre_acc + Fword;
end

always @ (posedge clk or negedge rst_n) begin
    if (!rst_n)
        Rom_Addr <= 0;
    else if (!EN)
        Rom_Addr <= 0;
    else
        Rom_Addr <= Fre_acc[`FWORD_WIDTH-1:`FWORD_WIDTH-`ADDR_WIDTH] + Pword;//取累加器中高ADDR_WIDTH位作为ROM查询地址
end

endmodule

3 仿真分析

3.1 仿真代码

`timescale 1ns / 1ns
`define clk_period 10
module DDS_tb();
    
    reg                    sys_clk  ;
    reg                      sys_rst_n ;
 reg   [2:0]     sw   ;
 reg    [4:0]     key   ;
                                             
 wire [7:0]     led   ;
    wire [7:0]     DA_data  ;
 wire       DA_clk      ;
 wire [7:0]     sseg_high ;
 wire [3:0]     an_high  ;
 wire [7:0]     sseg_low ;
 wire [3:0]     an_low      ;
 wire [1:0]     select  ;
                                              
 DDS i0( 
  
  .sys_clk  (sys_clk ), 
  .sys_rst_n  (sys_rst_n ),
  .sw    (sw   ),
  .key   (key  ), 
                              
  .led   (led  ), 
  .select   (select  ),
  .DA_data  (DA_data ), 
  .DA_clk       (DA_clk     ),
  .sseg_high  (sseg_high ), 
  .an_high  (an_high ),  
  .sseg_low  (sseg_low ), 
  .an_low   (an_low     )
   
 ); 
 always #(`clk_period/2) sys_clk = ~sys_clk;
 initial
  begin
   //初始化
   sys_clk = 1'b0;
   sys_rst_n = 1'b0;  //复位
   key    = 5'b11111;
   sw    = 3'b000;
   #(`clk_period*200)
   sys_rst_n = 1'b1;
   
   #(`clk_period*1100_000)//输出100HZ正弦波
   
   sw    = 3'b110;    //将频率挡设置为1MHZ,相位挡100度
   key[1]   = 1'b0;  //频率加1MHZ
   #(`clk_period*300)  //本应该延时大于20ms,但为了仿真方便,修改了按键计数器的值为200
   key[1]   = 1'b1;
   #(`clk_period*210)
   
   key[0]   = 1'b0;  //设置输出为方波
   #(`clk_period*300)
   key[0]   = 1'b1;
   #(`clk_period*210)
   
   key[0]   = 1'b0;  //设置输出为锯齿波
   #(`clk_period*300)
   key[0]   = 1'b1;
   #(`clk_period*210)
   
   key[0]   = 1'b0;  //设置输出为正弦波
   #(`clk_period*300)
   key[0]   = 1'b1;
   #(`clk_period*210)
   
   sw    = 3'b010;    //将频率挡设置为100HZ,相位挡10度
   key[2]   = 1'b0;  //频率减100HZ
   #(`clk_period*300)
   key[2]   = 1'b1;
   #(`clk_period*210)
   
   sw    = 3'b101;  //相位步进为90度,频率步进为100KHz
   key[3]   = 1'b0;  //相位加90度
   #(`clk_period*300)
   key[3]   = 1'b1;
   
  end
 endmodule

3.2 仿真波形

由于功能较为复杂,一些功能不好做仿真,这里只挑选了核心的功能进行仿真。有的输出信号是多余的,只是为了仿真才添加,实际运用时只需保留引脚约束文件xdc里面的输出信号即可。仿真时需要将para.v参数文件里面的参数KEY_CNT改小,以便按键方便仿真,以下仿真KEY_CNT = 200。

默认情况下输出

默认情况下输出

默认输出频率应为100Hz,周期为10ns图中正弦波峰和相邻波谷时间值相差为(7.51-2.54)ns=5ns,等于半个周期,仿真结果正确。

图3-2

图3-2

如图3-2信号key[1]出现下降沿,相当于频率加按键被触发,此时频率应该加一个当前档位的对应的步进。此时频率步进位1MHz,所以这之后频率应该变为1.0001MHz,对应周期为0.9999us。正弦波相邻波谷时间差为(11005.715-11004.715)us=1us。原因是在做相位累加器时是取频率控制字高12位作为查找表地址,查找表的深度不够大,做不到1Hz的步进,如果要做到可以增加查找表深度,但是会增加资源消耗。

图3-3

图3-3

如图3-3信号key[0]出现下降沿,相当于波形选择按键被触发,此时波形变为方波,频率用前面的方法计算也是正确的,所以仿真结果正确。

图3-4

图3-4

如图3-4信号key[0]再次出现下降沿,相当于波形选择按键被触发,此时波形变为锯齿波,频率用前面的方法计算也是正确的,所以仿真结果正确。

图3-5

图3-5

如图3-5信号key[2]出现下降沿,相当于频率减按键被触发,此时频率应该减去此时的一个频率步进100Hz,频率用前面的方法计算也是正确的,所以仿真结果正确。

图3-6

图3-6

如图3-6信号key[3]出现下降沿,相当于相位加按键被触发,此时波形相位应该加上一个此时的相位步进90度,在红色椭圆处看到相位发生了90度变化,所以仿真结果正确。

图3-7

图3-7

如图3-7sw=0时,led=0000_0001,sw=2时led=0000_0100。仿真结果正确。

图3-8

图3-8

如图3-8sseg_high[7:0]是数码管高四位的段选码,根据下面an_high[3:0]可以知道高四位显示的的位对应的段码。由图中标注可知此时显示数字应为00.000100MHz,即为100Hz,select值为00表示输出为正弦波。所以仿真结果正确。

图3-9

图3-9

如图3-9方波select为01,正弦波为00,锯齿波为11,满足前面说的设计要求全灭为正弦波,一亮一灭为方波,全亮为锯齿波。所以仿真结果正确。

图3-10

图3-10

如图3-10当前波形频率为1MHz,对应显示为01.000000MHz,仿真正确。

图3-11

图3-11

如图3-11,使DAC0832输入寄存器工作在锁存状态,而DAC寄存器工作在直通状态,要求、都为低电平,DAC寄存器的锁存选端得不到有效电平而直通;输入寄存器控制信号处于高电平、处于低电平,当端来一个负脉冲时就可以完成一次转换。

本次设计的资源占用率情况如下图所示:

图3-12

图3-12

图3-13

图3-13

图3-14

图3-14

图3-15

图3-15

4 实验总结

面对电子技术日新月异的发展,利用EDA手段进行设计已成为不可阻挡的趋势。相对于传统至底向上的设计方式,自上而下的设计具有其显著的优越性。利用EDA设计软件辅助设计,方便快捷,减少了错误率的产生,缩短了产品的设计及上市周期,既减轻了设计工作量又满足了商业利益的需求。

该系统以EGO1开发板为核心部件,可利用Vivado软件编程实现了简易函数信号发生器设计。努力做到了线路简单、高性价比的特点,充分利用了软件编程,弥补了硬件元器件的不足。在设计过程当中,遇到了软件操作不熟练,程序编写不规范等诸多问题,通过对问题的总结分析得出,应用软件的主要功能必须熟练操作,才能提高工作效率,需要规范操作的地方必须严格按照使用说明操作,避免由于软件使用不当造成的错误产生。程序的编写格式必须规范,模块、端口以及信号变量的命名应当反映实际意义,缩进格式工整明了,方便阅读理解,这样有利于程序的编写,有利于分析调试,也有利于程序的重复使用。此次课题的设计已告一段落,在这次设计过程中需要用一些不曾学过的东西时,就要去有针对性地查找资料,然后加以吸收利用,以提高自己的应用能力,而且还能增长自己见识,补充最新的专业知识,学会了一些编程方面的常用算法。

作为一名电子专业的学生,我将会继续在新技术的道路上不断钻研、开拓进取。相信通过此次设计的锻炼,我对专业知识和技能的掌握将更加牢靠,在今后的工作和学习中,必将使我受益匪浅,取得应有的成绩。

参考文献

[1] 汤勇明,张圣清,陆佳华. 搭建你的数字积木[M]. 北京:清华大学出版社,2017.
[2] 梅雪松,袁玉卓,曾凯锋. FPGA自学笔记—设计与验证[M]. 北京:北京航空航天大学出版社,2017.
[3] https://wenku.baidu.com/view/bcb5fa05eff9aef8941e0680
[4] https://blog.csdn.net/qq_36854651/article/details/104433727?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-5
[5] https://blog.csdn.net/zf_suan/article/details/53039514

其中所需要波形可以由matlab生成,或者使用如下所示的波形数据生成器:

波形数据生成器

波形数据生成器

获取源码和工程可点击如下链接:https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzkxNjM0NDk2Nw==&action=getalbum&album_id=3473393253968314372#wechat_redirect

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前端 CSS 经典:SVG 描边动画

1. 原理 使用 css 中的 stroke 属性&#xff0c;用来描述描边的样式&#xff0c;其中重要的属性 stroke-dasharray、stroke-dashoffset。理解了这两个属性的原理&#xff0c;才能理解描边动画实现的原理。 stroke-dasharray&#xff1a;将描边线变成虚线、其中实线和虚线部分…

年轻人逆转生活方式,胰岛功能关键在于饮食与运动的配合!

平常在生活方面&#xff0c;控制好饮食和运动&#xff0c;但是有的年轻人&#xff0c;比如说工作原因&#xff0c;或者是个人喜好等原因&#xff0c;可能饮食他配合不了&#xff0c;这样逆转起来也很困难。 有一个例子&#xff0c;就是那种公交车司机&#xff0c;他的排班就是夜…

C++容器之无序多集(std::unordered_multiset)

目录 1 概述2 使用实例3 接口使用3.1 construct3.2 assigns3.3 iterators3.4 capacity3.5 find3.6 count3.7 equal_range3.8 emplace3.9 emplace_hint3.10 insert3.11 erase3.12 clear3.13 swap3.14 bucket_count3.15 max_bucket_count3.16 bucket_size3.17 bucket3.18 load_fa…

【正点原子Linux连载】 第四十七章 音频驱动实验摘自【正点原子】ATK-DLRK3568嵌入式Linux驱动开发指南

1&#xff09;实验平台&#xff1a;正点原子ATK-DLRK3568开发板 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id731866264428 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/docs/boards/xiaoxitongban 第四十…

llama3-8b-instruct-262k微调过程的问题笔记(场景为llama论文审稿)

目录 一、环境配置 1.1、模型 1.2、微调环境 1.3、微调数据 二、发现的问题 2.1、过拟合问题 2.2、Qlora zero3 保存模型时OOM问题(已解决) 一、环境配置 1.1、模型 llama3-8b-instruct-262k &#xff08;英文&#xff09; 1.2、微调环境 Package Version ------------------…

安全态势管理的六大挑战:态势感知

德迅云安全鉴于如今的安全威胁不断变幻&#xff0c;企业对实施态势管理策略至关重要&#xff0c;可以让安全团队根据需要进行安全策略的动态调整。如果企业在研究构建态势感知管理&#xff0c;需要特别关注以下六个方面的挑战。 如果企业正在使用一个或多个平台&#xff0c;那么…

stm32常用编写C语言基础知识,条件编译,结构体等

位操作 宏定义#define 带参数的宏定义 条件编译 下面是头文件中常见的编译语句&#xff0c;其中_LED_H可以认为是一个编译段的名字。 下面代码表示满足某个条件&#xff0c;进行包含头文件的编译&#xff0c;SYSTEM_SUPPORT_OS可能是条件&#xff0c;当非0时&#xff0c;可以…

小程序-购物车-基于SKU电商规格组件实现

SKU 概念&#xff1a; 存货单位&#xff08; Stock Keeping Unit &#xff09;&#xff0c; 库存 管理的最小可用单元&#xff0c;通常称为“单品”。 SKU 常见于电商领域&#xff0c;对于前端工程师而言&#xff0c;更多关注 SKU 算法 &#xff0c;基于后端的 SKU 数据…

总结 HTTPS 的加密流程

一、前言 http是为了解决http存在的问题而在http基础上加入了SSL/TSL&#xff0c;在HTTP/2中TCP三次握手后会进入SSL/TSL握手&#xff0c;当SSL/TSL建立链接后&#xff0c;才会进行报文的传输。 二、HTTPS的混合加密 我们先来认识密钥&#xff1a; 密钥是用于加密和解密数据…

VMware安装保姆教程、Docker安装/依赖安装缓慢等问题

常见问题前置: 1、docker依赖安装缓慢,没有走设置的资源库:解决安装docker-ce过慢 Operation too slow. Less than 1000 bytes/sec transferred the last 30 seconds‘) 在添加阿里云镜像后安装依旧慢: yum-config-manager --add-repo http://mirrors.aliyun.com/docker…

JavaSE--基础语法(第一期)

Java是一种优秀的程序设计语言&#xff0c;它具有令人赏心悦目的语法和易于理解的语义。不仅如此&#xff0c;Java还是一个有一系列计算机软件和规范形成的技术体系&#xff0c;这个技术体系提供了完整的用于软件开发和 跨平台部署的支持环境&#xff0c;并广泛应用于嵌入式系统…

鸿蒙HarmonyOS开发:tabs结合tabContent实现底部tabBar导航栏页面布局

文章目录 一、组件介绍1、Tabs参数属性事件TabsController 2、子组件属性说明 二、基础示例1、基础顶部导航2、效果3、可以滚动导航栏2、效果 三、扩展示例自定义导航栏1、代码2、效果 一、组件介绍 Tabs组件的页面组成包含两个部分&#xff0c;分别是TabContent和TabBar。Tab…

宝塔面板修改端口后无法登入

今天通过宝塔面板登录腾讯云主机&#xff0c;看到下面的提醒&#xff0c;顺便点进去随便改了个端口 本以为改端口是很简单事情&#xff0c;结果我改完之后面板立马登不上了&#xff0c;接下来我改了登录地址和端口也不行&#xff0c;我以为是防火墙的问题&#xff0c;增加了防火…

告别登录烦恼,WPS免登录修改器体验!(如何实现不登录使用WPS)

文章目录 &#x1f4d6; 介绍 &#x1f4d6;&#x1f3e1; 演示环境 &#x1f3e1;&#x1f4d2; 解决方案 &#x1f4d2;&#x1f388; 获取方式 &#x1f388;⚓️ 相关链接 ⚓️ &#x1f4d6; 介绍 &#x1f4d6; 想象一下&#xff0c;如果你能够绕过繁琐的登录流程&#x…

微信小程序--微信开发者工具使用小技巧(3)

一、微信开发者工具使用小技巧 1、快速创建小程序页面 在app.json中的pages配置项&#xff0c;把需要创建的页面填写上去 2、快捷键使用 进入方式 1&#xff1a; 文件–>首选项–> keyboard shortcuts 进入快捷键查看与设置 进入方式 2&#xff1a; 设置–>快捷键…

Tower在深度学习中的概念,tower没有确切定义

在论文UniTS中&#xff0c;来自Havard的工作。 tower更像是针对一个task的组件 tower这个概念貌似在REC&#xff08;recommendation&#xff09;推荐系统中使用较多 deep learning - What is a tower? - Data Science Stack Exchange https://developers.google.com/machin…

lvgl无法显示中文

环境&#xff1a; VS2019、LVGL8.3 问题&#xff1a; VS2019默认编码为GB2312&#xff0c; 解决&#xff1a; VS2022设置编码方式为utf-8的三种方式_vs utf8-CSDN博客 我用的方法2&#xff0c;设置为 utf-8无签名就行。

基于transformers框架实践Bert系列6-完形填空

本系列用于Bert模型实践实际场景&#xff0c;分别包括分类器、命名实体识别、选择题、文本摘要等等。&#xff08;关于Bert的结构和详细这里就不做讲解&#xff0c;但了解Bert的基本结构是做实践的基础&#xff0c;因此看本系列之前&#xff0c;最好了解一下transformers和Bert…

c++入门的基础知识

c入门 C是在C的基础之上&#xff0c;容纳进去了面向对象编程思想&#xff0c;并增加了许多有用的库&#xff0c;以及编程范式等。熟悉C语言之后&#xff0c;对C学习有一定的帮助&#xff0c;本章节主要目标&#xff1a; 补充C语言语法的不足&#xff0c;以及C是如何对C语言设计…

ClickHouse vs. Elasticsearch: 计数聚合的工作原理

本文字数&#xff1a;7875&#xff1b;估计阅读时间&#xff1a;20 分钟 审校&#xff1a;庄晓东&#xff08;魏庄&#xff09; 介绍 在另一篇博客文章中&#xff0c;我们对 ClickHouse 和 Elasticsearch 在大规模数据分析和可观测性用例中的性能进行了比较&#xff0c;特别是对…