跳转到内容

可编程逻辑/Verilog 运算符

来自维基教科书,开放的书籍,开放的世界

本页将讨论一些 Verilog 运算符。

算术运算符

[编辑 | 编辑源代码]

算术运算符如下

+ (加法)
- (减法)
* (乘法)
/ (除法)
% (模运算或余数)。

实际上,除法和模运算符通常仅在仿真中可用,而不是在综合中可用。除法是一个特别复杂的运算,大多数可编程芯片没有专门的除法模块。

逻辑运算符

[编辑 | 编辑源代码]

有许多逻辑运算符。逻辑运算符作用于整个值(多个位),并将“零”值视为“假”,并将“非零”值视为“真”。

! (逻辑非)
&& (逻辑与)
|| (逻辑或)

归约运算符是

  • ! 非
  • && 与
  • || 或

Verilog 会将整个数字转换为 1(如果包含非零位)或 0(如果仅包含零),然后执行等效的位运算。因此,答案也是一位。

示例

!0000 = ~0 = 1
!1101 = ~1 = 0
!1000 = ~1 = 0

!(任何非零二进制数) = ~1 = 0

0000 && 1101 = 0 & 1 = 0
0010 && 1101 = 1 & 1 = 1

0000 || 0110 = 0 | 1 = 1
0000 || 0000 = 0 | 0 = 0

位运算符

[编辑 | 编辑源代码]

有许多位运算符,可以在总线中的每个单独位上执行布尔运算。

~ (位非)
& (位与)
| (位或)
^ (位异或)
~^ (位异或非)

示例:全加器

[编辑 | 编辑源代码]
右侧的图示给出了一个常见的 1 位全加器电路。我们可以使用位运算符在 Verilog 中构建此电路
module FullAdder(a, b, s, cin, cout);
  input a, b, cin;
  output s, cout;

  wire axorb;
  wor partial;

  assign axorb = a ^ b;
  assign s = axorb ^ cin;
  assign partial = (axorb & cin);
  assign partial = (a & b);
  assign cout = partial;
endmodule

这将有助于说明这些位运算是如何执行的。

赋值运算符

[编辑 | 编辑源代码]

有三个赋值运算符,每个运算符都执行不同的任务,并且与不同的数据类型一起使用

assign (连续赋值)
<= (非阻塞赋值)
= (阻塞赋值)

连续赋值通常与没有存储器的线和其他结构一起使用。连续赋值是连续发生的,并且与所有其他计算任务并行进行。连续赋值的顺序或它们在代码中的位置无关紧要。

非阻塞赋值是一次性发生的赋值,但可以同时发生。这些赋值通常与寄存器和整数数据类型以及其他具有存储器的其他数据类型一起使用。以下两个带有非阻塞赋值的代码片段是等效的

a <= a + b;
b <= b + a;

b <= b + a;
a <= a + b;

单个代码块中的所有非阻塞赋值同时发生。它们只发生一次,并且在执行操作之前读取所有此类赋值的输入值(这需要在综合中使用额外的锁存器结构)。

阻塞赋值也用于寄存器和整数(以及其他存储器数据类型)。阻塞赋值按顺序发生,并且赋值后的代码只有在赋值发生后才会执行。

移位和旋转

[编辑 | 编辑源代码]

如果要右移,则分配 shr = a >> 1 // 将 a 右移 1 位。

例如 a=8'b10011011 则 x=8'b01001101

分配 shr = a >> 2 // 将 a 右移 2 位。

例如 a=8'b10010101 则 x=8'b00100101

如果要左移,则分配 shl = a << 1 // 将 a 左移 1 位。

例如 a=8'b10011011 则 x=8'b00110110

分配 shl = a << 2 // 将 a 左移 2 位。

例如 a=8'b10011011 则 x=8'b01101100

连接和复制

[编辑 | 编辑源代码]

组合 2 个或多个操作数

归约运算符

[编辑 | 编辑源代码]

这些与上面的位运算相同。

条件运算符

[编辑 | 编辑源代码]
<condition> ? <if true> : <else>;

如果条件为真,则将使用 <if true> 的值,否则将使用 <else> 的值。示例

assign EDB = ram_rd_en ? ram[EAB[9:0]] : 32'bz;

如果 ram_rd_en 为真,则 ram[EAB[9:0]] 将被分配给 EDB。

运算符优先级

[编辑 | 编辑源代码]
华夏公益教科书