Programmable Logic/Verilog Operators

This page is going to talk about some of the verilog operators.

Arithmetic 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.

↑Jump back a section

Logical Operators

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.

Examples:

!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

↑Jump back a section

Bitwise Operators

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

Full-adder.svg
A common 1-bit full adder circuit is given by the diagram at right. We can use the bitwise operators to construct this circuit in 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

This should help to demonstrate how these bitwise operations are performed.

↑Jump back a section

Assignment Operators

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;

and

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.

↑Jump back a section

Shift and Rotate

↑Jump back a section

Concatenation and Replication

↑Jump back a section

Reduction Operators

These are the same as the bitwise operations above.

↑Jump back a section

Conditional Operator

<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.

↑Jump back a section

Operator Precedence

↑Jump back a section
Last modified on 24 October 2012, at 01:13