示例一段最初的结构
module mux2_1
(
input wire [0:0] in_1, //输入信号1
input wire [0:0] in_2, //输入信号2
input wire [0:0] sel, //选通信号
output reg out
);
always@(*) //等效为 always@(sel,in_1,in_2)
if(sel==1'b1)
out=in_1;
else
out=in_2;
endmodule
->verilog基础
1.认识module和endmodule
module和endmodule是定义硬件模块的核心语法结构- 通过
module封装代码,实现功能模块化,结束以endmodule。
module 名称
(
代码部分(涉及的输入输出设置)
);
代码(逻辑)部分
endmodule
- 注意:一个Verilog文件可以包含多个
module吗?可以,但不推荐。通常一个文件只定义一个module,便于管理。
2.wire和reg(Verilog中两种数据类型)
- wire:表示电路中的物理连线,用于连接模块或逻辑元件(一般是直接的简单的逻辑单元)(不可存储值)
- reg :不属于寄存器(多用于复杂的逻辑处理)(可存储值)
| 特性 | wire | reg |
|---|---|---|
| 赋值方式 | assign或模块端口连接 | always或initial块 |
| 默认状态 | z(高阻态) | x(未知状态) |
3.assign和always
- 在Verilog中,
assign和always是两种不同的赋值方式,分别对应组合逻辑和时序逻辑/复杂逻辑的实现。对比:
| 特性 | assign | always |
|---|---|---|
| 赋值方式 | assign 信号 = 表达式; | always @(敏感列表) begin ... end |
| 赋值触发条件 | 右侧表达式任何变化立即更新 | 敏感列表中的信号变化(组合逻辑)或事件(时序逻辑)触发 |
| 代码位置 | 模块内部任意位置 | 必须位于过程块(always或initial)内 |
| 使用场景 | 简单逻辑(如门电路、多路选择器) | 复杂逻辑(如if-else、case多分支) |
| 赋值对象 | wire类型 | reg类型 |
- 个人的理解:wire配合assign使用,此处应用于简单的逻辑赋值,比如直接给定信号。而reg配合always使用,应用于具有复杂逻辑的场景
- assign是在芯片上直接实现物理上的连接,而always是进行触发
- 对于always句式中的敏感列表:
//敏感列表的核心作用:
//敏感列表的作用是指定触发条件,当列表中的信号满足特定变化时,`always` 块内的代码会被执行。
// **语法**:`always @(a, b, c)` 或 `always @(*)`(自动推断敏感信号)。```
//方式1: 显式列出所有输入信号(易遗漏,不推荐!)
always @(a, b, sel) begin
out = sel ? a : b;
end
//方式2: 使用 @(*) 自动推断所有输入信号(推荐!)
always @(*) begin
out = sel ? a : b;
end
仿真文件
示例一段最初仿真文件
`timescale 1ns/1ns
module tb_mux2_1(); //模块定义
reg in_1; //信号声明
reg in_2;
reg sel ;
wire out ;
initial //初始化
begin
in_1 <= 1'b0;
in_2 <= 1'b0;
sel <= 1'b0;
end
always #10 in_1 <= {$random} % 2; //输入信号生成
always #10 in_2 <= {$random} % 2;
always #10 sel <= {$random} % 2;
initial begin //初始化
$timeformat(-9,0,"ns",6);
$monitor("@time %t:in_1=%b in_2=%b sel=%b out=%b",$time,in_1,in_2,sel,out);
end
mux2_1 mux2_1_inst //实例化
(
.in_1(in_1), //输入信号
.in_2(in_2),
.sel(sel),
.out (out)
);
endmodule
1.定义模块
-说明:
- 测试平台没有输入输出端口(空括号 `()`),因为它是仿真的顶层模块。
- 通常以 `tb_` 前缀命名测试平台,表明其测试性质。
2.信号声明
- 信号包含原模块需要进行测试的信号(可根据类型进行修改,以本测试文件为主体面向测试对象)
3.初始化
- 初始化使用
initial
//initial语法结构
//单个initial在整体代码中只执行一次
//复杂赋值:
initial begin
语句
end
//简单赋值:
initial 语句
- 对于
initial begin //初始化
$timeformat(-9,0,"ns",6);
$monitor("@time %t:in_1=%b in_2=%b sel=%b out=%b",$time,in_1,in_2,sel,out);
end
- $timeformat(-9,0,"ns",6); //(ns,保留小数点后0位,时间后缀字符,最小显示六位数)
- $monitor句式中- 触发条件:当被监测的信号(如
in1,in2,sel,out)发生改变时,自动打印信息。 - $monitor只需调用一次,即可在整个仿真过程中生效。
4.实例化
- 在Verilog中,实例化模块时,模块名必须与被测文件中定义的模块名完全相同,而实例名可以自定义,但需符合命名规则。
- 实例名的位置在模块实例化语句中明确指定:
模块名 实例名 (
.端口1 (连接信号1),
.端口2 (连接信号2),
// ...
);
- 同
模块名 实例名 (
.子模块端口1 (父模块信号1),
.子模块端口2 (父模块信号2),
// ...
);
注:学习过程个人理解