data/full_repos/permissive/489980666/vivado_proj/ip_rtl/sdc/sd_cmd_serial_host.v
data/verilator_xmls/feb16571-b9ce-4c1b-8518-e220ebabf137.xml
module sd_cmd_serial_host (

    input clock,
    input clock_posedge,
    input clock_data_in,
    input rst,
    input [1:0] setting_i,
    input [39:0] cmd_i,
    input start_i,
    input cmd_dat_i,

    output reg [119:0] response_o,
    output reg finish_o,
    output reg crc_ok_o,
    output reg index_ok_o,
    output reg cmd_oe_o,
    output reg cmd_out_o
);


parameter INIT_DELAY    = 4;
parameter BITS_TO_SEND  = 48;
parameter CMD_SIZE      = 40;
parameter RESP_SIZE     = 128;


reg cmd_dat_reg;
integer resp_len;
reg with_response;
reg [CMD_SIZE-1:0] cmd_buff;
reg [RESP_SIZE-1:0] resp_buff;
integer resp_idx;

reg crc_rst;
reg [6:0]crc_in;
wire [6:0] crc_val;
reg crc_enable;
reg crc_bit;
reg crc_ok;

integer counter;

parameter
    STATE_SIZE = 8,
    INIT      = 8'b00000001,
    IDLE      = 8'b00000010,
    SETUP_CRC = 8'b00000100,
    WRITE     = 8'b00001000,
    READ_WAIT = 8'b00010000,
    READ      = 8'b00100000,
    FINISH_WR = 8'b01000000,
    FINISH_WO = 8'b10000000;
reg [STATE_SIZE-1:0] state;


`define cmd_idx  (CMD_SIZE-1-counter)


always @(posedge clock) begin
    if (clock_data_in) cmd_dat_reg <= cmd_dat_i;
end


sd_crc_7 CRC_7(
    crc_bit,
    crc_enable & clock_posedge,
    clock,
    crc_rst,
    crc_val);



always @(posedge clock) begin
    if (rst) begin
        resp_len <= 0;
        with_response <= 0;
        cmd_buff <= 0;
        crc_enable <= 0;
        resp_idx <= 0;
        cmd_oe_o <= 1;
        cmd_out_o <= 1;
        resp_buff <= 0;
        finish_o <= 0;
        crc_rst <= 1;
        crc_bit <= 0;
        crc_in <= 0;
        response_o <= 0;
        index_ok_o <= 0;
        crc_ok_o <= 0;
        crc_ok <= 0;
        counter <= 0;
        state <= INIT;
    end else if (clock_posedge) begin
        case (state)
            INIT: begin
                counter <= counter+1;

                cmd_oe_o <= 1;
                cmd_out_o <= 1;
                if (counter >= INIT_DELAY) state <= IDLE;
            end
            IDLE: begin
                cmd_oe_o <= 0;
                counter <= 0;
                crc_rst <= 1;
                crc_enable <= 0;
                response_o <= 0;
                resp_idx <= 0;
                crc_ok_o <= 0;
                index_ok_o <= 0;
                finish_o <= 0;
                if (start_i) begin
                    resp_len <= setting_i[1] ? 127 : 39;
                    with_response <= setting_i[0];
                    cmd_buff <= cmd_i;
                    state <= SETUP_CRC;
                end
            end
            SETUP_CRC: begin
                crc_rst <= 0;
                crc_enable <= 1;
                crc_bit <= cmd_buff[`cmd_idx];
                state <= WRITE;
            end
            WRITE: begin
                if (counter < BITS_TO_SEND-8) begin
                    cmd_oe_o <= 1;
                    cmd_out_o <= cmd_buff[`cmd_idx];
                    if (counter < BITS_TO_SEND-9) begin
                        crc_bit <= cmd_buff[`cmd_idx-1];
                    end else begin
                        crc_enable <= 0;
                    end
                end else if (counter < BITS_TO_SEND-1) begin
                    cmd_oe_o <= 1;
                    crc_enable <= 0;
                    cmd_out_o <= crc_val[BITS_TO_SEND-counter-2];
                end else if (counter == BITS_TO_SEND-1) begin
                    cmd_oe_o <= 1;
                    cmd_out_o <= 1'b1;
                end else begin
                    cmd_oe_o <= 0;
                    cmd_out_o <= 1'b1;
                end
                counter <= counter + 1;
                if (counter >= BITS_TO_SEND && with_response) state <= READ_WAIT;
                else if (counter >= BITS_TO_SEND) state <= FINISH_WO;
            end
            READ_WAIT: begin
                crc_enable <= 0;
                crc_rst <= 1;
                counter <= 1;
                cmd_oe_o <= 0;
                resp_buff[RESP_SIZE-1] <= cmd_dat_reg;
                if (!cmd_dat_reg) state <= READ;
            end
            FINISH_WO: begin
                finish_o <= 1;
                crc_enable <= 0;
                crc_rst <= 1;
                counter <= 0;
                cmd_oe_o <= 0;
                state <= IDLE;
            end
            READ: begin
                crc_rst <= 0;
                crc_enable <= (resp_len != RESP_SIZE-1 || counter > 7);
                cmd_oe_o <= 0;
                if (counter <= resp_len) begin
                    if (counter < 8)
                        resp_buff[RESP_SIZE-1-counter] <= cmd_dat_reg;
                    else begin
                        resp_idx <= resp_idx + 1;
                        resp_buff[RESP_SIZE-9-resp_idx] <= cmd_dat_reg;
                    end
                    crc_bit <= cmd_dat_reg;
                end else if (counter-resp_len <= 7) begin
                    crc_in[(resp_len+7)-(counter)] <= cmd_dat_reg;
                    crc_enable <= 0;
                end else begin
                    crc_enable <= 0;
                    crc_ok <= crc_in == crc_val;
                end
                counter <= counter + 1;
                if (counter >= resp_len+8) state <= FINISH_WR;
            end
            FINISH_WR: begin
                index_ok_o <= cmd_buff[37:32] == resp_buff[125:120];
                crc_ok_o <= crc_ok;
                finish_o <= 1;
                crc_enable <= 0;
                crc_rst <= 1;
                counter <= 0;
                cmd_oe_o <= 0;
                response_o <= resp_buff[119:0];
                state <= IDLE;
            end
            default:
                state <= INIT;
        endcase
    end
end

endmodule
module sd_cmd_serial_host (

    input clock,
    input clock_posedge,
    input clock_data_in,
    input rst,
    input [1:0] setting_i,
    input [39:0] cmd_i,
    input start_i,
    input cmd_dat_i,

    output reg [119:0] response_o,
    output reg finish_o,
    output reg crc_ok_o,
    output reg index_ok_o,
    output reg cmd_oe_o,
    output reg cmd_out_o
);



parameter INIT_DELAY    = 4;
parameter BITS_TO_SEND  = 48;
parameter CMD_SIZE      = 40;
parameter RESP_SIZE     = 128;


reg cmd_dat_reg;
integer resp_len;
reg with_response;
reg [CMD_SIZE-1:0] cmd_buff;
reg [RESP_SIZE-1:0] resp_buff;
integer resp_idx;

reg crc_rst;
reg [6:0]crc_in;
wire [6:0] crc_val;
reg crc_enable;
reg crc_bit;
reg crc_ok;

integer counter;

parameter
    STATE_SIZE = 8,
    INIT      = 8'b00000001,
    IDLE      = 8'b00000010,
    SETUP_CRC = 8'b00000100,
    WRITE     = 8'b00001000,
    READ_WAIT = 8'b00010000,
    READ      = 8'b00100000,
    FINISH_WR = 8'b01000000,
    FINISH_WO = 8'b10000000;
reg [STATE_SIZE-1:0] state;


`define cmd_idx  (CMD_SIZE-1-counter)


always @(posedge clock) begin
    if (clock_data_in) cmd_dat_reg <= cmd_dat_i;
end


sd_crc_7 CRC_7(
    crc_bit,
    crc_enable & clock_posedge,
    clock,
    crc_rst,
    crc_val);



always @(posedge clock) begin
    if (rst) begin
        resp_len <= 0;
        with_response <= 0;
        cmd_buff <= 0;
        crc_enable <= 0;
        resp_idx <= 0;
        cmd_oe_o <= 1;
        cmd_out_o <= 1;
        resp_buff <= 0;
        finish_o <= 0;
        crc_rst <= 1;
        crc_bit <= 0;
        crc_in <= 0;
        response_o <= 0;
        index_ok_o <= 0;
        crc_ok_o <= 0;
        crc_ok <= 0;
        counter <= 0;
        state <= INIT;
    end else if (clock_posedge) begin
        case (state)
            INIT: begin
                counter <= counter+1;

                cmd_oe_o <= 1;
                cmd_out_o <= 1;
                if (counter >= INIT_DELAY) state <= IDLE;
            end
            IDLE: begin
                cmd_oe_o <= 0;
                counter <= 0;
                crc_rst <= 1;
                crc_enable <= 0;
                response_o <= 0;
                resp_idx <= 0;
                crc_ok_o <= 0;
                index_ok_o <= 0;
                finish_o <= 0;
                if (start_i) begin
                    resp_len <= setting_i[1] ? 127 : 39;
                    with_response <= setting_i[0];
                    cmd_buff <= cmd_i;
                    state <= SETUP_CRC;
                end
            end
            SETUP_CRC: begin
                crc_rst <= 0;
                crc_enable <= 1;
                crc_bit <= cmd_buff[`cmd_idx];
                state <= WRITE;
            end
            WRITE: begin
                if (counter < BITS_TO_SEND-8) begin
                    cmd_oe_o <= 1;
                    cmd_out_o <= cmd_buff[`cmd_idx];
                    if (counter < BITS_TO_SEND-9) begin
                        crc_bit <= cmd_buff[`cmd_idx-1];
                    end else begin
                        crc_enable <= 0;
                    end
                end else if (counter < BITS_TO_SEND-1) begin
                    cmd_oe_o <= 1;
                    crc_enable <= 0;
                    cmd_out_o <= crc_val[BITS_TO_SEND-counter-2];
                end else if (counter == BITS_TO_SEND-1) begin
                    cmd_oe_o <= 1;
                    cmd_out_o <= 1'b1;
                end else begin
                    cmd_oe_o <= 0;
                    cmd_out_o <= 1'b1;
                end
                counter <= counter + 1;
                if (counter >= BITS_TO_SEND && with_response) state <= READ_WAIT;
                else if (counter >= BITS_TO_SEND) state <= FINISH_WO;
            end
            READ_WAIT: begin
                crc_enable <= 0;
                crc_rst <= 1;
                counter <= 1;
                cmd_oe_o <= 0;
                resp_buff[RESP_SIZE-1] <= cmd_dat_reg;
                if (!cmd_dat_reg) state <= READ;
            end
            FINISH_WO: begin
                finish_o <= 1;
                crc_enable <= 0;
                crc_rst <= 1;
                counter <= 0;
                cmd_oe_o <= 0;
                state <= IDLE;
            end
            READ: begin
                crc_rst <= 0;
                crc_enable <= (resp_len != RESP_SIZE-1 || counter > 7);
                cmd_oe_o <= 0;
                if (counter <= resp_len) begin
                    if (counter < 8)
                        resp_buff[RESP_SIZE-1-counter] <= cmd_dat_reg;
                    else begin
                        resp_idx <= resp_idx + 1;
                        resp_buff[RESP_SIZE-9-resp_idx] <= cmd_dat_reg;
                    end
                    crc_bit <= cmd_dat_reg;
                end else if (counter-resp_len <= 7) begin
                    crc_in[(resp_len+7)-(counter)] <= cmd_dat_reg;
                    crc_enable <= 0;
                end else begin
                    crc_enable <= 0;
                    crc_ok <= crc_in == crc_val;
                end
                counter <= counter + 1;
                if (counter >= resp_len+8) state <= FINISH_WR;
            end
            FINISH_WR: begin
                index_ok_o <= cmd_buff[37:32] == resp_buff[125:120];
                crc_ok_o <= crc_ok;
                finish_o <= 1;
                crc_enable <= 0;
                crc_rst <= 1;
                counter <= 0;
                cmd_oe_o <= 0;
                response_o <= resp_buff[119:0];
                state <= IDLE;
            end
            default:
                state <= INIT;
        endcase
    end
end

endmodule