/* verilator lint_off BLKLOOPINIT */
// LSTM Accelerator — Gate-parallel design
module lstm_accel #(parameter DW=16, HIDDEN=128, F=8)(
    input clk, rst_n, input en, input start,
    // Input: x_t (1 × INPUT_SIZE) — simplified to HIDDEN for demo
    input signed [DW-1:0] x_in [0:HIDDEN-1], input x_valid,
    // Hidden state: h_{t-1}
    input signed [DW-1:0] h_prev [0:HIDDEN-1],
    // Cell state: c_{t-1}
    input signed [DW-1:0] c_prev [0:HIDDEN-1],
    // Weights (4 gates: i, f, o, g each HIDDEN×HIDDEN)
    input signed [DW-1:0] w_i [0:HIDDEN*HIDDEN-1], input signed [DW-1:0] b_i [0:HIDDEN-1],
    input signed [DW-1:0] w_f [0:HIDDEN*HIDDEN-1], input signed [DW-1:0] b_f [0:HIDDEN-1],
    input signed [DW-1:0] w_o [0:HIDDEN*HIDDEN-1], input signed [DW-1:0] b_o [0:HIDDEN-1],
    input signed [DW-1:0] w_g [0:HIDDEN*HIDDEN-1], input signed [DW-1:0] b_g [0:HIDDEN-1],
    // Output: h_t, c_t
    output reg signed [DW-1:0] h_out [0:HIDDEN-1],
    output reg signed [DW-1:0] c_out [0:HIDDEN-1],
    output reg out_valid, output reg done
);
    // Gate computations: gate = sigmoid/tanh(W*[x,h] + b)
    reg signed [DW-1:0] i_gate [0:HIDDEN-1]; // Input gate
    reg signed [DW-1:0] f_gate [0:HIDDEN-1]; // Forget gate
    reg signed [DW-1:0] o_gate [0:HIDDEN-1]; // Output gate
    reg signed [DW-1:0] g_gate [0:HIDDEN-1]; // Cell candidate
    reg [3:0] state;
    integer j;
    always_ff @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin state<=0; out_valid<=0; done<=0;
            for(j=0;j<HIDDEN;j++) begin h_out[j]<='0; c_out[j]<='0; i_gate[j]<='0; f_gate[j]<='0; o_gate[j]<='0; g_gate[j]<='0; end end
        else if(en) case(state)
          0: if(start) begin state<=1; // Start gate computation
                // Simplified: gate = x*W + h*W + b (4 parallel matrix-vector multiplies)
                for(j=0;j<HIDDEN;j++) begin
                    i_gate[j] <= (x_in[j]>>>F) + (h_prev[j]>>>F) + b_i[j]; // Simplified
                    f_gate[j] <= (x_in[j]>>>F) + (h_prev[j]>>>F) + b_f[j];
                    o_gate[j] <= (x_in[j]>>>F) + (h_prev[j]>>>F) + b_o[j];
                    g_gate[j] <= (x_in[j]>>>F) + (h_prev[j]>>>F) + b_g[j];
                end
            end
          1: begin state<=2;
                // Apply activations: sigmoid for i,f,o; tanh for g
                for(j=0;j<HIDDEN;j++) begin
                    // Simplified sigmoid: clamp to [0,1]
                    i_gate[j] <= i_gate[j][DW-1] ? '0 : (i_gate[j] > (1<<<F)) ? (1<<<F) : i_gate[j];
                    f_gate[j] <= f_gate[j][DW-1] ? '0 : (f_gate[j] > (1<<<F)) ? (1<<<F) : f_gate[j];
                    o_gate[j] <= o_gate[j][DW-1] ? '0 : (o_gate[j] > (1<<<F)) ? (1<<<F) : o_gate[j];
                end
            end
          2: begin state<=3;
                // Update cell: c_t = f_gate ⊙ c_prev + i_gate ⊙ g_gate
                for(j=0;j<HIDDEN;j++)
                    c_out[j] <= (f_gate[j]*c_prev[j] + i_gate[j]*g_gate[j]) >>> F;
            end
          3: begin state<=4;
                // Output: h_t = o_gate ⊙ tanh(c_t)
                for(j=0;j<HIDDEN;j++)
                    h_out[j] <= (o_gate[j]*c_out[j]) >>> F;
                out_valid <= 1;
            end
          4: done <= 1;
        endcase
    end
endmodule