/*
 * Authored by: Robert Metchev / Chips & Scripts (rmetchev@ieee.org)
 *
 * CERN Open Hardware Licence Version 2 - Permissive
 *
 * Copyright (C) 2024 Robert Metchev
 */
// auto-generated by: quant_seq_mult.py
module quant_seq_mult_15x13_p4 (
    input   logic signed[14:0] a_in,
    input   logic unsigned[12:0] b_in,
    output  logic signed[27:0] out,
    input   logic in_valid,
    output  logic out_valid,
    input   logic en,
    input   logic clk,
    input   logic resetn
);
logic signed[14:0] a_pipe_stg0, a_pipe_stg1, a_pipe_stg2, a_pipe_stg3;
logic signed[14:0] a_pipe_stg0_next, a_pipe_stg1_next, a_pipe_stg2_next, a_pipe_stg3_next;
logic signed[12:0] b_pipe_stg0, b_pipe_stg1, b_pipe_stg2, b_pipe_stg3;
logic signed[12:0] b_pipe_stg0_next, b_pipe_stg1_next, b_pipe_stg2_next, b_pipe_stg3_next;
logic signed[27:0] z_pipe_stg0, z_pipe_stg1, z_pipe_stg2, z_pipe_stg3;
logic signed[27:0] z_pipe_stg0_next, z_pipe_stg1_next, z_pipe_stg2_next, z_pipe_stg3_next;
logic valid_pipe_stg0, valid_pipe_stg1, valid_pipe_stg2, valid_pipe_stg3;
logic valid_pipe_stg0_next, valid_pipe_stg1_next, valid_pipe_stg2_next, valid_pipe_stg3_next;
always @(posedge clk) if (!resetn) begin
    valid_pipe_stg3 <= 0;
    valid_pipe_stg2 <= 0;
    valid_pipe_stg1 <= 0;
    valid_pipe_stg0 <= 0;
end else if(en) begin
    valid_pipe_stg3 <= valid_pipe_stg3_next;
    valid_pipe_stg2 <= valid_pipe_stg2_next;
    valid_pipe_stg1 <= valid_pipe_stg1_next;
    valid_pipe_stg0 <= valid_pipe_stg0_next;
end
always @(posedge clk) if(en) begin
    if (valid_pipe_stg3_next) a_pipe_stg3 <= a_pipe_stg3_next;
    if (valid_pipe_stg2_next) a_pipe_stg2 <= a_pipe_stg2_next;
    if (valid_pipe_stg1_next) a_pipe_stg1 <= a_pipe_stg1_next;
    if (valid_pipe_stg0_next) a_pipe_stg0 <= a_pipe_stg0_next;
    if (valid_pipe_stg3_next) b_pipe_stg3 <= b_pipe_stg3_next;
    if (valid_pipe_stg2_next) b_pipe_stg2 <= b_pipe_stg2_next;
    if (valid_pipe_stg1_next) b_pipe_stg1 <= b_pipe_stg1_next;
    if (valid_pipe_stg0_next) b_pipe_stg0 <= b_pipe_stg0_next;
    if (valid_pipe_stg3_next) z_pipe_stg3 <= z_pipe_stg3_next;
    if (valid_pipe_stg2_next) z_pipe_stg2 <= z_pipe_stg2_next;
    if (valid_pipe_stg1_next) z_pipe_stg1 <= z_pipe_stg1_next;
    if (valid_pipe_stg0_next) z_pipe_stg0 <= z_pipe_stg0_next;
end
always_comb begin
    valid_pipe_stg3_next = valid_pipe_stg2;
    valid_pipe_stg2_next = valid_pipe_stg1;
    valid_pipe_stg1_next = valid_pipe_stg0;
    valid_pipe_stg0_next = in_valid;
    a_pipe_stg3_next = a_pipe_stg2;
    a_pipe_stg2_next = a_pipe_stg1;
    a_pipe_stg1_next = a_pipe_stg0;
    a_pipe_stg0_next = a_in;
    b_pipe_stg3_next = b_pipe_stg2;
    b_pipe_stg2_next = b_pipe_stg1;
    b_pipe_stg1_next = b_pipe_stg0;
    b_pipe_stg0_next = b_in;
    z_pipe_stg3_next = z_pipe_stg2
        + (1 << 11) // rounding bit
        + (b_pipe_stg3_next[12] ? (a_pipe_stg3_next << 12) : 0)
        + (b_pipe_stg3_next[11] ? (a_pipe_stg3_next << 11) : 0)
        + (b_pipe_stg3_next[10] ? (a_pipe_stg3_next << 10) : 0);
    z_pipe_stg2_next = z_pipe_stg1
        + (b_pipe_stg2_next[9] ? (a_pipe_stg2_next << 9) : 0)
        + (b_pipe_stg2_next[8] ? (a_pipe_stg2_next << 8) : 0)
        + (b_pipe_stg2_next[7] ? (a_pipe_stg2_next << 7) : 0);
    z_pipe_stg1_next = z_pipe_stg0
        + (b_pipe_stg1_next[6] ? (a_pipe_stg1_next << 6) : 0)
        + (b_pipe_stg1_next[5] ? (a_pipe_stg1_next << 5) : 0)
        + (b_pipe_stg1_next[4] ? (a_pipe_stg1_next << 4) : 0);
    z_pipe_stg0_next = 0
        + (b_pipe_stg0_next[3] ? (a_pipe_stg0_next << 3) : 0)
        + (b_pipe_stg0_next[2] ? (a_pipe_stg0_next << 2) : 0)
        + (b_pipe_stg0_next[1] ? (a_pipe_stg0_next << 1) : 0)
        + (b_pipe_stg0_next[0] ? (a_pipe_stg0_next << 0) : 0);
end
always_comb out = z_pipe_stg3;
always_comb out_valid = valid_pipe_stg3;
endmodule
