/**************************************
* Module: DP_DRP_wrapper
* Date:2014-10-13  
* Author: rdikshi     
*
* Description: 
***************************************/
module  DP_DRP_wrapper(
    input [1:0]LINERATE,
    input DRPCLK,
    input DRPRST,
    input TXRESETDONE,
    input FSMRESETDONE,
    input DRPRDY,
    input [15:0]DRPDO,
    output [8:0]DRPADDR,
    output DRPEN,
    output [15:0]DRPDI,
    output DRPWE,
    output PHYSTATUS,
    output TXRESET
);
//*************************************************************************************************
// State Machine declaration
//*************************************************************************************************
parameter idle=3'b000, read5E=3'b001, write5E=3'b010, recover5E=3'b011, read88=3'b100, write88=3'b101, recover88=3'b110, genphystatus=3'b111;
reg [2:0]pstate;

//*************************************************************************************************
// Interface wire signal declaration
//*************************************************************************************************
wire resetDone;

//*************************************************************************************************
// Interface reg signal declaration
//*************************************************************************************************
reg LineRateChanged;
reg SwitchLineRate; 
reg [1:0]LineRate_r;
reg [8:0]drpaddr_r;
reg drpen_r;
reg drpwe_r;
reg [15:0]drpdo_r;
reg [15:0]drpdi_r;
reg [4:0]cpll_refclk_div_r;
reg cpll_fbdiv_45_r;
reg lookforLineRate;
reg [6:0]cpll_fbdiv_r;
reg [2:0]txout_div_r;
reg [2:0]rxout_div_r;
reg phystatus_r;
reg txreset_r;
//*************************************************************************************************
// Registering LINERATE Only with DRP is ready for line change &
// DRP reset is deasserted. LineRate_r default value to 2'b00 
// once through the software user starts the link training 
// the link rate chan be changed through linerate port.
//*************************************************************************************************
    always @(posedge DRPCLK) begin
        if (DRPRST)
            LineRate_r <= 2'b00; 
        else if (lookforLineRate == 1'b1 && resetDone == 1'b1)
            LineRate_r <= LINERATE;
    end

//*************************************************************************************************
// Important Txresetdone and fsmresetdone are the two important singnals which are driven from gt
// fsm reset signal is asserted once tx link is ready
// txresetdone is asserted or deasserted everytimg txreset signal is asserted in GT.
//*************************************************************************************************
 assign resetDone = TXRESETDONE & FSMRESETDONE;
 
//*************************************************************************************************    
// Assert SwitchLineRate signal only when There is a difference 
// Between LINERATE and registered version of lineRate
// switchlinerate is generated by statemachine upon configuring the link successfully.
// LINERATE is registered only when the state machine is in IDLE state and is cleared
// when both 5E and 88 registers are updated with current value.
//*************************************************************************************************    
    always @(posedge DRPCLK) begin
        if (DRPRST)
            SwitchLineRate <= 1'b0;
        else
            if ( LineRateChanged == 1'b1)
                SwitchLineRate <= 1'b0; 
            else if (LineRate_r != LINERATE) 
                SwitchLineRate <= 1'b1;
          
    end
    
//*************************************************************************************************
// LineRate confgiuration area.
// the values of registers and parameters are different 
// refer 7series_transceivers pdf UG476 for difference between attributes and DRP registers.
// NOTE: Please dont compare gtwizard_0_gt.v parameters with below parameters
//************************************************************************************************* 
    always @(posedge DRPCLK) begin
        if (DRPRST) begin
            cpll_refclk_div_r <= 5'b10000;
            cpll_fbdiv_45_r <= 1'b0;
            cpll_fbdiv_r <= 7'b0000001;
            rxout_div_r <= 3'b001;
            txout_div_r <= 3'b001;
        end else begin
            case (LineRate_r) 
                2'b00: // 1.62
                    begin
                        cpll_refclk_div_r <= 5'b10000;
                        cpll_fbdiv_45_r <= 1'b0;
                        cpll_fbdiv_r <= 7'b0000001;
                        txout_div_r <= 3'b001;
                        rxout_div_r <= 3'b001;                        
                    end
                2'b01: // 2.7
                    begin
                        cpll_refclk_div_r <= 5'b10000;
                        cpll_fbdiv_45_r <= 1'b1;
                        cpll_fbdiv_r <= 7'b0000010;
                        txout_div_r <= 3'b001;
                        rxout_div_r <= 3'b001;                        
                    end
                2'b10: // 5.4
                    begin
                        cpll_refclk_div_r <= 5'b10000;
                        cpll_fbdiv_45_r <= 1'b1;
                        cpll_fbdiv_r <= 7'b0000010;
                        txout_div_r <= 3'b000;
                        rxout_div_r <= 3'b000;                                       
                    end
                2'b11: //reserved case linerate switched to 1.67
                    begin
                        cpll_refclk_div_r <= 5'b10000;
                        cpll_fbdiv_45_r <= 1'b0;
                        cpll_fbdiv_r <= 7'b0000001;
                        txout_div_r <= 3'b001;
                        rxout_div_r <= 3'b001;                                            
                    end
                default:
                    begin
                        cpll_refclk_div_r <= 5'b10000;
                        cpll_fbdiv_45_r <= 1'b0;
                        cpll_fbdiv_r <= 7'b0000001;
                        txout_div_r <= 3'b001;
                        rxout_div_r <= 3'b001;                                            
                    end
            endcase
        end
    end
    
//*************************************************************************************************
// Statemachie for DRP writes.
//*************************************************************************************************     
    always @(posedge DRPCLK) begin
        if (DRPRST) begin
            pstate <= idle;
            drpaddr_r <= 9'h000;
            drpen_r <= 1'b0;
            drpwe_r <= 1'b0;
            drpdo_r <= 16'h0000;
            drpdi_r <= 16'h0000;
            LineRateChanged <= 1'b0;
            phystatus_r <= 1'b1;
            txreset_r <= 1'b1;
        end else begin
            drpaddr_r <= 9'h000;
            drpen_r <= 1'b0;
            drpwe_r <= 1'b0;
            LineRateChanged <= 1'b0;
            lookforLineRate <= 1'b0;
            phystatus_r <= 1'b1;
            txreset_r <= 1'b0;
            case(pstate)
                idle:
                    begin
                        lookforLineRate <= 1'b1;
                        if (SwitchLineRate == 1'b1 && resetDone == 1'b1) begin
                            drpaddr_r <= 9'h05E;
                            drpen_r <= 1'b1;
                            phystatus_r <= 1'b0;
                            pstate <= read5E;
                        end else if ( resetDone == 1'b1 ) begin
                            phystatus_r <= 1'b0;
                            pstate <= idle;
                        end else begin
                            phystatus_r <= 1'b1;
                            pstate <= idle;
                        end
                    end
                    
                read5E:
                    begin
                        phystatus_r <= 1'b0;
                        if (DRPRDY == 1'b1) begin
                            drpdi_r <= DRPDO;
                            pstate <= write5E;
                        end else
                            pstate <= read5E;
                    end
                    
                write5E:
                    begin
                        phystatus_r <= 1'b0;
                        drpdo_r <= {drpdi_r[15:13], cpll_refclk_div_r, cpll_fbdiv_45_r, cpll_fbdiv_r};
                        drpaddr_r <= 9'h05E;
                        drpen_r <= 1'b1;
                        drpwe_r <= 1'b1;
                        pstate <= recover5E;
                    end
                    
                recover5E:
                    begin
                        phystatus_r <= 1'b0;
                        if (DRPRDY == 1'b1) begin
                            drpaddr_r <= 9'h088;
                            drpen_r <= 1'b1;
                            pstate <= read88;
                        end else
                            pstate <= recover5E;
                    end
                        
                read88:
                    begin
                        phystatus_r <= 1'b0;
                        if (DRPRDY == 1'b1) begin
                            drpdi_r <= DRPDO;
                            pstate <= write88;
                        end else
                            pstate <= read88;
                    end
                    
                write88:
                    begin
                        phystatus_r <= 1'b0;
                        drpdo_r <= {drpdi_r[15:7], txout_div_r, drpdi_r[3], rxout_div_r};
                        drpaddr_r <= 9'h088;
                        drpen_r <= 1'b1;
                        drpwe_r <= 1'b1;
                        pstate <= recover88;
                    end
                    
                recover88:
                    begin
                        phystatus_r <= 1'b0;
                        if (DRPRDY == 1'b1) begin
                            txreset_r <= 1'b1;
                            LineRateChanged <= 1'b1;
                            pstate <= recover88;
                        end else if (resetDone == 1'b0) begin
                            pstate <= genphystatus;
                        end else
                            pstate <= recover88; 
                    end
                    
                genphystatus:
                    begin
                        phystatus_r <= 1'b0;
                        if (resetDone == 1'b1) begin
                            phystatus_r <= 1'b1;
                            pstate <= idle;
                        end else
                            pstate <= genphystatus;
                    end
                default:
                    pstate <= idle;
            endcase
        end
    end
    
//*************************************************************************************************
// Assigning IO ports
//*************************************************************************************************
assign DRPADDR = drpaddr_r;
assign DRPDI = drpdo_r;
assign DRPEN = drpen_r;
assign DRPWE = drpwe_r;
assign PHYSTATUS = phystatus_r;
assign TXRESET = txreset_r;

endmodule

