可编程逻辑/Verilog 数据类型
Verilog 有四种值,任何信号都可以取这些值
值 | 意义 |
---|---|
0 | 二进制值为 0。对应于零伏。 |
1 | 二进制值为 1。根据底层制造工艺,可能对应于 +5V、+3.3V 或其他一些正值。 |
x | “无关紧要”的值。x值既不是 0 也不是 1,应将其视为未知值。 |
z | 当控制信号未被断言时,来自三态缓冲器的阻抗值很高。对应于未连接或“浮动”的导线。 |
在实践中,x和z值难以在综合中使用,通常应避免使用,除非有非常具体的理由使用它们。
线,用 wire 关键字指定,表示从一个模块到另一个模块的物理线,承载电信号。线不存储任何数据,必须不断提供值,否则它们将不包含值。线不能是阻塞或顺序赋值的目标。
线有三种类型
类型 | 功能 |
---|---|
线 | 这些线将简单数据从一个端口传输到另一个端口。 |
wor | 这些线是对应用于该线的所有输入数据值的逻辑或运算。这些综合为具有多个输入端口的或门。 |
wand | 这些线是对应用于该线的所有输入数据值的逻辑与运算。这些综合为具有多个输入端口的与门。 |
线可以使用以下方法分配值assign关键字。所有assign声明被认为是并发且持续运行的。
在以下情况下,a 的值取决于 b 和 c 的值。b 或 c 的任何变化都会导致 a 的值自动且立即发生变化。
wire a, b, c; assign a = b & c;
使用assign关键字不能进行循环赋值,因为这会产生一个连续循环。在以下示例中,a 的值未定义,因为它依赖于自身通过组合逻辑(即异步、连续运行)传递。
wire a, b; assign a = a | b;
对于 wand 和 wor 数据类型,对该线的所有赋值都被认为是逻辑门的端口。例如,以下代码
wire a, b, c; wor x; assign x = a; assign x = b; assign x = c;
等效于此代码
wire a, b, c, x assign x = (a | b | c);
虽然使用wor或wand可能看起来工作量更大,但它们可以极大地简化一些复杂的逻辑操作,并且可以帮助提高代码的可读性。
检查语法
一个寄存器,用 reg 关键字表示,是一个内存存储位置。寄存器存储值而无需持续赋值,但它们必须使用阻塞或顺序赋值手动更新。寄存器值都被视为无符号值,任何将值扩展到更大寄存器的操作都不会导致逻辑符号扩展。
寄存器可与“=”和“<="
b <= y + z;
使用“=”运算符的赋值是阻塞赋值,它们将按顺序执行。使用“<=”运算符的赋值是非阻塞的。特定代码块中的所有非阻塞赋值将同时开始。该块将不会终止,直到所有非阻塞赋值完成。
向量是变量的集合,用相同名称但不同的下标表示,例如:[2:0]i;
assign y=i[2]^i[1]; assign y=i[1]^i[0]; endmodule
整数,用 integer 关键字指定,在功能上类似于寄存器,只是它们被隐式视为有符号数。整数将在赋值时进行逻辑符号扩展。
实数可以用以下两种形式之一指定。
- 十进制表示法:此形式的数字示例包括:2.0、5.678、1154.76、0.1
- 科学计数法:此形式的数字示例包括
23_5.1e2 23510.0 (underscores are ignored) 3.6e2 360.0 (e and E are the same) 5E-4 0.0005
参数类似于 C 中的预定义标识符。它用于声明全局常量
example: parameter u=8; local parameter is used to declare single digit
寄存器和线类型可以指定为多位总线。此赋值是在使用 [] 运算符的变量声明中进行的。例如
wire [5:0] a;
这将线 a 声明为 6 根线的总线,其中位 5 (a[5]) 是 MSB,位 0 (a[0]) 是 LSB。LSB 的位数必须低于 MSB 的位数,但不必为零。
总线中的各个线或寄存器可以直接与之交互,并且可以操纵总线的子集。给定以下声明
wire [15:0] a;
以下代码将为总线的位 14 设置一个值
assign a[14] = 1'b1;
以下代码将为总线的低 8 位分配一个值
assign a[7:0] = 8'b01101101;
同样,我们也可以从总线的某一部分读取。以下代码将 8 位总线 b 分配为 16 位总线 a 的高 8 位
wire [15:0] a; wire [7:0] b; assign b[7:0] = a[15:8];
部分选择运算符让编译器根据起点和数据宽度大小计算范围;
wire [15:0] a; wire [7:0] b; assign b[7:0] = a[15:8]; assign b[7:0] = a[8+:8]; // equivalent assign b[7:0] = a[15-:8]; // equivalent