//==============================================================================
//! @file dna_reader.v
//==============================================================================
//------------------------------------------------------------------------------
// --
// CERN - DNA Reader Xilinx FPGA --
// --
//------------------------------------------------------------------------------
//
// unit name:  DNA Reader Xilinx FPGA
//
//! @brief DNA Reader Xilinx FPGA
//
//! @author alen.arias.vazquez@cern.ch
//
//! @date 11/05/2022
//
//! @details
//!     PL DNA is 96bits width in the Ultrascale/Ultrascale+
//
//------------------------------------------------------------------------------

module dna_reader # (
        parameter g_SIM_DNA_VALUE = 96'hAABBCCDDEEFF112233445566
    )
    (
        input           clk_i,
        input           rst_n_i,
        output          dna_rdy_o,
        output [95:0]   dna_o
    );

    //! Status
    localparam [1:0] SET = 2'b00;
    localparam [1:0] UNSET = 2'b01;
    localparam [1:0] COUNT = 2'b11;
    localparam [1:0] DONE = 2'b10;
    (* fsm_encoding = "gray" *) reg [1:0] s_state;

    //! Constants
    localparam [6:0] c_MAX_CTR = 7'd96;

    //! Signals
    reg         s_read;
    reg         s_shift;
    reg         s_dna_rdy;
    reg [6:0]   s_shift_c;
    reg [95:0]  s_dna;
    wire        s_data;

    //! FSM
    always @(posedge clk_i, negedge rst_n_i)
    begin : p_fsm
        if(! rst_n_i) begin
            s_read <= 1'b0;
            s_shift <= 1'b0;
            s_shift_c <= 'h0;
            s_dna_rdy <= 1'b0;
            s_state <= SET;
        end
        else begin
            case (s_state)
                //! State SET
                SET:
                    begin
                        s_shift_c <= 'h0;
                        s_read <= 1'b1;
                        s_shift <= 1'b1;
                        s_dna_rdy <= 1'b0;
                        s_state <= UNSET;
                    end
                //! State UNSET
                UNSET:
                    begin
                        s_shift_c <= 'h0;
                        s_read <= 1'b0;
                        s_shift <= 1'b1;
                        s_dna_rdy <= 1'b0;
                        s_state <= COUNT;
                    end
                //! State COUNT
                COUNT:
                    begin
                        s_read <= 1'b0;
                        if (s_shift_c < c_MAX_CTR) begin
                            s_shift_c <= s_shift_c + 'd1;
                            s_shift <= 1'b1;
                            s_dna_rdy <= 1'b0;
                        end
                        else begin
                            s_shift <= 1'b0;
                            s_shift_c <= 'h0;
                            s_dna_rdy <= 1'b1;
                            s_state <= DONE;
                        end
                    end
                //! State DONE
                DONE:
                    begin
                        s_read <= 1'b0;
                        s_shift <= 1'b0;
                        s_shift_c <= 'h0;
                        s_dna_rdy <= 1'b1;
                        s_state <= DONE;
                    end
            endcase
        end
    end : p_fsm

    //! Shift Register
    always @(posedge clk_i, negedge rst_n_i)
    begin : p_shift
        if (! rst_n_i)
            s_dna <= 'h0;
        else begin
            if (s_shift)
                s_dna <= {s_data, s_dna[95:1]};
        end
    end : p_shift

    assign dna_rdy_o = s_dna_rdy;
    assign dna_o = s_dna;

    //! Instance Xilinx Macro
    DNA_PORTE2 # (
        .SIM_DNA_VALUE  (g_SIM_DNA_VALUE)
    ) i_DNA_PORTE2 (
        .CLK            (clk_i),
        .DIN            ('h0),
        .READ           (s_read),   //! input: load DNA
        .SHIFT          (s_shift),  //! input: shift enable input
        .DOUT           (s_data)    //! output: DNA output bit
    );

endmodule
//------------------------------------------------------------------------------
//! end module
//------------------------------------------------------------------------------
