← Back to Blogs

Digital PID Controller in Verilog: Tackling RTL and Overflow Challenges

Published on September 24, 2025 • 4 min read • VLSI Design

Designing a digital PID controller in Verilog pushed my RTL coding skills to the limit. While translating PID equations into hardware, I ran into subtle overflow and fixed-point scaling issues that broke simulation and synthesis until I understood the root causes.

RTL Architecture and Fixed-Point Representation

The core PID formula combines proportional, integral, and derivative terms. In hardware, I implemented each term as a 16-bit signed fixed-point value (8 integer bits, 8 fractional bits). My initial Verilog snippet looked like this:

assign err = setpoint - feedback;
assign P   = Kp * err;
assign I   = integral + Ki * err;
assign D   = Kd * (err - prev_err);
assign output = P + I + D;

At first, everything synthesized cleanly, but functional simulation showed wrap-around artifacts whenever values exceeded the 16-bit range. The integral term grew unbounded, causing I to overflow and corrupt the output.

Detecting and Preventing Overflow

The solution required adding saturation logic around each term. For example, after computing the integral update, I clamped the result:

wire signed [17:0] int_calc = integral + (Ki * err);
always @(posedge clk) begin
  if (int_calc >  18'sh7FFF) integral <= 16'sh7FFF;
  else if (int_calc < 18'sh8000) integral <= 16'sh8000;
  else integral <= int_calc[15:0];
end

This approach ensured the integral term remained within bounds, preventing downstream overflow when summing P, I, and D. I applied similar saturation to the proportional and derivative outputs.

Pipeline and Timing Considerations

Adding multipliers and saturation logic increased the critical path. My first FPGA implementation failed timing. To fix this, I pipelined the multiplier outputs and separated the adders into dedicated stages:

Pipelining reduced the maximum combinatorial delay, meeting timing at 50 MHz clock rate.

Lessons Learned

This project taught me three key lessons:

• Fixed-Point Precision: Always define bit-widths and fractional scaling clearly to avoid unexpected wrap-around.

• Overflow Handling: Saturation logic is essential for robust control loops.

• Pipelining: Breaking logic into stages helps meet FPGA timing constraints.

Conclusion

Implementing a PID controller in hardware is more than translating math—it’s about managing data widths, preventing overflow, and balancing performance with resource usage. Overcoming these RTL challenges deepened my understanding of digital design fundamentals and prepared me for more complex control systems in future FPGA projects.