What is the difference between:
if (dataoutput[7:0] == 8'bx) begin
and
if (dataoutput[7:0] === 8'bx) begin
After executing dataoutput = 52'bx, the second gives 1, but the first gives 0. Why? (0 or 1 is the comparison result.)
Some data types in Verilog, such as reg, are 4-state. This means that each bit can be one of 4 values: 0,1,x,z.
With the "case equality" operator, ===, x's are compared, and the result is 1.
With ==, the result of the comparison is not 0, as you stated; rather, the result is x, according to the IEEE Std (1800-2009), section 11.4.5 "Equality operators":
For the logical equality and logical inequality operators (== and !=), if, due to unknown or high-impedance bits in the operands, the relation is ambiguous, then the result shall be a 1-bit unknown value (x).
== For comparing bits (0 or 1) === For comparing all 4 states (0, 1, x, z)
== can be synthesized into a hardware (x-nor gate), but === can't be synthesized as x is not a valid logic level in digital, it is infact having voltages in between 0 and 1. And z is not itself any logic, it shows disconnection of the circuit.
As many already commented, in case a signal has an X, the "normal" comparison operator can led to unknow states/answers. Therefore, if you are comparing from a RAM that can deliver U or X states and you want to really check a match, then you should use the "===" and "!==" operators.
I would add some guidance on use (which other answers don't give; actually, Karan Shah did try to address this).
Review: What is four value?
We normally like to operate in the domain of the first two.
For simulation, you can intentionally set values to the 'X' state. Such values do not exist in synthesis. The use of !== and === in simulation test is excellent as it will take care of these values. Intentionally forcing test inputs to 'x' when they should be ignored, due to bus signalling, can allow a 'black box' tests to see if any output also become 'x'.
However, most logic for synthesis is internal and doesn't use high Z values. An 'X' value cannot occur during synthesis; although it can be an unknown 0/1 value (at least for FPGA synthesis). So, for synthesis, it is better to opt for == and != in the majority of the cases.
The gtkwave tool kit has an 'lxt2miner' program which can be used to look for 'X' simulation signals beyond the reset cycle. I have a build rule as such,
$(CHECK_DEFINED) : %.check : %.lxt
$(INFO) ------- Mining $^ ----------
$(Q)lxt2miner $^ -c 2> /dev/null | grep x$$ | grep '^#[^0]' || true
So, values can be undetermined at t=0 when the reset is applied, but should not occur past that. Of course you can also add checks for 'z' and 'x' by using these operators in a test harness.
=== may synthesize, but is better not to use it when synthesizing.