显示系统任务主要用于显示信息和调试消息,以跟踪日志文件中的模拟流程,也有助于更快地调试。有不同组的显示任务和格式,它们可以打印值。 显示/写入任务 语法 $display 和 $write 按照参数在参数列表中出现的顺序显示参数。 $display(<list_of_arguments>); $write(<list_of_arguments>); $write 不附加换行符 到其字符串的末尾,而 $display 从下面的例子中可以看出。 示例 module tb; initial begin $display (Thi
时钟是构建数字电路的基础,因为它允许不同的模块相互同步。 时钟的属性 数字时钟的关键属性是它的频率 决定时钟周期 , 它的占空比 和时钟相位 相对于其他时钟。 时钟周期 频率表示在某个时间段内可以找到多少个周期。因此时钟周期是完成 1 个周期所用的时间。 时钟占空比 时钟与其时间周期相比处于高电平的时间量定义了占空比。 时钟相位 如果一个时钟的一个周期可以看成一个360度的完整圆,那么另一个时钟可以相对放置在圆的不同位置,占据不同的相位。例如,同一时间周期的另一个时钟右移了其周期的1/4,可以说是相差90度。 Verilog 时钟发生器 模拟需要在给定的时间尺度上运行,该
Verilog 设计和测试平台通常有很多行代码,包括 always 或 initial 块、连续赋值和其他在模拟过程中在不同时间变得活跃的程序语句。 Verilog 模型中信号值的每一次变化都被视为一个更新事件 .以及always等流程 和 assign 对这些更新事件敏感的块以任意顺序进行评估,称为评估事件 .由于这些事件可能发生在不同的时间,因此可以通过将它们安排到 事件队列 来更好地管理它们并确保它们的正确执行顺序 按模拟时间排列。 module tb; reg a, b, c; wire d; // always is a process that gets ev
Verilog 模拟取决于如何定义时间,因为模拟器需要知道 #1 在时间方面的含义。 `timescale 编译器指令为它后面的模块指定时间单位和精度。 语法 `timescale <time_unit>/<time_precision> // Example `timescale 1ns/1ps `timescale 10us/100ns `timescale 10ns/1ns 时间单位 是延迟和仿真时间的测量,而 time_precision 指定延迟值在用于模拟之前如何四舍五入。 使用以下时间尺度结构在同一设计中使用不同的时间单位。请记住,设
Verilog 是一种硬件描述语言,设计人员无需模拟其 RTL 设计即可将其转换为逻辑门。那么需要模拟什么? 仿真是一种在不同时间对设计应用不同输入激励以检查 RTL 代码是否按照预期方式运行的技术。从本质上讲,仿真是一种被广泛采用的技术,用于验证设计的稳健性。它也类似于制造芯片在现实世界中的使用方式以及它对不同输入的反应方式。 例如,上面的设计表示一个上升沿检测器,其输入时钟和信号以周期性间隔进行评估以找到输出 pe 如图所示。仿真让我们可以查看相关信号的时序图,从而了解 Verilog 中的设计描述实际上是如何表现的。 有几家 EDA 公司开发模拟器 能够计算出设计中各种输
标准 Verilog 原语,例如 nand 和 not 可能并不总是容易或足以表示复杂的逻辑。称为 UDP 的新原始元素 或用户定义的原语 可以定义为对组合逻辑或顺序逻辑进行建模。 所有 UDP 都只有一个输出,可以是 0、1 或 X,而不是 Z(不支持)。任何具有值 Z 的输入都将被视为 X。 Verilog UDP 符号 Verilog 用户定义的原语可以写在与 module 相同的级别 定义,但从不在 module 之间 和 endmodule .它们可以有多个输入端口,但始终只有一个输出端口,双向端口无效。所有端口信号都必须是标量,这意味着它们必须是 1 位宽。 硬件行为被描述为
Verilog 还提供对晶体管级建模的支持,尽管如今设计人员很少使用它,因为电路的复杂性要求他们转向更高级别的抽象,而不是使用开关级建模。 NMOS/PMOS module des (input d, ctrl, output outn, outp); nmos (outn, d, ctrl); pmos (outp, d, ctrl); endmodule module tb; reg d, ctrl; wire outn, outp; des u0 (.d(d), .ctrl(ctrl), .outn(outn), .o
数字元素是二进制实体,只能保存两个值中的任何一个 - 0 和 1。但是,从 0 到 1 和从 1 到 0 的转换有一个转换延迟,每个门元素都将值从输入传播到其输出。 例如,如果两个输入都变为 1,则双输入 AND 门必须将输出切换为 1,当其任何输入变为 0 时,必须将输出切换回 0。这些门和引脚到引脚延迟可以在实例化逻辑原语时在 Verilog 中指定。 上升、下降和关闭延迟 门的输出从某个值变为 1 所需的时间称为 上升 延迟。门的输出从某个值变为 0 所需的时间称为 fall 延迟。门的输出从某个值变为高阻抗所需的时间称为关闭 延迟。 这些延迟实际上适用于任何信号,因为它们都可以
一些主要的内置原语在上一篇文章中已经讨论过,如果能看到一些使用简单 and 的实际例子会很好 , nor 和 not 大门。 请注意,为了使用门编写 Verilog 代码,您必须知道如何连接元素。这与行为描述非常不同,在这种情况下,元素的选择和连接由综合工具决定。 示例 #1:2x1 多路复用器 模块的输出必须是 wire 类型 为了连接一个原语的输出端口。 module mux_2x1 ( input a, b, sel, output out); wire sel_n; wire out_0; not (sel_n, sel); and (out_0
大多数数字设计都是在 RTL 等更高的抽象层次上完成的,尽管有时通过使用 和 等组合元素在较低层次上构建更小的确定性电路变得很直观 和或 .在此级别完成的建模通常称为门级建模 因为它涉及到门 并且在硬件原理图和 Verilog 代码之间具有一对一的关系。 Verilog 支持一些称为 primitives 的基本逻辑门 因为它们可以像模块一样被实例化,因为它们已经被预定义了。 与/或/异或门 这些原语实现了 AND 和一个 OR 门,它接受许多标量输入并提供单个标量输出。这些原语的参数列表中的第一个终端是输出,每当任何输入发生变化时都会更新。 module gates ( inp
大多数编程语言都有一个特征,称为 scope 它定义了某些代码部分对变量和方法的可见性。范围定义了一个命名空间 避免同一命名空间内不同对象名称之间的冲突。 Verilog 为模块、函数、任务、命名块和生成块定义了一个新的范围。 module tb; reg signal; // Another variable cannot be declared with // an already existing name in the same scope reg signal; // However, the name signal can be reused insi
Verilog 延迟语句可以在赋值运算符的左侧或右侧指定延迟。 任务间延迟 // Delay is specified on the left side #<delay> <LHS> = <RHS> 内部分配 delay 语句在赋值运算符的 LHS 上具有延迟值。这表明语句本身是在之后执行的 延迟到期,是最常用的延迟控制形式。 module tb; reg a, b, c, q; initial begin $monitor([%0t] a=%0b b=%0b c=%0b q=%0b, $time, a, b, c,
Verilog中有两种时序控制——delay 和事件 表达式。 延迟 控制只是在模拟器遇到语句和实际执行语句之间添加延迟的一种方式。 事件表达式 允许将语句延迟到某个模拟事件发生,该事件可以是网络或变量上的值变化(隐式事件 ) 或在另一个过程中触发的显式命名事件。 可以通过以下方法之一来提前模拟时间。 已被建模为具有内部延迟的门和网络也会提前仿真时间。 延迟控制 如果延迟表达式计算为未知或高阻抗值,它将被解释为零延迟。如果计算结果为负值,则将其解释为与时间变量大小相同的 2 的补码无符号整数。 `timescale 1ns/1psmodule tb; reg [3:0] a,
Verilog 支持一些编译器指令,这些指令基本上指导编译器以某种方式处理代码。例如,部分代码可能代表某个功能的实现,如果不使用该功能,则应该有某种方式不将代码包含在设计中。 这可以通过 conditional 解决 编译,设计者可以将代码包装在编译器指令中,这些指令告诉编译器在设置给定的命名标志时包含或排除要编译的代码。 语法 Verilog `ifdef可以实现条件编译 和 `ifndef 关键词。这些关键字可以出现在设计中的任何位置,并且可以嵌套在另一个里面。 关键字 `ifdef 只是告诉编译器包含这段代码,直到下一个 `else 或 `endif 如果给定的名为 FLAG 的宏
参数是允许以不同规范重用模块的 Verilog 结构。例如,可以对 4 位加法器进行参数化以接受位数的值,并且可以在模块实例化期间传入新的参数值。因此,N 位加法器可以变成 4 位、8 位或 16 位加法器。它们就像在函数调用期间传入的函数的参数。 parameter MSB = 7; // MSB is a parameter with a constant value 7 parameter REAL = 4.5; // REAL holds a real number parameter FIFO_DEPT
function 旨在对输入进行一些处理并返回单个值,而 task 更通用,可以计算多个结果值并使用 output 返回它们 和 inout 类型参数。任务可以包含模拟耗时的元素,例如 @ , 摆姿势 和别的。 语法 任务不需要在端口列表中有一组参数,在这种情况下它可以保持为空。 // Style 1 task [name]; input [port_list]; inout [port_list]; output [port_list]; begin [statements] end endtask // Style 2 task [n
我们经常发现某些代码片段在 RTL 中重复并被多次调用。它们大多不消耗模拟时间,并且可能涉及需要使用不同数据值完成的复杂计算。在这种情况下,我们可以声明一个 function 并将重复的代码放在函数内并让它返回结果。这将大大减少 RTL 中的行数,因为您现在需要做的就是执行 函数调用 并传递需要执行计算的数据。其实这和C中的函数很相似。 函数的目的是返回要在表达式中使用的值。函数定义总是以关键字 function 开头 后面是返回类型、名称和括在括号中的端口列表。 Verilog在找到endfunction时就知道函数定义结束了 关键词。请注意,函数应至少声明一个输入,返回类型将为 void
case 语句检查给定表达式是否与列表中的其他表达式之一匹配并相应地分支。它通常用于实现多路复用器。如果要检查的条件很多并且会综合到优先级编码器而不是多路复用器中,则 if-else 构造可能不适合。 语法 Verilog 案例 语句以 case 开头 关键字并以 endcase 结尾 关键词。括号内的表达式将只计算一次,并按照它们的编写顺序与备选列表进行比较,并执行备选与给定表达式匹配的语句。多个语句的块必须分组并在 begin 内 和 end . // Here expression should match one of the items (item 1,2,3 or 4
一个for 循环是软件中使用最广泛的循环,但它主要用于复制 Verilog 中的硬件逻辑。 for 背后的理念 循环是迭代循环内给定的一组语句,只要给定条件为真。这与 while 非常相似 循环,但更多地用于迭代器可用且条件取决于该迭代器的值的上下文中。 语法 for (<initial_condition>; <condition>; <step_assignment>) begin // Statements end 关键字 for 用于指定这种类型的循环,分为三个部分: 指定信号初始值的初始条件 检查给定条件是否为真 为下一
如果没有条件语句和其他控制逻辑流的方法,就无法实现硬件行为。 Verilog 有一套控制流块和机制来实现这一点。 如果-否则-如果 这个条件语句 用于决定是否应该执行某些语句。这与 if-else-if 非常相似 C 中的语句。如果表达式的计算结果为真,则将执行第一条语句。如果表达式计算结果为 false 并且如果 else 部分存在,else 部分将被执行。 语法 // if statement without else part if (expression) [statement] // if statment with an else part if (expres
Verilog