Given a [15:0]
number (there is no fractional part, only integer). How do I truncate the lower two bits [1:0]
and round it off to the closest possible value? Consider a case where no overflow happens. I need to do it in Verilog.
input [15:0] A;
output [13:0] B;
2 Answers 2
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.)
I would try something like this:
wire [15:0] C;
assign C = A+2; //rounding offset
assign B = {C[15:2]}; //drop 2 trailing bits
A=1 => C=3 => B=0
A=2 => C=4 => B=1
A=3 => C=5 => B=1
This would of course round up on a tie; to round down, change the 2 to 1. For the highest values, this will overflow (ie 0xFFFD, 0xFFFE and 0xFFFF will output 0x000). If this isn't wanted, extend C to 17 bits and catch the overflow.