Verilog Conditional Operator
Just what the heck is that question mark doing?
Have you ever come across a strange looking piece of Verilog code that has a question mark in the middle of it? A question mark in the middle of a line of code looks so bizarre; they’re supposed to go at the end of sentences! However in Verilog the ? operator is a very useful one, but it does take a bit of getting used to.
The question mark is known in Verilog as a conditional operator though in other programming languages it also is referred to as a ternary operator, an inline if, or a ternary if. It is used as a short-hand way to write a conditional expression in Verilog (rather than using if/else statements). Let’s look at how it is used:
Here, condition is the check that the code is performing. This condition might be things like, “Is the value in A greater than the value in B?” or “Is A=1?”. Depending on if this condition evaluates to true, the first expression is chosen. If the condition evaluates to false, the part after the colon is chosen. I wrote an example of this. The code below is really elegant stuff. The way I look at the question mark operator is I say to myself, “Tell me about the value in r_Check. If it’s true, then return “HI THERE” if it’s false, then return “POTATO”. You can also use the conditional operator to assign signals, as shown with the signal w_Test1 in the example below. Assigning signals with the conditional operator is useful!
module test2; reg r_Check = 1'b1; wire w_Test1; assign w_Test1 = r_Check ? 1'b1 : 1'b0; initial begin #1; $display("OUTPUT: %s", r_Check ? "HI THERE" : "POTATO"); $display("Value of w_Test1: %b", w_Test1); $display("%h", (10 > 5) ? 16'hABCD : 16'h1234); $display("%s", (1 == 1) ? "YES, ONE EQUALS ONE" : "HOW DID YOU GET HERE"); end endmodule // test2
# OUTPUT: HI THERE # Value of w_Test1: 1 # abcd # YES, ONE EQUALS ONE
Nested Conditional Operators
There are examples in which it might be useful to combine two or more conditional operators in a single assignment. Consider the truth table below. The truth table shows a 2-input truth table. You need to know the value of both r_Sel[1] and r_Sel[0] to determine the value of the output w_Out. This could be achieved with a bunch of if-else if-else if combinations, or a case statement, but it’s much cleaner and simpler to use the conditional operator to achieve the same goal.
r_Sel[1] | r_Sel[0] | Output w_Out |
0 | 0 | 1 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
module test3; reg [1:0] r_Sel; wire w_Out; assign w_Out = r_Sel[1] ? (r_Sel[0] ? 1'b0 : 1'b1) : (r_Sel[0] ? 1'b1 : 1'b1); initial begin r_Sel = 2'b00; #1; $display("w_Out = %b", w_Out); r_Sel = 2'b01; #1; $display("w_Out = %b", w_Out); r_Sel = 2'b10; #1; $display("w_Out = %b", w_Out); r_Sel = 2'b11; #1; $display("w_Out = %b", w_Out); end endmodule // test3
# w_Out = 1 # w_Out = 1 # w_Out = 1 # w_Out = 0
The input “r_Sel” must be reg type? Could it be wire type?