Case statement in Verilog
The case statement has a given expression and it is checked with the expression (case item) mentioned in the list in the written order and if it matches then the statement or group of statements are executed. If it does not match with any of the written expressions of the list then, the default statement will be executed.
If the ‘default’ statement is not given and the given expression is not matched with any expression in the list, then the case statement evaluation will exit.
Verilog case statement uses case, endcase, and default keywords.
Syntax:
case(<expression>)
<case_item1>:
<case_item2>:
<case_item3>:
<case_item4>: begin
...
...
end
default:
endcase
Note:
- The default statement is not mandatory. There must be only one default statement for the single case statement.
- The nested case statement is allowed.
- Verilog case statements work similarly as switch statements in C language.
- An expression inside a case statement can not use <= (relational operator).
- The === operator is used instead of == operator in case statement comparison. I.e. case statement checks for 0, 1, x and z values in the expression explicitly. (Check example)
Example:
module case_example;
reg [2:0] data;
always @(data) begin
case(data)
3'h2: $display("value of data is 2");
3'h4: $display("value of data is 4");
3'h5: $display("value of data is 5");
default: $display("default statement is executed for data = %0d", data);
endcase
end
initial begin
repeat(10) begin
data = $random;
#1;
end
end
endmodule
Output:
value of data is 4
default statement is executed for data = 1
default statement is executed for data = 3
value of data is 5
value of data is 2
default statement is executed for data = 1
value of data is 5
4:1 Mux Verilog implementation
The case statement is also used to design multiplexers. Below 4:1 MUX has two select inputs (sel) and four inputs (i3,i2,i1, and i0) and has one output (y).
module mux_example(
input [1:0] sel,
input i0,i1,i2,i3,
output reg y);
always @(*) begin
case(sel)
2'h0: y = i0;
2'h1: y = i1;
2'h2: y = i2;
2'h3: y = i3;
default: $display("Invalid sel input");
endcase
end
endmodule
Output:
sel = 00 -> i3 = 0, i2 = 1 ,i1 = 0, i0 = 1 -> y = 1
sel = 01 -> i3 = 0, i2 = 1 ,i1 = 0, i0 = 1 -> y = 0
sel = 11 -> i3 = 0, i2 = 1 ,i1 = 0, i0 = 1 -> y = 0
sel = 01 -> i3 = 0, i2 = 1 ,i1 = 0, i0 = 1 -> y = 0
Ambiguous inputs to the case statement
Now, let’s see if the user provides ambiguous values to the case statement (Point 5)
module case_example(
input a,
output reg [3:0] out);
always @(*) begin
case(a)
1'h0: out = 4;
1'h1: out = 5;
1'hx: out = 6;
1'hz: out = 7;
default: $display("Invalid sel input");
endcase
end
endmodule
Testbench: User has provided ambiguous values as x and z.
module tb;
reg a;
wire [3:0] out;
case_example case_ex(a, out);
initial begin
$monitor("a = %b -> out = %0h", a, out);
a = 1'b1;
#1 a = 1'b0;
#1 a = 1'bz;
#1 a = 1'bx;
end
endmodule
Output:
a = 1 -> out = 5
a = 0 -> out = 4
a = z -> out = 7
a = x -> out = 6
casex and cazez statements
The case statement also has a total of three variations: case, casex and casez. Note the following differences.
- case: considers x and z as it is (as shown in above example). If an exact match is not found, the default statement will be executed.
- casex: considers all x and z values as don’t care.
- casez: considers all z values as don’t cares. The z can also be specified as ?
casez statement example
module casez_example(
input [1:0] data,
output reg [3:0] out);
always @(*) begin
casez(data)
2'b0z: out = 1;
2'bz0: out = 2;
2'b1z: out = 3;
2'bxz: out = 4;
2'b0x: out = 5;
2'bx0: out = 6;
2'b1x: out = 7;
2'bx1: out = 8;
default: $display("Invalid sel input");
endcase
end
endmodule
Output:
data = x1 -> out = 4
data = 0x -> out = 1
data = x0 -> out = 2
data = z1 -> out = 1
data = 0z -> out = 1
data = z0 -> out = 1
data = 1z -> out = 2
casex statement example
module casex_example(
input [1:0] data,
output reg [3:0] out);
always @(*) begin
casex(data)
2'b0z: out = 1;
2'bz0: out = 2;
2'b1z: out = 3;
2'bxz: out = 4;
2'b0x: out = 5;
2'bx0: out = 6;
2'b1x: out = 7;
2'bx1: out = 8;
default: $display("Invalid sel input");
endcase
end
endmodule
Output:
data = x1 -> out = 1
data = 0x -> out = 1
data = x0 -> out = 1
data = z1 -> out = 1
data = 0z -> out = 1
data = z0 -> out = 1
data = 1z -> out = 2
Note:
- In simple terms, casez ignores bit positions having z value alone and casex ignores bit positions having x or z values.
- The ‘casez’ is more likely used as compared to ‘casex’ as the ‘casez’ does not ignore bit positions having x values and ‘casex’ is not synthesizable as well.
Verilog Tutorials