Hi, I am trying to understand some Verilog source code, but I am confused about the following

1 | reg [29-PSR-1: 0] kp_reg ; |

2 | wire [ 29-1: 0] kp_mult ; |

3 | always @(posedge clk_i) begin |

4 | if (rstn_i == 1'b0) begin |

5 | kp_reg <= {29-PSR{1'b0}}; |

6 | ```
end
``` |

7 | else begin |

8 | kp_reg <= kp_mult[29-1:PSR] ; |

9 | ```
end
``` |

10 | ```
end
``` |

11 | |

12 | assign kp_mult = $signed(error) * $signed(set_kp_i); |

where PSR is a paramter equal = 12. So, kp_mult keeps the value of the product. But then it is truncated and only MSB are assigned to kp_reg. I am wondering what this is happened? My guess is that it is related to the fixed-point arithmetics and PSR defines the position of the binary point but I am not sure.

You are right with your assumption! Multiplications tends to blow up the bit widths of your signals because the resulting bit width is always the sum of both input bit widths. That's why you often have to truncate the result after a multiplication. And that's exactly what happens here. When you consider a number as fixed point you can easily cut off some of the fractional bits when the required accuracy is not so high. Of course rounding would be better than truncating, but this is more complicated and requires more logic resources.

Hi Andi, I would agree with you if kp_mult is used for the accumulation. However, it just a single multiplication. Consider for example that kp_mult equals to 3 in decimal, kp_mult = 0000 0000 0000 0000 0000 0000 0000 11. If we move only 17 MSB to kp_reg it will equal to zero. And it will be zero until really big number (2^11). This is why, I am not sure that just truncation is a reasonable explanation. Apart from it, error and set_kp_i are integer values.