data/full_repos/permissive/135820056/sys/sd_card.sv
 line:117: before: "."
1: b'%Error: data/full_repos/permissive/135820056/sys/sd_card.sv:88: Cannot find file containing module: \'altsyncram\'\naltsyncram sdbuf\n^~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/135820056/sys,data/full_repos/permissive/135820056/altsyncram\n             data/full_repos/permissive/135820056/sys,data/full_repos/permissive/135820056/altsyncram.v\n             data/full_repos/permissive/135820056/sys,data/full_repos/permissive/135820056/altsyncram.sv\n             altsyncram\n             altsyncram.v\n             altsyncram.sv\n             obj_dir/altsyncram\n             obj_dir/altsyncram.v\n             obj_dir/altsyncram.sv\n%Warning-WIDTH: data/full_repos/permissive/135820056/sys/sd_card.sv:175: Operator COND expects 8 bits on the Conditional True, but Conditional True\'s VARREF \'mosi\' generates 1 bits.\n                                                                       : ... In instance sd_card\nwire [7:0] ibuf = OCTAL ? mosi : {sbuf,mosi[0]};\n                        ^\n                ... Use "/* verilator lint_off WIDTH */" and lint_on around source to disable this message.\n%Error: Exiting due to 1 error(s), 1 warning(s)\n'
module sd_card #(parameter WIDE = 0, OCTAL=0)
(
	input             clk_sys,
	input             reset,

	input             sdhc,
	input             img_mounted,
	input      [63:0] img_size,

	output reg [31:0] sd_lba,
	output reg        sd_rd,
	output reg        sd_wr,
	input             sd_ack,

	input      [AW:0] sd_buff_addr,
	input      [DW:0] sd_buff_dout,
	output     [DW:0] sd_buff_din,
	input             sd_buff_wr,


	input             clk_spi,

	input             ss,
	input             sck,
	input      [SW:0] mosi,
	output reg [SW:0] miso
);

localparam AW = WIDE  ?  7 : 8;
localparam DW = WIDE  ? 15 : 7;
localparam SZ = OCTAL ?  8 : 1;
localparam SW = SZ-1;

wire [7:0] DATA_TOKEN_CMD25    = 8'hfc;
wire [7:0] STOP_TRAN           = 8'hfd;
wire [7:0] DATA_TOKEN          = 8'hfe;
wire [7:0] WRITE_DATA_RESPONSE = 8'h05;


localparam NCR = 5+3;

localparam RD_STATE_IDLE       = 0;
localparam RD_STATE_START      = 1;
localparam RD_STATE_WAIT_IO    = 2;
localparam RD_STATE_SEND_TOKEN = 3;
localparam RD_STATE_SEND_DATA  = 4;
localparam RD_STATE_WAIT_M     = 5;

localparam WR_STATE_IDLE       = 0;
localparam WR_STATE_EXP_DTOKEN = 1;
localparam WR_STATE_RECV_DATA  = 2;
localparam WR_STATE_RECV_CRC0  = 3;
localparam WR_STATE_RECV_CRC1  = 4;
localparam WR_STATE_SEND_DRESP = 5;
localparam WR_STATE_BUSY       = 6;

localparam PREF_STATE_IDLE     = 0;
localparam PREF_STATE_RD       = 1;
localparam PREF_STATE_FINISH   = 2;

altsyncram sdbuf
(
	.clock0    (clk_sys),
	.address_a ({sd_buf,sd_buff_addr}),
	.data_a    (sd_buff_dout),
	.wren_a    (sd_ack & sd_buff_wr),
	.q_a       (sd_buff_din),

	.clock1    (clk_spi),
	.address_b ({spi_buf,buffer_ptr}),
	.data_b    (buffer_din),
	.wren_b    (buffer_wr),
	.q_b       (buffer_dout),

	.aclr0(1'b0),
	.aclr1(1'b0),
	.addressstall_a(1'b0),
	.addressstall_b(1'b0),
	.byteena_a(1'b1),
	.byteena_b(1'b1),
	.clocken0(1'b1),
	.clocken1(1'b1),
	.clocken2(1'b1),
	.clocken3(1'b1),
	.eccstatus(),
	.rden_a(1'b1),
	.rden_b(1'b1)
);
defparam
	sdbuf.numwords_a = 1<<(AW+3),
	sdbuf.widthad_a  = AW+3,
	sdbuf.width_a    = DW+1,
	sdbuf.numwords_b = 2048,
	sdbuf.widthad_b  = 11,
	sdbuf.width_b    = 8,
	sdbuf.address_reg_b = "CLOCK1",
	sdbuf.clock_enable_input_a = "BYPASS",
	sdbuf.clock_enable_input_b = "BYPASS",
	sdbuf.clock_enable_output_a = "BYPASS",
	sdbuf.clock_enable_output_b = "BYPASS",
	sdbuf.indata_reg_b = "CLOCK1",
	sdbuf.intended_device_family = "Cyclone V",
	sdbuf.lpm_type = "altsyncram",
	sdbuf.operation_mode = "BIDIR_DUAL_PORT",
	sdbuf.outdata_aclr_a = "NONE",
	sdbuf.outdata_aclr_b = "NONE",
	sdbuf.outdata_reg_a = "UNREGISTERED",
	sdbuf.outdata_reg_b = "UNREGISTERED",
	sdbuf.power_up_uninitialized = "FALSE",
	sdbuf.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ",
	sdbuf.read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ",
	sdbuf.width_byteena_a = 1,
	sdbuf.width_byteena_b = 1,
	sdbuf.wrcontrol_wraddress_reg_b = "CLOCK1";

reg [26:0] csd_size;
reg        csd_sdhc;
always @(posedge clk_sys) begin
	if (img_mounted) begin
		csd_sdhc <= sdhc;
		if (sdhc) begin
			csd_size[0]     <= 0;
			csd_size[22:1]  <= img_size[40:19];
			csd_size[26:23] <= 0;
		end
		else begin
			csd_size[2:0]   <= 7;
			csd_size[14:3]  <= 12'b101101101101;
			csd_size[26:15] <= img_size[29:18];
		end
	end
end

wire [127:0] CSD = {1'b0,csd_sdhc,6'h00,8'h0e,8'h00,8'h32,8'h5b,8'h59,6'h00,csd_size,7'h7f,8'h80,8'h0a,8'h40,8'h40,8'hf1};
wire [127:0] CID = {8'hcd,8'hc7,8'h00,8'h93,8'h6f,8'h2f,8'h73,8'h00,8'h00,8'h44,8'h32,8'h38,8'h34,8'h00,8'h00,8'h3e};

reg  [8:0] buffer_ptr;
reg  [7:0] buffer_din;
wire [7:0] buffer_dout;
reg        buffer_wr;

reg  [1:0] sd_buf, spi_buf;

reg  [6:0] sbuf;
reg  [2:0] bit_cnt;

wire       last_bit = &bit_cnt || OCTAL;
wire [7:0] ibuf = OCTAL ? mosi : {sbuf,mosi[0]};

always @(posedge clk_spi) begin
	reg  [2:0] read_state;
	reg  [2:0] write_state;
	reg  [1:0] pref_state;
	reg  [5:0] cmd;
	reg        cmd55;
	reg [39:0] reply;
	reg  [3:0] byte_cnt;
	reg        old_sck;
	reg  [2:0] ack;
	reg  [2:0] wait_m_cnt;
	reg [31:0] arg;

	ack[1:0] <= {ack[0],sd_ack};
	if(ack[1] == ack[0]) ack[2] <= ack[1];

	if(~ack[2] &  ack[1]) {sd_rd,sd_wr} <= 0;
	if( ack[2] & ~ack[1]) begin
		sd_buf <= sd_buf + 1'd1;
		sd_lba <= sd_lba + 1;
	end

	buffer_wr <= 0;

	if(reset) begin
		bit_cnt     <= 0;
		byte_cnt    <= '1;
		miso        <= '1;
		cmd         <= 0;
		sd_wr 		<= 0;
		sd_rd 		<= 0;
		read_state  <= RD_STATE_IDLE;
		write_state <= WR_STATE_IDLE;
		pref_state  <= PREF_STATE_IDLE;
	end
	else begin

		if(buffer_wr) begin
			if(~&buffer_ptr) buffer_ptr <= buffer_ptr + 1'd1;
			else begin
				spi_buf <= spi_buf + 1'd1;
				sd_wr <= 1;
			end
		end

		case(pref_state)
			PREF_STATE_IDLE:
				if(((sd_buf - spi_buf) <= 1) && (read_state != RD_STATE_IDLE) && (cmd == 17 || cmd == 18)) begin
					sd_rd <= 1;
					pref_state <= PREF_STATE_RD;
				end

			PREF_STATE_RD:
				if(read_state == RD_STATE_IDLE) begin
					pref_state <= PREF_STATE_IDLE;
				end
				else if(ack[2] & ~ack[1]) begin
					pref_state <= (cmd == 18) ? PREF_STATE_IDLE : PREF_STATE_FINISH;
				end

			PREF_STATE_FINISH:
				if(read_state == RD_STATE_IDLE) begin
					pref_state <= PREF_STATE_IDLE;
				end
		endcase

		old_sck <= sck;
		if(ss) begin
			bit_cnt  <= 0;
			byte_cnt <= '1;
			miso     <= '1;
		end
		else if(old_sck & ~sck) begin
			miso <= '1;
			if(byte_cnt >= NCR) {miso,reply} <= {reply, {SZ{1'b1}}};


			case(read_state)
				RD_STATE_IDLE: ;

				RD_STATE_START: begin
					if(byte_cnt == NCR && last_bit) read_state <= (cmd == 9 || cmd == 10) ? RD_STATE_SEND_TOKEN : RD_STATE_WAIT_IO;
				end


				RD_STATE_WAIT_IO: begin
					if(sd_buf != spi_buf && last_bit) read_state <= RD_STATE_SEND_TOKEN;
				end


				RD_STATE_SEND_TOKEN: begin
					miso <= DATA_TOKEN[~bit_cnt -:SZ];
					if(last_bit) begin
						read_state <= RD_STATE_SEND_DATA;
						buffer_ptr <= 0;
					end
				end


				RD_STATE_SEND_DATA: begin

					miso <= (cmd == 9) ? CSD[{buffer_ptr[3:0],~bit_cnt} -:SZ] : (cmd == 10) ? CID[{buffer_ptr[3:0],~bit_cnt} -:SZ] : buffer_dout[~bit_cnt -:SZ];

					if(last_bit) begin


						if(cmd == 17 && &buffer_ptr) read_state <= RD_STATE_IDLE;
						else if(cmd == 18 && &buffer_ptr) begin
							read_state <= RD_STATE_WAIT_M;
							wait_m_cnt <= 0;
						end


						else if((cmd == 9 || cmd == 10) && &buffer_ptr[3:0]) read_state <= RD_STATE_IDLE;


						else buffer_ptr <= buffer_ptr + 1'd1;
					end
				end

				RD_STATE_WAIT_M: begin
					if(last_bit) begin
						wait_m_cnt <= wait_m_cnt + 1'd1;
						if(&wait_m_cnt) begin
							spi_buf <= spi_buf + 1'd1;
							read_state <= RD_STATE_WAIT_IO;
						end
					end
				end
			endcase



			if(write_state == WR_STATE_SEND_DRESP) miso <= WRITE_DATA_RESPONSE[~bit_cnt -:SZ];


			if(write_state == WR_STATE_BUSY) miso <= 0;
		end
		else if(~old_sck & sck) begin

			sbuf[6:0] <= {sbuf[5:0],mosi[0]};
			bit_cnt <= bit_cnt + SZ[2:0];

			if(last_bit) begin


				if(~&byte_cnt) byte_cnt <= byte_cnt + 1'd1;




				if(byte_cnt > 5 &&
						((write_state == WR_STATE_IDLE && read_state == RD_STATE_IDLE && ibuf[7:6] == 1) || 
						(read_state != RD_STATE_IDLE && ibuf == 8'h4c))) begin
					byte_cnt <= 0;
					cmd      <= ibuf[5:0];
					cmd55    <= (cmd == 55);
					if(ibuf[5:0] == 12) read_state <= RD_STATE_IDLE;
				end


				if(byte_cnt == 0) arg[31:24] <= ibuf;
				if(byte_cnt == 1) arg[23:16] <= ibuf;
				if(byte_cnt == 2) arg[15:8]  <= ibuf;
				if(byte_cnt == 3) arg[7:0]   <= ibuf;


				if(byte_cnt == 4) begin


					reply <= 40'h04FFFFFFFF;

					case(cmd)

						 0: reply[39:32] <= 1;


						 1: reply[39:32] <= 0;


						 8: reply <= 40'h01000001AA;


						 9,

						10: begin
								reply[39:32] <= 0;
								read_state <= RD_STATE_START;
							end


						12: reply[39:32] <= 0;
						

						13: reply[39:24] <= 16'h0000;


						16: reply[39:32] <= (arg == 512) ? 8'h00 : 8'h40;


						17,

						18: begin
								reply[39:32] <= 0;
								read_state <= RD_STATE_START;
								spi_buf <= 0;
								sd_buf <= 0;
								sd_lba <= csd_sdhc ? arg : {9'd0, arg[31:9]};
							end


						23: reply[39:32] <= 0;


						24,

						25: begin
								reply[39:32] <= 0;
								write_state <= WR_STATE_EXP_DTOKEN;
								spi_buf <= 0;
								sd_buf <= 0;
								sd_lba <= csd_sdhc ? arg : {9'd0, arg[31:9]};
							end


						41: if(cmd55) reply[39:32] <= 0;


						55: reply[39:32] <= 1;


						58: reply <= { 8'h00, 1'b1, csd_sdhc, 30'd0 };


						59: reply[39:32] <= 0;
					endcase
				end


				case(write_state)

					WR_STATE_IDLE: ;


					WR_STATE_EXP_DTOKEN: begin
						buffer_ptr <= 0;
						if(cmd == 24) begin
							if(ibuf == DATA_TOKEN)       write_state <= WR_STATE_RECV_DATA;
						end
						else begin
							if(ibuf == DATA_TOKEN_CMD25) write_state <= WR_STATE_RECV_DATA;
							if(ibuf == STOP_TRAN)        write_state <= WR_STATE_IDLE;
						end
					end


					WR_STATE_RECV_DATA: begin

						buffer_wr  <= 1;
						buffer_din <= ibuf;


						if(&buffer_ptr) write_state <= WR_STATE_RECV_CRC0;
					end


					WR_STATE_RECV_CRC0:
						write_state <= WR_STATE_RECV_CRC1;


					WR_STATE_RECV_CRC1:
						write_state <= WR_STATE_SEND_DRESP;


					WR_STATE_SEND_DRESP:
						write_state <= WR_STATE_BUSY;


					WR_STATE_BUSY:
						if(spi_buf == sd_buf) write_state <= (cmd == 25) ? WR_STATE_EXP_DTOKEN : WR_STATE_IDLE;
				endcase
			end
		end
	end
end

endmodule
module sd_card #(parameter WIDE = 0, OCTAL=0)
(
	input             clk_sys,
	input             reset,

	input             sdhc,
	input             img_mounted,
	input      [63:0] img_size,

	output reg [31:0] sd_lba,
	output reg        sd_rd,
	output reg        sd_wr,
	input             sd_ack,

	input      [AW:0] sd_buff_addr,
	input      [DW:0] sd_buff_dout,
	output     [DW:0] sd_buff_din,
	input             sd_buff_wr,


	input             clk_spi,

	input             ss,
	input             sck,
	input      [SW:0] mosi,
	output reg [SW:0] miso
);


localparam AW = WIDE  ?  7 : 8;
localparam DW = WIDE  ? 15 : 7;
localparam SZ = OCTAL ?  8 : 1;
localparam SW = SZ-1;

wire [7:0] DATA_TOKEN_CMD25    = 8'hfc;
wire [7:0] STOP_TRAN           = 8'hfd;
wire [7:0] DATA_TOKEN          = 8'hfe;
wire [7:0] WRITE_DATA_RESPONSE = 8'h05;


localparam NCR = 5+3;

localparam RD_STATE_IDLE       = 0;
localparam RD_STATE_START      = 1;
localparam RD_STATE_WAIT_IO    = 2;
localparam RD_STATE_SEND_TOKEN = 3;
localparam RD_STATE_SEND_DATA  = 4;
localparam RD_STATE_WAIT_M     = 5;

localparam WR_STATE_IDLE       = 0;
localparam WR_STATE_EXP_DTOKEN = 1;
localparam WR_STATE_RECV_DATA  = 2;
localparam WR_STATE_RECV_CRC0  = 3;
localparam WR_STATE_RECV_CRC1  = 4;
localparam WR_STATE_SEND_DRESP = 5;
localparam WR_STATE_BUSY       = 6;

localparam PREF_STATE_IDLE     = 0;
localparam PREF_STATE_RD       = 1;
localparam PREF_STATE_FINISH   = 2;

altsyncram sdbuf
(
	.clock0    (clk_sys),
	.address_a ({sd_buf,sd_buff_addr}),
	.data_a    (sd_buff_dout),
	.wren_a    (sd_ack & sd_buff_wr),
	.q_a       (sd_buff_din),

	.clock1    (clk_spi),
	.address_b ({spi_buf,buffer_ptr}),
	.data_b    (buffer_din),
	.wren_b    (buffer_wr),
	.q_b       (buffer_dout),

	.aclr0(1'b0),
	.aclr1(1'b0),
	.addressstall_a(1'b0),
	.addressstall_b(1'b0),
	.byteena_a(1'b1),
	.byteena_b(1'b1),
	.clocken0(1'b1),
	.clocken1(1'b1),
	.clocken2(1'b1),
	.clocken3(1'b1),
	.eccstatus(),
	.rden_a(1'b1),
	.rden_b(1'b1)
);
defparam
	sdbuf.numwords_a = 1<<(AW+3),
	sdbuf.widthad_a  = AW+3,
	sdbuf.width_a    = DW+1,
	sdbuf.numwords_b = 2048,
	sdbuf.widthad_b  = 11,
	sdbuf.width_b    = 8,
	sdbuf.address_reg_b = "CLOCK1",
	sdbuf.clock_enable_input_a = "BYPASS",
	sdbuf.clock_enable_input_b = "BYPASS",
	sdbuf.clock_enable_output_a = "BYPASS",
	sdbuf.clock_enable_output_b = "BYPASS",
	sdbuf.indata_reg_b = "CLOCK1",
	sdbuf.intended_device_family = "Cyclone V",
	sdbuf.lpm_type = "altsyncram",
	sdbuf.operation_mode = "BIDIR_DUAL_PORT",
	sdbuf.outdata_aclr_a = "NONE",
	sdbuf.outdata_aclr_b = "NONE",
	sdbuf.outdata_reg_a = "UNREGISTERED",
	sdbuf.outdata_reg_b = "UNREGISTERED",
	sdbuf.power_up_uninitialized = "FALSE",
	sdbuf.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ",
	sdbuf.read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ",
	sdbuf.width_byteena_a = 1,
	sdbuf.width_byteena_b = 1,
	sdbuf.wrcontrol_wraddress_reg_b = "CLOCK1";

reg [26:0] csd_size;
reg        csd_sdhc;
always @(posedge clk_sys) begin
	if (img_mounted) begin
		csd_sdhc <= sdhc;
		if (sdhc) begin
			csd_size[0]     <= 0;
			csd_size[22:1]  <= img_size[40:19];
			csd_size[26:23] <= 0;
		end
		else begin
			csd_size[2:0]   <= 7;
			csd_size[14:3]  <= 12'b101101101101;
			csd_size[26:15] <= img_size[29:18];
		end
	end
end

wire [127:0] CSD = {1'b0,csd_sdhc,6'h00,8'h0e,8'h00,8'h32,8'h5b,8'h59,6'h00,csd_size,7'h7f,8'h80,8'h0a,8'h40,8'h40,8'hf1};
wire [127:0] CID = {8'hcd,8'hc7,8'h00,8'h93,8'h6f,8'h2f,8'h73,8'h00,8'h00,8'h44,8'h32,8'h38,8'h34,8'h00,8'h00,8'h3e};

reg  [8:0] buffer_ptr;
reg  [7:0] buffer_din;
wire [7:0] buffer_dout;
reg        buffer_wr;

reg  [1:0] sd_buf, spi_buf;

reg  [6:0] sbuf;
reg  [2:0] bit_cnt;

wire       last_bit = &bit_cnt || OCTAL;
wire [7:0] ibuf = OCTAL ? mosi : {sbuf,mosi[0]};

always @(posedge clk_spi) begin
	reg  [2:0] read_state;
	reg  [2:0] write_state;
	reg  [1:0] pref_state;
	reg  [5:0] cmd;
	reg        cmd55;
	reg [39:0] reply;
	reg  [3:0] byte_cnt;
	reg        old_sck;
	reg  [2:0] ack;
	reg  [2:0] wait_m_cnt;
	reg [31:0] arg;

	ack[1:0] <= {ack[0],sd_ack};
	if(ack[1] == ack[0]) ack[2] <= ack[1];

	if(~ack[2] &  ack[1]) {sd_rd,sd_wr} <= 0;
	if( ack[2] & ~ack[1]) begin
		sd_buf <= sd_buf + 1'd1;
		sd_lba <= sd_lba + 1;
	end

	buffer_wr <= 0;

	if(reset) begin
		bit_cnt     <= 0;
		byte_cnt    <= '1;
		miso        <= '1;
		cmd         <= 0;
		sd_wr 		<= 0;
		sd_rd 		<= 0;
		read_state  <= RD_STATE_IDLE;
		write_state <= WR_STATE_IDLE;
		pref_state  <= PREF_STATE_IDLE;
	end
	else begin

		if(buffer_wr) begin
			if(~&buffer_ptr) buffer_ptr <= buffer_ptr + 1'd1;
			else begin
				spi_buf <= spi_buf + 1'd1;
				sd_wr <= 1;
			end
		end

		case(pref_state)
			PREF_STATE_IDLE:
				if(((sd_buf - spi_buf) <= 1) && (read_state != RD_STATE_IDLE) && (cmd == 17 || cmd == 18)) begin
					sd_rd <= 1;
					pref_state <= PREF_STATE_RD;
				end

			PREF_STATE_RD:
				if(read_state == RD_STATE_IDLE) begin
					pref_state <= PREF_STATE_IDLE;
				end
				else if(ack[2] & ~ack[1]) begin
					pref_state <= (cmd == 18) ? PREF_STATE_IDLE : PREF_STATE_FINISH;
				end

			PREF_STATE_FINISH:
				if(read_state == RD_STATE_IDLE) begin
					pref_state <= PREF_STATE_IDLE;
				end
		endcase

		old_sck <= sck;
		if(ss) begin
			bit_cnt  <= 0;
			byte_cnt <= '1;
			miso     <= '1;
		end
		else if(old_sck & ~sck) begin
			miso <= '1;
			if(byte_cnt >= NCR) {miso,reply} <= {reply, {SZ{1'b1}}};


			case(read_state)
				RD_STATE_IDLE: ;

				RD_STATE_START: begin
					if(byte_cnt == NCR && last_bit) read_state <= (cmd == 9 || cmd == 10) ? RD_STATE_SEND_TOKEN : RD_STATE_WAIT_IO;
				end


				RD_STATE_WAIT_IO: begin
					if(sd_buf != spi_buf && last_bit) read_state <= RD_STATE_SEND_TOKEN;
				end


				RD_STATE_SEND_TOKEN: begin
					miso <= DATA_TOKEN[~bit_cnt -:SZ];
					if(last_bit) begin
						read_state <= RD_STATE_SEND_DATA;
						buffer_ptr <= 0;
					end
				end


				RD_STATE_SEND_DATA: begin

					miso <= (cmd == 9) ? CSD[{buffer_ptr[3:0],~bit_cnt} -:SZ] : (cmd == 10) ? CID[{buffer_ptr[3:0],~bit_cnt} -:SZ] : buffer_dout[~bit_cnt -:SZ];

					if(last_bit) begin


						if(cmd == 17 && &buffer_ptr) read_state <= RD_STATE_IDLE;
						else if(cmd == 18 && &buffer_ptr) begin
							read_state <= RD_STATE_WAIT_M;
							wait_m_cnt <= 0;
						end


						else if((cmd == 9 || cmd == 10) && &buffer_ptr[3:0]) read_state <= RD_STATE_IDLE;


						else buffer_ptr <= buffer_ptr + 1'd1;
					end
				end

				RD_STATE_WAIT_M: begin
					if(last_bit) begin
						wait_m_cnt <= wait_m_cnt + 1'd1;
						if(&wait_m_cnt) begin
							spi_buf <= spi_buf + 1'd1;
							read_state <= RD_STATE_WAIT_IO;
						end
					end
				end
			endcase



			if(write_state == WR_STATE_SEND_DRESP) miso <= WRITE_DATA_RESPONSE[~bit_cnt -:SZ];


			if(write_state == WR_STATE_BUSY) miso <= 0;
		end
		else if(~old_sck & sck) begin

			sbuf[6:0] <= {sbuf[5:0],mosi[0]};
			bit_cnt <= bit_cnt + SZ[2:0];

			if(last_bit) begin


				if(~&byte_cnt) byte_cnt <= byte_cnt + 1'd1;




				if(byte_cnt > 5 &&
						((write_state == WR_STATE_IDLE && read_state == RD_STATE_IDLE && ibuf[7:6] == 1) || 
						(read_state != RD_STATE_IDLE && ibuf == 8'h4c))) begin
					byte_cnt <= 0;
					cmd      <= ibuf[5:0];
					cmd55    <= (cmd == 55);
					if(ibuf[5:0] == 12) read_state <= RD_STATE_IDLE;
				end


				if(byte_cnt == 0) arg[31:24] <= ibuf;
				if(byte_cnt == 1) arg[23:16] <= ibuf;
				if(byte_cnt == 2) arg[15:8]  <= ibuf;
				if(byte_cnt == 3) arg[7:0]   <= ibuf;


				if(byte_cnt == 4) begin


					reply <= 40'h04FFFFFFFF;

					case(cmd)

						 0: reply[39:32] <= 1;


						 1: reply[39:32] <= 0;


						 8: reply <= 40'h01000001AA;


						 9,

						10: begin
								reply[39:32] <= 0;
								read_state <= RD_STATE_START;
							end


						12: reply[39:32] <= 0;
						

						13: reply[39:24] <= 16'h0000;


						16: reply[39:32] <= (arg == 512) ? 8'h00 : 8'h40;


						17,

						18: begin
								reply[39:32] <= 0;
								read_state <= RD_STATE_START;
								spi_buf <= 0;
								sd_buf <= 0;
								sd_lba <= csd_sdhc ? arg : {9'd0, arg[31:9]};
							end


						23: reply[39:32] <= 0;


						24,

						25: begin
								reply[39:32] <= 0;
								write_state <= WR_STATE_EXP_DTOKEN;
								spi_buf <= 0;
								sd_buf <= 0;
								sd_lba <= csd_sdhc ? arg : {9'd0, arg[31:9]};
							end


						41: if(cmd55) reply[39:32] <= 0;


						55: reply[39:32] <= 1;


						58: reply <= { 8'h00, 1'b1, csd_sdhc, 30'd0 };


						59: reply[39:32] <= 0;
					endcase
				end


				case(write_state)

					WR_STATE_IDLE: ;


					WR_STATE_EXP_DTOKEN: begin
						buffer_ptr <= 0;
						if(cmd == 24) begin
							if(ibuf == DATA_TOKEN)       write_state <= WR_STATE_RECV_DATA;
						end
						else begin
							if(ibuf == DATA_TOKEN_CMD25) write_state <= WR_STATE_RECV_DATA;
							if(ibuf == STOP_TRAN)        write_state <= WR_STATE_IDLE;
						end
					end


					WR_STATE_RECV_DATA: begin

						buffer_wr  <= 1;
						buffer_din <= ibuf;


						if(&buffer_ptr) write_state <= WR_STATE_RECV_CRC0;
					end


					WR_STATE_RECV_CRC0:
						write_state <= WR_STATE_RECV_CRC1;


					WR_STATE_RECV_CRC1:
						write_state <= WR_STATE_SEND_DRESP;


					WR_STATE_SEND_DRESP:
						write_state <= WR_STATE_BUSY;


					WR_STATE_BUSY:
						if(spi_buf == sd_buf) write_state <= (cmd == 25) ? WR_STATE_EXP_DTOKEN : WR_STATE_IDLE;
				endcase
			end
		end
	end
end

endmodule