Combinational Logic Styles

There are many different styles of SystemVerilog code that you can use to generate combinational circuits.

Consider the following logic function that outputs a 1 when an odd number of the three input bits are 1. (This is a 3-input XOR).

in[2] in[1] in[0] out
0 0 0 0
0 0 1 1
0 1 0 1
0 1 1 0
1 0 0 1
1 0 1 0
1 1 0 0
1 1 1 1
logic [2:0] in;
logic       out;

<Combinational Logic Here>

Assuming the above SystemVerilog code, there are many different ways to implement the same combinational logic. Here are some different examples.


Structural SV

As a sum of products:

logic [2:0] in_not;

not(in_not[0], in[0]);
not(in_not[1], in[1]);
not(in_not[2], in[2]);

and(term1, in_not[2], in_not[1], in[0]);
and(term2, in_not[2], in[1], in_not[0]);
and(term3, in[2], in_not[1], in_not[0]);
and(term4, in[2], in[1], in[0]);
or(out, term1, term2, term3, term4);

Minimized (single XOR gate):

xor(out, in[2], in[1], in[0]);

Dataflow SV

Using assign statement, and the ternary operator (also known as the ?: operator):

assign out =
  (in==3b000)?0:
  (in==3b001)?1:
  (in==3b010)?1:
  (in==3b011)?0:
  (in==3b100)?1:
  (in==3b101)?0:
  (in==3b110)?0:
  1;

Using assign statement, with sum of products, and dataflow operators:

assign out = (~in[2] & ~in[1] & in[0]) | (~in[2] & in[1] & ~in[0]) |
             (in[2] & ~in[1] & ~in[0]) | (in[2] & in[1] & in[0]);

Using assign statement, vectored comparison operators, binary literals:

assign out = (in == 3'b001) || (in == 3'b010) || (in == 3'b100) || (in == 3'b111);

Using assign statement, vectored comparison operators, decimal literals:

assign out = (in == 3'd1) || (in == 3'd2) || (in == 3'd4) || (in == 3'd7);

Behavioral SV

Using always_comb block with if statement:

always_comb begin
    out = 1'b0;
    if ((in == 3'b001) || (in == 3'b010) || (in == 3'b100) || (in == 3'b111)) begin
        out = 1'b1;
    end else begin
        // This else isn't necessary because of the default value at the top, but is included here
        // to show you the syntax.
        out = 1'b0;
    end
end

Using always_comb block with case statement:

always_comb begin
    out = 1'b0;
    case(in)
        3'b001: out = 1'b1;
        3'b010: out = 1'b1;
        3'b100:
            out = 1'b1;
        3'b111: begin
            out = 1'b1;
        end
        default: begin
            // This default isn't necessary because of the default value at the top, but is included here
            // to show you the syntax.
            out = 1'b0;
        end
    endcase
end

The example above mixes different formatting of the case statements to show you the variations available. Note: Similar to if and always blocks, you will need to include a begin and end if your case contains more than one statement.