module QuadSPIs (
    input Clk_i,
    input Rst_i,

    input Sck_i,
    input Ss_i,
    input Mosi0_i,
    input Mosi1_i,
    input Mosi2_i,
    input Mosi3_i,

    input [1:0] WidthSel_i,
    input SELST_i,
    input EndianSel_i,
   

    output reg [23:0] Data_o,
    output reg [7:0] Addr_o,
    output [31:0] DataToRxFifo_o,
    output reg [191:0] DebugData_o,
    output reg Val_o
);

//================================================================================
//	REG/WIRE
//================================================================================

reg ssReg;
reg ssRegR; 
reg SckReg; 
reg [7:0] addrReg;
reg [7:0] shiftReg0;
reg [7:0] shiftReg1;
reg [7:0] shiftReg2;

reg [7:0] addrRegLSB;
reg [7:0] shiftReg0LSB;
reg [7:0] shiftReg1LSB;
reg [7:0] shiftReg2LSB;

reg [7:0] shiftReg0M;
reg [7:0] shiftReg1M;
reg [7:0] shiftReg2M;
reg [7:0] addrRegM;

reg [47:0] shiftReg0Debug;
reg [47:0] shiftReg1Debug;
reg [47:0] shiftReg2Debug;
reg [47:0] shiftReg3Debug;

//===============================================================================
//  ASSIGNMENTS

assign DataToRxFifo_o = {Addr_o, Data_o};
//================================================================================
//	CODING
//================================================================================

always	@(posedge	Clk_i)	begin
	ssReg	<=	Ss_i;
	ssRegR	<=	ssReg;
end


always @(*) begin 
    if (Rst_i) begin
        addrRegM = 8'h0; 
        shiftReg0M = 8'h0;
        shiftReg1M = 8'h0;
        shiftReg2M = 8'h0;
    end
    else begin
        if (!EndianSel_i) begin  
            case(WidthSel_i)  
                 0: begin 
                    addrRegM   = addrReg  [1:0];
                    shiftReg0M = shiftReg0[1:0];
                    shiftReg1M = shiftReg1[1:0];
                    shiftReg2M = shiftReg2[1:0];
                end
                1: begin 
                    addrRegM   = addrReg  [3:0];
                    shiftReg0M = shiftReg0[3:0];
                    shiftReg1M = shiftReg1[3:0];
                    shiftReg2M = shiftReg2[3:0];
                end
                2: begin 
                    addrRegM   = addrReg  [5:0];
                    shiftReg0M = shiftReg0[5:0];
                    shiftReg1M = shiftReg1[5:0];
                    shiftReg2M = shiftReg2[5:0];
                end
                3: begin 
                    addrRegM   = addrReg  [7:0];
                    shiftReg0M = shiftReg0[7:0];
                    shiftReg1M = shiftReg1[7:0];
                    shiftReg2M = shiftReg2[7:0];
                end
            endcase
        end
        else begin 
            case(WidthSel_i) 
                    0: begin 
                        addrRegM   = addrRegLSB[1:0];
                        shiftReg0M = shiftReg0LSB[1:0];
                        shiftReg1M = shiftReg1LSB[1:0];
                        shiftReg2M = shiftReg2LSB[1:0];
                    end
                    1: begin 
                        addrRegM   = addrRegLSB[3:0];
                        shiftReg0M = shiftReg0LSB[3:0];
                        shiftReg1M = shiftReg1LSB[3:0];
                        shiftReg2M = shiftReg2LSB[3:0];
                    end
                    2: begin 
                        addrRegM   = addrRegLSB[5:0];
                        shiftReg0M = shiftReg0LSB[5:0];
                        shiftReg1M = shiftReg1LSB[5:0];
                        shiftReg2M = shiftReg2LSB[5:0];
                    end
                    3: begin 
                        addrRegM   = addrRegLSB[7:0];
                        shiftReg0M = shiftReg0LSB[7:0];
                        shiftReg1M = shiftReg1LSB[7:0];
                        shiftReg2M = shiftReg2LSB[7:0];
                    end
            endcase
        end
    end
end


always @(posedge Clk_i) begin 
    if (Rst_i) begin 
        Data_o <= 24'h0;
    end
    else begin
        if (!EndianSel_i) begin 
            if (SELST_i) begin  
                if (ssReg && !ssRegR) begin 
                    Data_o <= {shiftReg0M, shiftReg1M, shiftReg2M};
                end
            end
            else begin 
                if (!ssReg && ssRegR) begin 
                    Data_o <= {shiftReg0M, shiftReg1M, shiftReg2M};
                end
            end
        end
        else begin 
            if (SELST_i) begin  
                if (ssReg && !ssRegR) begin 
                    Data_o <= {shiftReg2M, shiftReg1M, shiftReg0M};
                end
            end
            else begin 
                if (!ssReg && ssRegR) begin 
                    Data_o <= {shiftReg2M, shiftReg1M, shiftReg0M};
                end
            end
        end
    end
end

always @(posedge Clk_i) begin 
    if (Rst_i) begin 
        DebugData_o <= 192'h0;
    end
    else begin 
        DebugData_o <= {shiftReg0Debug,shiftReg1Debug, shiftReg2Debug,shiftReg3Debug};
    end
end

always @(posedge Sck_i or posedge Rst_i) begin 
    if (Rst_i) begin 
        shiftReg0Debug <= 48'h0;
    end
    else begin 
        if (!Ss_i) begin 
            shiftReg0Debug <= {shiftReg0Debug[46:0], Mosi0_i};
        end
        else begin 
            shiftReg0Debug <= 48'h0;
        end
    end
end

always @(posedge Sck_i or posedge Rst_i) begin 
    if (Rst_i) begin 
        shiftReg1Debug <= 48'h0;
    end
    else begin 
        if (!Ss_i) begin 
            shiftReg1Debug <= {shiftReg1Debug[46:0], Mosi1_i};
        end
        else begin 
            shiftReg1Debug <= 48'h0;
        end
    end
end

always @(posedge Sck_i or posedge Rst_i) begin 
    if (Rst_i) begin 
        shiftReg2Debug <= 48'h0;
    end
    else begin 
        if (!Ss_i) begin 
            shiftReg2Debug <= {shiftReg2Debug[46:0], Mosi2_i};
        end
        else begin 
            shiftReg2Debug <= 48'h0;
        end
    end
end

always @(posedge Sck_i or posedge Rst_i) begin 
    if (Rst_i) begin 
        shiftReg3Debug <= 48'h0;
    end
    else begin 
        if (!Ss_i) begin 
            shiftReg3Debug <= {shiftReg3Debug[46:0], Mosi3_i};
        end
        else begin 
            shiftReg3Debug <= 48'h0;
        end
    end
end

always @(posedge Clk_i) begin 
    if (Rst_i) begin 
        Addr_o <= 8'h0;
    end
    else begin
        if (SELST_i) begin 
            if (ssReg && !ssRegR) begin 
                Addr_o <= addrRegM;
            end
        end
        else begin 
            if (!ssReg && ssRegR) begin 
                Addr_o <= addrRegM;
            end
        end
    end
end




always @(posedge Sck_i) begin 
    if (Rst_i) begin 
        shiftReg0 <= 8'h0;
    end
    else begin
        if (SELST_i) begin   
            if (!Ss_i) begin 
                shiftReg0 <= {shiftReg0[6:0], Mosi1_i};
            end
            else begin 
                shiftReg0 <= 8'h0;
            end
        end
        else begin 
            if (Ss_i) begin 
                shiftReg0 <= {shiftReg0[6:0], Mosi1_i};
            end
            else begin 
                shiftReg0<= 8'h0;
            end
        end
    end
end


always @(posedge Sck_i ) begin 
    if (Rst_i) begin 
        shiftReg1 <= 8'h0;
    end
    else begin
        if (SELST_i) begin   
            if (!Ss_i) begin 
                shiftReg1 <= {shiftReg1[6:0], Mosi2_i};
            end
            else begin 
                shiftReg1 <= 8'h0;
            end
        end
        else begin 
            if (Ss_i) begin 
                shiftReg1 <= {shiftReg1[6:0], Mosi2_i};
            end
            else begin 
                shiftReg1 <= 8'h0;
            end
        end
    end
end


always @(posedge Sck_i ) begin 
    if (Rst_i) begin 
        shiftReg2 <= 8'h0;
    end
    else begin
        if (SELST_i) begin   
            if (!Ss_i) begin 
                shiftReg2 <= {shiftReg2[6:0], Mosi3_i};
            end
            else begin 
                shiftReg2 <= 8'h0;
            end
        end
        else begin 
            if (Ss_i) begin 
                shiftReg2 <= {shiftReg2[6:0], Mosi3_i};
            end
            else begin 
                shiftReg2 <= 8'h0;
            end
        end
    end
end


always @(posedge Sck_i or posedge Rst_i ) begin 
    if (Rst_i) begin 
        addrReg <= 8'h0;
    end
    else begin
        if (SELST_i) begin 
            if (!Ss_i) begin 
                addrReg <={addrReg[6:0], Mosi0_i};
            end
            else begin 
                addrReg <= 8'h0;
            end
        end
        else begin 
            if (Ss_i) begin 
                addrReg <= {addrReg[6:0], Mosi0_i};
            end
            else begin 
                addrReg <= 8'h0;
            end
        end
    end
end

always @(posedge Sck_i or posedge Rst_i) begin
    if (Rst_i) begin 
        addrRegLSB <= 8'h0;
    end
    else begin 
        if (SELST_i) begin 
            if (!Ss_i) begin 
                addrRegLSB <= {Mosi3_i, addrRegLSB[7:1]};
            end
            else begin 
                addrRegLSB <= 8'h0;
            end
        end
        else begin 
            if (Ss_i) begin 
                addrRegLSB <= {Mosi3_i, addrRegLSB[7:1]};
            end
            else begin 
                addrRegLSB <= 8'h0;
            end
        end
    end
end

always @(posedge Sck_i or posedge Rst_i) begin 
    if (Rst_i) begin 
        shiftReg0LSB <= 8'h0;
    end
    else begin
        if (SELST_i) begin   
            if (!Ss_i) begin 
                shiftReg0LSB <= {Mosi0_i, shiftReg0LSB[7:1]};
            end
            else begin 
                shiftReg0LSB <= 8'h0;
            end
        end
        else begin 
            if (Ss_i) begin 
                shiftReg0LSB <= {Mosi0_i, shiftReg0LSB[7:1]};
            end
            else begin 
                shiftReg0LSB <= 8'h0;
            end
        end
    end
end

always @(posedge Sck_i or posedge Rst_i) begin 
    if (Rst_i) begin 
        shiftReg1LSB <= 8'h0;
    end
    else begin
        if (SELST_i) begin   
            if (!Ss_i) begin 
                shiftReg1LSB <= {Mosi1_i, shiftReg1LSB[7:1]};
            end
            else begin 
                shiftReg1LSB <= 8'h0;
            end
        end
        else begin 
            if (Ss_i) begin 
                shiftReg1LSB <= {Mosi1_i, shiftReg1LSB[7:1]};
            end
            else begin 
                shiftReg1LSB <= 8'h0;
            end
        end
    end
end


always @(posedge Sck_i or posedge Rst_i) begin 
    if (Rst_i) begin 
        shiftReg2LSB <= 8'h0;
    end
    else begin
        if (SELST_i) begin   
            if (!Ss_i) begin 
                shiftReg2LSB <= {Mosi2_i, shiftReg2LSB[7:1]};
            end
            else begin 
                shiftReg2LSB <= 8'h0;
            end
        end
        else begin 
            if (Ss_i) begin 
                shiftReg2LSB <= {Mosi2_i, shiftReg2LSB[7:1]};
            end
            else begin 
                shiftReg2LSB <= 8'h0;
            end
        end
    end
end


always @(posedge Clk_i) begin
    if (SELST_i) begin 
        if (ssReg && !ssRegR) begin 
            Val_o <= 1'b1;
        end
        else begin 
            Val_o <= 1'b0;
        end
    end
    else begin 
        if (!ssReg&& ssRegR) begin 
            Val_o <= 1'b1;
        end
        else begin 
            Val_o <= 1'b0;
        end
    end
end




endmodule