OpenCores
URL https://opencores.org/ocsvn/aoocs/aoocs/trunk

Subversion Repositories aoocs

[/] [aoocs/] [trunk/] [tests/] [model_sd.v] - Rev 2

Compare with Previous | Blame | View Log

 
module model_sd(
	input reset_n,
 
	input sd_clk,
	inout sd_cmd_io,
	inout sd_dat_io
);
 
reg sd_cmd_o;
reg sd_dat_o;
reg sd_cmd_enable;
reg sd_data_enable;
 
assign sd_cmd_io = (sd_cmd_enable == 1'b1) ? sd_cmd_o : 1'bZ;
assign sd_dat_io = (sd_data_enable == 1'b1) ? sd_dat_o : 1'bZ;
 
reg [3:0] cmd_state;
reg [47:0] cmd_contents;
reg [135:0] cmd_reply;
reg [7:0] cmd_counter;
reg [6:0] crc7;
 
parameter [3:0]
	S_CMD_START_BIT = 4'd0,
	S_CMD_CONTENTS = 4'd1,
	S_CMD_CRC7_END_BIT = 4'd2,
	S_CMD_CHECK = 4'd3,
	S_CMD_WAIT = 4'd4,
	S_CMD_SEND_CONTENTS = 4'd5,
	S_CMD_SEND_CRC7 = 4'd6,
	S_CMD_SEND_END_BIT = 4'd7,
	S_CMD_SEND_FINISHED = 4'd8;
 
always @(posedge sd_clk or negedge reset_n) begin
	if(reset_n == 1'b0) begin
		cmd_state <= S_CMD_START_BIT;
		sd_cmd_enable <= 1'b0;
		sd_cmd_o <= 1'b1;
		cmd_contents <= 48'd0;
		cmd_counter <= 8'd0;
		crc7 <= 7'd0;
	end
	else if(cmd_state == S_CMD_START_BIT) begin
		if(sd_cmd_io == 1'b0) begin
			cmd_contents <= { cmd_contents[46:0], sd_cmd_io };
			crc7 <= { sd_cmd_io ^ crc7[0], crc7[6:5], sd_cmd_io ^ crc7[4] ^ crc7[0], crc7[3:1] };
			cmd_state <= S_CMD_CONTENTS;
			cmd_counter <= 8'd0;
		end
	end
	else if(cmd_state == S_CMD_CONTENTS) begin
		cmd_contents <= { cmd_contents[46:0], sd_cmd_io };
		crc7 <= { sd_cmd_io ^ crc7[0], crc7[6:5], sd_cmd_io ^ crc7[4] ^ crc7[0], crc7[3:1] };
 
		if(cmd_counter == 8'd38) begin
			cmd_state <= S_CMD_CRC7_END_BIT;
			cmd_counter <= 8'd0;
		end
		else cmd_counter <= cmd_counter + 8'd1;
	end
	else if(cmd_state == S_CMD_CRC7_END_BIT) begin
		cmd_contents <= { cmd_contents[46:0], sd_cmd_io };
 
		if(cmd_counter == 8'd7) begin
			cmd_state <= S_CMD_CHECK;
			cmd_counter <= 8'd0;
		end
		else cmd_counter <= cmd_counter + 8'd1;
	end
	else if(cmd_state == S_CMD_CHECK) begin
		crc7 <= 7'd0;
 
		if(
			cmd_contents == { 1'b0, 1'b1, 6'd0, 32'd0, crc7[0],crc7[1],crc7[2],crc7[3],crc7[4],crc7[5],crc7[6], 1'b1 }
		) begin 
			$display("CMD0");
			cmd_state <= S_CMD_START_BIT;
		end
		else if(
			cmd_contents == { 1'b0, 1'b1, 6'd8, 20'd0, 4'b0001, 8'b10101010, crc7[0],crc7[1],crc7[2],crc7[3],crc7[4],crc7[5],crc7[6], 1'b1 }
		) begin 
			$display("CMD8");
			cmd_reply[135:88] <= { 1'b0, 1'b0, 6'd8, 20'd0, 4'b0001, cmd_contents[15:8], 7'd0, 1'b1}; 
			cmd_state <= S_CMD_WAIT;
		end
		else if(
			cmd_contents == { 1'b0, 1'b1, 6'd55, 16'd0, 16'd0, crc7[0],crc7[1],crc7[2],crc7[3],crc7[4],crc7[5],crc7[6], 1'b1 }
		) begin 
			$display("CMD55");
			cmd_reply[135:88] <= { 1'b0, 1'b0, 6'd55, 32'b100000, 7'd0, 1'b1}; 
			cmd_state <= S_CMD_WAIT;
		end
		else if(
			cmd_contents == { 1'b0, 1'b1, 6'd41, 1'b0, 1'b1, 6'b0, 24'b0001_0000_0000_0000_0000_0000,
				crc7[0],crc7[1],crc7[2],crc7[3],crc7[4],crc7[5],crc7[6], 1'b1 }
		) begin 
			$display("CMD41");
			cmd_reply[135:88] <= { 1'b0, 1'b0, 6'b111111, 32'b1100_0000_00000000_00000000_00000000, 7'b1111111, 1'b1}; 
			cmd_state <= S_CMD_WAIT;
		end
		else if(
			cmd_contents == { 1'b0, 1'b1, 6'd2, 32'd0, crc7[0],crc7[1],crc7[2],crc7[3],crc7[4],crc7[5],crc7[6], 1'b1 }
		) begin 
			$display("CMD2");
			cmd_reply[135:0] <= { 135'd0, 1'b1}; 
			cmd_state <= S_CMD_WAIT;
		end
		else if(
			cmd_contents == { 1'b0, 1'b1, 6'd3, 32'd0, crc7[0],crc7[1],crc7[2],crc7[3],crc7[4],crc7[5],crc7[6], 1'b1 }
		) begin 
			$display("CMD3");
			cmd_reply[135:88] <= { 1'b0, 1'b0, 6'd3, 16'hA0A0, 16'b0, 7'd0, 1'b1}; 
			cmd_state <= S_CMD_WAIT;
		end
		else if(
			cmd_contents == { 1'b0, 1'b1, 6'd7, 16'hA0A0, 16'd0, crc7[0],crc7[1],crc7[2],crc7[3],crc7[4],crc7[5],crc7[6], 1'b1 }
		) begin 
			$display("CMD7: %08h", cmd_contents);
 
			cmd_reply[135:88] <= { 1'b0, 1'b0, 6'd7, 32'b0, 7'd0, 1'b1}; 
			cmd_state <= S_CMD_WAIT;
		end
		else if(
			cmd_contents[47:40] == { 1'b0, 1'b1, 6'd17 } && cmd_contents[7:0] == { crc7[0],crc7[1],crc7[2],crc7[3],crc7[4],crc7[5],crc7[6], 1'b1 }
		) begin 
			$display("CMD17: %08h", cmd_contents);
 
			cmd_reply[135:88] <= { 1'b0, 1'b0, 6'd17, 32'b0, 7'd0, 1'b1}; 
			cmd_state <= S_CMD_WAIT;
		end
		else if(
			cmd_contents[47:40] == { 1'b0, 1'b1, 6'd24 } && cmd_contents[7:0] == { crc7[0],crc7[1],crc7[2],crc7[3],crc7[4],crc7[5],crc7[6], 1'b1 }
		) begin 
			$display("CMD24: %08h", cmd_contents);
 
			cmd_reply[135:88] <= { 1'b0, 1'b0, 6'd24, 32'b0, 7'd0, 1'b1}; 
			cmd_state <= S_CMD_WAIT;
		end
		else begin
			$display("Other cmd: %02d, contents: %08h", cmd_contents[45:40], cmd_contents);
			cmd_state <= S_CMD_START_BIT;
		end
	end
	else if(cmd_state == S_CMD_WAIT) begin
		if(cmd_counter == 8'd15) begin
			cmd_counter <= 8'd0;
			sd_cmd_enable <= 1'b1;
			sd_cmd_o <= 1'b1;
			cmd_state <= S_CMD_SEND_CONTENTS;
		end
		else cmd_counter <= cmd_counter + 8'd1;
	end
	else if(cmd_state == S_CMD_SEND_CONTENTS) begin
		sd_cmd_o <= cmd_reply[135];
		cmd_reply <= { cmd_reply[134:0], 1'b0 };
		crc7 <= { cmd_reply[135] ^ crc7[0], crc7[6:5], cmd_reply[135] ^ crc7[4] ^ crc7[0], crc7[3:1] };
 
		if(cmd_counter == 8'd47 && cmd_contents[45:40] == 6'd41) begin
			cmd_counter <= 8'd0;
			cmd_state <= S_CMD_SEND_FINISHED;
		end
		else if(cmd_counter == 8'd39 && cmd_contents[45:40] != 6'd2 && cmd_contents[45:40] != 6'd41) begin
			cmd_counter <= 8'd0;
			cmd_state <= S_CMD_SEND_CRC7;
		end
		else if(cmd_counter == 8'd135 && cmd_contents[45:40] == 8'd2) begin
			cmd_counter <= 8'd0;
			cmd_state <= S_CMD_SEND_FINISHED;
		end
		else cmd_counter <= cmd_counter + 8'd1;
	end
	else if(cmd_state == S_CMD_SEND_CRC7) begin
		sd_cmd_o <= crc7[0];
		crc7 <= { 1'b0, crc7[6:1] };
 
		if(cmd_counter == 8'd6) begin
			cmd_counter <= 8'd0;
			cmd_state <= S_CMD_SEND_END_BIT;
		end
		else cmd_counter <= cmd_counter + 8'd1;
	end
	else if(cmd_state == S_CMD_SEND_END_BIT) begin
		sd_cmd_o <= 1'b1;
		cmd_state <= S_CMD_SEND_FINISHED;
	end
	else if(cmd_state == S_CMD_SEND_FINISHED) begin
		sd_cmd_o <= 1'b1;
		sd_cmd_enable <= 1'b0;
		crc7 <= 7'd0;
		cmd_state <= S_CMD_START_BIT;
	end
end
 
reg [2:0] data_state;
reg [11:0] data_counter;
reg [4095:0] data_contents;
reg [15:0] crc16;
 
parameter [2:0]
	S_DATA_IDLE = 3'd0,
	S_DATA_R1B_REPLY = 3'd1,
	S_DATA_R1B_REPLY_1 = 3'd2,
	S_DATA_READ = 3'd3,
	S_DATA_READ_1 = 3'd4,
	S_DATA_READ_2 = 3'd5,
	S_DATA_READ_3 = 3'd6;
 
 
always @(posedge sd_clk or negedge reset_n) begin
	if(reset_n == 1'b0) begin
		sd_data_enable <= 1'b0;
		sd_dat_o <= 1'b1;
		data_state <= S_DATA_IDLE;
		data_counter <= 12'd0;
		crc16 <= 16'd0;
	end
	else if(data_state == S_DATA_IDLE) begin
		if(cmd_contents[45:40] == 6'd7 && cmd_state == S_CMD_SEND_CRC7) begin
			sd_data_enable <= 1'b1;
			sd_dat_o <= 1'b1;
			data_state <= S_DATA_R1B_REPLY;
		end
		else if(cmd_contents[45:40] == 6'd17 && cmd_state == S_CMD_SEND_CRC7) begin
			sd_data_enable <= 1'b1;
			sd_dat_o <= 1'b1;
			data_contents <= { 1'b1, 31'b0, 1'b1, 4062'd0, 1'b1 };
			data_state <= S_DATA_READ;
		end
	end
	else if(data_state == S_DATA_R1B_REPLY) begin
		if(data_counter == 12'd16) begin
			sd_dat_o <= 1'b1;
			data_counter <= 12'd0;
			data_state <= S_DATA_R1B_REPLY_1;
		end
		else begin
			sd_dat_o <= 1'b0;
			data_counter <= data_counter + 12'd1;
		end
	end
	else if(data_state == S_DATA_R1B_REPLY_1) begin
		sd_data_enable <= 1'b0;
		data_state <= S_DATA_IDLE;
	end
 
 
	else if(data_state == S_DATA_READ) begin
		sd_dat_o <= 1'b0;
		crc16 <= { 1'b0 ^ crc16[0], crc16[15:12], 1'b0 ^ crc16[11] ^ crc16[0], crc16[10:5],
			1'b0 ^ crc16[4] ^ crc16[0], crc16[3:1] };
 
		data_counter <= 12'd0;
		data_state <= S_DATA_READ_1;
	end
	else if(data_state == S_DATA_READ_1) begin
		sd_dat_o <= data_contents[4095];
		crc16 <= { data_contents[4095] ^ crc16[0], crc16[15:12], data_contents[4095] ^ crc16[11] ^ crc16[0], crc16[10:5],
			data_contents[4095] ^ crc16[4] ^ crc16[0], crc16[3:1] };
		data_contents <= { data_contents[4094:0], 1'b0 };
 
		if(data_counter == 12'd4095) begin
			data_counter <= 12'd0;
			data_state <= S_DATA_READ_2;
		end
		else data_counter <= data_counter + 12'd1;
	end
 
	else if(data_state == S_DATA_READ_2) begin
		sd_dat_o <= crc16[0];
 
		if(data_counter == 12'd16) begin
			data_counter <= 12'd0;
			data_state <= S_DATA_READ_3;
		end
		else begin
			crc16 <= { 1'b1, crc16[15:1] };
			data_counter <= data_counter + 12'd1;
		end
	end
	else if(data_state == S_DATA_READ_3) begin
		sd_data_enable <= 1'b0;
		crc16 <= 16'd0;
		data_state <= S_DATA_IDLE;
	end
 
end
 
endmodule
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.