diff --git a/rtl/ibex_alu.sv b/rtl/ibex_alu.sv index 563f571cf..afbbcfbc9 100644 --- a/rtl/ibex_alu.sv +++ b/rtl/ibex_alu.sv @@ -437,21 +437,16 @@ module ibex_alu #( assign bitcnt_cz = bitcnt_ctz | bitcnt_clz; assign bitcnt_result = bitcnt_partial[31]; - // Bit-mask generation for clz and ctz: - // The bit mask is generated by spreading the lowest-order set bit in the operand to all - // higher order bits. The resulting mask is inverted to cover the lowest order zeros. In order - // to create the bit mask for leading zeros, the input operand needs to be reversed. - assign bitcnt_mask_op = bitcnt_clz ? operand_a_rev : operand_a_i; + // Bitcnt_bits generation for clz and ctz: + // The operand of ctz can be divided into 3 parts: the don't-care bits in the high-order bits, + // the lowest-order set bit, and the trailing zeros. Bitcnt_bit_mask is obtained by subtracting 1 + // from bitcnt_mask_op, which clears the lowest-order set bit and sets all the trailing zeros to 1. + // Then, bitcnt_bit_mask & ~bitcnt_mask_op clears the don't-care bits. + // At this point, counting the number of 1s gives the number of trailing zeros. + // In order to create the bit mask for leading zeros, the input operand needs to be reversed. - always_comb begin - bitcnt_bit_mask = bitcnt_mask_op; - bitcnt_bit_mask |= bitcnt_bit_mask << 1; - bitcnt_bit_mask |= bitcnt_bit_mask << 2; - bitcnt_bit_mask |= bitcnt_bit_mask << 4; - bitcnt_bit_mask |= bitcnt_bit_mask << 8; - bitcnt_bit_mask |= bitcnt_bit_mask << 16; - bitcnt_bit_mask = ~bitcnt_bit_mask; - end + assign bitcnt_mask_op = bitcnt_clz ? operand_a_rev : operand_a_i; + assign bitcnt_bit_mask = bitcnt_mask_op - 32'h1; assign zbe_op = (operator_i == ALU_BCOMPRESS) | (operator_i == ALU_BDECOMPRESS);