Signed comparison in Verilog¶
When you write this in Verilog:
wire [7:0] a;
wire [7:0] b;
wire less;
assign less = (a < b);
the comparison between a and b is unsigned, that is a and b are numbers in the range 0-255. Writing this instead:
wire [7:0] a;
wire [7:0] b;
wire less;
assign less = ($signed(a) < $signed(b));
means that the comparison treats a and b as signed 8-bit numbers, which have a range of -128 to +127. Another way of writing the same thing is:
wire signed [7:0] a;
wire signed [7:0] b;
wire less;
assign less = (a < b);
A common operation on signed numbers is sign-extension. Here’s an easy way of doing it:
wire [7:0] a;
wire [15:0] ax; // a sign-extended to 16-bit
assign ax = {{8{a[7]}}, a};
This works by concatenating 8 copies of a’s sign bit with a itself.
While it’s legal to write comparisons between values with different sizes and signednesses, the rules are so confusing that you’re better off converting the arguments explicitly beforehand.