module ramp_gen (
    // system ports
    input         clk,
    input         rst_n,
    input  [1:0]  dac_mode_sel,
    input         cen,
    input  [7:0]  step,          // 8-bit step value
    input         fixed,
    input  [7:0]  fixed_value,   // 8-bit fixed value
    input  [31:0] ifs,
    output [7:0]  ramp [63:0],   // 64 channels of 8-bit output
    output        ramp_vld
);

//////////////////////////////////////////////////////////////
// Counter to generate ramp_add_en enable signal
//////////////////////////////////////////////////////////////
reg [31:0] cnt_c;
wire add_cnt = cen & ~fixed;
wire end_cnt = add_cnt && (cnt_c == ifs - 1);

wire [31:0] cnt_n = end_cnt ? 32'h0         :
                    add_cnt ? cnt_c + 1'b1  :
                              cnt_c;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) cnt_c <= 32'h0;
    else        cnt_c <= cnt_n;
end

reg ramp_add_en;
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) ramp_add_en <= 1'b0;
    else        ramp_add_en <= end_cnt | ((ifs == 32'b0) & cen) | fixed;
end

//////////////////////////////////////////////////////////////
// Pre-calculated step multiples (for special mode)
//////////////////////////////////////////////////////////////
wire [7:0] step2_w  = step << 1;
wire [7:0] step4_w  = step << 2;
wire [7:0] step8_w  = step << 3;
wire [7:0] step16_w = step << 4;
wire [7:0] step32_w = step << 5;
wire [7:0] step64_w = step << 6;

//////////////////////////////////////////////////////////////
// Generate 64 independent always blocks using generate
//////////////////////////////////////////////////////////////
genvar i;
generate
    for (i = 0; i < 64; i = i + 1) begin : ramp_chan
        reg [7:0] ramp_r;

        always @(posedge clk or negedge rst_n) begin
            if (!rst_n) begin
                ramp_r <= 8'b0;
            end
            else if (fixed) begin
                ramp_r <= fixed_value;
            end
            else if (ifs == 32'b0) begin
                // Special mode: ifs == 0
                if (cen & ~ramp_add_en) begin
                    // Initial phase loading: channel i gets (i+1)*step
                    ramp_r <= (i + 1) * step;
                end
                else if (ramp_add_en) begin
                    // Add large step each cycle (select 64¡Ástep or 32¡Ástep according to dac_mode_sel[1])
                    ramp_r <= ramp_r + (dac_mode_sel[1] ? step64_w : step32_w);
                end
                else begin
                    // Hold current value
                    ramp_r <= ramp_r;
                end
            end
            else begin
                // Normal mode: add step every ifs cycles
                if (ramp_add_en) begin
                    ramp_r <= ramp_r + step;
                end
                else begin
                    ramp_r <= ramp_r;
                end
            end
        end

        // Connect internal register to output port
        assign ramp[i] = ramp_r;
    end
endgenerate

//////////////////////////////////////////////////////////////
// Output valid signal
//////////////////////////////////////////////////////////////
reg en_dly;
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) en_dly <= 1'b0;
    else        en_dly <= cen | fixed;
end

assign ramp_vld = en_dly;

endmodule
