2
\$\begingroup\$

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;
\$\endgroup\$

2 Answers 2

5
\$\begingroup\$

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.)

\$\endgroup\$
0
0
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.