//////////////////////////////////////////////////////////////////////////////////
// Company:			TAIR
// Engineer:		
// 
// Create Date:		10/30/2023 11:24:31 AM
// Design Name:
// Module Name:		SPIs
// Project Name:	S5443_V3_FPGA3
// Target Devices:	BOARD: BY5443v3. FPGA: xc7s25csga225-2
// Tool Versions:
// Description: 	This is module implements an Spi Slave protocol.
// 
// Dependencies: 
// 
// Revision:
// Revision 1.0 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////
module SPIs (
    input Clk_i,
    input Rst_i,

    input Sck_i,
    input Ss_i,
    input Mosi0_i,
    input [1:0] WidthSel_i,
    input EndianSel_i,
    input SelSt_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 [31:0] shiftReg;
    reg [31:0] shiftRegM;

    reg [255:0] shiftRegDebug; 
 

//===============================================================================
//  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
          shiftRegM = 32'h0;
        end
        else begin 
            case(WidthSel_i)  
                 0: begin 
                    shiftRegM = shiftReg[7:0];
                end
                1: begin 
                    shiftRegM = shiftReg[15:0];
                end
                2: begin 
                    shiftRegM = shiftReg[23:0];
                end
                3: begin 
                    shiftRegM = shiftReg[31:0];
                end
            endcase
        end
    end

    always @(posedge Clk_i) begin 
        if (Rst_i) begin 
            Data_o <= 24'h0;
        end
        else begin
            if (SelSt_i) begin  
                if (ssReg && !ssRegR) begin 
                    Data_o <= shiftRegM;
                end
            end
            else begin 
                if (!ssReg && ssRegR) begin 
                    Data_o <= shiftRegM[23:0];
                end
            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 <= shiftRegM[31:24];
                end
            end
            else begin 
                if (!ssReg && ssRegR) begin 
                    Addr_o <= shiftRegM[31:24];
                end
            end
        end
    end

    always @(posedge Sck_i or posedge Rst_i) begin 
        if (Rst_i) begin 
            shiftRegDebug <= 0;
        end
        else begin
            if (!Ss_i) begin  
                shiftRegDebug <= {shiftRegDebug[190:0],Mosi0_i};
                // shiftRegDebug <= {Mosi0_i, shiftRegDebug[191:1]};
            end
            else begin
                shiftRegDebug <= 192'h0;
            end
        end
    end
    always @(posedge Clk_i) begin 
        if (Rst_i) begin 
            DebugData_o <= 192'h0;
        end
        else begin 
            if (ssReg && !ssRegR) begin 
                DebugData_o <= shiftRegDebug;
            end
        end
    end

    always @(posedge Sck_i) begin 
        if (Rst_i) begin 
            shiftReg<= 32'h0;
        end
        else begin
            if (!EndianSel_i) begin 
                if (SelSt_i) begin   
                    if (!Ss_i) begin
                        case (WidthSel_i)
                            0: begin 
                                shiftReg<= {shiftReg[6:0], Mosi0_i};
                            end
                            1: begin 
                                shiftReg<= {shiftReg[14:0], Mosi0_i};
                            end
                            2: begin 
                                shiftReg<= {shiftReg[22:0], Mosi0_i};
                            end
                            3: begin 
                                shiftReg<= {shiftReg[30:0], Mosi0_i};
                            end
                        endcase
                    end
                    else begin 
                        shiftReg<= 32'h0;
                    end
                end
                else begin 
                    if (Ss_i) begin
                        case (WidthSel_i)
                            0: begin 
                                shiftReg<= {shiftReg[6:0], Mosi0_i};
                            end
                            1: begin 
                                shiftReg<= {shiftReg[14:0], Mosi0_i};
                            end
                            2: begin 
                                shiftReg<= {shiftReg[22:0], Mosi0_i};
                            end
                            3: begin 
                                shiftReg<= {shiftReg[30:0], Mosi0_i};
                            end
                        endcase
                    end 
                    else begin 
                        shiftReg<= 32'h0;
                    end
                end
            end
            else begin 
                if (SelSt_i) begin   
                    if (!Ss_i) begin
                        case (WidthSel_i)
                            0: begin 
                                shiftReg<= {Mosi0_i, shiftReg[7:1]};
                            end
                            1: begin 
                                shiftReg<= {Mosi0_i, shiftReg[15:1]};
                            end
                            2: begin 
                                shiftReg<= {Mosi0_i, shiftReg[23:1]};
                            end
                            3: begin 
                                shiftReg<= {Mosi0_i, shiftReg[31:1]};
                            end
                        endcase
                    end
                    else begin 
                        shiftReg<= 32'h0;
                    end
                end
                else begin 
                    if (Ss_i) begin
                        case (WidthSel_i)
                            0: begin 
                                shiftReg<= {Mosi0_i, shiftReg[7:1]};
                            end
                            1: begin 
                                shiftReg<= {Mosi0_i, shiftReg[15:1]};
                            end
                            2: begin 
                                shiftReg<= {Mosi0_i, shiftReg[23:1]};
                            end
                            3: begin 
                                shiftReg<= {Mosi0_i, shiftReg[31:1]};
                            end
                        endcase
                    end
                    else begin 
                        shiftReg<= 32'h0;
                    end
                end
            end
        end
    end

    always @(posedge Clk_i) begin
        if (Rst_i) begin 
            Val_o <= 1'b0;
        end
        else 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
    end

    endmodule