data/full_repos/permissive/42815087/cpu/SyzygyB100.srcs/sources_1/new/SDController.v
1: b'%Error: data/full_repos/permissive/42815087/cpu/SyzygyB100.srcs/sources_1/new/SDController.v:194: Cannot find file containing module: \'Mux2to1\'\n  Mux2to1 muxMOSISel0(\n  ^~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/42815087/cpu/SyzygyB100.srcs/sources_1/new,data/full_repos/permissive/42815087/Mux2to1\n             data/full_repos/permissive/42815087/cpu/SyzygyB100.srcs/sources_1/new,data/full_repos/permissive/42815087/Mux2to1.v\n             data/full_repos/permissive/42815087/cpu/SyzygyB100.srcs/sources_1/new,data/full_repos/permissive/42815087/Mux2to1.sv\n             Mux2to1\n             Mux2to1.v\n             Mux2to1.sv\n             obj_dir/Mux2to1\n             obj_dir/Mux2to1.v\n             obj_dir/Mux2to1.sv\n%Error: data/full_repos/permissive/42815087/cpu/SyzygyB100.srcs/sources_1/new/SDController.v:200: Cannot find file containing module: \'Mux2to1\'\n  Mux2to1 muxMOSISel1(\n  ^~~~~~~\n%Warning-WIDTH: data/full_repos/permissive/42815087/cpu/SyzygyB100.srcs/sources_1/new/SDController.v:298: Operator SUB expects 32 or 16 bits on the LHS, but LHS\'s VARREF \'responseLen\' generates 8 bits.\n                                                                                                        : ... In instance SDController\n              count = responseLen - 1;\n                                  ^\n                ... Use "/* verilator lint_off WIDTH */" and lint_on around source to disable this message.\n%Warning-WIDTH: data/full_repos/permissive/42815087/cpu/SyzygyB100.srcs/sources_1/new/SDController.v:520: Operator ASSIGN expects 8 bits on the Assign RHS, but Assign RHS\'s VARREF \'BLOCK_COUNT\' generates 32 or 13 bits.\n                                                                                                        : ... In instance SDController\n        blockCount = BLOCK_COUNT;\n                   ^\n%Warning-WIDTH: data/full_repos/permissive/42815087/cpu/SyzygyB100.srcs/sources_1/new/SDController.v:681: Operator SUB expects 32 or 16 bits on the LHS, but LHS\'s VARREF \'responseLen\' generates 8 bits.\n                                                                                                        : ... In instance SDController\n            count = responseLen - 1;\n                                ^\n%Error: data/full_repos/permissive/42815087/cpu/SyzygyB100.srcs/sources_1/new/SDController.v:955: Cannot find file containing module: \'Mux16B8to1\'\n  Mux16B8to1 sdDbgMux(\n  ^~~~~~~~~~\n%Error: Exiting due to 3 error(s), 3 warning(s)\n'
module SDController(
    input ctrlClk,
    input [31:0] addr,
    input [15:0] dIn,
    input [15:0] op,
    input exec,
    input reset,
    input miso,
    input [3:0] debugRegSelect,
    output reg serialClockOut = 1'b0,
    output reg [2:0] status = 3'b001,
    output reg updateStatus = 1'b0,
    output reg clkR1 = 1'b0,
    output reg [15:0] dOut = 16'h0000,
    output reg updateDataOut = 1'b0,
    output reg clkR3 = 1'b0,
    output reg chipSelect = 1'b1,
    output mosi,
    output [15:0] debugOut
  );
  












  

  parameter LO = 1'b0;
  parameter HI = 1'b1;
  

  parameter STATUS_BUSY_INIT = 0;
  parameter STATUS_READY = 1;
  parameter STATUS_BUSY_BLKRD = 2;
  parameter STATUS_BUSY_BLKWR = 3;
  parameter STATUS_ERR_INIT = 4;
  parameter STATUS_ERR_BLK_CMD = 5;
  parameter STATUS_WAITING_BLKRD = 6;
  parameter STATUS_WAITING_BLKWR = 7;
  

  parameter TIMEOUT_COUNT = 128;
  parameter CMD_LENGTH = 48;
  parameter RESP_R1_LEN = 8;
  parameter RESP_R7_LEN = 40;
  parameter FLUSH_COUNT = 100;
  parameter DESELECT_COUNT = 4;
  parameter BLOCK_BIT_COUNT = 4096;
  parameter CLOCK_REDUCE_AMT = 1023;
  parameter WORD_LENGTH = 16;
  parameter BLOCK_COUNT = BLOCK_BIT_COUNT / WORD_LENGTH;
  

  parameter MUX_CONST_HI = 2'b00;
  parameter MUX_CMD_MSB = 2'b10;
  parameter MUX_DAT_MSB = 2'b11;
  

  parameter TOKEN_DATA_START = 8'hfe;
  parameter TOKEN_DATA_LEN = 8;
  parameter TOKEN_CMD0_RESP = 8'h01;
  parameter TOKEN_R1_RESP = 8'h00;
  parameter TOKEN_DATA_ACC = 5'b00101;
  parameter TOKEN_DATA_CRC_ERR = 5'b01011;
  parameter TOKEN_DATA_WRITE_ERR = 5'b01101;
  

  parameter CMD_CMD0 = 8'h40;
  parameter CMD_CMD8 = 8'h48;
  parameter CMD_CMD55 = 8'h77;
  parameter CMD_CMD41 = 8'h69;
  parameter CMD_CMD17 = 8'h51;
  parameter CMD_CMD24 = 8'h58;
  

  parameter CRC_CMD0 = 8'h95;
  parameter CRC_CMD8 = 8'h87;
  parameter CRC_DUMMY = 8'hff;
  

  parameter ARG_CMD8 = 32'h000001aa;
  parameter ARG_ACMD41 = 32'h40000000;
  parameter ARG_EMPTY = 32'h00000000;
  

  parameter STATE_FLUSH_BITS = 5'b00000;
  parameter STATE_READY_CMD0 = 5'b00001;
  parameter STATE_SEND_CMD = 5'b00010;
  parameter STATE_AWAIT_RESPONSE = 5'b00011;
  parameter STATE_GET_RESPONSE = 5'b00100;
  parameter STATE_CHECK_R1_RESPONSE = 5'b00101;
  parameter STATE_CHECK_R7_RESPONSE = 5'b00110;
  parameter STATE_DESELECT = 5'b00111;
  parameter STATE_READY_CMD8 = 5'b01000;
  parameter STATE_READY_CMD55 = 5'b01001;
  parameter STATE_READY_CMD41 = 5'b01010;
  parameter STATE_FINISH_INIT = 5'b01011;
  

  parameter STATE_WAIT_FOR_HOST = 5'b01100;
  parameter STATE_WAIT_FOR_CONTINUE = 5'b01101;
  parameter STATE_FINISH_BLOCK_IO = 5'b01110;
  parameter STATE_UPDATE_R1 = 5'b01111;
  

  parameter STATE_READY_CMD17 = 5'b10000;
  parameter STATE_SETUP_AWAIT_TOKEN = 5'b10001;
  parameter STATE_AWAIT_DATA_TOKEN = 5'b10010;
  parameter STATE_CHECK_DATA_TOKEN = 5'b10011;
  parameter STATE_READ_WORD = 5'b10100;
  parameter STATE_UPDATE_R3 = 5'b10101;
  

  parameter STATE_READY_CMD24 = 5'b10110;
  parameter STATE_READY_DATA_TOKEN = 5'b10111;
  parameter STATE_SEND_DATA_TOKEN = 5'b11000;
  parameter STATE_GET_R2_DATA = 5'b11001;
  parameter STATE_WRITE_WORD = 5'b11010;
  

  parameter STATE_CLOCK_COUNTDOWN = 5'b11111;
  

  reg [4:0] state = STATE_FLUSH_BITS;
  
  reg [4:0] returnState = STATE_FLUSH_BITS;

                                            
  reg [4:0] nextState = STATE_READY_CMD0;

                                            
  reg [4:0] errState = STATE_READY_CMD0;

                                            
  reg [15:0] count = FLUSH_COUNT;
  
  reg [15:0] clockCount = 0;




                                            
  reg [7:0] blockCount = 0;

                                            
  reg [39:0] response = 0;
  
  reg [47:0] command = 0;
  
  reg [1:0] mosiSrc = MUX_CONST_HI;

  
  reg [7:0] responseLen = 0;

                                              
  reg [7:0] expectedResp = 0;

  
  reg blockMode = 0;



                                            
  reg [15:0] data = 0;

                                            
  reg [31:0] blockAddr = 0;

                                            
  reg accessMode = 0;

                                            
  reg clockTicked = 0;

  

  reg misoVal = 0;
  reg mosiVal = 0;
  
  wire [15:0] wDebugSignals = {12'h000, serialClockOut, chipSelect, mosiVal, misoVal};
  

  wire wMuxTemp;
  Mux2to1 muxMOSISel0(
    .aIn(command[47]),
    .bIn(data[15]),
    .sel(mosiSrc[0]),
    .out(wMuxTemp)
  );
  Mux2to1 muxMOSISel1(
    .aIn(HI),
    .bIn(wMuxTemp),
    .sel(mosiSrc[1]),
    .out(mosi)
  );
  

  always @ (negedge ctrlClk) begin
    
    case(state[4:0])
      



      STATE_FLUSH_BITS: begin
      
        if(count > 0) begin
          if(serialClockOut == HI) begin
            count = count - 1;
          end
          

          serialClockOut = ~serialClockOut;
          returnState = STATE_FLUSH_BITS;
          clockCount = CLOCK_REDUCE_AMT;
          state = STATE_CLOCK_COUNTDOWN;
          
        end else begin
          state = nextState;
        end
        
      end
      



      STATE_READY_CMD0: begin
        command[47:0] = {CMD_CMD0, ARG_EMPTY, CRC_CMD0};
        state = STATE_SEND_CMD;
        nextState = STATE_READY_CMD8;
        errState = STATE_READY_CMD0;
        responseLen = RESP_R1_LEN;
        expectedResp = TOKEN_CMD0_RESP;
        count = CMD_LENGTH;
        mosiSrc = MUX_CMD_MSB;
        chipSelect = LO;
      end
      



      STATE_SEND_CMD: begin
        if(count > 0) begin
        
          if(serialClockOut == HI) begin
            serialClockOut = LO;
          end else if(clockTicked == HI) begin
            command[47:0] = {command[46:0], LO};
            count = count - 1;
            clockTicked = LO;
          end else begin
            serialClockOut = HI;
            clockTicked = HI;
          end
        

          returnState = STATE_SEND_CMD;
          clockCount = CLOCK_REDUCE_AMT;
          state = STATE_CLOCK_COUNTDOWN;
        
        end else begin
          mosiSrc = MUX_CONST_HI;
          state = STATE_AWAIT_RESPONSE;
          count = TIMEOUT_COUNT;
          returnState = STATE_AWAIT_RESPONSE;
        end
        
      end
      




      STATE_AWAIT_RESPONSE: begin
      
        case({serialClockOut, clockTicked})
        

          2'b00: begin
            serialClockOut = HI;
          end
          

          2'b01: begin
            
            if(response[0] == LO) begin
              returnState = STATE_GET_RESPONSE;
              count = responseLen - 1;
            end else if(count == 0) begin
              returnState = STATE_GET_RESPONSE;
              nextState = errState;
              count = DESELECT_COUNT;
              chipSelect = HI;
            end else begin
              count = count - 1;
              returnState = STATE_AWAIT_RESPONSE;
            end
            
            clockTicked = LO;
          end
          

          2'b10: begin
            
            response[39:0] = {response[38:0], miso};
            clockTicked = HI;
            
          end
          

          2'b11: begin
            serialClockOut = LO;
          end
        
        endcase
      

        clockCount = CLOCK_REDUCE_AMT;
        state = STATE_CLOCK_COUNTDOWN;
        
      end
    



    STATE_GET_RESPONSE: begin
    

      if(count == 0) begin
          

        if(responseLen == RESP_R7_LEN) begin
          state = STATE_CHECK_R7_RESPONSE;
          returnState = STATE_CHECK_R7_RESPONSE;
        end else begin
          state = STATE_CHECK_R1_RESPONSE;
          returnState = STATE_CHECK_R1_RESPONSE;
        end
        

      end else begin
      
        case({serialClockOut, clockTicked})
              

          2'b00: begin
            serialClockOut = HI;
          end
          

          2'b01: begin
            
            count = count - 1;
            returnState = STATE_GET_RESPONSE;
            clockTicked = LO;
          end
          

          2'b10: begin
            
            response[39:0] = {response[38:0], miso};
            clockTicked = HI;
            
          end
          

          2'b11: begin
            serialClockOut = LO;
          end
        
        endcase
      

        clockCount = CLOCK_REDUCE_AMT;
        state = STATE_CLOCK_COUNTDOWN;
      end
    
    end
    



    STATE_CHECK_R1_RESPONSE: begin
      if(response[7:0] != expectedResp[7:0]) begin
        nextState <= errState;
      end
      if(blockMode == HI) begin
        state <= nextState;
      end else begin
        state = STATE_DESELECT;
        count = DESELECT_COUNT;
        chipSelect = HI;
      end
    end
    




    STATE_CHECK_R7_RESPONSE: begin
      if(response[39:32] != expectedResp[7:0]) begin
        nextState = errState;
      end
      state = STATE_DESELECT;
      count = DESELECT_COUNT;
      chipSelect = HI;
    end
    



    STATE_DESELECT: begin
      if(count > 0) begin
        if(serialClockOut == HI) begin
          count = count - 1;
        end
        

        serialClockOut = ~serialClockOut;
        returnState = STATE_DESELECT;
        clockCount = CLOCK_REDUCE_AMT;
        state = STATE_CLOCK_COUNTDOWN;
        
      end else begin
        

        if(blockMode == HI) begin
          state = STATE_UPDATE_R1;
          nextState = STATE_WAIT_FOR_HOST;
        end else begin
          state = nextState;
        end
      end
    end
    



    STATE_READY_CMD8: begin
      command[47:0] = {CMD_CMD8, ARG_CMD8, CRC_CMD8};
      state = STATE_SEND_CMD;
      nextState = STATE_READY_CMD55;
      errState = STATE_READY_CMD8;
      responseLen = RESP_R7_LEN;
      expectedResp = TOKEN_CMD0_RESP;
      count = CMD_LENGTH;
      mosiSrc = MUX_CMD_MSB;
      chipSelect = LO;
    end
    



    STATE_READY_CMD55: begin
      command[47:0] = {CMD_CMD55, ARG_EMPTY, CRC_DUMMY};
      state = STATE_SEND_CMD;
      nextState = STATE_READY_CMD41;
      errState = STATE_READY_CMD55;
      responseLen = RESP_R1_LEN;
      expectedResp = TOKEN_CMD0_RESP;
      count = CMD_LENGTH;
      mosiSrc = MUX_CMD_MSB;
      chipSelect = LO;
    end
    



    STATE_READY_CMD41: begin
      command[47:0] = {CMD_CMD41, ARG_ACMD41, CRC_DUMMY};
      state = STATE_SEND_CMD;
      nextState = STATE_FINISH_INIT;
      errState = STATE_READY_CMD55;
      responseLen = RESP_R1_LEN;
      expectedResp = TOKEN_R1_RESP;
      count = CMD_LENGTH;
      mosiSrc = MUX_CMD_MSB;
      chipSelect = LO;
    end
    



    STATE_FINISH_INIT: begin
      if(clockTicked == HI) begin
        updateStatus = LO;
        clockTicked = LO;
        state = STATE_WAIT_FOR_HOST;
      end else if(updateStatus == HI) begin
        clockTicked = HI;
        clkR1 = LO;
      end else begin
        errState = STATE_WAIT_FOR_HOST;
        response = 0;
        blockMode = HI;
        status = STATUS_READY;
        updateStatus = HI;
        clkR1 = HI;
        returnState = STATE_WAIT_FOR_HOST;
      end
    end
    



    STATE_WAIT_FOR_HOST: begin
      if(exec) begin
      
        blockAddr[31:0] = addr[31:0];
        blockCount = BLOCK_COUNT;
        response = 0;
      

        case(op[1:0])
          

          2'b00: begin
            nextState = STATE_READY_CMD17;
            state = STATE_UPDATE_R1;
            status = STATUS_BUSY_BLKRD;
            accessMode = 0;
          end
          

          2'b01: begin
            nextState = STATE_READY_CMD24;
            state = STATE_UPDATE_R1;
            status = STATUS_BUSY_BLKWR;
            accessMode = 1;
          end
          

          default: begin

          end
        endcase
      end
    end
    



    STATE_WAIT_FOR_CONTINUE: begin
      

      if(blockCount == 0) begin
        count = TIMEOUT_COUNT;
        returnState = STATE_FLUSH_BITS;
        nextState = STATE_FINISH_BLOCK_IO;
        state = STATE_FLUSH_BITS;
      

      end else if(exec) begin
        case(op[1:0])
          

          2'b10: begin
            count = WORD_LENGTH;
            if(accessMode == 0) begin
              nextState = STATE_READ_WORD;
              status = STATUS_BUSY_BLKRD;
              returnState = STATE_READ_WORD;
            end else begin
              nextState = STATE_GET_R2_DATA;
              status = STATUS_BUSY_BLKWR;
              returnState = STATE_GET_R2_DATA;
            end
            state = STATE_UPDATE_R1;
          end
          

          2'b11: begin
            count = BLOCK_BIT_COUNT + WORD_LENGTH;
            nextState = STATE_FINISH_BLOCK_IO;
            state = STATE_FLUSH_BITS;
          end
          

          default: begin

          end
        endcase
      end
    end
    



    STATE_FINISH_BLOCK_IO: begin
      accessMode = 0;
      count = DESELECT_COUNT;
      clockCount = 0;
      blockCount = 0;
      nextState = STATE_UPDATE_R1;
      errState = STATUS_READY;
      returnState = STATE_DESELECT;
      data = 0;
      response = 0;
      command = 0;
      mosiSrc = MUX_CONST_HI;
      blockAddr = 0;
      status = STATUS_READY;
      state = STATE_DESELECT;
      chipSelect = HI;
    end
    



    STATE_UPDATE_R1: begin
      
      if(clockTicked == HI) begin
        clockTicked = LO;
        state = nextState;
      end else if(clkR1 == HI) begin
        clkR1 = LO;
      end else if(updateStatus == HI) begin
        updateStatus = LO;
        clockTicked = HI;
      end else begin
        clkR1 = HI;
        updateStatus = HI;
      end
      
    end




    STATE_READY_CMD17: begin
      returnState = STATE_SEND_CMD;
      command[47:0] = {CMD_CMD17[7:0], blockAddr[31:0], CRC_DUMMY[7:0]};
      state = STATE_SEND_CMD;
      nextState = STATE_SETUP_AWAIT_TOKEN;
      errState = STATE_FINISH_BLOCK_IO;
      responseLen = RESP_R1_LEN;
      expectedResp = TOKEN_R1_RESP;
      count = CMD_LENGTH;
      mosiSrc = MUX_CMD_MSB;
      chipSelect = LO;
    end
    



    STATE_SETUP_AWAIT_TOKEN: begin
      count = TIMEOUT_COUNT;
      returnState = STATE_AWAIT_DATA_TOKEN;
      response = 0;
      state = STATE_AWAIT_DATA_TOKEN;
    end
    



    STATE_AWAIT_DATA_TOKEN: begin
      
      case({serialClockOut, clockTicked})
            

        2'b00: begin
          serialClockOut = HI;
        end
        

        2'b01: begin
          

          if(response[0] == LO) begin
            returnState = STATE_CHECK_DATA_TOKEN;
            count = responseLen - 1;
            

          end else if(count == 0) begin
            count = BLOCK_BIT_COUNT + TIMEOUT_COUNT;
            returnState = STATE_FLUSH_BITS;
            nextState = STATE_FINISH_BLOCK_IO;
            status = STATUS_ERR_BLK_CMD;
          

          end else begin
            count = count - 1;
            returnState = STATE_AWAIT_DATA_TOKEN;
          end
          
          clockTicked = LO;
        end
        

        2'b10: begin
          
          response[39:0] = {response[38:0], miso};
          clockTicked = HI;
          
        end
        

        2'b11: begin
          serialClockOut = LO;
        end
      
      endcase
    

      clockCount = CLOCK_REDUCE_AMT;
      state = STATE_CLOCK_COUNTDOWN;
      
    end
    



    STATE_CHECK_DATA_TOKEN: begin
      

      if(response[7:0] != TOKEN_DATA_START) begin
        state = STATE_FLUSH_BITS;
        nextState = STATE_FINISH_BLOCK_IO;
        returnState = STATE_FLUSH_BITS;
        count = WORD_LENGTH;
        status = STATUS_ERR_BLK_CMD;
      

      end else begin
        state = STATE_READ_WORD;
        returnState = STATE_READ_WORD;
        count = WORD_LENGTH;
      end
    end
    



    STATE_READ_WORD: begin
    
      if(count == 0) begin
      
        blockCount = blockCount - 1;
        nextState = STATE_UPDATE_R1;
        returnState = STATE_UPDATE_R3;
        state = STATE_UPDATE_R3;
        
      end else begin
      
        case({serialClockOut, clockTicked})
                    

          2'b00: begin
            serialClockOut = HI;
          end
          

          2'b01: begin
            
            count <= count - 1;
            returnState = STATE_READ_WORD;
            clockTicked = LO;
          end
          

          2'b10: begin
            
            data[15:0] = {data[14:0], miso};
            clockTicked = HI;
            
          end
          

          2'b11: begin
            serialClockOut = LO;
          end
        
        endcase
      

        clockCount = CLOCK_REDUCE_AMT;
        state = STATE_CLOCK_COUNTDOWN;
      end
    
    end
    



    STATE_UPDATE_R3: begin
    
      if(clockTicked == HI) begin
        dOut = 0;
        state = nextState;
        status = STATUS_WAITING_BLKRD;
        clockTicked = LO;
        nextState = STATE_WAIT_FOR_CONTINUE;
      end else if(clkR3 == HI) begin
        clkR3 = LO;
      end else if(updateDataOut == HI) begin
        updateDataOut = LO;
        clockTicked = HI;
      end else begin
        clkR3 = HI;
        updateDataOut = HI;
        dOut = data;
      end
      
    end
    



    STATE_READY_CMD24: begin
      command[47:0] = {CMD_CMD24, blockAddr[31:0], CRC_DUMMY};
      state = STATE_SEND_CMD;
      nextState = STATE_READY_DATA_TOKEN;
      errState = STATE_FINISH_BLOCK_IO;
      responseLen = RESP_R1_LEN;
      expectedResp = TOKEN_R1_RESP;
      count = CMD_LENGTH;
      mosiSrc = MUX_CMD_MSB;
      chipSelect = LO;
    end
    



    STATE_READY_DATA_TOKEN: begin
      command[47:0] = {TOKEN_DATA_START, 40'h0000000000};
      state = STATE_SEND_DATA_TOKEN;
      nextState = STATE_WAIT_FOR_CONTINUE;
      returnState = STATE_SEND_DATA_TOKEN;
      count = TOKEN_DATA_LEN;
      mosiSrc = MUX_CMD_MSB;
    end
    



    STATE_SEND_DATA_TOKEN: begin
      
      if(count > 0) begin
      
        if(serialClockOut == HI) begin
          serialClockOut = LO;
        end else if(clockTicked == HI) begin
          command[47:0] = {command[46:0], LO};
          count = count - 1;
          clockTicked = LO;
        end else begin
          serialClockOut = HI;
          clockTicked = HI;
        end
      

        returnState = STATE_SEND_DATA_TOKEN;
        clockCount = CLOCK_REDUCE_AMT;
        state = STATE_CLOCK_COUNTDOWN;
      
      end else begin
        mosiSrc = MUX_CONST_HI;
        state = STATE_GET_R2_DATA;
        returnState = STATE_GET_R2_DATA;
      end
      
    end
    



    STATE_GET_R2_DATA: begin
      count = WORD_LENGTH;
      mosiSrc = MUX_DAT_MSB;
      data[15:0] = dIn[15:0];
      returnState = STATE_WRITE_WORD;
      state = STATE_WRITE_WORD;
    end
    



    STATE_WRITE_WORD: begin
      
      if(count > 0) begin
      
        if(serialClockOut == HI) begin
          serialClockOut = LO;
        end else if(clockTicked == HI) begin
          data[15:0] = {data[14:0], 1'b0};
          count = count - 1;
          clockTicked = LO;
        end else begin
          serialClockOut = HI;
          clockTicked = HI;
        end
      

        returnState = STATE_WRITE_WORD;
        clockCount = CLOCK_REDUCE_AMT;
        state = STATE_CLOCK_COUNTDOWN;
      
      end else begin
        returnState = STATE_UPDATE_R1;
        state = STATE_UPDATE_R1;
        nextState = STATE_WAIT_FOR_CONTINUE;
        status = STATUS_WAITING_BLKWR;
        blockCount = blockCount - 1;
        mosiSrc = MUX_CONST_HI;
      end
      
    end
    




    STATE_CLOCK_COUNTDOWN: begin
      if(clockCount == 0) begin
        state = returnState;
      end else begin
        clockCount = clockCount - 1;
      end
    end
    



    default: begin
      state = STATUS_ERR_INIT;
      nextState = STATUS_ERR_INIT;
      errState = STATUS_ERR_INIT;
      chipSelect = HI;
      response = 0;
      count = 0;
      command = 0;
      mosiSrc = MUX_CONST_HI;
      responseLen = 0;
      expectedResp = 0;
      blockMode = HI;
    end
    
    endcase
    
    mosiVal = mosi;
    misoVal = miso;
    
  end
  
  Mux16B8to1 sdDbgMux(
    .dIn0(wDebugSignals[15:0]),
    .dIn1({11'b00000000000, state[4:0]}),
    .dIn2({11'b00000000000, returnState[4:0]}),
    .dIn3(count[15:0]),
    .dIn4({8'h00, blockCount[7:0]}),
    .dIn5(response[15:0]),
    .dIn6(response[39:24]),
    .dIn7(clockCount[15:0]),
    .sel(debugRegSelect[2:0]),
    .dOut(debugOut[15:0])
  );
  
endmodule
module SDController(
    input ctrlClk,
    input [31:0] addr,
    input [15:0] dIn,
    input [15:0] op,
    input exec,
    input reset,
    input miso,
    input [3:0] debugRegSelect,
    output reg serialClockOut = 1'b0,
    output reg [2:0] status = 3'b001,
    output reg updateStatus = 1'b0,
    output reg clkR1 = 1'b0,
    output reg [15:0] dOut = 16'h0000,
    output reg updateDataOut = 1'b0,
    output reg clkR3 = 1'b0,
    output reg chipSelect = 1'b1,
    output mosi,
    output [15:0] debugOut
  );

  












  

  parameter LO = 1'b0;
  parameter HI = 1'b1;
  

  parameter STATUS_BUSY_INIT = 0;
  parameter STATUS_READY = 1;
  parameter STATUS_BUSY_BLKRD = 2;
  parameter STATUS_BUSY_BLKWR = 3;
  parameter STATUS_ERR_INIT = 4;
  parameter STATUS_ERR_BLK_CMD = 5;
  parameter STATUS_WAITING_BLKRD = 6;
  parameter STATUS_WAITING_BLKWR = 7;
  

  parameter TIMEOUT_COUNT = 128;
  parameter CMD_LENGTH = 48;
  parameter RESP_R1_LEN = 8;
  parameter RESP_R7_LEN = 40;
  parameter FLUSH_COUNT = 100;
  parameter DESELECT_COUNT = 4;
  parameter BLOCK_BIT_COUNT = 4096;
  parameter CLOCK_REDUCE_AMT = 1023;
  parameter WORD_LENGTH = 16;
  parameter BLOCK_COUNT = BLOCK_BIT_COUNT / WORD_LENGTH;
  

  parameter MUX_CONST_HI = 2'b00;
  parameter MUX_CMD_MSB = 2'b10;
  parameter MUX_DAT_MSB = 2'b11;
  

  parameter TOKEN_DATA_START = 8'hfe;
  parameter TOKEN_DATA_LEN = 8;
  parameter TOKEN_CMD0_RESP = 8'h01;
  parameter TOKEN_R1_RESP = 8'h00;
  parameter TOKEN_DATA_ACC = 5'b00101;
  parameter TOKEN_DATA_CRC_ERR = 5'b01011;
  parameter TOKEN_DATA_WRITE_ERR = 5'b01101;
  

  parameter CMD_CMD0 = 8'h40;
  parameter CMD_CMD8 = 8'h48;
  parameter CMD_CMD55 = 8'h77;
  parameter CMD_CMD41 = 8'h69;
  parameter CMD_CMD17 = 8'h51;
  parameter CMD_CMD24 = 8'h58;
  

  parameter CRC_CMD0 = 8'h95;
  parameter CRC_CMD8 = 8'h87;
  parameter CRC_DUMMY = 8'hff;
  

  parameter ARG_CMD8 = 32'h000001aa;
  parameter ARG_ACMD41 = 32'h40000000;
  parameter ARG_EMPTY = 32'h00000000;
  

  parameter STATE_FLUSH_BITS = 5'b00000;
  parameter STATE_READY_CMD0 = 5'b00001;
  parameter STATE_SEND_CMD = 5'b00010;
  parameter STATE_AWAIT_RESPONSE = 5'b00011;
  parameter STATE_GET_RESPONSE = 5'b00100;
  parameter STATE_CHECK_R1_RESPONSE = 5'b00101;
  parameter STATE_CHECK_R7_RESPONSE = 5'b00110;
  parameter STATE_DESELECT = 5'b00111;
  parameter STATE_READY_CMD8 = 5'b01000;
  parameter STATE_READY_CMD55 = 5'b01001;
  parameter STATE_READY_CMD41 = 5'b01010;
  parameter STATE_FINISH_INIT = 5'b01011;
  

  parameter STATE_WAIT_FOR_HOST = 5'b01100;
  parameter STATE_WAIT_FOR_CONTINUE = 5'b01101;
  parameter STATE_FINISH_BLOCK_IO = 5'b01110;
  parameter STATE_UPDATE_R1 = 5'b01111;
  

  parameter STATE_READY_CMD17 = 5'b10000;
  parameter STATE_SETUP_AWAIT_TOKEN = 5'b10001;
  parameter STATE_AWAIT_DATA_TOKEN = 5'b10010;
  parameter STATE_CHECK_DATA_TOKEN = 5'b10011;
  parameter STATE_READ_WORD = 5'b10100;
  parameter STATE_UPDATE_R3 = 5'b10101;
  

  parameter STATE_READY_CMD24 = 5'b10110;
  parameter STATE_READY_DATA_TOKEN = 5'b10111;
  parameter STATE_SEND_DATA_TOKEN = 5'b11000;
  parameter STATE_GET_R2_DATA = 5'b11001;
  parameter STATE_WRITE_WORD = 5'b11010;
  

  parameter STATE_CLOCK_COUNTDOWN = 5'b11111;
  

  reg [4:0] state = STATE_FLUSH_BITS;
  
  reg [4:0] returnState = STATE_FLUSH_BITS;

                                            
  reg [4:0] nextState = STATE_READY_CMD0;

                                            
  reg [4:0] errState = STATE_READY_CMD0;

                                            
  reg [15:0] count = FLUSH_COUNT;
  
  reg [15:0] clockCount = 0;




                                            
  reg [7:0] blockCount = 0;

                                            
  reg [39:0] response = 0;
  
  reg [47:0] command = 0;
  
  reg [1:0] mosiSrc = MUX_CONST_HI;

  
  reg [7:0] responseLen = 0;

                                              
  reg [7:0] expectedResp = 0;

  
  reg blockMode = 0;



                                            
  reg [15:0] data = 0;

                                            
  reg [31:0] blockAddr = 0;

                                            
  reg accessMode = 0;

                                            
  reg clockTicked = 0;

  

  reg misoVal = 0;
  reg mosiVal = 0;
  
  wire [15:0] wDebugSignals = {12'h000, serialClockOut, chipSelect, mosiVal, misoVal};
  

  wire wMuxTemp;
  Mux2to1 muxMOSISel0(
    .aIn(command[47]),
    .bIn(data[15]),
    .sel(mosiSrc[0]),
    .out(wMuxTemp)
  );
  Mux2to1 muxMOSISel1(
    .aIn(HI),
    .bIn(wMuxTemp),
    .sel(mosiSrc[1]),
    .out(mosi)
  );
  

  always @ (negedge ctrlClk) begin
    
    case(state[4:0])
      



      STATE_FLUSH_BITS: begin
      
        if(count > 0) begin
          if(serialClockOut == HI) begin
            count = count - 1;
          end
          

          serialClockOut = ~serialClockOut;
          returnState = STATE_FLUSH_BITS;
          clockCount = CLOCK_REDUCE_AMT;
          state = STATE_CLOCK_COUNTDOWN;
          
        end else begin
          state = nextState;
        end
        
      end
      



      STATE_READY_CMD0: begin
        command[47:0] = {CMD_CMD0, ARG_EMPTY, CRC_CMD0};
        state = STATE_SEND_CMD;
        nextState = STATE_READY_CMD8;
        errState = STATE_READY_CMD0;
        responseLen = RESP_R1_LEN;
        expectedResp = TOKEN_CMD0_RESP;
        count = CMD_LENGTH;
        mosiSrc = MUX_CMD_MSB;
        chipSelect = LO;
      end
      



      STATE_SEND_CMD: begin
        if(count > 0) begin
        
          if(serialClockOut == HI) begin
            serialClockOut = LO;
          end else if(clockTicked == HI) begin
            command[47:0] = {command[46:0], LO};
            count = count - 1;
            clockTicked = LO;
          end else begin
            serialClockOut = HI;
            clockTicked = HI;
          end
        

          returnState = STATE_SEND_CMD;
          clockCount = CLOCK_REDUCE_AMT;
          state = STATE_CLOCK_COUNTDOWN;
        
        end else begin
          mosiSrc = MUX_CONST_HI;
          state = STATE_AWAIT_RESPONSE;
          count = TIMEOUT_COUNT;
          returnState = STATE_AWAIT_RESPONSE;
        end
        
      end
      




      STATE_AWAIT_RESPONSE: begin
      
        case({serialClockOut, clockTicked})
        

          2'b00: begin
            serialClockOut = HI;
          end
          

          2'b01: begin
            
            if(response[0] == LO) begin
              returnState = STATE_GET_RESPONSE;
              count = responseLen - 1;
            end else if(count == 0) begin
              returnState = STATE_GET_RESPONSE;
              nextState = errState;
              count = DESELECT_COUNT;
              chipSelect = HI;
            end else begin
              count = count - 1;
              returnState = STATE_AWAIT_RESPONSE;
            end
            
            clockTicked = LO;
          end
          

          2'b10: begin
            
            response[39:0] = {response[38:0], miso};
            clockTicked = HI;
            
          end
          

          2'b11: begin
            serialClockOut = LO;
          end
        
        endcase
      

        clockCount = CLOCK_REDUCE_AMT;
        state = STATE_CLOCK_COUNTDOWN;
        
      end
    



    STATE_GET_RESPONSE: begin
    

      if(count == 0) begin
          

        if(responseLen == RESP_R7_LEN) begin
          state = STATE_CHECK_R7_RESPONSE;
          returnState = STATE_CHECK_R7_RESPONSE;
        end else begin
          state = STATE_CHECK_R1_RESPONSE;
          returnState = STATE_CHECK_R1_RESPONSE;
        end
        

      end else begin
      
        case({serialClockOut, clockTicked})
              

          2'b00: begin
            serialClockOut = HI;
          end
          

          2'b01: begin
            
            count = count - 1;
            returnState = STATE_GET_RESPONSE;
            clockTicked = LO;
          end
          

          2'b10: begin
            
            response[39:0] = {response[38:0], miso};
            clockTicked = HI;
            
          end
          

          2'b11: begin
            serialClockOut = LO;
          end
        
        endcase
      

        clockCount = CLOCK_REDUCE_AMT;
        state = STATE_CLOCK_COUNTDOWN;
      end
    
    end
    



    STATE_CHECK_R1_RESPONSE: begin
      if(response[7:0] != expectedResp[7:0]) begin
        nextState <= errState;
      end
      if(blockMode == HI) begin
        state <= nextState;
      end else begin
        state = STATE_DESELECT;
        count = DESELECT_COUNT;
        chipSelect = HI;
      end
    end
    




    STATE_CHECK_R7_RESPONSE: begin
      if(response[39:32] != expectedResp[7:0]) begin
        nextState = errState;
      end
      state = STATE_DESELECT;
      count = DESELECT_COUNT;
      chipSelect = HI;
    end
    



    STATE_DESELECT: begin
      if(count > 0) begin
        if(serialClockOut == HI) begin
          count = count - 1;
        end
        

        serialClockOut = ~serialClockOut;
        returnState = STATE_DESELECT;
        clockCount = CLOCK_REDUCE_AMT;
        state = STATE_CLOCK_COUNTDOWN;
        
      end else begin
        

        if(blockMode == HI) begin
          state = STATE_UPDATE_R1;
          nextState = STATE_WAIT_FOR_HOST;
        end else begin
          state = nextState;
        end
      end
    end
    



    STATE_READY_CMD8: begin
      command[47:0] = {CMD_CMD8, ARG_CMD8, CRC_CMD8};
      state = STATE_SEND_CMD;
      nextState = STATE_READY_CMD55;
      errState = STATE_READY_CMD8;
      responseLen = RESP_R7_LEN;
      expectedResp = TOKEN_CMD0_RESP;
      count = CMD_LENGTH;
      mosiSrc = MUX_CMD_MSB;
      chipSelect = LO;
    end
    



    STATE_READY_CMD55: begin
      command[47:0] = {CMD_CMD55, ARG_EMPTY, CRC_DUMMY};
      state = STATE_SEND_CMD;
      nextState = STATE_READY_CMD41;
      errState = STATE_READY_CMD55;
      responseLen = RESP_R1_LEN;
      expectedResp = TOKEN_CMD0_RESP;
      count = CMD_LENGTH;
      mosiSrc = MUX_CMD_MSB;
      chipSelect = LO;
    end
    



    STATE_READY_CMD41: begin
      command[47:0] = {CMD_CMD41, ARG_ACMD41, CRC_DUMMY};
      state = STATE_SEND_CMD;
      nextState = STATE_FINISH_INIT;
      errState = STATE_READY_CMD55;
      responseLen = RESP_R1_LEN;
      expectedResp = TOKEN_R1_RESP;
      count = CMD_LENGTH;
      mosiSrc = MUX_CMD_MSB;
      chipSelect = LO;
    end
    



    STATE_FINISH_INIT: begin
      if(clockTicked == HI) begin
        updateStatus = LO;
        clockTicked = LO;
        state = STATE_WAIT_FOR_HOST;
      end else if(updateStatus == HI) begin
        clockTicked = HI;
        clkR1 = LO;
      end else begin
        errState = STATE_WAIT_FOR_HOST;
        response = 0;
        blockMode = HI;
        status = STATUS_READY;
        updateStatus = HI;
        clkR1 = HI;
        returnState = STATE_WAIT_FOR_HOST;
      end
    end
    



    STATE_WAIT_FOR_HOST: begin
      if(exec) begin
      
        blockAddr[31:0] = addr[31:0];
        blockCount = BLOCK_COUNT;
        response = 0;
      

        case(op[1:0])
          

          2'b00: begin
            nextState = STATE_READY_CMD17;
            state = STATE_UPDATE_R1;
            status = STATUS_BUSY_BLKRD;
            accessMode = 0;
          end
          

          2'b01: begin
            nextState = STATE_READY_CMD24;
            state = STATE_UPDATE_R1;
            status = STATUS_BUSY_BLKWR;
            accessMode = 1;
          end
          

          default: begin

          end
        endcase
      end
    end
    



    STATE_WAIT_FOR_CONTINUE: begin
      

      if(blockCount == 0) begin
        count = TIMEOUT_COUNT;
        returnState = STATE_FLUSH_BITS;
        nextState = STATE_FINISH_BLOCK_IO;
        state = STATE_FLUSH_BITS;
      

      end else if(exec) begin
        case(op[1:0])
          

          2'b10: begin
            count = WORD_LENGTH;
            if(accessMode == 0) begin
              nextState = STATE_READ_WORD;
              status = STATUS_BUSY_BLKRD;
              returnState = STATE_READ_WORD;
            end else begin
              nextState = STATE_GET_R2_DATA;
              status = STATUS_BUSY_BLKWR;
              returnState = STATE_GET_R2_DATA;
            end
            state = STATE_UPDATE_R1;
          end
          

          2'b11: begin
            count = BLOCK_BIT_COUNT + WORD_LENGTH;
            nextState = STATE_FINISH_BLOCK_IO;
            state = STATE_FLUSH_BITS;
          end
          

          default: begin

          end
        endcase
      end
    end
    



    STATE_FINISH_BLOCK_IO: begin
      accessMode = 0;
      count = DESELECT_COUNT;
      clockCount = 0;
      blockCount = 0;
      nextState = STATE_UPDATE_R1;
      errState = STATUS_READY;
      returnState = STATE_DESELECT;
      data = 0;
      response = 0;
      command = 0;
      mosiSrc = MUX_CONST_HI;
      blockAddr = 0;
      status = STATUS_READY;
      state = STATE_DESELECT;
      chipSelect = HI;
    end
    



    STATE_UPDATE_R1: begin
      
      if(clockTicked == HI) begin
        clockTicked = LO;
        state = nextState;
      end else if(clkR1 == HI) begin
        clkR1 = LO;
      end else if(updateStatus == HI) begin
        updateStatus = LO;
        clockTicked = HI;
      end else begin
        clkR1 = HI;
        updateStatus = HI;
      end
      
    end




    STATE_READY_CMD17: begin
      returnState = STATE_SEND_CMD;
      command[47:0] = {CMD_CMD17[7:0], blockAddr[31:0], CRC_DUMMY[7:0]};
      state = STATE_SEND_CMD;
      nextState = STATE_SETUP_AWAIT_TOKEN;
      errState = STATE_FINISH_BLOCK_IO;
      responseLen = RESP_R1_LEN;
      expectedResp = TOKEN_R1_RESP;
      count = CMD_LENGTH;
      mosiSrc = MUX_CMD_MSB;
      chipSelect = LO;
    end
    



    STATE_SETUP_AWAIT_TOKEN: begin
      count = TIMEOUT_COUNT;
      returnState = STATE_AWAIT_DATA_TOKEN;
      response = 0;
      state = STATE_AWAIT_DATA_TOKEN;
    end
    



    STATE_AWAIT_DATA_TOKEN: begin
      
      case({serialClockOut, clockTicked})
            

        2'b00: begin
          serialClockOut = HI;
        end
        

        2'b01: begin
          

          if(response[0] == LO) begin
            returnState = STATE_CHECK_DATA_TOKEN;
            count = responseLen - 1;
            

          end else if(count == 0) begin
            count = BLOCK_BIT_COUNT + TIMEOUT_COUNT;
            returnState = STATE_FLUSH_BITS;
            nextState = STATE_FINISH_BLOCK_IO;
            status = STATUS_ERR_BLK_CMD;
          

          end else begin
            count = count - 1;
            returnState = STATE_AWAIT_DATA_TOKEN;
          end
          
          clockTicked = LO;
        end
        

        2'b10: begin
          
          response[39:0] = {response[38:0], miso};
          clockTicked = HI;
          
        end
        

        2'b11: begin
          serialClockOut = LO;
        end
      
      endcase
    

      clockCount = CLOCK_REDUCE_AMT;
      state = STATE_CLOCK_COUNTDOWN;
      
    end
    



    STATE_CHECK_DATA_TOKEN: begin
      

      if(response[7:0] != TOKEN_DATA_START) begin
        state = STATE_FLUSH_BITS;
        nextState = STATE_FINISH_BLOCK_IO;
        returnState = STATE_FLUSH_BITS;
        count = WORD_LENGTH;
        status = STATUS_ERR_BLK_CMD;
      

      end else begin
        state = STATE_READ_WORD;
        returnState = STATE_READ_WORD;
        count = WORD_LENGTH;
      end
    end
    



    STATE_READ_WORD: begin
    
      if(count == 0) begin
      
        blockCount = blockCount - 1;
        nextState = STATE_UPDATE_R1;
        returnState = STATE_UPDATE_R3;
        state = STATE_UPDATE_R3;
        
      end else begin
      
        case({serialClockOut, clockTicked})
                    

          2'b00: begin
            serialClockOut = HI;
          end
          

          2'b01: begin
            
            count <= count - 1;
            returnState = STATE_READ_WORD;
            clockTicked = LO;
          end
          

          2'b10: begin
            
            data[15:0] = {data[14:0], miso};
            clockTicked = HI;
            
          end
          

          2'b11: begin
            serialClockOut = LO;
          end
        
        endcase
      

        clockCount = CLOCK_REDUCE_AMT;
        state = STATE_CLOCK_COUNTDOWN;
      end
    
    end
    



    STATE_UPDATE_R3: begin
    
      if(clockTicked == HI) begin
        dOut = 0;
        state = nextState;
        status = STATUS_WAITING_BLKRD;
        clockTicked = LO;
        nextState = STATE_WAIT_FOR_CONTINUE;
      end else if(clkR3 == HI) begin
        clkR3 = LO;
      end else if(updateDataOut == HI) begin
        updateDataOut = LO;
        clockTicked = HI;
      end else begin
        clkR3 = HI;
        updateDataOut = HI;
        dOut = data;
      end
      
    end
    



    STATE_READY_CMD24: begin
      command[47:0] = {CMD_CMD24, blockAddr[31:0], CRC_DUMMY};
      state = STATE_SEND_CMD;
      nextState = STATE_READY_DATA_TOKEN;
      errState = STATE_FINISH_BLOCK_IO;
      responseLen = RESP_R1_LEN;
      expectedResp = TOKEN_R1_RESP;
      count = CMD_LENGTH;
      mosiSrc = MUX_CMD_MSB;
      chipSelect = LO;
    end
    



    STATE_READY_DATA_TOKEN: begin
      command[47:0] = {TOKEN_DATA_START, 40'h0000000000};
      state = STATE_SEND_DATA_TOKEN;
      nextState = STATE_WAIT_FOR_CONTINUE;
      returnState = STATE_SEND_DATA_TOKEN;
      count = TOKEN_DATA_LEN;
      mosiSrc = MUX_CMD_MSB;
    end
    



    STATE_SEND_DATA_TOKEN: begin
      
      if(count > 0) begin
      
        if(serialClockOut == HI) begin
          serialClockOut = LO;
        end else if(clockTicked == HI) begin
          command[47:0] = {command[46:0], LO};
          count = count - 1;
          clockTicked = LO;
        end else begin
          serialClockOut = HI;
          clockTicked = HI;
        end
      

        returnState = STATE_SEND_DATA_TOKEN;
        clockCount = CLOCK_REDUCE_AMT;
        state = STATE_CLOCK_COUNTDOWN;
      
      end else begin
        mosiSrc = MUX_CONST_HI;
        state = STATE_GET_R2_DATA;
        returnState = STATE_GET_R2_DATA;
      end
      
    end
    



    STATE_GET_R2_DATA: begin
      count = WORD_LENGTH;
      mosiSrc = MUX_DAT_MSB;
      data[15:0] = dIn[15:0];
      returnState = STATE_WRITE_WORD;
      state = STATE_WRITE_WORD;
    end
    



    STATE_WRITE_WORD: begin
      
      if(count > 0) begin
      
        if(serialClockOut == HI) begin
          serialClockOut = LO;
        end else if(clockTicked == HI) begin
          data[15:0] = {data[14:0], 1'b0};
          count = count - 1;
          clockTicked = LO;
        end else begin
          serialClockOut = HI;
          clockTicked = HI;
        end
      

        returnState = STATE_WRITE_WORD;
        clockCount = CLOCK_REDUCE_AMT;
        state = STATE_CLOCK_COUNTDOWN;
      
      end else begin
        returnState = STATE_UPDATE_R1;
        state = STATE_UPDATE_R1;
        nextState = STATE_WAIT_FOR_CONTINUE;
        status = STATUS_WAITING_BLKWR;
        blockCount = blockCount - 1;
        mosiSrc = MUX_CONST_HI;
      end
      
    end
    




    STATE_CLOCK_COUNTDOWN: begin
      if(clockCount == 0) begin
        state = returnState;
      end else begin
        clockCount = clockCount - 1;
      end
    end
    



    default: begin
      state = STATUS_ERR_INIT;
      nextState = STATUS_ERR_INIT;
      errState = STATUS_ERR_INIT;
      chipSelect = HI;
      response = 0;
      count = 0;
      command = 0;
      mosiSrc = MUX_CONST_HI;
      responseLen = 0;
      expectedResp = 0;
      blockMode = HI;
    end
    
    endcase
    
    mosiVal = mosi;
    misoVal = miso;
    
  end
  
  Mux16B8to1 sdDbgMux(
    .dIn0(wDebugSignals[15:0]),
    .dIn1({11'b00000000000, state[4:0]}),
    .dIn2({11'b00000000000, returnState[4:0]}),
    .dIn3(count[15:0]),
    .dIn4({8'h00, blockCount[7:0]}),
    .dIn5(response[15:0]),
    .dIn6(response[39:24]),
    .dIn7(clockCount[15:0]),
    .sel(debugRegSelect[2:0]),
    .dOut(debugOut[15:0])
  );
  
endmodule