1
\$\begingroup\$

This question is related to article on rounding found here.

The "Convergent rounding: Round half to even" code is written as follows:

assign  w_convergent = i_data[(IWID-1):0]
            + { {(OWID){1'b0}},
                i_data[(IWID-OWID)],
                {(IWID-OWID-1){!i_data[(IWID-OWID)]}}};

always @(posedge i_clk)
    o_convergent <= w_convergent[(IWID-1):(IWID-OWID)];

I am not able to understand what exactly the following lines are doing and why they are required:

        + { {(OWID){1'b0}},
            i_data[(IWID-OWID)],
            {(IWID-OWID-1){!i_data[(IWID-OWID)]}}};

EDIT:

There are three things that are confusing me about this,

(1) Why is there no IF statement to accomodate the case where the input is exactly half-way e.g 1.5, 2.5 e.t.c.

(2) Why do we need the third part {(IWID-OWID-1){!i_data[(IWID-OWID)]}}, aren't these bits always supposed to be 0?

(3) Since SystemVerilog can easily add two logic vectors together when they have different size, why do we need the {(OWID){1'b0}}?

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Another way to write that is:

+
    { 
        {(OWID){1'b0}}      ,
        i_data[(IWID-OWID)] ,
        {(IWID-OWID-1){!i_data[(IWID-OWID)]}}
    };

This means we are concatenating 3 expressions (separated by the 2 commas).

Assume the following constants:

parameter IWID = 16;
parameter OWID =  5;

Now let's plug in the values:

+
    { 
        {(5){1'b0}}    ,
        i_data[(16-5)] ,
        {(16-5-1){!i_data[(16-5)]}}
    };

In the term {(5){1'b0}}, the 2 sets of braces are known as the replicated concatenation operator. This replicates the one bit (1'b0) 5 times, yeilding the 5-bit constant 5'b0_0000. Simplifying, we have:

+
    { 
        5'b0_0000  ,
        i_data[11] ,
        {10{!i_data[11]}}
    };

Assume i_data[11] = 1'b1:

+
    { 
        5'b0_0000,
        1'b1,
        {10{1'b0}}
    };

This leaves the 16-bit value:

+
    { 
        5'b0_0000,
        1'b1,
        10'b00_0000_0000
    };
\$\endgroup\$
4
  • \$\begingroup\$ Thanks, I have update the questions with three things that are specifically confusing for me. \$\endgroup\$
    – quantum231
    Commented Apr 4 at 23:51
  • \$\begingroup\$ (1) Why is there no IF statement to accomodate the case where the input is exactly half-way e.g 1.5, 2.5 e.t.c. (2) Why do we need the third part {(IWID-OWID-1){!i_data[(IWID-OWID)]}}, aren't these bits always supposed to be 0? (3) Since SystemVerilog can easily add two logic vectors together when they have different size, why do we need the {(OWID){1'b0}}? \$\endgroup\$
    – quantum231
    Commented Apr 6 at 12:30
  • \$\begingroup\$ @quantum231: The original question was focused. Instead of adding new questions into the question, I recommend accepting this answer, then posting a new question. For the new question, I recommend running simulations, then asking a specific qustion if there is something about the simulation you do not understand. \$\endgroup\$
    – toolic
    Commented Apr 7 at 10:24
  • \$\begingroup\$ Are you able to figure out how this actually performs the rounding operation? I thought that we need to look at the bit just after decimal point (or the one just after OWID) but this code does not do that. \$\endgroup\$
    – quantum231
    Commented Apr 9 at 4:45

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.