Search code examples
verilogsystem-verilogfpgadigitaldigital-logic

Shifting in Verilog for multiplication


How does this line of code below works as the multiplication of (1024-31)?

The code is intended to be synthesized for FPGA, so shifting is used instead of direct division.

But what I do not understand is that how such shifting mimics the multiplication of the value of reg_acc * (1024-31).

reg [27:0] reg_adj;
reg [27:0] reg_acc;

...
    reg_adj <= ((reg_acc[11:0] << (20)) - ((reg_acc[11:0] << (15)) - (reg_acc[11:0] << (10)))) // x (1024-31)
...


Solution

  • Remember that the (n << k) = n * 2**k (the double * denoting power)

    Then

    (n << 20) - ((n << 15) - (n << 10)) =
    (n * 2**20) - ((n*2**15) - (n*2**10)) =
    (n * 2**10)*2**10 - ((n*2**5) - n)*2**10 =
    2**10*(n*(2**10-(2**5-1)))
    

    2**10 = 1024, 2**5=32, so the expression is multiplying 1024*(1024-(32-1)), but the result will be almost always wrong because when you shift bits out they will become zero, e.g. you are shifting a 12-bit number by 15 positions.

    I would simply write (reg_acc << 10) - ((reg_acc << 5) - reg_acc), if the additional 10 shifting is necessary you can wrap this whole expression in another shift.