// Generated by EML-lang Verilog backend
// Source module: aerospace_actuator_guard_band
// Source file:   /home/monogate/monogate/forge/examples/actuator_guard.eml
//
// Target device: Arty A7-100
// Pipeline depth: 4 stages
// Estimated:    200 LUTs, 4 DSPs, 0 KB BRAM
// Throughput:   25.0 Msamples/s @ 100 MHz

`default_nettype none

// Pipeline: actuator_command_within_band
// Chain order: 0     Cost class: p0-d4-w0-c0
// EML depth:   4  Width: 32 bits
// Total latency: 2 cycles (1 internal + 1 output reg)
module actuator_command_within_band_pipeline #(
    parameter WIDTH = 32,
    parameter FRAC  = 16
) (
    input  wire             clk,
    input  wire             rst,
    input  wire             valid_in,
    input  wire signed [WIDTH-1:0] error,
    input  wire signed [WIDTH-1:0] integral,
    input  wire signed [WIDTH-1:0] deriv,
    input  wire signed [WIDTH-1:0] kp,
    input  wire signed [WIDTH-1:0] ki,
    input  wire signed [WIDTH-1:0] kd,
    input  wire signed [WIDTH-1:0] u_min,
    input  wire signed [WIDTH-1:0] u_max,
    output reg              valid_out,
    output reg signed [WIDTH-1:0] result
);

    wire signed [2*WIDTH-1:0] _w1_full;
    wire signed [WIDTH-1:0] _w2;
    reg signed [WIDTH-1:0] _d1 [0:0];
    wire signed [WIDTH-1:0] _w3;
    wire signed [2*WIDTH-1:0] _w4_full;
    wire signed [WIDTH-1:0] _w5;
    reg signed [WIDTH-1:0] _d2 [0:0];
    wire signed [WIDTH-1:0] _w6;
    wire signed [WIDTH-1:0] _w7;
    wire signed [2*WIDTH-1:0] _w8_full;
    wire signed [WIDTH-1:0] _w9;
    reg signed [WIDTH-1:0] _d3 [0:0];
    wire signed [WIDTH-1:0] _w10;
    wire signed [WIDTH-1:0] _w11;
    reg signed [WIDTH-1:0] _d4 [0:0];
    wire signed [WIDTH-1:0] _w12;
    reg signed [WIDTH-1:0] _d5 [0:0];
    wire signed [WIDTH-1:0] _w13;
    wire signed [WIDTH-1:0] _w14;

    assign _w1_full = kp * error;
    assign _w2 = _w1_full >>> FRAC;
    assign _w3 = _d1[0];
    assign _w4_full = ki * integral;
    assign _w5 = _w4_full >>> FRAC;
    assign _w6 = _d2[0];
    assign _w7 = _w3 + _w6;
    assign _w8_full = kd * deriv;
    assign _w9 = _w8_full >>> FRAC;
    assign _w10 = _d3[0];
    assign _w11 = _w7 + _w10;
    assign _w12 = _d4[0];
    assign _w13 = _d5[0];
    assign _w14 = (_w11 < _w12) ? _w12 : ((_w11 > _w13) ? _w13 : _w11);

    // F23 latency balance: _w2 delayed 1 cycle
    always @(posedge clk) begin
        if (rst) begin
            _d1[0] <= {WIDTH{1'b0}};
        end else begin
            _d1[0] <= _w2;
        end
    end

    // F23 latency balance: _w5 delayed 1 cycle
    always @(posedge clk) begin
        if (rst) begin
            _d2[0] <= {WIDTH{1'b0}};
        end else begin
            _d2[0] <= _w5;
        end
    end

    // F23 latency balance: _w9 delayed 1 cycle
    always @(posedge clk) begin
        if (rst) begin
            _d3[0] <= {WIDTH{1'b0}};
        end else begin
            _d3[0] <= _w9;
        end
    end

    // F23 latency balance: u_min delayed 1 cycle
    always @(posedge clk) begin
        if (rst) begin
            _d4[0] <= {WIDTH{1'b0}};
        end else begin
            _d4[0] <= u_min;
        end
    end

    // F23 latency balance: u_max delayed 1 cycle
    always @(posedge clk) begin
        if (rst) begin
            _d5[0] <= {WIDTH{1'b0}};
        end else begin
            _d5[0] <= u_max;
        end
    end

    // F23: valid_out aligned with result via 1-cycle shift register.
    reg valid_chain [0:0];
    always @(posedge clk) begin
        if (rst) begin
            valid_chain[0] <= 1'b0;
        end else begin
            valid_chain[0] <= valid_in;
        end
    end

    // Registered output: valid_out aligned with result.
    always @(posedge clk) begin
        if (rst) begin
            valid_out <= 1'b0;
            result    <= {WIDTH{1'b0}};
        end else begin
            valid_out <= valid_chain[0];
            result    <= _w14;
        end
    end

endmodule
