verilog笔记

news2025/2/23 16:16:23

Verilog学习笔记(一)入门和基础语法BY电棍233

由于某些不可抗拒的因素和各种的特殊原因,主要是因为我是微电子专业的,我需要去学习一门名为verilog的硬件解释语言,由于我是在某西部地区的神秘大学上学,这所大学的数字系统设计基础课程的考试居然是手写代码,十分的令人好笑,教育资源的匮乏可见一斑。这种编程课靠听课记笔记显然是没有办法学好的,怎么办,只有敲代码。下面的笔记是我借助AI+网上帖子+自己实践手敲代码验证写出来的。这部分笔记是从verilog入门到基础知识部分。

引入与描述性解释

verilog是硬件描述语言,诞生于1988年,现在所用的verilog标准是2005年的。

Verilog 主要用于以下领域:

  • 数字电路设计:描述数字系统的行为和结构。
  • 仿真:验证设计是否按预期工作。
  • 综合:将 Verilog 代码转换成门级网表,进而可以用于制造芯片。
  • 测试和验证:编写测试平台来验证设计的正确性。

语言特点

  • 模块化:Verilog 设计是基于模块的,每个模块代表设计中的一个功能单元。
  • 并行性:Verilog 代码模拟硬件的并行行为,模块内的语句并行执行。
  • 时序:可以描述信号的时序关系,如延迟和时序控制。
  • 数据流:通过连续赋值语句(assign)和过程块(always)来描述数据流。

基本语法

以下是一些 Verilog 的基本语法元素:

  • 模块定义:使用 module 关键字定义模块,endmodule 结束模块定义。
  • 端口声明:模块的输入和输出通过端口声明来定义。
  • 变量类型:包括 wire(用于连接逻辑门),reg(用于存储值),integer 等。
  • 逻辑操作:使用 &&(逻辑与),||(逻辑或),!(逻辑非)等。
  • 算术操作:加(+),减(-),乘(*),除(/)等。
  • 条件语句:if-else,case,casex,casez 等。
  • 循环语句:for,while,repeat 等。

模块

模块是verilog语法中的基础,module可以视为verilog中的基础,是一个具备输入和输出的黑盒子。verilog中的每一个模块必须是以.v为后缀的,且文件名即为模块名称。

module top_module(
    input in1,
    input in2,
    output out


)
    ***
end module

但是在实际过程中往往不可能只用到一个模块,通常是会用到多个模块,类似于c语言中的头文件,在verilog中也可以相互去引入。在 Verilog 中,模块实例化是将一个模块(module)的实例(instance)放入另一个模块中的过程。这是构建复杂硬件设计的基础,允许设计者重用和组合较小的设计单元来创建更大的系统。举个例子,在主模块中调用与门模块。

module and_gate (input wire A, input wire B, output wire Y);
    assign Y = A & B;//输出Y=A&B
endmodule

把上面的模块保存为and_gate.v
然后再定义一个top_module.v文件,在其中实例化应用and_gate 模块。

module top_module;
    // 声明内部信号
    wire A, B, Y;

    // 实例化 and_gate 模块
    and_gate instance_name (
        .A(A),      // 将 and_gate 的 A 端口连接到 top_module 的 A 信号
        .B(B),      // 将 and_gate 的 B 端口连接到 top_module 的 B 信号
        .Y(Y)       // 将 and_gate 的 Y 端口连接到 top_module 的 Y 信号
    );

    // 其他模块逻辑...
endmodule

逻辑块

在verilog中,逻辑块被用来描述硬件的行为和结构,主要有两种类型的逻辑块,分别是initial块和always块。

always逻辑块可以用来构建组合逻辑和时序逻辑,复杂的逻辑操作都需要出于此该逻辑块中。当然了,always逻辑块需要被写在模块module中。

下面是一些简单的always逻辑块的示例代码:

首先是组合逻辑的always逻辑块,其次是时许逻辑的always逻辑块。

always @(*) begin
    out = a & b; // 输出是输入 a 和 b 的逻辑与
end

reg data_reg;//reg是一种数据存储类型
always @(posedge clk or negedge rstn) begin
    if (!rstn) begin
        data_reg <= 1'b0; // 当复位信号为低时,将寄存器清零
    end else begin
        data_reg <= data_in; // 在时钟上升沿,将输入数据赋值给寄存器
    end
end

其中posedge是上升沿,negedge是下降沿。

完整的示例代码如下,在模块中嵌套逻辑块:

module top_module();
 
    always @(posedge clk) begin
        ....
    end
 
endmodule

generate逻辑块通常是结合for循环使用的,在 Verilog 中,generate 逻辑块是一个非常有用的结构,它允许你根据参数或循环来生成硬件结构。这可以用来创建可参数化的模块,或者生成大量的相同或相似的硬件结构,而不需要手动编写重复的代码。主要的用途有:

1.操作向量

2.模块重复多次实例化。

Verilog 中有三种类型的 generate 逻辑块:

  1. generate-for:用于基于循环生成多个相同的硬件实例。

  2. generate-if:用于基于条件判断生成或不生成硬件。

  3. generate-case:用于基于多个条件生成不同的硬件结构。

下面是一个generate-for的实例:

module register_array(
    input wire clk,
    input wire reset,
    input wire [3:0] data_in,
    output wire [3:0] data_out
);

parameter NUM_REGISTERS = 4;

generate//generate-for逻辑块
    genvar i;
    for (i = 0; i < NUM_REGISTERS; i = i + 1) begin : gen_registers
        reg [3:0] reg_i;
        always @(posedge clk or posedge reset) begin
            if (reset) begin
                reg_i <= 4'b0000;
            end else begin
                reg_i <= data_in;
            end
        end
        assign data_out[i] = reg_i;
    end
endgenerate

endmodule//结束module的定义

initial逻辑块

在 Verilog 中,initial 逻辑块用于在仿真开始时执行一次性的初始化操作。它与 always 块不同,always 块在仿真过程中会无限循环执行,而 initial 块只在仿真开始时执行一次,之后就不会再执行。

initial 块通常用于以下几种情况:

  1. 初始化寄存器的值。

  2. 定义测试平台的激励(stimulus)。

  3. 配置仿真环境,如设置初始时间分辨率。

  4. 打印仿真开始时的消息。

initial逻辑块的示例代码如下:

module testbench;
    reg my_reg;
    initial begin
        // 在仿真时间0时初始化my_reg为0
        my_reg = 0;
        #10; // 等待10个时间单位
        my_reg = 1; // 在仿真时间10时将my_reg设置为1
        #20; // 再等待20个时间单位
        my_reg = 0; // 在仿真时间30时将my_reg重新设置为0
        $display("Simulation ended at time %t",$time);
    end
endmodule

赋值方式

在verilog中有三种赋值方式,分别是连续赋值,阻塞赋值与非阻塞赋值,如下:

在Verilog硬件描述语言中,赋值语句用于定义信号的行为。根据赋值的类型,Verilog中的赋值可以分为以下几种:阻塞赋值(Blocking Assignment)、非阻塞赋值(Non-Blocking Assignment)和连续赋值(Continuous Assignment)。阻塞赋值使用等号(=)表示。在执行过程中,当前语句必须等待赋值完成之后,才会执行下一条语句。这意味着在同一个always块中,阻塞赋值的执行是顺序的。非阻塞赋值使用小于等于号(<=)表示。在执行过程中,当前语句不会阻塞后续语句的执行。在同一个always块中,非阻塞赋值的操作是并行的,即它们同时开始但完成时间不一定相同。连续赋值使用等号(=)表示,但它不同于阻塞赋值,因为它没有放在always块中。连续赋值描述的是组合逻辑,只要右侧的表达式发生变化,赋值就会立即更新左侧的信号。

示例代码如下:

assign x=y//此为连续赋值,用assign关键词
// 组合块
always @(*)  begin//此为阻塞赋值
	out1 = a ;
    a = b ;
    out2 = a ;
end
// 时序块
always @(posedge clk)  begin//此为非阻塞赋值
	out1 <= a ;
    a <= b ;
    out2 <= a ;
end

基础语法

逻辑值与逻辑运算

逻辑值

在Verilog中,主要有以下四种逻辑值:

  1. 0:表示逻辑低电平,通常对应于电压的0V或GND。
  2. 1:表示逻辑高电平,通常对应于电源电压(如5V或3.3V)。
  3. x:表示未知逻辑值,可以是0或1。
  4. z:表示高阻态,通常用于三态门或双向端口,表示输出既不是高电平也不是低电平,而是处于不驱动状态。

逻辑运算

Verilog支持以下逻辑运算,下面这些是按位运算,假如要做逻辑运算,则用&&,||这些

  1. 逻辑与(&)
    • 运算规则:只有当两个操作数都为1时,结果才为1;否则结果为0。
    • 示例:4'b1010 & 4'b1100 的结果为 4'b1000
  2. 逻辑或(|)
    • 运算规则:只要有一个操作数为1,结果就为1;只有当两个操作数都为0时,结果才为0。
    • 示例:4'b1010 | 4'b1100 的结果为 4'b1110
  3. 逻辑异或(^)
    • 运算规则:当两个操作数不相同时,结果为1;当两个操作数相同时,结果为0。
    • 示例:4'b1010 ^ 4'b1100 的结果为 4'b0110
  4. 逻辑同或(~^ 或 ^~)
    • 运算规则:当两个操作数相同时,结果为1;当两个操作数不相同时,结果为0。
    • 示例:4'b1010 ~^ 4'b1100 的结果为 4'b1000
  5. 逻辑非(! 或 ~)
    • 运算规则:将操作数的逻辑值取反。
    • 示例:!4'b1010 的结果为 4'b0101~4'b1010 的结果也是 4'b0101

这里补充一下在verilog中的数字表示形式:'b在verilog中是二进制的意思,4’b1100是4位二进制数1100,这种表示方法我没学习的时候是一头雾水的。'b是二进制,'h是八进制,'d是十进制。

变量(wire,reg)

在Verilog中,wirereg是两种不同的变量类型,它们用于表示硬件电路中的不同信号和功能。

wire

wire类型用于表示硬件电路中的物理连线。它通常用于表示模块间的连接、组合逻辑的输出以及芯片上的实际电线。以下是关于wire的一些特点:

  • wire用于表示线网(net),即它是一个无状态的变量,它的值由驱动它的逻辑门或模块的输出决定。

  • wire不能存储值,它的值是连续分配的,即它的值在任何时刻都是由连接到它的驱动器所决定的。

  • wire主要用于表示组合逻辑的输出。

  • wire可以在连续赋值语句(assign statement)中使用,用于连续赋值。

reg

reg类型用于表示寄存器类型的变量,它通常用于表示时序逻辑中的存储元素。以下是关于reg的一些特点:

  • reg用于表示变量,它可以存储值,通常用于在always块中赋值。
  • reg并不总是代表硬件寄存器,它也可以用于表示用于仿真的内部变量。
  • reg可以在过程赋值语句(procedural assignment)中使用,如always块、initial块等。
  • reg通常用于表示触发器(flip-flop)的输出。
wire a, b, sum;

assign sum = a & b; // 使用assign语句将a和b的逻辑与结果赋值给sum,wire用在assign 语句中

reg a, b, q;

always @(posedge clk) begin
    q <= a & b; // 在时钟上升沿将a和b的逻辑与结果赋值给q,reg用在always逻辑块中
end

区别如下

  • wire用于组合逻辑,而reg用于时序逻辑。
  • wire通过连续赋值语句赋值,而reg通过过程赋值语句赋值。
  • wire不能在always块中直接赋值,而reg可以在always块中赋值。

值得注意的是即使register(reg)暗示了其是一个寄存器,但实际上这还要和其在电路中是如何使用的对应上。

向量与参数(常量)

parameter 参数:

parameter是一种常量,通常出现在module内部,常被用于定义状态、数据位宽等

vector(向量):

在Verilog中,向量变量是一种表示多位宽信号的方式,它允许我们以单个变量的形式处理一组位。向量可以是线网(wire)或变量(reg)类型,并且可以用于表示组合逻辑或时序逻辑的输出。以下是关于Verilog中向量变量形式的详细介绍:

向量通过在变量名后面加上方括号[]来定义,方括号内指定了向量的位宽。位宽可以是确定的数字,也可以是参数化的表达式。向量的位宽定义了向量包含的位数。

wire [3:0] w;  // 定义一个4位的wire类型向量,位宽从3到0
reg  [7:0] r;  // 定义一个8位的reg类型向量,位宽从7到0

向量索引:

Verilog允许通过索引来访问向量中的单个位或连续的位段。索引可以是常数或计算得到的表达式。

reg [7:0] r;

// 访问单个位
r[0] = 1'b1;  // 设置r的第0位为1
r[7] = 1'b0;  // 设置r的最高位为0

// 访问连续的位段
r[3:1] = 3'b101;  // 设置r的第3位到第1位为101

向量拼接:

允许将向量进行相连,如此看来向量和c语言中的字符串更加相似。

wire [3:0] a = 4'b1010;
wire [3:0] b = 4'b1100;
wire [7:0] c;

// 向量拼接
c = {a, b};  // c将会是8'b10101100

向量赋值:

向量赋值允许整体赋值和部分赋值。

reg [7:0] r;//八位向量,[7:0]

// 整体赋值
r = 8'b10101010;

// 部分选择赋值
r[7:4] = 4'b1111;  // r现在为8'b11111010

向量的操作:

向量间允许进行逻辑运算,算术运算和比较运算。向量间运算的时候,需要保持其长度一样。

reg [3:0] a = 4'b1010;
reg [3:0] b = 4'b1100;
reg [3:0] result;

// 逻辑运算
result = a & b;  // 结果为4'b1000

在verilog中的向量一般来说是从最高位到最低位这样设定的,比如reg [4:0] a中就是从第四位到第0位如此设定的。

三元表达式

在Verilog中,三元表达式是一种简洁的书写方式,用于在单个表达式中实现条件赋值。它类似于C语言中的条件运算符 ? :。三元表达式的语法如下:

condition ? expression1 : expression2

部分使用示例如下:

reg a, b, c;
wire d;

// 如果a为1,则d赋值为b,否则赋值为c
d = a ? b : c;
reg [3:0] a, b, result;

// 如果a的最高位为1,则result的最高4位赋值为b,否则赋值为a
result[3:0] = a[3] ? b[3:0] : a[3:0];

分支语句

在Verilog中,分支语句用于根据条件的真假来执行不同的代码块。Verilog提供了两种主要的分支语句:if语句和case语句。下面将详细介绍这两种分支语句的用法。

if语句:

if语句是最基本的分支结构,它根据条件的真假来决定是否执行某个代码块。

reg [1:0] a;
reg b;

always @(posedge clk) begin
    if (a == 2'b01) begin
        b <= 1'b1; // 如果a等于01,则b赋值为1
    end
    else begin
        b <= 1'b0; // 否则,b赋值为0
    end
end

case语句:

case语句是一种多路分支结构,它允许根据表达式的值选择多个代码块中的一个来执行。case语句中假如不满足所有的值就执行default条件。示例代码如下,类似于c语言中的case语句:

reg [1:0] a;
reg [2:0] b;

always @(posedge clk) begin
    case (a)
        2'b00: b <= 3'b000; // 如果a等于00,则b赋值为000
        2'b01: b <= 3'b001; // 如果a等于01,则b赋值为001
        2'b10: b <= 3'b010; // 如果a等于10,则b赋值为010
        default: b <= 3'b111; // 如果a不匹配上述任何值,则b赋值为111
    endcase
end

for循环语句

在Verilog中,for循环语句是一种重复执行代码块的构造,它允许你根据给定的条件重复执行一系列操作。这在初始化寄存器数组或执行重复计算时非常有用。以下是for循环的基本语法和用法。在verilog中的for循环语句和c语言中的for循环语句相似。

reg [7:0] my_array [0:99]; // 声明一个包含100个8位寄存器的数组

initial begin
    for (int i = 0; i < 100; i = i + 1) begin
        my_array[i] = 8'h00; // 将数组中的每个元素初始化为0
    end
end

  • 循环变量通常声明为整数类型(int),这是Verilog中的一个4态变量,可以表示正值、负值、0和x(未知)。
  • 在Verilog中,for循环通常用于initialalways块中。
  • 在可综合的Verilog代码中,for循环必须保证在有限的时间内完成。这意味着循环的迭代次数必须是可预测的,通常基于常数或参数。
  • 在仿真中,for循环可以无限运行,但在实际硬件中,循环必须在一个时钟周期内完成,或者分解为多个时钟周期内的操作。
  • 在可综合的代码中,for循环的索引变量不应在循环体内被赋值,除非是按照循环迭代的固定模式更新。

拼接运算符

在Verilog中,拼接运算符(Concatenation Operator)用于将多个位宽不同的信号或变量组合成一个连续的位宽更大的信号。拼接运算符有两种形式:连续拼接运算符 {} 和重复拼接运算符 {n{}}。连续拼接运算符允许你将多个信号或值按顺序拼接起来,形成一个更大的向量。重复拼接运算符允许你将一个信号或值重复多次,形成一个更大的向量。示例代码如下:

wire [3:0] a = 4'b1010;
wire [1:0] b = 2'b11;
wire [5:0] c;

assign c = {a, b}; // c 将被赋值为 6'b101011
wire [1:0] a = 2'b11;
wire [7:0] b;

assign b = {4{a}}; // b 将被赋值为 8'b11111111

while循环

在Verilog中,while循环是一种过程性语句,它允许在initial块或always块中根据给定的条件重复执行一段代码。while循环的行为类似于C语言中的while循环,它在每次迭代之前检查条件,如果条件为真(即非零),则执行循环体内的代码;如果条件为假(即零),则退出循环。示例代码如下:

reg [7:0] accumulator; // 8位累加器
reg [7:0] counter;     // 8位计数器

initial begin
    accumulator = 0; // 初始化累加器
    counter = 0;     // 初始化计数器

    while (counter < 100) begin
        accumulator = accumulator + counter; // 累加计数器的值
        counter = counter + 1;              // 计数器递增
    end

    $display("Accumulator value: %d", accumulator); // 显示累加器的最终值
end

在下面的示例中编写了test_bench文件并编译和查看结果:

在这里插入图片描述

repeat循环

在Verilog中,repeat 循环是一个用于重复执行一段代码的循环结构。它类似于 C 语言中的 for 循环,但是 repeat 循环的语法更简单,因为它只指定了循环次数,而不需要初始化表达式和递增表达式。示例代码如下:

module repeat_test;
reg [3:0] count; // 4位计数器
initial begin//initial逻辑块
    count = 0; // 初始化计数器
    repeat (10) begin
        #5; // 等待5个时间单位
        count = count + 1; // 计数器递增
        $display("Count is %d", count); // 打印计数器的值
    end
end
endmodule

实际上说明在verilog编译的时候不需要test_bench也是可行的,仅仅编写一个module文件也是可以编译并查看结果的,具体如下所示:

在这里插入图片描述

函数与任务

在Verilog中,函数(function)和任务(task)是两种用于封装和重用代码块的重要机制。它们在模块内部定义,可以用来执行特定的操作或计算。函数是一种返回单个值的操作,它不能包含任何时间延迟(#)或非阻塞赋值(<=)。函数通常用于计算和返回一个结果。

函数的特点:

  • 函数必须有一个返回类型,可以是线网(wire)或寄存器(reg)类型,并且可以指定宽度。
  • 函数可以接受输入参数,但不能有输出参数。
  • 函数不能包含任何时间延迟(#)或非阻塞赋值(<=)。
  • 函数在调用时必须有一个返回值。
function [7:0] add_bytes(input [7:0] a, input [7:0] b);//定义函数,输出是[7:0]的向量,输入是[7:0]a和[7:0]b,这是system verilog的语法,传统的verilog实际上不支持参数的声明在括号中
    add_bytes = a + b;
endfunction

任务是一种可以执行多个操作的块,它可以包含时间延迟和非阻塞赋值。任务可以没有返回值,但可以有输入和输出参数。

任务的特点:

  • 任务可以没有返回值,因此不需要指定返回类型。
  • 任务可以接受输入参数和输出参数。
  • 任务可以包含时间延迟(#)和非阻塞赋值(<=)。
  • 任务可以调用其他任务或函数。

值得注意的是,任务的特点在于其可以包含时间延迟和非阻塞赋值,且其不一定得有一个返回值。

task delay_and_print(input [7:0] data, output reg done);
    #10; // 延迟10个时间单位
    $display("Data is %h", data);
    done = 1'b1; // 设置完成标志
endtask

下面的代码示例展示了如何在verilog中编写并调用函数。

module task_test;
    // 函数定义(传统Verilog语法)
    function [7:0] myfunction;
        input [7:0] a;  // 在函数体内声明输入参数
        input [7:0] b;
        begin
            myfunction = a + b; // 通过赋值给函数名返回结果
        end
    endfunction

    reg [7:0] out;
    initial begin
        out = myfunction(8'b11000011, 8'b10101010);
        $display("out is %b", out); 
    end
endmodule

在这里插入图片描述

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

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

相关文章

Java+SpringBoot+Vue+数据可视化的综合健身管理平台(程序+论文+讲解+安装+调试+售后)

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。 系统介绍 在当今社会&#xff0c;随着人们生活水平的不断提高和健康意识的日益增强&#xff0c;健…

python绘制年平均海表温度、盐度、ph分布图

python绘制年平均海表温度、盐度、ph图 文章目录 python绘制年平均海表温度、盐度、ph分布图前言一、数据准备二、代码编写2.1. python绘制年平均海表温度&#xff08;主要&#xff09;2.2. python绘制年平均海表盐度&#xff08;选看&#xff09;2.3. python绘制年平均海表ph&…

网络空间安全(2)应用程序安全

前言 应用程序安全&#xff08;Application Security&#xff0c;简称AppSec&#xff09;是一个综合性的概念&#xff0c;它涵盖了应用程序从开发到部署&#xff0c;再到后续维护的整个过程中的安全措施。 一、定义与重要性 定义&#xff1a;应用程序安全是指识别和修复应用程序…

全链路优化:如何让单点登录认证接口并发性能翻倍?

背景 最近针对一个单点登录认证项目进行性能优化&#xff0c;在 8核 16G 环境下的认证并发能力从每秒800次提升至每秒1600次&#xff0c;性能提升一倍&#xff0c;整理此次优化过程中的相关性能优化操作总结和大家分享一下。 Nginx配置优化 在并发认证场景下&#xff0c;Ngi…

http代理IP怎么实现?如何解决代理IP访问不了问题?

HTTP代理是一种网络服务&#xff0c;它充当客户端和目标服务器之间的中介。当客户端发送请求时&#xff0c;请求首先发送到代理服务器&#xff0c;然后由代理服务器转发到目标服务器。同样&#xff0c;目标服务器的响应也会先发送到代理服务器&#xff0c;再由代理服务器返回给…

USC安防平台之地图临近资源列表

USC安防平台通过配置多层地图&#xff0c;并把相关的摄像机和门禁对象配置到数据上&#xff0c;用户可以方便的在地图上查看并操作。 但是对于大型的视频监控项目&#xff0c;同一个经纬度可能安装了很多台摄像机&#xff0c;这时候就需要显示同一个经纬度的临近资源列表&…

JavaScript数组方法reduce详解

JavaScript数组方法reduce详解 目录 JavaScript数组方法reduce详解一&#xff0c;前言二&#xff0c;核心语法三&#xff0c;案例1.求和2.找最大值3.数组转对象4.复合操作&#xff08;同时实现 map filter&#xff09; 四&#xff0c;常见错误1.空数组没有初始值2.没有返回累加…

计算机毕业设计SpringBoot+Vue.js服装商城 服装购物系统(源码+LW文档+PPT+讲解+开题报告)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

Web自动化中Selenium下Chrome与Edge的Webdriver常用Options参数

目录 引言 说明 Add_argument() 添加方式 常用参数 Add_experimental_option() 添加方式 常用方法 任务结束后仍然保持浏览器打开 禁用“Chrome 正受到自动测试软件的控制”提示 设置下载路径 禁用弹窗拦截 禁用图片加载 禁用 JavaScript 注意 引言 …

现代未来派品牌海报徽标设计无衬线英文字体安装包 THANKS LAB

THANK LAB 是一种高级未来主义的软字体&#xff0c;将时尚的现代设计与光滑圆润的边缘相结合&#xff0c;营造出大胆而平易近人的美感。这款字体非常适合品牌、海报、标题、UI/UX 和科幻主题项目&#xff0c;旨在激发创造力。THANK LAB Futuristic Soft Font 完全支持拉丁字母、…

【算法通关村 Day6】二叉树层次遍历

树与层次遍历青铜挑战 理解树的结构 通过中序和后序遍历序列恢复二叉树是一个经典的二叉树构建问题。给定二叉树的中序遍历序列和后序遍历序列&#xff0c;我们可以利用以下步骤进行恢复。 思路&#xff1a; 后序遍历的特点&#xff1a; 后序遍历的最后一个节点是树的根节点…

安全面试2

文章目录 简单描述一下什么是水平越权&#xff0c;什么是垂直越权&#xff0c;我要发现这两类漏洞&#xff0c;那我代码审计要注意什么地方水平越权&#xff1a;垂直越权&#xff1a;水平越权漏洞的审计重点垂直越权漏洞的审计重点 解释一下ssrf漏洞原理攻击场景修复方法 横向移…

【JavaScript进阶】构造函数数据常用函数

目录 本章节用到的所有素材都可以找到&#xff1a;素材自取~~~~ 1、深入对象 1.1创建对象三种方式 1.2 构造函数 练习 利用构造函数创建多个对象 实例化执行过程 1.3实例成员&静态成员 2. 内置构造函数 2.1 Object 2.2 Array 练习 员工涨薪计算成本 2.3 St…

在PiscTrace开发者版上直接处理图像色阶分布

在图像处理和计算机视觉中&#xff0c;色阶分布&#xff08;或称灰度分布&#xff09;是描述图像中像素强度分布的一个重要概念。它对于理解图像的亮度、对比度、纹理和细节等方面具有关键作用。通过色阶分布的分析&#xff0c;我们能够获得图像的整体信息&#xff0c;从而帮助…

趣味数学300题1981版-十五个正方形

分析&#xff1a;移动两根变成11个正方形很简单&#xff1a; 移动4根变成15个正方形&#xff0c;分析&#xff1a; 一个田字格包含5个正方形&#xff0c;若要15个正方形需要3个田字格&#xff0c;如果3个田字格完全不重合&#xff0c;需要6*318根火柴。如果合并正方形的边&…

Selenium实战案例1:论文pdf自动下载

在上一篇文章中&#xff0c;我们介绍了Selenium的基础用法和一些常见技巧。今天&#xff0c;我们将通过中国科学&#xff1a;信息科学网站内当前目录论文下载这一实战案例来进一步展示Selenium的web自动化流程。 目录 中国科学&#xff1a;信息科学当期目录论文下载 1.网页内…

nginx 反向代理 配置请求路由

nginx | 反向代理 | 配置请求路由 nginx简介 Nginx&#xff08;发音为“Engine-X”&#xff09;是一款高性能、开源的 Web 服务器和反向代理服务器&#xff0c;同时也支持邮件代理和负载均衡等功能。它由俄罗斯程序员伊戈尔西索夫&#xff08;Igor Sysoev&#xff09;于 2004…

用户中心项目教程(十)---注册里面的重定向排查和相关的修改

文章目录 1.注册逻辑的设计和实现2.解决自带的这个重定向的问题3.增加属性的相关操作4.关于如何修改页面上面的绿色按钮 1.注册逻辑的设计和实现 上次说到了的是登录功能&#xff0c;我们使用数据库里面存在的这个存在的账户和密码进行登录&#xff0c;但是是无法进行跳转的&a…

根据音频中的不同讲述人声音进行分离音频 | 基于ai的说话人声音分离项目

0.研究背景 在实际的开发中可能会遇到这样的问题&#xff0c;老板让你把音频中的每个讲话人的声音分离成不同的音频片段。你可以使用au等专业的音频处理软件手动分离。但是这样效率太慢了&#xff0c;现在ai这么发达&#xff0c;我们能否借助ai之力来分离一条音频中的不同的说…

【单片机】【UDS】 (单帧与多帧) 数据传输

对于使用 CAN 的诊断通信系统&#xff0c;每个单帧 (SF)、 第一帧 (FF)、 连续帧 (CF) 或流控 制帧 (FC) 有 8 字节数据场&#xff1b;其中单帧的 CAN_DL≤8 且第一帧的 FF_DL≤4095&#xff1b;下表 中已定义 每个报文的类型。 CAN FD 帧的数据场支持最大 64 个字节&#xff0…