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:
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]);
Using assign statement, and the ternary operator (also known as the ?: operator):
assign out = (in==3’b000)?0: (in==3’b001)?1: (in==3’b010)?1: (in==3’b011)?0: (in==3’b100)?1: (in==3’b101)?0: (in==3’b110)?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[2] & 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);
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.