Revision 240
Added by markw almost 11 years ago
mist/sd_card.v | ||
---|---|---|
|
||
// set io_rd once read_state machine starts waiting (rising edge of req_io_rd)
|
||
// and clear it once io controller uploads something (io_ack==1)
|
||
wire req_io_rd = (read_state == RD_STATE_WAIT_IO);
|
||
// wire req_io_rd = (read_state == RD_STATE_WAIT_IO);
|
||
wire req_io_rd = (read_state != RD_STATE_IDLE);
|
||
always @(posedge req_io_rd or posedge io_ack) begin
|
||
if(io_ack) io_rd <= 1'b0;
|
||
else io_rd <= 1'b1;
|
||
... | ... | |
// 0=idle, 1=wait for io ctrl, 2=wait for byte start, 3=send token, 4=send data, 5/6=send crc[0..1]
|
||
localparam RD_STATE_IDLE = 3'd0;
|
||
localparam RD_STATE_WAIT_IO = 3'd1;
|
||
localparam RD_STATE_WAIT_START = 3'd2;
|
||
localparam RD_STATE_SEND_TOKEN = 3'd3;
|
||
localparam RD_STATE_SEND_DATA = 3'd4;
|
||
localparam RD_STATE_SEND_CRC0 = 3'd5;
|
||
localparam RD_STATE_SEND_CRC1 = 3'd6;
|
||
localparam RD_STATE_SEND_TOKEN = 3'd2;
|
||
localparam RD_STATE_SEND_DATA = 3'd3;
|
||
localparam RD_STATE_SEND_CRC0 = 3'd4;
|
||
localparam RD_STATE_SEND_CRC1 = 3'd5;
|
||
reg [2:0] read_state = RD_STATE_IDLE;
|
||
|
||
// 0=idle
|
||
... | ... | |
|
||
reg [31:0] lba;
|
||
assign io_lba = io_sdhc?lba:{9'd0, lba[31:9]};
|
||
//assign io_lba = io_sdhc?{read_state, lba[31:3]}:{9'd0, lba[31:9]};
|
||
|
||
// the command crc is actually never evaluated
|
||
reg [7:0] crc;
|
||
... | ... | |
// falling edge of io_ack signals that a sector to be read has been written into
|
||
// the sector bufffer by the io controller. This signal is kept set as long
|
||
// as the read state machine is in the "wait for io controller" state (state 1)
|
||
wire rd_wait_io = (read_state == RD_STATE_WAIT_IO);
|
||
// wire rd_wait_io = (read_state == RD_STATE_WAIT_IO);
|
||
wire rd_wait_io = (read_state != RD_STATE_IDLE);
|
||
reg rd_io_ack = 1'b0 /* synthesis noprune */;
|
||
always @(negedge io_ack or negedge rd_wait_io) begin
|
||
if(!rd_wait_io) rd_io_ack <= 1'b0;
|
||
else rd_io_ack <= 1'b1;
|
||
end
|
||
|
||
|
||
wire wr_wait_io = (write_state == WR_STATE_BUSY);
|
||
reg wr_io_ack = 1'b0 /* synthesis noprune */;
|
||
always @(negedge io_ack or negedge wr_wait_io) begin
|
||
... | ... | |
csd_wptr <= csd_wptr + 1;
|
||
end
|
||
end
|
||
|
||
|
||
always @(posedge buffer_read_latch)
|
||
cid_byte <= cid[buffer_rptr];
|
||
|
||
always @(posedge buffer_read_latch)
|
||
csd_byte <= csd[buffer_rptr];
|
||
|
||
|
||
// ----------------- spi transmitter --------------------
|
||
reg rd_io_ackD, wr_io_ackD;
|
||
|
||
always@(negedge sd_sck or posedge sd_cs) begin
|
||
if(sd_cs == 1) begin
|
||
// sd_sdo <= 1'b1;
|
||
// read_state <= RD_STATE_IDLE;
|
||
end else begin
|
||
reg illegal_state /* synthesis noprune */;
|
||
|
||
always@(negedge sd_sck) begin
|
||
if(sd_cs == 0) begin
|
||
illegal_state <= 1'b0;
|
||
core_buffer_read_strobe <= 1'b0;
|
||
|
||
// using rd_io_ack directly brings the read state machine into an
|
||
// non-existing state every now and then. For unknown reason
|
||
rd_io_ackD <= rd_io_ack;
|
||
|
||
// -------- catch read commmand and reset read state machine ------
|
||
if(bit_cnt == 7) begin
|
||
if(byte_cnt == 4) begin
|
||
// wait for end of command plus NCR before replying
|
||
if(byte_cnt < 5+NCR) begin
|
||
sd_sdo <= 1'b1; // reply $ff -> wait
|
||
end else if(byte_cnt == 5+NCR) begin
|
||
sd_sdo <= reply[~bit_cnt];
|
||
|
||
if(bit_cnt == 7) begin
|
||
// these three commands all have a reply_len of 0 and will thus
|
||
// not send more than a single reply byte
|
||
|
||
// CMD9: SEND_CSD
|
||
// CMD10: SEND_CID
|
||
if((cmd == 8'h49)||(cmd == 8'h4a))
|
||
read_state <= RD_STATE_SEND_TOKEN; // jump directly to data transmission
|
||
|
||
// CMD17: READ_SINGLE_BLOCK
|
||
if(cmd == 8'h51)
|
||
read_state <= RD_STATE_WAIT_IO; // start waiting for data from io controller
|
||
end
|
||
end
|
||
else if((reply_len > 0) && (byte_cnt == 5+NCR+1))
|
||
sd_sdo <= reply0[~bit_cnt];
|
||
else if((reply_len > 1) && (byte_cnt == 5+NCR+2))
|
||
sd_sdo <= reply1[~bit_cnt];
|
||
else if((reply_len > 2) && (byte_cnt == 5+NCR+3))
|
||
sd_sdo <= reply2[~bit_cnt];
|
||
else if((reply_len > 3) && (byte_cnt == 5+NCR+4))
|
||
sd_sdo <= reply3[~bit_cnt];
|
||
else
|
||
sd_sdo <= 1'b1;
|
||
|
||
if(byte_cnt < 5+NCR) begin
|
||
sd_sdo <= 1'b1; // reply $ff -> wait
|
||
end else begin
|
||
// ---------- read state machine processing -------------
|
||
|
||
if(byte_cnt == 5+NCR) begin
|
||
sd_sdo <= reply[~bit_cnt];
|
||
case(read_state)
|
||
RD_STATE_IDLE: ;
|
||
// don't do anything
|
||
|
||
if(bit_cnt == 7) begin
|
||
// CMD9: SEND_CSD
|
||
// CMD10: SEND_CID
|
||
if((cmd == 8'h49)||(cmd == 8'h4a))
|
||
read_state <= RD_STATE_SEND_TOKEN; // jump directly to data transmission
|
||
end
|
||
// waiting for io controller to return data
|
||
RD_STATE_WAIT_IO: begin
|
||
if(rd_io_ack && (bit_cnt == 7))
|
||
read_state <= RD_STATE_SEND_TOKEN;
|
||
end
|
||
else if((reply_len > 0) && (byte_cnt == 5+NCR+1))
|
||
sd_sdo <= reply0[~bit_cnt];
|
||
else if((reply_len > 1) && (byte_cnt == 5+NCR+2))
|
||
sd_sdo <= reply1[~bit_cnt];
|
||
else if((reply_len > 2) && (byte_cnt == 5+NCR+3))
|
||
sd_sdo <= reply2[~bit_cnt];
|
||
else if((reply_len > 3) && (byte_cnt == 5+NCR+4))
|
||
sd_sdo <= reply3[~bit_cnt];
|
||
else
|
||
sd_sdo <= 1'b1;
|
||
|
||
// falling edge of io_ack signals end of incoming data stream
|
||
if((read_state == RD_STATE_WAIT_IO) && rd_io_ackD)
|
||
read_state <= RD_STATE_WAIT_START;
|
||
|
||
// wait for begin of new byte
|
||
else if((read_state == RD_STATE_WAIT_START) && (bit_cnt == 7))
|
||
read_state <= RD_STATE_SEND_TOKEN;
|
||
|
||
// send data token
|
||
else if(read_state == RD_STATE_SEND_TOKEN) begin
|
||
RD_STATE_SEND_TOKEN: begin
|
||
sd_sdo <= READ_DATA_TOKEN[~bit_cnt];
|
||
|
||
|
||
if(bit_cnt == 7)
|
||
read_state <= RD_STATE_SEND_DATA; // next: send data
|
||
end
|
||
|
||
|
||
// send data
|
||
else if(read_state == RD_STATE_SEND_DATA) begin
|
||
RD_STATE_SEND_DATA: begin
|
||
if(cmd == 8'h51) // CMD17: READ_SINGLE_BLOCK
|
||
sd_sdo <= buffer_byte[~bit_cnt];
|
||
else if(cmd == 8'h49) // CMD9: SEND_CSD
|
||
sd_sdo <= csd_byte[~bit_cnt];
|
||
else if(cmd == 8'h4a) // CMD10: SEND_CID
|
||
sd_sdo <= cid_byte[~bit_cnt];
|
||
else
|
||
sd_sdo <= 1'b1;
|
||
|
||
if(bit_cnt == 7) begin
|
||
core_buffer_read_strobe <= 1'b1;
|
||
|
||
|
||
// send 512 sector data bytes?
|
||
if((cmd == 8'h51) && (buffer_rptr == 511))
|
||
read_state <= RD_STATE_SEND_CRC0; // next: send crc
|
||
... | ... | |
read_state <= RD_STATE_IDLE; // return to idle state
|
||
end
|
||
end
|
||
|
||
|
||
// send crc[0]
|
||
else if(read_state == RD_STATE_SEND_CRC0) begin
|
||
RD_STATE_SEND_CRC0: begin
|
||
sd_sdo <= 1'b1;
|
||
if(bit_cnt == 7)
|
||
read_state <= RD_STATE_SEND_CRC1; // send second crc byte
|
||
end
|
||
|
||
|
||
// send crc[1]
|
||
else if(read_state == RD_STATE_SEND_CRC1) begin
|
||
RD_STATE_SEND_CRC1: begin
|
||
sd_sdo <= 1'b1;
|
||
if(bit_cnt == 7)
|
||
read_state <= RD_STATE_IDLE; // return to idle state
|
||
end
|
||
|
||
// ------------------ write support ----------------------
|
||
// send write data response
|
||
if(write_state == WR_STATE_SEND_DRESP)
|
||
sd_sdo <= WRITE_DATA_RESPONSE[~bit_cnt];
|
||
|
||
// busy after write until the io controller sends ack
|
||
if(write_state == WR_STATE_BUSY)
|
||
sd_sdo <= 1'b0;
|
||
end
|
||
|
||
default:
|
||
illegal_state <= 1'b1;
|
||
// read_state <= RD_STATE_IDLE;
|
||
|
||
endcase
|
||
|
||
// ------------------ write support ----------------------
|
||
// send write data response
|
||
if(write_state == WR_STATE_SEND_DRESP)
|
||
sd_sdo <= WRITE_DATA_RESPONSE[~bit_cnt];
|
||
|
||
// busy after write until the io controller sends ack
|
||
if(write_state == WR_STATE_BUSY)
|
||
sd_sdo <= 1'b0;
|
||
end
|
||
end
|
||
|
mist_5200/sd_card.v | ||
---|---|---|
|
||
// set io_rd once read_state machine starts waiting (rising edge of req_io_rd)
|
||
// and clear it once io controller uploads something (io_ack==1)
|
||
wire req_io_rd = (read_state == RD_STATE_WAIT_IO);
|
||
// wire req_io_rd = (read_state == RD_STATE_WAIT_IO);
|
||
wire req_io_rd = (read_state != RD_STATE_IDLE);
|
||
always @(posedge req_io_rd or posedge io_ack) begin
|
||
if(io_ack) io_rd <= 1'b0;
|
||
else io_rd <= 1'b1;
|
||
... | ... | |
// 0=idle, 1=wait for io ctrl, 2=wait for byte start, 3=send token, 4=send data, 5/6=send crc[0..1]
|
||
localparam RD_STATE_IDLE = 3'd0;
|
||
localparam RD_STATE_WAIT_IO = 3'd1;
|
||
localparam RD_STATE_WAIT_START = 3'd2;
|
||
localparam RD_STATE_SEND_TOKEN = 3'd3;
|
||
localparam RD_STATE_SEND_DATA = 3'd4;
|
||
localparam RD_STATE_SEND_CRC0 = 3'd5;
|
||
localparam RD_STATE_SEND_CRC1 = 3'd6;
|
||
localparam RD_STATE_SEND_TOKEN = 3'd2;
|
||
localparam RD_STATE_SEND_DATA = 3'd3;
|
||
localparam RD_STATE_SEND_CRC0 = 3'd4;
|
||
localparam RD_STATE_SEND_CRC1 = 3'd5;
|
||
reg [2:0] read_state = RD_STATE_IDLE;
|
||
|
||
// 0=idle
|
||
... | ... | |
|
||
reg [31:0] lba;
|
||
assign io_lba = io_sdhc?lba:{9'd0, lba[31:9]};
|
||
//assign io_lba = io_sdhc?{read_state, lba[31:3]}:{9'd0, lba[31:9]};
|
||
|
||
// the command crc is actually never evaluated
|
||
reg [7:0] crc;
|
||
... | ... | |
// falling edge of io_ack signals that a sector to be read has been written into
|
||
// the sector bufffer by the io controller. This signal is kept set as long
|
||
// as the read state machine is in the "wait for io controller" state (state 1)
|
||
wire rd_wait_io = (read_state == RD_STATE_WAIT_IO);
|
||
// wire rd_wait_io = (read_state == RD_STATE_WAIT_IO);
|
||
wire rd_wait_io = (read_state != RD_STATE_IDLE);
|
||
reg rd_io_ack = 1'b0 /* synthesis noprune */;
|
||
always @(negedge io_ack or negedge rd_wait_io) begin
|
||
if(!rd_wait_io) rd_io_ack <= 1'b0;
|
||
else rd_io_ack <= 1'b1;
|
||
end
|
||
|
||
|
||
wire wr_wait_io = (write_state == WR_STATE_BUSY);
|
||
reg wr_io_ack = 1'b0 /* synthesis noprune */;
|
||
always @(negedge io_ack or negedge wr_wait_io) begin
|
||
... | ... | |
csd_wptr <= csd_wptr + 1;
|
||
end
|
||
end
|
||
|
||
|
||
always @(posedge buffer_read_latch)
|
||
cid_byte <= cid[buffer_rptr];
|
||
|
||
always @(posedge buffer_read_latch)
|
||
csd_byte <= csd[buffer_rptr];
|
||
|
||
|
||
// ----------------- spi transmitter --------------------
|
||
reg rd_io_ackD, wr_io_ackD;
|
||
|
||
always@(negedge sd_sck or posedge sd_cs) begin
|
||
if(sd_cs == 1) begin
|
||
// sd_sdo <= 1'b1;
|
||
// read_state <= RD_STATE_IDLE;
|
||
end else begin
|
||
reg illegal_state /* synthesis noprune */;
|
||
|
||
always@(negedge sd_sck) begin
|
||
if(sd_cs == 0) begin
|
||
illegal_state <= 1'b0;
|
||
core_buffer_read_strobe <= 1'b0;
|
||
|
||
// using rd_io_ack directly brings the read state machine into an
|
||
// non-existing state every now and then. For unknown reason
|
||
rd_io_ackD <= rd_io_ack;
|
||
|
||
// -------- catch read commmand and reset read state machine ------
|
||
if(bit_cnt == 7) begin
|
||
if(byte_cnt == 4) begin
|
||
// wait for end of command plus NCR before replying
|
||
if(byte_cnt < 5+NCR) begin
|
||
sd_sdo <= 1'b1; // reply $ff -> wait
|
||
end else if(byte_cnt == 5+NCR) begin
|
||
sd_sdo <= reply[~bit_cnt];
|
||
|
||
if(bit_cnt == 7) begin
|
||
// these three commands all have a reply_len of 0 and will thus
|
||
// not send more than a single reply byte
|
||
|
||
// CMD9: SEND_CSD
|
||
// CMD10: SEND_CID
|
||
if((cmd == 8'h49)||(cmd == 8'h4a))
|
||
read_state <= RD_STATE_SEND_TOKEN; // jump directly to data transmission
|
||
|
||
// CMD17: READ_SINGLE_BLOCK
|
||
if(cmd == 8'h51)
|
||
read_state <= RD_STATE_WAIT_IO; // start waiting for data from io controller
|
||
end
|
||
end
|
||
else if((reply_len > 0) && (byte_cnt == 5+NCR+1))
|
||
sd_sdo <= reply0[~bit_cnt];
|
||
else if((reply_len > 1) && (byte_cnt == 5+NCR+2))
|
||
sd_sdo <= reply1[~bit_cnt];
|
||
else if((reply_len > 2) && (byte_cnt == 5+NCR+3))
|
||
sd_sdo <= reply2[~bit_cnt];
|
||
else if((reply_len > 3) && (byte_cnt == 5+NCR+4))
|
||
sd_sdo <= reply3[~bit_cnt];
|
||
else
|
||
sd_sdo <= 1'b1;
|
||
|
||
if(byte_cnt < 5+NCR) begin
|
||
sd_sdo <= 1'b1; // reply $ff -> wait
|
||
end else begin
|
||
// ---------- read state machine processing -------------
|
||
|
||
if(byte_cnt == 5+NCR) begin
|
||
sd_sdo <= reply[~bit_cnt];
|
||
case(read_state)
|
||
RD_STATE_IDLE: ;
|
||
// don't do anything
|
||
|
||
if(bit_cnt == 7) begin
|
||
// CMD9: SEND_CSD
|
||
// CMD10: SEND_CID
|
||
if((cmd == 8'h49)||(cmd == 8'h4a))
|
||
read_state <= RD_STATE_SEND_TOKEN; // jump directly to data transmission
|
||
end
|
||
// waiting for io controller to return data
|
||
RD_STATE_WAIT_IO: begin
|
||
if(rd_io_ack && (bit_cnt == 7))
|
||
read_state <= RD_STATE_SEND_TOKEN;
|
||
end
|
||
else if((reply_len > 0) && (byte_cnt == 5+NCR+1))
|
||
sd_sdo <= reply0[~bit_cnt];
|
||
else if((reply_len > 1) && (byte_cnt == 5+NCR+2))
|
||
sd_sdo <= reply1[~bit_cnt];
|
||
else if((reply_len > 2) && (byte_cnt == 5+NCR+3))
|
||
sd_sdo <= reply2[~bit_cnt];
|
||
else if((reply_len > 3) && (byte_cnt == 5+NCR+4))
|
||
sd_sdo <= reply3[~bit_cnt];
|
||
else
|
||
sd_sdo <= 1'b1;
|
||
|
||
// falling edge of io_ack signals end of incoming data stream
|
||
if((read_state == RD_STATE_WAIT_IO) && rd_io_ackD)
|
||
read_state <= RD_STATE_WAIT_START;
|
||
|
||
// wait for begin of new byte
|
||
else if((read_state == RD_STATE_WAIT_START) && (bit_cnt == 7))
|
||
read_state <= RD_STATE_SEND_TOKEN;
|
||
|
||
// send data token
|
||
else if(read_state == RD_STATE_SEND_TOKEN) begin
|
||
RD_STATE_SEND_TOKEN: begin
|
||
sd_sdo <= READ_DATA_TOKEN[~bit_cnt];
|
||
|
||
|
||
if(bit_cnt == 7)
|
||
read_state <= RD_STATE_SEND_DATA; // next: send data
|
||
end
|
||
|
||
|
||
// send data
|
||
else if(read_state == RD_STATE_SEND_DATA) begin
|
||
RD_STATE_SEND_DATA: begin
|
||
if(cmd == 8'h51) // CMD17: READ_SINGLE_BLOCK
|
||
sd_sdo <= buffer_byte[~bit_cnt];
|
||
else if(cmd == 8'h49) // CMD9: SEND_CSD
|
||
sd_sdo <= csd_byte[~bit_cnt];
|
||
else if(cmd == 8'h4a) // CMD10: SEND_CID
|
||
sd_sdo <= cid_byte[~bit_cnt];
|
||
else
|
||
sd_sdo <= 1'b1;
|
||
|
||
if(bit_cnt == 7) begin
|
||
core_buffer_read_strobe <= 1'b1;
|
||
|
||
|
||
// send 512 sector data bytes?
|
||
if((cmd == 8'h51) && (buffer_rptr == 511))
|
||
read_state <= RD_STATE_SEND_CRC0; // next: send crc
|
||
... | ... | |
read_state <= RD_STATE_IDLE; // return to idle state
|
||
end
|
||
end
|
||
|
||
|
||
// send crc[0]
|
||
else if(read_state == RD_STATE_SEND_CRC0) begin
|
||
RD_STATE_SEND_CRC0: begin
|
||
sd_sdo <= 1'b1;
|
||
if(bit_cnt == 7)
|
||
read_state <= RD_STATE_SEND_CRC1; // send second crc byte
|
||
end
|
||
|
||
|
||
// send crc[1]
|
||
else if(read_state == RD_STATE_SEND_CRC1) begin
|
||
RD_STATE_SEND_CRC1: begin
|
||
sd_sdo <= 1'b1;
|
||
if(bit_cnt == 7)
|
||
read_state <= RD_STATE_IDLE; // return to idle state
|
||
end
|
||
|
||
// ------------------ write support ----------------------
|
||
// send write data response
|
||
if(write_state == WR_STATE_SEND_DRESP)
|
||
sd_sdo <= WRITE_DATA_RESPONSE[~bit_cnt];
|
||
|
||
// busy after write until the io controller sends ack
|
||
if(write_state == WR_STATE_BUSY)
|
||
sd_sdo <= 1'b0;
|
||
end
|
||
|
||
default:
|
||
illegal_state <= 1'b1;
|
||
// read_state <= RD_STATE_IDLE;
|
||
|
||
endcase
|
||
|
||
// ------------------ write support ----------------------
|
||
// send write data response
|
||
if(write_state == WR_STATE_SEND_DRESP)
|
||
sd_sdo <= WRITE_DATA_RESPONSE[~bit_cnt];
|
||
|
||
// busy after write until the io controller sends ack
|
||
if(write_state == WR_STATE_BUSY)
|
||
sd_sdo <= 1'b0;
|
||
end
|
||
end
|
||
|
Also available in: Unified diff
sd emulation fix - thanks Till