Programmable Logic/Verilog Operators
This page is going to talk about some of the verilog operators.
The arithmetic operators are as follows:
- + (addition)
- - (subtraction)
- * (multiplication)
- / (division)
- % (modulus, or remainder).
In practice, the division and modulus operators are typically only usable in simulation, not synthesis. Division is a particularly complicated operation, and most programmable chips do not have dedicated divider modules.
There are a number of logical operators. Logical operators act on an entire value (multiple bits), and treat the values of "zero" as being "false", and "non-zero" as being "true".
- ! (Logical NOT)
- && (Logical AND)
- || (Logical OR)
The reduction operators are
- ! NOT
- && AND
- || OR
What happens is that Verilog converts the whole number into either a 1 (if it contains a nonzero bit) or 0 (if it only contains nonzero bits), then performs the equivalent bitwise operation. Thus, the answer is also one bit.
!0000 = ~0 = 1
!1101 = ~1 = 0
!1000 = ~1 = 0
!(any nonzero binary number) = ~1 = 0
0000 && 1101 = 0 & 1 = 0
0010 && 1101 = 1 & 1 = 1
0000 || 0110 = 0 | 1 = 1
0000 || 0000 = 0 | 0 = 0
There are a number of bitwise operators to perform boolean operations on each individual bit in a bus.
- ~ (Bitwise NOT)
- & (Bitwise AND)
- | (Bitwise OR)
- ^ (Bitwise XOR)
- ~^ (Bitwise XNOR)
Example: Full Adder
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
This should help to demonstrate how these bitwise operations are performed.
there are three assignment operators, each of which performs different tasks, and are used with different data types:
- assign (continuous assignment)
- <= (non-blocking assignment)
- = (blocking assignment)
The continuous assignment is typically used with wires and other structures that do not have memory. A continuous assignment is happening continuously and in parallel to all other computational tasks. The order of continuous assignments, or their location in the code do not matter.
Non-blocking assignments are assignments that occur once, but which can all happen at the same time. These assignments are typically used with registers and integer data types, and other data types with memory. The following two code snippets with non-blocking assignments are equivalent:
a <= a + b; b <= b + a;
b <= b + a; a <= a + b;
All non-blocking assignments in a single code block occur simultaneously. They happen only once, and the input values for all such assignments are read before the operation takes place (which requires the use of additional latch structures in synthesis).
Blocking assignments are also used with registers and integers (and other memory data types). Blocking assignments occur sequentially, and the code after the assignment will not execute until the assignment has occured.
Shift and Rotate
Concatenation and Replication
These are the same as the bitwise operations above.
<condition> ? <if true> : <else>;
If the Condition is true, the value of <if true> will be taken, otherwise the value of <else> will be taken. Example:
assign EDB = ram_rd_en ? ram[EAB[9:0]] : 32'bz;
ram[EAB[9:0]] will be assigned to EDB in case ram_rd_en is true.