Verilog – How to Truncate a 16-bit Number

digital-logicverilog

Given [15:0] number (there is no fractional part, only integer). How do I truncate lower two bits [1:0] and round it off to closest possible value. Consider a case where no overflow happens. Need to do it in verilog.

input [15:0] A;
output [13:0] B;

Best Answer

To implement rounding, you'll need an incrementer (add 1) for the round-up case.

Let's assume the rounding behavior you want is as follows:

  • lsb's = 0,0: truncate (round down)
  • lsb's = 0,1: truncate (round down)
  • lsb's = 1,0: round up
  • lsb's = 1,1: round up

The Verilog would look something like this:

wire [15:0] A;
wire [13:0] Y;
wire [0:0]  round_up;

    assign round_up = A[1:0] >= 2'b10;
    assign Y = A[15:2] + round_up;

The sharp-eyed among you will see that the increment select can be simplified as:

    assign round_up = A[1];

And you can suppress the wraparound case with one more trick, giving:

    assign round_up = A[1] && ~(A[15:2] == 14'h3fff);    // catch the wrap case
    assign Y = A[15:2] + round_up;

I'm sure there's other ways to code this, but they will all include at least the adder and the overflow range check to prevent wrap (that is, saturation.)

Related Topic