# Combinatorial Verilog¶

Al Wood

## Wires and net declarations¶

```wire a, b;
wire y;
wire [1:0] a2, b2;
```

Inputs and outputs to and from modules are automatically declared as wires, unless they are subsequently declared as registers (next talk).

```module mymod (
input  [1:0] y2;
output [2:0] y3;
)
```

## Logic bitwise primitives¶

Negation

```assign y = ~a;
```

AND, OR and exclusive-OR gates

```assign y = a & b;
assign y = a | b;
assign y = a ^ b;
```

## Reduction¶

```wire y;
wire [1:0] a2;
assign y = | a2;
```

is equivalent to:

```wire y;
wire [1:0] a2;
assign y = a2 | a2;
```

## Concatenation and Replication¶

```wire y;
wire [1:0] y2;
wire [2:0] y3;

assign y2 = {a,b};            // creates a 2-bit signal of a with b
assign y2 = {a,1'b0};         // a with 1 bit binary 0 (constant)
assign y3 = {a,b,1'b1};       // a with b with binary 1 (constant)
assign y3 = {a,2'b10};        // a with 2 binary bits 1, 0
assign y3 = {a,a2};           // a with a2 (a2 is 2 bits)
assign y3 = {a,a2,1'b1};   // a with single bit from a2 with 1
assign {y2,y} = {y3[1:0],a};  // multiple assignment: creates y2 as
// 2 bits from y3 and y as a
assign y3 = {a,2{1'b1}};      // a with 2 lots of binary 1
```

Note use of `//` to introduce a comment.

## Shifting¶

Both arithmetic and logic shifts are provided. The following table illustrates the difference.

```a           a >> 2      a >>> 2     a << 2      a <<< 3
01001111    00010011    00010011    00111100    00111100
11001111    00110011    11110011    00111100    00111100
```

Examples:

```assign y2 = a2 >> 1;    // Logical 0's shifted in
assign y2 = a2 >>> 1;   // Arithemtic MSB sign bit shifted in
assign y2 = a2 << 1;    // Logical shift left same result as
assign y2 = a2 <<< 1;   // Arithmetic shift left
```

## Rotation¶

Rotate right 1 bit:

```assign y4 = {y3,y3[2:1]};
```

Rotate right 2 bit:

```assign y4 = {y3[1:0],y3};
```

## Conditional expressions¶

A tertiary operator:

```assign max = (a > b) ? a : b;
```

## Operator precedence¶

```() [] :: .
+ - ! ~ & ~& | ~| ^ ~^ ^~ ++ -- (unary)
**
* / %
+ - (binary)
<< >> <<< >>>
< <= > >= inside dist
== != === !== =?= !?=
& (binary)
^ ~^ ^~ (binary)
| (binary)
&&
||
? : (conditional operator)
>
= += -= *= /= %= &= ^= |= <<= >>= <<<= >>>= := :/ <=
{} {{}}
```

## Combinatorial always blocks¶

For use when simple expressions get too complicated

```always @(*)
a = b;

always @(*)
begin
a = b;
y = a | b;
end
```

SystemVerilog offers a more explicit format

```always_comb
a = b;
```

## If/Else (1)¶

```wire [7:0] a, b;
wire [7:0] min;

always_comb
if(a < b)
min = a;
else
min = b;
```

## If/Else (2)¶

More generally:

```always_comb
if(boolean)
begin     // need begin...end if >1 line of code within block
// if code
end
else
begin
// else code
end
```

## Conditional example: 4-bit decoder¶

Given a 2 bit value input, set that bit in the output, but only if the enable input is asserted (high). Truth table:

```en      a1      a2      y
0       -       -       0000
1       0       0       0001
1       0       1       0010
1       1       0       0100
1       1       1       1000
```

## Conditional example: implementation¶

```module decoder (
input [1:0]  a,
input        en,
output [3:0] y
)

always_comb
if (~en)
y = 4'b0000;  // 4-bit wide, binary representation: 0000
else if(a == 2'b00)
y = 4'b0001;
else if(a == 2'b01)
y = 4'b0010;
else if(a == 2'b10)
y = 4'b0100;
else
y = 4'b1000;

endmodule
```

## Conditional example: improved¶

```module decoder (
input [1:0]  a,
input        en,
output [3:0] y
)

always_comb
case ({en,a})
3'b000, 3'b001,3'b010,3'b011: y = 4'b0000;
3'b100: y = 4'b0001;
3'b101: y = 4'b0010;
3'b110: y = 4'b0100;
3'b111: y = 4'b1000;
endcase    // {en,a}

endmodule
```

## Uncertainty: X and Z values¶

X is the “don’t care” value. Specifiying this can make for more efficient synthesis, since the tools can choose whichever value is most efficient.

Z is the “high impedence” value, typically used for connections that can be both inputs and outputs, typically under the control of an enable signal.

```assign y = (oen) ? a : 1'bz;
```

## Decoder example using X¶

```module decoder (
input  [1:0] a,
input        en,
output [3:0] y
)

always_comb
casex ({en,a})
3'b0xx: y = 4'b0000;
3'b100: y = 4'b0001;
3'b101: y = 4'b0010;
3'b110: y = 4'b0100;
3'b111: y = 4'b1000;
endcase    // {en,a}

endmodule
```

There is also `casez`.

## Multiple assignment¶

```always_comb
if (en) y = 1'b0;

always_comb
y = a & b;
```

Won’t synthesize because `y` is the output of two circuits which is contraditory. It should be written as:

```always_comb
if (en)
y = 1'b0;
else
y = a & b;
```

## Exercise 2¶

Start with `button_led.v` in the `basic_verilog/button_led` directory. Complete it so that the LED which is lit up depends on whether the button is pressed.

Build it with:

```make button_led
```

Then experiment using both buttons, so that each combination of buttons lights a different LED. Use a `case` statement for this.