Leading zero counter

I am implementing a normalization block for floating point and I want to know how to effectively implement a leading zero count?

I know I can write the following, but I was wondering if there is a better method if I'm aiming for low area and high energy efficiency ?:

always @(mantissa) begin
  case(mantissa)
    25'b1????????????????????????: newmant = mantissa[24:1];
    25'b01???????????????????????: newmant = mantissa[23:0];
    25'b001??????????????????????: newmant = {mantissa[22:0],1'b0};
    25'b0001?????????????????????: newmant = {mantissa[21:0],2'b0};
    // ... (details ommited for brevity)
  endcase
end

      

+3


source to share


2 answers


In VHDL (which should be easily portable for Verilog):

process
   variable leading_zeros : natural;
begin
   leading_zeros := 0;
   for i in input_vector'range loop
      if input_vector(i) = '1' then
         break;
      end if;
      leading_zeros := leading_zeros + 1;
   end for;
end process;

      



For non-VHDL loudspeakers, the whole thing loops through all the bits in input_vector

left to right, incrementing the counter every time it sees 0

. When it finds the first one 1

, it will drop out of the loop, leaving a counter containing the number of leading zeros.

To find out if it is highly effective enough you will have to try synthesis - let us know!

-1


source


Why do you need a leading zero counter? Even if you counted the number of zeros in the prefix, at the end you still need comparators and MUXs to determine how many zeros you have and calculate the result. This can waste more on your performance / area due to the large number of 1'b1 adders, MUXs and comparators.

The for / while loop will expand to 25 steps (according to the width) in the synthesizer. If you are using leading zero counters your architecture will look like



// you will have 25 mux and adders
always @(mantissa) begin
  leading_zeros = 0;
  // for-loop expanded
  if (mantissa[24] == 1)
    disable count_n_2;
  else begin : count_n_2
    leading_zeros ++;
    if (mantissa[23] == 1)
       disable count_n_3;
    else begin : count_n_3
      leading_zeros ++;
      ...
    end
  end
end // always

// you will have 25 comparator and mux
always @(leading_zeros) begin
  case(leading_zeros)
    5'd0: newmant = mantissa[24:1];
    5'd1: newmant = mantissa[23:0];
    5'd2: newmant = {mantissa[22:0],1'b0};
    5'd25: ...
  endcase
end

      

so ... you just use your own design and use the synth / mapping commands of the tools to see what it can do to achieve your area and power needs.

-1


source







All Articles