website statistics

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.

More VHDL, Verilog and FPGA notes.