--- Quote Start ---
Actually all loops have iterations, but in the case of HDL the iterations define hardware on the surface of the chip, not state as in software.
--- Quote End ---
Actually it isn't entirely true. The loops are unrolled by the synthesizer, that looks at the generated logic function, and only then it will synthesize logic to realize that function. So you won't get a chunk of logic for each loop iteration in the code. As an example, I synthesized that process (sorry, it's VHDL, I know it better than Verilog):
process(input) is
variable tap : unsigned(31 downto 0);
variable counter : integer;
begin
tap := input;
counter := 1;
while counter < 32 loop
tap := tap or (tap srl counter);
counter := counter * 2;
-- counter := counter + 1;
end loop;
output <= tap;
end process;
It synthesized the same logic with counter = counter + 1, even if the loop was executed more times by the synthesizer. In both cases 32 logic elements were used.
Personnaly I would go for the counter = counter + 1 syntax, which I find easier to read, or even better write a function that looks for the MSB and put the least significant ones to 1, as FVM said. It will generate the same logic in the end, while being more comprehensive.
As for your original question it could be a bug in how the synthesizer sees your code, because I don't see any reason why it wouldn't work with *2. Did you try to simulate it in Modelsim to see if you get the same result?