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
source to share
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!
source to share
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.
source to share