Verilog HDL 语言整理
Verilog HDL 语言
Verilog HDL 简介
硬件描述语言Hardware Description Language
是一种用形式化方法即文本形式 来描述和设计数字电路和数字系统的高级模块化语言
- Verilog HDL(Hardware Description Language)是一种硬件描述语言,用于建模、设计和验证数字系统,比如芯片(ASIC)、FPGA等。
- 它既可以用于描述电路结构(结构级建模),也可以描述电路行为(行为级建模)。
基本组成
- 模块(module):Verilog的基本单元,定义了输入输出端口和内部逻辑。
- 端口(ports):模块的输入(input)、输出(output)、双向(inout)信号。
- 信号类型(nets和variables):例如
wire
(连线类型),reg
(寄存器类型)。
数据类型
变量值
值 | 含义 |
---|---|
0 | 代表逻辑0 或 否条件 |
1 | 代表逻辑1 或 真条件 |
X | 代表未知的逻辑值(可能是0也可能是1) |
Z | 代表一个高阻态 |
0 在电路中一般是低电平
1 在电路中是高电平
X 一般是寄存器类型( reg )未初始化
Z 是线型( wire )变量未接驱动
(实际写代码时要避免出现X和Z)
wire(线网)
wire
表示一根连接线(物理连线)。- 它不能自己存值,通常用于连续赋值,只能连接别的东西,比如assign语句、模块的输出。
- 一般用于组合逻辑(纯逻辑运算)。
例子:
wire a; // 声明一根线,1-bit位宽
assign a = b & c; // a 由 b 和 c 按位与得到
wire d = 1'b0; //1代表1-bit位宽,'b'代表二进制,0是初值
reg(寄存器)
reg
是一个存储单元。- 在
always
块或initial
块里赋值。 - 不一定是真正硬件的"寄存器",但可以存住一个值直到下次变化。
例子:
reg rstn;
initial beginrstn = 1'b0;#100; // 等待100单位时间(单位根据仿真设置,比如ns或ps)// # 是延时操作rstn = 1'b1;
end
reg d; // 声明一个寄存单元
always @(posedge clk) begind <= a; // 非阻塞赋值,时序逻辑 每次时钟上升沿,d取a的值
end
🔔 注意:
wire
用在assign
、模块之间连线reg
用在always
块里
向量vector
当你声明多位的 wire
或 reg
时,就叫向量(Vector)。
向量本质上就是:一组用一根名字表示的多位信号。
你可以整体操作,也可以单独取其中一位或几位。
wire [7:0] data; // 8-bit位宽线
reg [15:0] addr; // 16-bit位宽寄存器
多位信号可以通过下标访问:
a = data[0]; // 取最低位
b = data[7:4]; // 取高4位
用途 | 说明 |
---|---|
表示多位数据 | 比如8位数据总线、16位寄存器、32位地址 |
方便整体操作 | 可以一次赋值、比较、传递 |
位选取灵活 | 可以随时取某几位,比如取高字节、低字节 |
节省命名空间 | 不用每一位单独声明变量 |
[高位:低位]
是强制要求高位写左边。
数组 Array
在 Verilog 中允许声明 reg, wire, integer, time, real 及其向量类型的数组,数组的大小代表深度
reg y1 [11:0]; //是一个1-bit位宽,深度为12的寄存器
wire [7:0] y2 [11:0]; //是一个8-bit位宽,深度为12的线
reg [15:0] y3[0:1][0:3]; //二维数组
数组定义时,索引的定义可以自由选择,但通常使用 [高:低]
的写法。
写法 | 含义 | 应用习惯 |
---|---|---|
[高:低] (如 [11:0] ) | 数字从高到低排列 | 通常用于总线、数据字节流,符合大部分硬件设计习惯 |
[低:高] (如 [0:11] ) | 数字从低到高排列 | 有些数组或存储器设计喜欢用递增顺序 |
其他类型
类型 | 说明 | 是否可综合 | 特别说明 |
---|---|---|---|
integer | 32位有符号整数变量 | ✅ 可综合(但慎用) | 适合建模简单计数器,但综合成硬件时表现不够精准 |
real | 浮点实数变量 | ❌ 不可综合 | 只能用于仿真,比如仿真计算,不能转成硬件 |
time | 64位无符号整数,存仿真时间 | ❌ 不可综合 | 只用于仿真(比如记录时间点) |
realtime | 浮点数形式存时间 | ❌ 不可综合 | 和 time 类似,但有小数精度 |
string | 字符串,存储在 reg 中 | ❌ 理论可综合,但实际几乎只用于仿真 | 硬件几乎不会真的合成字符串 |
logic [n:0] | SystemVerilog扩展型变量,结合了wire+reg特性 | ✅ 可综合 | 现在新项目基本用 logic 代替 reg |
概念 | 解释 | 举例 |
---|---|---|
可综合(Synthesisable) | 能够被综合工具(如 Vivado、Quartus)转成真正的硬件电路(逻辑门、触发器、存储单元等) | wire, reg, logic |
不可综合(Non-Synthesisable) | 只在仿真阶段起作用,不能转成电路,硬件里不会存在对应结构 | real, time, realtime, string |
模块 module
- 模块(module)是 Verilog 的基本单位,相当于C语言的函数、Java的类,代表一个可以综合为实际硬件的功能单元。
- 每一个
module
可以是一个门电路、触发器、加法器、CPU子模块,甚至整个SoC。
基本写法
Verilog模块的结构由在 module 和 endmodule 关键词之间的 4 个主要部分组成:
- 端口定义 module 模块名 端口 1 端口 2
- I/O 说明 包括输入 (input) 、 输出 (output) 和双向(inout)
- 信号类型声明 声明信号的数据类型和函数声明 wire,reg, integer, real, time
- 逻辑描述 用来描述设计模块的内部结构和模块端口间的逻辑关系 。 常用
assign
语句 、always
块语句等方法实现
module 模块名(端口列表);// 端口定义 (input output)// 内部信号定义(wire, reg等)// 电路描述(assign语句、always块等)
endmodule
例子:
module block1(a,b,c,d);input a,b,c;output d;wire x;assign d = a|x; //a或x 按位“或”运算assign x = (b & ~c);
endmodule
module and_gate (input a, input b, output y);assign y = a & b;
endmodule
意思:建了一个名字叫 and_gate
的模块,它有两个输入端口 a
、b
,一个输出端口 y
,输出是 a AND b
。
模块实例化
模块是具一个有特定功能的设计单元, 在电路综合时模块会被 转 换为相应的数字电路
给定模块一组输入, 模块会返回一组输出, 这意味着模块可以被重复使用, 由此来实现更加复杂的电路(相当于函数)
module mod1(input d, …);// 模块内容
endmodulemodule mod2;wire data;mod1 u0 (.d(data),…);// 模块内容
endmodule
mod1 u0 (.d(data),…);
这句在实例化模型时,需要把本模块内的data
信号连接到mod1
模块的端口d
上。
位置关联(不推荐)
module my_module;wire a, b, c;and_gate u1 (a, b, c); // a 连接 .a, b 连接 .b, c 连接 .y
endmodule
问题:你必须知道子模块端口的顺序,一旦顺序改了容易出错。
命名关联(推荐)
and_gate u1 (.a(a), // 上层的 a 连接到模块的 a.b(b), // 上层的 b 连接到模块的 b.y(c) // 上层的 c 连接到模块的 y
);
优点:
- 与顺序无关
- 更直观、可读性强
- 推荐用于所有复杂模块
带参数模块的实例化(parameter)
当模块带有 parameter
参数时,可以通过 #()
语法传值:
模块定义
module counter #(parameter WIDTH = 8
)(input clk,output [WIDTH-1:0] out
);...
endmodule
实例化方式
counter #(.WIDTH(4)) my_cnt (.clk(clk),.out(cnt_out)
);
多个实例的情况
可以实例化多个同一个模块:
and_gate U1 (.a(a1), .b(b1), .y(y1));
and_gate U2 (.a(a2), .b(b2), .y(y2));
每次实例代表“一个新的电路副本”。
实践建议 | 说明 |
---|---|
命名关联优于位置关联 | 尤其是模块接口复杂时 |
实例名推荐加前缀 | 如 u_and1 , u_mux4 |
参数化模块要注意 default | 给定默认值可提升复用性 |
用注释标出每个模块 | 增加结构清晰度 |
generate实例化
generate
是 Verilog 中的代码生成机制,用于在模块定义中动态、结构性地实例化多个模块、赋值、或条件逻辑。
它本质上是语法上的工具,允许我们在模块中通过 for
、if
等控制结构,自动生成重复或条件性的硬件结构。
generate 可以用来循环实例化模块或条件实例化模块
它常用于:
- 批量实例化模块(如多个乘法器、加法器)
- 条件生成不同的硬件结构
- 构建参数化设计(如可变位宽)
因为重复构建多个实例是结构层面的代码,不是行为逻辑,因此不能用
always
、if
、for
这种行为语句来写,必须用generate
。
基本语法
generate// 结构代码
endgenerate
generate ... endgenerate
包围的结构会在编译时处理,不会在仿真或综合时运行。
for-generate
用法(循环生成)
genvar i; // 必须用 genvar 声明控制变量generatefor (i = 0; i < N; i = i + 1) begin : gen_block// 可实例化模块、连接线、赋值等end
endgenerate
说明:
genvar
是 generate 专用的变量,不能用于普通 always 块gen_block
是可选的名字,用于结构层次(类似作用域)
if-generate
用法(条件生成)
generateif (USE_REG == 1) begin : reg_block// 生成寄存器逻辑end else begin : comb_block// 生成组合逻辑end
endgenerate
常用于根据参数开关生成不同的硬件结构。
case-generate
用法(多分支生成)
generatecase (WIDTH)8: begin : w8 // 8位逻辑end16: begin : w16 // 16位逻辑endendcase
endgenerate
根据参数选择不同硬件实现(比如不同位宽的乘法器)。
用途 | 描述 |
---|---|
多模块实例化 | 自动生成多个模块副本 |
参数化设计 | 根据传入的参数动态生成逻辑 |
条件生成 | 控制生成哪种逻辑(例如是否使用寄存器) |
多分支生成 | 根据参数做 case 分支 |
注意事项:
genvar
只能在generate
块中使用generate
块中的变量不会出现在仿真或综合时刻的信号列表中- 实例名称尽量唯一,可用
gen_block[i]
等结构防止冲突 generate
是静态生成语法,不可在运行时决定
【例子】
// 半加器模块的定义
module ha ( input a, b, // 输入 a 和 boutput sum, cout // 输出 sum 和进位 cout);assign sum = a ^ b; // sum 为 a 和 b 的异或运算结果assign cout = a & b; // cout 为 a 和 b 的与运算结果(即进位)
endmodule// 顶层模块:包含 N 个半加器实例
module my_design#(parameter N = 4) // 定义参数 N,默认值为 4,表示半加器的个数(input [N-1:0] a, b, // 输入 a、b 是 N 位的向量output [N-1:0] sum, cout // 输出 sum 和 cout 也是 N 位向量);// 声明一个用于 generate 的临时变量 i,仿真时不可见genvar i;// generate-for 循环,实例化 N 个半加器generatefor (i = 0; i < N; i = i + 1) begin// 实例化名为 u0 的半加器模块,第 i 位的输入和输出分别连接ha u0 (.a(a[i]), // 输入 a 的第 i 位.b(b[i]), // 输入 b 的第 i 位.sum(sum[i]), // 输出 sum 的第 i 位.cout(cout[i]) // 输出 cout 的第 i 位);endendgenerateendmodule
运算符
在逻辑运算中 如果操作数不止一位 应将操作数作为一个整体来对待
算术运算符
运算符 | 含义 | 示例 | 说明 |
---|---|---|---|
+ | 加法 | a + b | |
- | 减法 | a - b | |
* | 乘法 | a * b | |
/ | 除法 | a / b | 整数除法,小数部分舍弃 |
% | 取模(余数) | a % b |
✅ 注意:除法/
是取整除,不是浮点数除法!
比较运算符(返回1或 0 或 x)
运算符 | 含义 | 示例 | 结果 |
---|---|---|---|
== | 等于 | a == b | 相等为1,不等为0,不确定为 X |
!= | 不等于 | a != b | |
=== | 全等于 | a === b | 相等为1,不等为0 |
!== | 不全等于 | a !== b | |
< | 小于 | a < b | |
> | 大于 | a > b | |
<= | 小于等于 | a <= b | |
>= | 大于等于 | a >= b |
==
和 !=
的特点(普通等于)
- 只看数值是否一致
- 忽略未知值
X
或高阻值Z
- 若任一位为
X
或Z
,比较结果是X
(也就是逻辑不确定)
===
和 !==
的特点(全等运算符)
- 会逐位比较
- 不会忽略
X
和Z
- 只有每一位都完全一致(包括
X/Z
),才返回1
使用建议:
场景 | 建议用 |
---|---|
判断具体数值(如状态) | 使用 == |
判断信号是否含 X 或用于测试用例 | 使用 === |
testbench 中对 X/Z 做比较 | 一定用 === 或 !== |
case语句中的匹配项 | 默认用 == ,可以用 casez/casex 处理模糊匹配 |
位逻辑运算符(逐位操作)
两个不同长度的操作数进行位运算时, 将自动按右端对齐, 位数少的操作数会在高位用 0 补齐
运算符 | 含义 | 示例 | 说明 |
---|---|---|---|
~ | 按位取反 | ~a | 0变1,1变0 |
& | 按位与 | a & b | 两位都1,结果才是1 |
` | ` | 按位或 | `a |
~& | 与非 | ||
`~ | ` | 或非 | |
^ | 按位异或 | a ^ b | 不同为1,相同为0 |
~^ 或 ^~ | 按位同或(XNOR) | a ~^ b | 相同为1,不同为0 |
逻辑运算符(整体为0或1)
运算符 | 含义 | 示例 | 说明 |
---|---|---|---|
! | 逻辑非 | !a | a 为0则返回1,非0返回0 |
&& | 逻辑与 | a && b | 两个都非0才返回1 |
` | ` |
✅ 区别:
- 位运算是每一位单独算,
- 逻辑运算是整体判断真假(0或非0)。
移位运算符
在移位运算中 将操作数左移或者右移后空位补 0
运算符 | 含义 | 示例 | 说明 |
---|---|---|---|
<< | 左移 | a << 2 | 左移2位,右边补0 |
>> | 右移 | a >> 2 | 右移2位,左边补0(逻辑右移) |
<<< | 算术左移 | a <<< 2 | 保持符号位,左移(和逻辑左移相同) |
>>> | 算术右移 | a >>> 2 | 保持符号位(最高位扩展)右移 |
✅ 一般情况下,普通>>
逻辑右移,>>>
符号扩展右移。
条件运算符(三目运算符)
运算符 | 含义 | 示例 |
---|---|---|
? : | 条件判断 | d = sel ? a : b; |
意思是:
- 如果
sel==1
,那么d=a
- 如果
sel==0
,那么d=b
拼接与重复运算符
拼接运算符 { , }
- 把多个信号拼接成一个大的信号。
例子:
{a, b} // a在高位,b在低位
如果:
a = 4'b1100;
b = 4'b0011;
{a,b} = 8'b11000011;
重复运算符 {N{表达式}}
- 把表达式复制N次。
例子:
{4{1'b1}} // 结果是 4'b1111
优先级
顺序(高到低):
1. () 小括号
2. ~ ! 取反(位、逻辑)
3. * / % 乘除取模
4. + - 加减
5. << >> <<< >>> 移位
6. < <= > >= 比较
7. == != 等于、不等
8. & 位与
9. ^ ~^ 位异或/同或
10. | 位或
11. && 逻辑与
12. || 逻辑或
13. ?: 条件选择
✅ 写复杂表达式时,一定多用小括号 ()
,不要只靠优先级,避免出错。
分类 | 常用运算符 |
---|---|
算术运算 | + - * / % |
比较运算 | == != < > <= >= |
位运算 | `~ & |
逻辑运算 | `! && |
移位运算 | << >> <<< >>> |
条件运算 | ? : |
拼接/重复 | { , } , {N{}} |
信号赋值
assign 连续赋值(只给wire用)
- 用来连接信号或者表达式。
- 等式左边必须是一个标量或者线性向量,而不能是寄存器类型
- 等式右边的类型没有要求,等式右边的值一旦发生变化,就会立刻重新计算并同时赋值给左侧
例子:
assign y = a & b;
意思:y
始终是 a
和 b
按位与的结果。
分类 | 特点 | 常用赋值方式 |
---|---|---|
wire | 连线,不存储数据 | assign |
reg | 存储单元,可在always赋值 | always块 |
assign | 连续赋值,只能给wire | assign y = a & b; |
always块 | 过程赋值,时序或组合逻辑 | always @(…) begin … end |
wire初始化写法
这段:
wire c = 1'b0;
实际上是简写,它等价于:
wire c;
assign c = 1'b0;
就是说:
- 声明了一根名叫
c
的线。 - 然后用
assign
把1'b0
这个常量连上去。 - 在综合和仿真里,
c
就相当于一直是0。
常量表示法
-
N'bX
格式- N是位宽(多少位)
'b
是进制(b是binary,d是decimal,h是hexadecimal)- X是值
-
例子:
4'b1010 // 4位宽,二进制1010 8'd255 // 8位宽,十进制255 16'h1A2B // 16位宽,16进制1A2B
过程赋值(时序控制)
-
阻塞赋值(=):语句顺序执行。下一条语句执行前,当前语句一定会执行完毕。
【例】:
always @(posedge clk) beginb=ac=b end
-
非阻塞赋值(<=):语句并行执行,常用于时序逻辑(如D触发器)。下一条语句和当前语句是同时进行的。
【例】:
always @(posedge clk)beginb <= a;c <= b; end
不要在同一个
always
块中混用=
和<=
对同一个变量赋值
类型 | 运算符 | 执行顺序 | 典型作用域 | 用法建议 |
---|---|---|---|---|
阻塞赋值 | = | 顺序执行 | initial 、always @* | 组合逻辑、测试初始化等 |
非阻塞赋值 | <= | 并发执行 | always @(posedge ...) | 时序逻辑 |
always块(过程赋值)
过程赋值 是在 initial 或 always 语句块里的赋值 主要用于对寄存器(rag)类型变量进行赋值。
寄存器变量在被赋值后,其值将保持不变,直到重新被赋予新值
- 描述时序逻辑或组合逻辑。
- 过程赋值可以是**阻塞赋值 **或者 非阻塞赋值 。
always 语句块通常带有触发条件
语句块中的语句会重复执行,一个变量不能在多个 always 块中被赋值。
在 always 块中被赋值的只能是 register 型变量
always 语句块即可以用来实现组合逻辑也可以用来实现时序逻辑
基础语法:
always @(sensitivity_list)
begin// 一系列语句
end
其中 sensitivity_list
是敏感列表,表示当列表中的信号发生变化时触发 always
块。
always
块的分类
根据 sensitivity_list
内容不同,分为以下几种类型:
① 组合逻辑(组合逻辑电路建模)
always @(*) // 或 always @(a or b or sel)
begin// 组合逻辑
end
等价于 assign
写的逻辑,常用于使用 if
、case
等构建复杂组合逻辑。
🔸 示例:多路选择器(MUX)
module mux_2to1 (input wire a, b,input wire sel,output reg y
);always @(*) beginif (sel)y = b;elsey = a;end
endmodule
② 时序逻辑(用于寄存器建模)
always @(posedge clk)
begin// 时序逻辑(寄存器)
end
或
always @(posedge clk or negedge rst_n)
beginif (!rst_n)q <= 0;elseq <= d;
end
🔸 示例:D触发器
module dff (input clk,input rst_n,input d,output reg q
);always @(posedge clk or negedge rst_n) beginif (!rst_n)q <= 1'b0;elseq <= d;end
endmodule
③ 时序逻辑 + 状态机
🔸 示例:简单 FSM(两个状态,翻转输出)
module fsm (input clk, rst_n,input in,output reg out
);reg state;always @(posedge clk or negedge rst_n) beginif (!rst_n)state <= 1'b0;elsestate <= ~state;endalways @(*) beginif (state)out = in;elseout = ~in;end
endmodule
项目 | 内容 |
---|---|
@(*) | 自动推导敏感信号,建议用于组合逻辑 |
=(阻塞赋值) | 常用于组合逻辑 |
<=(非阻塞赋值) | 常用于时序逻辑 |
always 不是函数 | 它是对“硬件电路行为”的一种模拟 |
多个 always 可同时使用 | 同时描述不同逻辑块或功能单元 |
类型 | 敏感列表 | 用途 | 赋值类型 |
---|---|---|---|
组合逻辑 | @(*) | 多路选择器、加法器等 | = |
时序逻辑 | @(posedge clk) 或 @(posedge clk or negedge rst) | 寄存器、计数器、状态机 | <= |
状态机建模 | 多个 always 配合使用 | 控制逻辑、序列识别 | 混合 |
另外,不带有敏感信号的 always 语句块会一直执行,因此可用于仿真时钟信号生成
always #10 clk = ~clk;
initial块(只在仿真用)
- 只在仿真(simulation)时使用。沿时间轴只执行一次。
- 主要用途是在仿真的初级阶段对各变量进行初始化
- 在电路上不综合成硬件。
【例】:初始时,a赋0,b赋1。
initial begina = 0;b = 1;
end
组合逻辑 vs 时序逻辑
-
组合逻辑:输出只依赖输入,没有存储状态
assign y = a & b;
或者
always @(a or b) beginy = a & b; end
-
时序逻辑:输出依赖时钟(clk),有状态记忆
always @(posedge clk) beginq <= d; end
关键语法
-
模块定义
module module_name (input a, input b, output y);// 逻辑 endmodule
-
连续赋值
assign y = a & b;
-
过程块
-
always块(常用于描述时序逻辑和组合逻辑)
always @(posedge clk) beginq <= d; end
-
initial块(仅用于仿真初始化)
initial begina = 0;b = 1; end
-
-
**设计层次
结构建模(Structural Modeling)
像搭积木一样,用已有的模块(门级、子模块)实例化并连接,描述硬件结构。
特点:
- 接近硬件电路图结构
- 每个模块都要明确实例化
- 比如用
and
、or
、xor
、not
或用户定义模块来搭建电路
示例(半加器结构建模):
module ha (input a, b, output sum, cout);wire xor_out, and_out;xor u1 (xor_out, a, b); // 门级建模and u2 (and_out, a, b);assign sum = xor_out;assign cout = and_out;
endmodule
也可以这样模块化使用:
module top;wire s, c;ha u0 (.a(1'b1), .b(1'b0), .sum(s), .cout(c)); // 实例化 half-adder
endmodule
📌 优点:
- 电路结构直观,适合底层硬件构建
- 可以重用子模块
⚠️ 缺点:
- 不适合复杂逻辑描述
- 可读性差,模块多时臃肿
数据流建模(Dataflow Modeling)
数据流建模 方式要比结构化描述方式抽象级别要高一些,因为它不在需要清因为它不在需要清晰地刻画出具体的数字电路架构
用连续赋值语句(assign
)表示信号间的数据传递关系,相当于表达电路逻辑函数。
特点:
- 更抽象,强调“数据如何流动”
- 使用
assign
+ 表达式建模逻辑 - 属于组合逻辑
示例(半加器的数据流建模):
module ha (input a, b, output sum, cout);assign sum = a ^ b;assign cout = a & b;
endmodule
📌 优点:
- 简洁易写,适合组合逻辑
- 比结构更抽象,便于阅读
⚠️ 缺点:
- 不适用于时序逻辑(需要时钟的寄存器等)
- 纯数据流的描述方式只适用于小规模的电路设计
行为建模(Behavioral Modeling)
行为描述 是对设计电路的逻辑功能的描述 并不关心设计电路使用哪些元件以及这些元件之间的连接关系(更接近高级语言)
属于高层次的描述方法 类似高级语言可以使用 控制流 和 循环语句 等功能
描述电路行为,比如if-else、case等。
定义:
描述的是“行为”或“功能”,用**过程语句(always
、initial
)**来控制电路行为。更接近写软件代码的风格。
特点:
- 使用
always
块来表示组合/时序逻辑 - 可使用
if
、case
、for
等语句 - 分为组合逻辑建模和时序逻辑建模
示例(时序逻辑建模 - 寄存器):
module dff(input clk, rst, d, output reg q);always @(posedge clk or negedge rst) beginif (!rst)q <= 1'b0;elseq <= d;end
endmodule
📌 优点:
- 抽象度最高,适合复杂控制逻辑(如 FSM)
- 逻辑简洁,代码量少
⚠️ 缺点:
- 与硬件结构关系不直接,难以优化资源
- 更依赖综合工具识别其意图
常用语句
-
if语句
always @(a or b) beginif (a)y = 1;elsey = 0; end
-
case语句
always @(sel or a or b) begincase(sel)0: y = a;1: y = b;default: y = 0;endcase end
-
for循环(通常只用于仿真或者可综合的有限循环)
1.给控制循环次数的变量赋初值
2.判定循环执行条件, 若为假则跳出循环;若为真, 执行指定的语句后, 转到第 3 步
3.修改循环变量的值 返回第 2 步integer i; always @(posedge clk) beginfor (i = 0; i < 8; i = i + 1)mem[i] <= 0; end
-
while循环
执行一条语句直到某个条件不满足 。
首先判断循环执行条件表达式是否为真:
若为真 则执行后面的语句或语句块 直到条件表达式不为真;
若不为真 则其后的语句一次也不被执行
-
repeat 语句
-
forever语句
-
task语句
-
function语句
其他常见概念
-
参数(parameter):定义常量或可配置的参数。
parameter WIDTH = 8; wire [WIDTH-1:0] data;
-
生成块(generate):用于生成结构化重复硬件(如阵列结构)。
genvar i; generatefor (i = 0; i < 4; i = i + 1) beginmy_module u (.in(in[i]), .out(out[i]));end endgenerate
-
仿真专用语句
$display
:打印信息。$monitor
:实时监视信号变化。$finish
:仿真结束。
测试平台(Testbench)
- Testbench是验证设计模块正确性的仿真代码,不综合进电路。
- 包含:
initial
块生成激励(stimulus)- 实例化待测模块(DUT)
- 观察输出(可加断言、检查)
相关文章:
Verilog HDL 语言整理
Verilog HDL 语言 Verilog HDL 简介 硬件描述语言Hardware Description Language是一种用形式化方法即文本形式 来描述和设计数字电路和数字系统的高级模块化语言 Verilog HDL(Hardware Description Language)是一种硬件描述语言,用于建模…...
[250516] OpenAI 升级 ChatGPT:GPT-4.1 及 Mini 版上线!
目录 ChatGPT 迎来重要更新:GPT-4.1 和 GPT-4.1 mini 正式上线用户如何访问新模型?技术亮点与用户体验优化 ChatGPT 迎来重要更新:GPT-4.1 和 GPT-4.1 mini 正式上线 OpenAI 宣布在 ChatGPT 平台正式推出其最新的 AI 模型 GPT-4.1 和 GPT-4.…...
R语言学习--Day03--数据清洗技巧
在一般情况下,我们都是在数据分析的需求前提下去选择使用R语言。而实际上,数据分析里,百分之八十的工作,都是在数据清洗。并不只是我们平时会提到的异常值处理或者是整合格式,更多会涉及到将各种各样的数据整合&#x…...
文件系统交互实现
关于之前的搭建看QT控件文件系统的实现-CSDN博客,接下来是对本程序的功能完善,我想着是这样设计的,打开一个目录以后,鼠标选中一个项可以是目录,也可以是文件,右键可以出现一个菜单选择操作,比如…...
SqlHelper 实现类,支持多数据库,提供异步操作、自动重试、事务、存储过程、分页、缓存等功能。
/// <summary> /// SqlHelper 实现类,支持多数据库,提供异步操作、自动重试、事务、存储过程、分页、缓存等功能。 /// </summary> public class SqlHelper : IDbHelper {private readonly IDbConnectionFactory _connectionFactory;private…...
DevExpressWinForms-RichEditControl-基础应用
RichEditControl-基础应用 在企业级WinForms应用开发中,富文本编辑与文档处理是常见需求。DevExpress WinForms的RichEditControl作为一款功能强大的富文本编辑控件,提供了媲美Microsoft Word的文档处理能力,支持复杂格式编辑、打印导出、界…...
Elasticsearch 索引副本数
作者:来自 Elastic Kofi Bartlett 解释如何配置 number_of_replicas、它的影响以及最佳实践。 更多阅读:Elasticsearch 中的一些重要概念: cluster, node, index, document, shards 及 replica 想获得 Elastic 认证?查看下一期 Elasticsearc…...
RabbitMQ 扇形交换器工作原理详解
目录 一、扇形交换器简介二、扇形交换器工作原理2.1 消息广播机制2.2 路由键的忽略三、代码示例3.1 生产者代码3.2 消费者代码四、实际应用场景4.1 日志收集系统4.2 实时通知系统4.3 事件驱动架构五、总结在 RabbitMQ 的众多交换器类型中,扇形交换器(Fanout Exchange)是一种…...
IDEA中springboot项目中连接docker
具体内容如下: 1、在Linux中安装docker 使用安装命令: apt-get install docker.io 还有一个是更新软件并安装docker: sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io 运行docker systemctl start …...
arxiv等开源外文书数据的获取方式
一、一些基本说明 开放API接口文档:https://info.arxiv.org/help/api/user-manual.html#2-api-quickstart研究领域分类说明文档:https://arxiv.org/category_taxonomy 二、基于url接口方式检索并获取数据 本质是get方式,在url中传检索参数…...
ChatGPT再升级!
近日,OpenAI 正式发布 GPT-4.1 和轻量级版本 GPT-4.1mini,并已全面上线 ChatGPT 平台,迅速引发全球 AI 圈热议,标志着 ChatGPT 在智能化和效率上再登新高峰。 GPT-4.1 是为编程与任务处理优化的高性能模型。相较前作 GPT-4o&#…...
23、电网数据管理与智能分析 - 负载预测模拟 - /能源管理组件/grid-data-smart-analysis
76个工业组件库示例汇总 电网数据管理与智能分析组件 1. 组件概述 本组件旨在模拟一个城市配电网的运行状态,重点关注数据管理、可视化以及基于模拟数据的智能分析,特别是负载预测功能。用户可以通过界面交互式地探索电网拓扑、查看节点状态、控制时间…...
#跟着若城学鸿蒙# web篇-获取定位
前言 在业务中,某些网页上需要获取用户的地理位置,然后按照用户搜索的兴趣点与用户的距离远近进行排序,这就需要h5能够获取到用户的位置。 由于 web 组件基于Chromium M114 版本开发,前端就可以使用navigator.geolocation.getC…...
前端批量下载文件打包为zip
多文件需要一次性下载为zip文件 这是近期遇到的一个需求,本身是多文件上传的,下载时单个下载太慢又繁杂,用户希望能一次性批量下载,就选择了jszip import axios from "axios" import JSZip from "jszip" im…...
Vue百日学习计划Day9-15天详细计划-Gemini版
重要提示: 番茄时钟: 每个番茄钟为25分钟学习,之后休息5分钟。每完成4个番茄钟,进行一次15-30分钟的长休息。灵活性: JavaScript 的概念较多,尤其是 this、原型链、闭包和异步编程,可能需要更多…...
MySQL8.x新特性:与mysql5.x的版本区别
MySQL8.x新特性 1.与mysql5.x的区别:MySQL8.x新特性:与mysql5.x的版本区别-CSDN博客 2.窗口函数(Window Functions):MySQL8.x新特性:窗口函数(Window Functions)-CSDN博客 引言 …...
RabbitMQ 消息模式实战:从简单队列到复杂路由(三)
精准投递:路由模式 路由模式详解 路由模式是 RabbitMQ 中一种功能强大且灵活的消息传递模式,它在发布订阅模式的基础上,引入了路由键(Routing Key)的概念,实现了消息的精准路由和分发 。在路由模式中&…...
STM32 定时器主从模式配置解析
STM32 定时器主从模式配置解析 下面这两行代码是配置STM32定时器主从模式的关键设置 代码功能解析 TIM_SelectInputTrigger(TIM3, TIM_TS_TI2FP2); // 选择从模式输出的触发源 TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset); // 选择从模式1. TIM_SelectInputTrigger(T…...
Leetcode76覆盖最小子串
覆盖最小子串 代码来自b站左程云 class Solution {public String minWindow(String str, String tar) {char[] s str.toCharArray();char[] t tar.toCharArray();int[] cnt new int[256];for (char cha : t) { cnt[cha]--;}int len Integer.MAX_VALUE;int debt t.length…...
Perl语言深度考查:从文本处理到正则表达式的全面掌握
阅读原文 前言:为什么Perl依然值得学习? "这个脚本用Perl写只需要5分钟!"——在当今Python大行其道的时代,你依然能在不少企业的运维部门听到这样的对话。Perl作为一门有着30多年历史的语言,凭借其强大的文…...
idea中Lombok失效的解决方案
Lombok 是一个 Java 库,旨在通过注解简化 Java 代码的编写,减少样板代码,提高开发效率。它通过自动生成常见的代码(如 getter、setter、构造函数等)来减少开发者的手动编码工作。 一般Lombok失效有四步排查方案&#…...
【LeetCode 热题 100】动态规划 系列
📁 70. 爬楼梯 状态标识:爬到第i层楼梯时,有多少种方法。 状态转移方程:dp[i] dp[i-1] dp[i-2],表示从走一步和走两步的方式。 初始化:dp[1] 1 , dp[2] 2。 返回值:dp[n],即走到…...
刷leetcodehot100返航版--双指针5/16
for (int i 0, j 0; i < n; i ) { while (j < i && check(i, j)) j ; // 具体问题的逻辑 } 常见问题分类: (1) 对于一个序列,用两个指针维护一段区间 (2) 对于两个序列,维护某种次序,比如归并排序中…...
DAY24元组和OS模块
元组 元组的特点: 有序,可以重复,这一点和列表一样元组中的元素不能修改,这一点非常重要,深度学习场景中很多参数、形状定义好了确保后续不能被修改。 很多流行的 ML/DL 库(如 TensorFlow, PyTorch, Num…...
CSS:三大特性
文章目录 一、层叠性二、继承性三、优先级 一、层叠性 二、继承性 可以在MDN网站上查看属性是否可以被继承 例如color 三、优先级...
Cross-Site Scripting(XSS)
1. XSS介绍 跨站脚本攻击(Cross-Site Scripting)简称XSS,人们经常将跨站脚本攻击(Cross Site Scripting)缩写为CSS,但这会与层叠样式表(Cascading Style Sheets,CSS)的缩…...
掌握HTML文件上传:从基础到高级技巧
HTML中input标签的上传文件功能详解 一、基础概念 1. 文件上传的基本原理 在Web开发中,文件上传是指将本地计算机中的文件(如图片、文档、视频等)传输到服务器的过程。HTML中的<input type"file">标签是实现这一功能的基础…...
WebRTC中的几个Channel
一、我指的是谁? 以视频为例,常见的有:MediaChannel、VideoMediaChannel、WebRtcVideoChannel、BaseChannel、VideoChannel,那么,为什么要这么多Channel,只写一个叫做SuperChannel行不行(很多程…...
【设计模式】- 行为型模式1
模板方法模式 定义了一个操作中的算法骨架,将算法的一些步骤推迟到子类,使得子类可以不改变该算法结构的情况下重定义该算法的某些步骤 【主要角色】: 抽象类:给出一个算法的轮廓和骨架(包括一个模板方法 和 若干基…...
容器化-k8s-使用和部署
一、K8s 使用 1、基本概念 集群: 由 master 节点和多个 slaver 节点组成,是 K8s 的运行基础。节点: 可以是物理机或虚拟机,是 K8s 集群的工作单元,运行容器化应用。Pod: K8s 中最小的部署单元,一个 Pod 可以包含一个或多个紧密相关的容器,这些容器共享网络和存储资源。…...
黑马k8s(九)
1.Pod-生命周期概述 2.Pod生命周期-创建和终止 3.Pod生命周期-初始化容器...
Android trace中CPU的RenderThread与GPU
Android trace中CPU的RenderThread与GPU RenderThread是系统的GPU绘制线程,GPU渲染就是通常所谓的硬件加速,如果应用关闭硬件加速,就没有了RenderThread,只有UI Thread,即Android主线程。 Android GPU渲染SurfaceFlin…...
测试工程师如何学会Kubernetes(k8s)容器知识
Kubernetes(K8s)作为云原生时代的关键技术之一,对于运维工程师、开发工程师以及测试工程师来说,都是一门需要掌握的重要技术。作为一名软件测试工程师,学习Kubernetes是一个有助于提升自动化测试、容器化测试以及云原生应用测试能力的重要过程…...
接触感知 钳位电路分析
以下是NG板接触感知电路的原理图。两极分别为P3和P4S,电压值P4S < P3。 电路结构分两部分,第一部分对输入电压进行分压钳位。后级电路使用LM113比较器芯片进行电压比较,输出ST接触感知信号。 钳位电路输出特性分析 输出电压变化趋势&a…...
码蹄集——圆包含
MT1181 圆包含 输入2个圆的圆心的坐标值(x,y)和半径,判断断一个圆是否完全包含另一个圆,输出YES或者NO。另:内切不算做完全包含。 格式 输入格式:输入整型,空格分隔。 每行输入一组…...
ConcurrentSkipListMap的深入学习
目录 1、介绍 1.1、线程安全 1.2、有序性 1.3、跳表数据结构 1.4、API 提供的功能 1.5、高效性 1.6、应用场景 2、数据结构 2.1、跳表(Skip List) 2.2、节点类型: 1.Node 2.Index 3.HeadIndex 2.3、特点 3、选择层级 3.1、随…...
ProfibusDP主站转modbusTCP网关接DP从站网关通讯案例
ProfibusDP主站转modbusTCP网关接DP从站网关通讯案例 在工业自动化领域,Profibus DP和Modbus TCP是两种常见的通信协议。Profibus DP广泛应用于过程自动化、工厂自动化等场景,而Modbus TCP则常见于楼宇自动化、能源管理等领域。由于设备和系统之间往往存…...
第一次做逆向
题目来源:ctf.show 1、下载附件,发现一个exe和一个txt文件 看看病毒加没加壳,发现没加那就直接放IDA 放到IDA找到main主函数,按F5反编译工具就把他还原成类似C语言的代码 然后我们看逻辑,将flag.txt文件的内容进行加…...
【项目】自主实现HTTP服务器:从Socket到CGI全流程解析
00 引言 在构建高效、可扩展的网络应用时,理解HTTP服务器的底层原理是一项必不可少的技能。现代浏览器与移动应用大量依赖HTTP协议完成前后端通信,而这一过程的背后,是由网络套接字驱动的请求解析、响应构建、数据传输等一系列机制所支撑…...
AI最新资讯,GPT4.1加入网页端、Claude 3.7 Sonnet携“极限推理”发布在即
目录 一、GPT4.1加入网页端二、Claude 3.7 Sonnet携“极限推理”发布在即三、这项功能的关键特点1、双模式操作2、可视化思考过程3、可控的思考预算4、性能提升 四、Claude制作SVG图像1、Prompt提示词模板2、demo:技术路线图**Prompt提示词:**3、甘特图4…...
Android 中使用通知(Kotlin 版)
1. 前置条件 Android Studio:确保使用最新版本(2023.3.1)目标 API:最低 API 21,兼容 Android 8.0(渠道)和 13(权限)依赖库:使用 WorkManager 和 Notificatio…...
在 Kotlin 中,什么是解构,如何使用?
在 Kotlin 中,解构是一种语法糖,允许将一个对象分解为多个独立的变量。 这种特性可以让代码更简洁、易读,尤其适用于处理数据类、集合(如 Pair、Map)或其他结构化数据。 1 解构的核心概念 解构通过定义 componentN()…...
apisix透传客户端真实IP(real-ip插件)
文章目录 apisix透传客户端真实IP需求和背景apisix real-ip插件为什么需要 trusted_addresses?安全架构的最佳实践 示例场景apisix界面配置 apisix透传客户端真实IP 需求和背景 当 APISIX 前端有其他反向代理(如 Nginx、HAProxy、云厂商的 LBÿ…...
初学者如何用 Python 写第一个爬虫?
初学者如何用 Python 写第一个爬虫? 一、爬虫的基本概念 (一)爬虫的定义 爬虫,英文名为 Web Crawler,也被叫做网络蜘蛛、网络机器人。想象一下,有一个勤劳的小蜘蛛,在互联网这个巨大的蜘蛛网中…...
基于MNIST数据集的手写数字识别(CNN)
目录 一,模型训练 1.1 数据集介绍 1.2 CNN模型层结构 1.3 定义CNN模型 1.4 神经网络的前向传播过程 1.5 数据预处理 1.6 加载数据 1.7 初始化 1.8 模型训练过程 1.9 保存模型 二,模型测试 2.1 定义与训练时相同的CNN模型架构 2.2 图像的预处…...
QT6 源(103)篇三:阅读与注释 QPlainTextEdit,给出源代码
(10)关于文本处理的内容很多,来不及全面阅读、思考与整理。先给出类的继承图: (11)本源代码来自于头文件 qplaintextedit . h : #ifndef QPLAINTEXTEDIT_H #define QPLAINTEXTEDIT_H#include &…...
yocto5.2开发任务手册-7 升级配方
此文为机器辅助翻译,仅供个人学习使用,如有翻译不当之处欢迎指正 7 升级配方 随着时间的推移,上游开发者会为图层配方构建的软件发布新版本。建议使配方保持与上游版本发布同步更新。 虽然有多种升级配方的方法,但您可能需要先…...
LangPDF: Empowering Your PDFs with Intelligent Language Processing
LangPDF: Empowering Your PDFs with Intelligent Language Processing Unlock Global Communication: AI-Powered PDF Translation and Beyond In an interconnected world, seamless multilingual document management is not just an advantage—it’s a necessity. LangP…...
DDS(数据分发服务) 和 P2P(点对点网络) 的详细对比
1. 核心特性对比 维度 DDS P2P 实时性 微秒级延迟,支持硬实时(如自动驾驶) 毫秒至秒级,依赖网络环境(如文件传输) 架构 去中心化发布/订阅模型,节点自主发现 完全去中心化,节…...
TC8:SOMEIP_ETS_029-030
SOMEIP_ETS_029: echoUINT8Array16Bitlength 目的 检查当method echoUINT8Array16BitLength的参数中长度字段为16bit时,SOME/IP协议层是否能对参数进行序列化和反序列化。 对于可变长度的数组而言,必须用长度字段表示数组长度。否则接收方无法判断有效数据。 SOMEIP_ETS_02…...