Takes in a binary number and returns an unsigned binary number of the same width containing the count of zeros from the least-significant bit up to the first 1 bit (trailing zeros), or the width of the word if all-zero. For example:
`default_nettype none module Number_of_Trailing_Zeros #( parameter WORD_WIDTH = 0 ) ( input wire [WORD_WIDTH-1:0] word_in, output reg [WORD_WIDTH-1:0] word_out ); localparam WORD_ZERO = {WORD_WIDTH{1'b0}}; initial begin word_out = WORD_ZERO; end
First, isolate the least-significant 1 bit
wire [WORD_WIDTH-1:0] lsb_1; Bitmask_Isolate_Rightmost_1_Bit #( .WORD_WIDTH (WORD_WIDTH) ) find_lsb_1 ( .word_in (word_in), .word_out (lsb_1) );
A single bit is a power of two, so take its logarithm, which returns its zero-based index, which is also the number of trailing zeros behind it.
wire [WORD_WIDTH-1:0] trailing_zero_count_raw; wire logarithm_undefined; Logarithm_of_Powers_of_Two #( .WORD_WIDTH (WORD_WIDTH) ) calc_bit_index ( .one_hot_in (lsb_1), .logarithm_out (trailing_zero_count_raw), .logarithm_undefined (logarithm_undefined) );
However, there is a corner case: if the input word is all zero, then the logarithm output is undefined, and the number of trailing zeros is equal to WORD_WIDTH, which is a value the logarithm (base 2) can never take.
always @(*) begin word_out = (logarithm_undefined == 1'b1) ? WORD_WIDTH : trailing_zero_count_raw; end endmodule