URL
https://opencores.org/ocsvn/sdcard_mass_storage_controller/sdcard_mass_storage_controller/trunk
Subversion Repositories sdcard_mass_storage_controller
Compare Revisions
- This comparison shows the changes necessary to convert path
/sdcard_mass_storage_controller/trunk/rtl
- from Rev 124 to Rev 127
- ↔ Reverse comparison
Rev 124 → Rev 127
/sdc_dma/verilog/SD_data_host.v
1,457 → 1,458
|
|
`include "SD_defines.v" |
|
|
module SD_DATA_SERIAL_HOST( |
input sd_clk, |
input rst, |
//Tx Fifo |
input [31:0] data_in , |
|
output reg rd, |
//Rx Fifo |
output reg [`SD_BUS_W-1:0] data_out , |
output reg we, |
//tristate data |
output reg DAT_oe_o, |
output reg[`SD_BUS_W-1:0] DAT_dat_o, |
input [`SD_BUS_W-1:0] DAT_dat_i, |
//Controll signals |
input [1:0] start_dat, |
input ack_transfer, |
|
output reg busy_n, |
output reg transm_complete, |
output reg crc_ok |
); |
|
//CRC16 |
reg [`SD_BUS_W-1:0] crc_in; |
reg crc_en; |
reg crc_rst; |
wire [15:0] crc_out [`SD_BUS_W-1:0]; |
reg [`SD_BUS_W-1:0] temp_in; |
|
reg [10:0] transf_cnt; |
parameter SIZE = 6; |
reg [SIZE-1:0] state; |
reg [SIZE-1:0] next_state; |
parameter IDLE = 6'b000001; |
parameter WRITE_DAT = 6'b000010; |
parameter WRITE_CRC = 6'b000100; |
parameter WRITE_BUSY = 6'b001000; |
parameter READ_WAIT = 6'b010000; |
parameter READ_DAT = 6'b100000; |
reg [2:0] crc_status; |
reg busy_int; |
|
genvar i; |
generate |
for(i=0; i<`SD_BUS_W; i=i+1) begin:CRC_16_gen |
SD_CRC_16 CRC_16_i (crc_in[i],crc_en, sd_clk, crc_rst, crc_out[i]); |
end |
endgenerate |
|
reg ack_transfer_int; |
reg ack_q; |
always @ (posedge sd_clk or posedge rst ) |
begin: ACK_SYNC |
if (rst) begin |
ack_transfer_int <=0; |
ack_q<=0;end |
else begin |
ack_q<=ack_transfer; |
ack_transfer_int<=ack_q; |
end |
end |
|
reg q_start_bit; |
always @ (state or start_dat or q_start_bit or transf_cnt or crc_status or busy_int or DAT_dat_i or ack_transfer_int) |
begin : FSM_COMBO |
next_state = 0; |
case(state) |
IDLE: begin |
if (start_dat == 2'b01) |
next_state=WRITE_DAT; |
else if (start_dat == 2'b10) |
next_state=READ_WAIT; |
else |
next_state=IDLE; |
end |
WRITE_DAT: begin |
if (transf_cnt >= `BIT_BLOCK) |
next_state= WRITE_CRC; |
else if (start_dat == 2'b11) |
next_state=IDLE; |
else |
next_state=WRITE_DAT; |
end |
|
WRITE_CRC: begin |
if (crc_status ==0) |
next_state= WRITE_BUSY; |
else |
next_state=WRITE_CRC; |
|
end |
WRITE_BUSY: begin |
if ( (busy_int ==1) & ack_transfer_int) |
next_state= IDLE; |
else |
next_state = WRITE_BUSY; |
end |
|
READ_WAIT: begin |
if (q_start_bit== 0 ) |
next_state= READ_DAT; |
else |
next_state=READ_WAIT; |
end |
|
READ_DAT: begin |
if ( ack_transfer_int) //Startbit consumed... |
next_state= IDLE; |
else if (start_dat == 2'b11) |
next_state=IDLE; |
else |
next_state=READ_DAT; |
end |
|
|
|
|
|
endcase |
end |
|
always @ (posedge sd_clk or posedge rst ) |
begin :START_SYNC |
if (rst ) begin |
q_start_bit<=1; |
end |
else begin |
q_start_bit <= DAT_dat_i[0]; |
end |
end |
|
|
//----------------Seq logic------------ |
always @ (posedge sd_clk or posedge rst ) |
begin : FSM_SEQ |
if (rst ) begin |
state <= #1 IDLE; |
end |
else begin |
state <= #1 next_state; |
end |
end |
|
reg [4:0] crc_c; |
reg [3:0] last_din; |
reg [2:0] crc_s ; |
reg [31:0] write_buf_0,write_buf_1, sd_data_out; |
reg out_buff_ptr,in_buff_ptr; |
reg [2:0] data_send_index; |
|
always @ (negedge sd_clk or posedge rst ) |
begin : FSM_OUT |
if (rst) begin |
write_buf_0<=0; |
write_buf_1<=0; |
DAT_oe_o<=0; |
crc_en<=0; |
crc_rst<=1; |
transf_cnt<=0; |
crc_c<=15; |
rd<=0; |
last_din<=0; |
crc_c<=0; |
crc_in<=0; |
DAT_dat_o<=0; |
crc_status<=7; |
crc_s<=0; |
transm_complete<=0; |
busy_n<=1; |
we<=0; |
data_out<=0; |
crc_ok<=0; |
busy_int<=0; |
data_send_index<=0; |
out_buff_ptr<=0; |
in_buff_ptr<=0; |
end |
else begin |
case(state) |
IDLE: begin |
DAT_oe_o<=0; |
DAT_dat_o<=4'b1111; |
crc_en<=0; |
crc_rst<=1; |
transf_cnt<=0; |
crc_c<=16; |
crc_status<=7; |
crc_s<=0; |
we<=0; |
rd<=0; |
busy_n<=1; |
data_send_index<=0; |
out_buff_ptr<=0; |
in_buff_ptr<=0; |
end |
WRITE_DAT: begin |
transm_complete <=0; |
busy_n<=0; |
crc_ok<=0; |
transf_cnt<=transf_cnt+1; |
rd<=0; |
|
|
|
if ( (in_buff_ptr != out_buff_ptr) || (!transf_cnt) ) begin |
rd <=1; |
if (!in_buff_ptr) |
write_buf_0<=data_in; |
else |
write_buf_1 <=data_in; |
|
in_buff_ptr<=in_buff_ptr+1; |
end |
|
if (!out_buff_ptr) |
sd_data_out<=write_buf_0; |
else |
sd_data_out<=write_buf_1; |
|
if (transf_cnt==1) begin |
|
crc_rst<=0; |
crc_en<=1; |
`ifdef LITLE_ENDIAN |
last_din <=write_buf_0[3:0]; |
crc_in<= write_buf_0[3:0]; |
`endif |
`ifdef BIG_ENDIAN |
last_din <=write_buf_0[31:28]; |
crc_in<= write_buf_0[31:28]; |
`endif |
|
DAT_oe_o<=1; |
DAT_dat_o<=0; |
|
data_send_index<=1; |
end |
else if ( (transf_cnt>=2) && (transf_cnt<=`BIT_BLOCK-`CRC_OFF )) begin |
DAT_oe_o<=1; |
case (data_send_index) |
`ifdef LITLE_ENDIAN |
0:begin |
last_din <=sd_data_out[3:0]; |
crc_in <=sd_data_out[3:0]; |
end |
1:begin |
last_din <=sd_data_out[7:4]; |
crc_in <=sd_data_out[7:4]; |
end |
2:begin |
last_din <=sd_data_out[11:8]; |
crc_in <=sd_data_out[11:8]; |
end |
3:begin |
last_din <=sd_data_out[15:12]; |
crc_in <=sd_data_out[15:12]; |
end |
4:begin |
last_din <=sd_data_out[19:16]; |
crc_in <=sd_data_out[19:16]; |
end |
5:begin |
last_din <=sd_data_out[23:20]; |
crc_in <=sd_data_out[23:20]; |
end |
6:begin |
last_din <=sd_data_out[27:24]; |
crc_in <=sd_data_out[27:24]; |
out_buff_ptr<=out_buff_ptr+1; |
end |
7:begin |
last_din <=sd_data_out[31:28]; |
crc_in <=sd_data_out[31:28]; |
end |
`endif |
`ifdef BIG_ENDIAN |
0:begin |
last_din <=sd_data_out[31:28]; |
crc_in <=sd_data_out[31:28]; |
end |
1:begin |
last_din <=sd_data_out[27:24]; |
crc_in <=sd_data_out[27:24]; |
end |
2:begin |
last_din <=sd_data_out[23:20]; |
crc_in <=sd_data_out[23:20]; |
end |
3:begin |
last_din <=sd_data_out[19:16]; |
crc_in <=sd_data_out[19:16]; |
end |
4:begin |
last_din <=sd_data_out[15:12]; |
crc_in <=sd_data_out[15:12]; |
end |
5:begin |
last_din <=sd_data_out[11:8]; |
crc_in <=sd_data_out[11:8]; |
end |
6:begin |
last_din <=sd_data_out[7:4]; |
crc_in <=sd_data_out[7:4]; |
out_buff_ptr<=out_buff_ptr+1; |
end |
7:begin |
last_din <=sd_data_out[3:0]; |
crc_in <=sd_data_out[3:0]; |
end |
`endif |
|
|
endcase |
data_send_index<=data_send_index+1; |
|
DAT_dat_o<= last_din; |
|
|
|
if ( transf_cnt >=`BIT_BLOCK-`CRC_OFF ) begin |
crc_en<=0; |
end |
end |
else if (transf_cnt>`BIT_BLOCK-`CRC_OFF & crc_c!=0) begin |
rd<=0; |
crc_en<=0; |
crc_c<=crc_c-1; |
DAT_oe_o<=1; |
DAT_dat_o[0]<=crc_out[0][crc_c-1]; |
DAT_dat_o[1]<=crc_out[1][crc_c-1]; |
DAT_dat_o[2]<=crc_out[2][crc_c-1]; |
DAT_dat_o[3]<=crc_out[3][crc_c-1]; |
end |
else if (transf_cnt==`BIT_BLOCK-2) begin |
DAT_oe_o<=1; |
DAT_dat_o<=4'b1111; |
rd<=0; |
end |
else if (transf_cnt !=0) begin |
DAT_oe_o<=0; |
rd<=0; |
end |
end |
WRITE_CRC : begin |
rd<=0; |
DAT_oe_o<=0; |
crc_status<=crc_status-1; |
if (( crc_status<=4) && ( crc_status>=2) ) |
crc_s[crc_status-2] <=DAT_dat_i[0]; |
end |
WRITE_BUSY : begin |
transm_complete <=1; |
if (crc_s == 3'b010) |
crc_ok<=1; |
else |
crc_ok<=0; |
|
busy_int<=DAT_dat_i[0]; |
|
|
end |
READ_WAIT:begin |
DAT_oe_o<=0; |
crc_rst<=0; |
crc_en<=1; |
crc_in<=0; |
crc_c<=15;// end |
busy_n<=0; |
transm_complete<=0; |
end |
|
READ_DAT: begin |
|
|
if (transf_cnt<`BIT_BLOCK_REC) begin |
we<=1; |
|
data_out<=DAT_dat_i; |
crc_in<=DAT_dat_i; |
crc_ok<=1; |
transf_cnt<=transf_cnt+1; |
|
end |
else if ( transf_cnt <= (`BIT_BLOCK_REC +`BIT_CRC_CYCLE)) begin |
transf_cnt<=transf_cnt+1; |
crc_en<=0; |
last_din <=DAT_dat_i; |
|
if (transf_cnt> `BIT_BLOCK_REC) begin |
crc_c<=crc_c-1; |
we<=0; |
`ifdef SD_BUS_WIDTH_1 |
if (crc_out[0][crc_status] == last_din[0]) |
crc_ok<=0; |
`endif |
|
`ifdef SD_BUS_WIDTH_4 |
if (crc_out[0][crc_c] != last_din[0]) |
crc_ok<=0; |
if (crc_out[1][crc_c] != last_din[1]) |
crc_ok<=0; |
if (crc_out[2][crc_c] != last_din[2]) |
crc_ok<=0; |
if (crc_out[3][crc_c] != last_din[3]) |
crc_ok<=0; |
|
`endif |
`ifdef SIM |
crc_ok<=1; |
`endif |
if (crc_c==0) begin |
transm_complete <=1; |
busy_n<=0; |
we<=0; |
end |
end |
end |
|
|
|
end |
|
|
|
endcase |
|
end |
|
end |
|
|
|
|
|
|
|
|
|
//Sync |
|
|
|
|
|
|
|
endmodule |
|
|
|
|
|
|
`include "SD_defines.v" |
|
|
module SD_DATA_SERIAL_HOST( |
input sd_clk, |
input rst, |
//Tx Fifo |
input [31:0] data_in , |
|
output reg rd, |
//Rx Fifo |
output reg [`SD_BUS_W-1:0] data_out , |
output reg we, |
//tristate data |
output reg DAT_oe_o, |
output reg[`SD_BUS_W-1:0] DAT_dat_o, |
input [`SD_BUS_W-1:0] DAT_dat_i, |
//Controll signals |
input [1:0] start_dat, |
input ack_transfer, |
|
output reg busy_n, |
output reg transm_complete, |
output reg crc_ok |
); |
|
//CRC16 |
reg [`SD_BUS_W-1:0] crc_in; |
reg crc_en; |
reg crc_rst; |
wire [15:0] crc_out [`SD_BUS_W-1:0]; |
reg [`SD_BUS_W-1:0] temp_in; |
|
reg [10:0] transf_cnt; |
parameter SIZE = 6; |
reg [SIZE-1:0] state; |
reg [SIZE-1:0] next_state; |
parameter IDLE = 6'b000001; |
parameter WRITE_DAT = 6'b000010; |
parameter WRITE_CRC = 6'b000100; |
parameter WRITE_BUSY = 6'b001000; |
parameter READ_WAIT = 6'b010000; |
parameter READ_DAT = 6'b100000; |
reg [2:0] crc_status; |
reg busy_int; |
|
genvar i; |
generate |
for(i=0; i<`SD_BUS_W; i=i+1) begin:CRC_16_gen |
SD_CRC_16 CRC_16_i (crc_in[i],crc_en, sd_clk, crc_rst, crc_out[i]); |
end |
endgenerate |
|
reg ack_transfer_int; |
reg ack_q; |
always @ (posedge sd_clk or posedge rst ) |
begin: ACK_SYNC |
if (rst) begin |
ack_transfer_int <=0; |
ack_q<=0;end |
else begin |
ack_q<=ack_transfer; |
ack_transfer_int<=ack_q; |
end |
end |
|
reg q_start_bit; |
always @ (state or start_dat or q_start_bit or transf_cnt or crc_status or busy_int or DAT_dat_i or ack_transfer_int) |
begin : FSM_COMBO |
next_state = 0; |
case(state) |
IDLE: begin |
if (start_dat == 2'b01) |
next_state=WRITE_DAT; |
else if (start_dat == 2'b10) |
next_state=READ_WAIT; |
else |
next_state=IDLE; |
end |
WRITE_DAT: begin |
if (transf_cnt >= `BIT_BLOCK) |
next_state= WRITE_CRC; |
else if (start_dat == 2'b11) |
next_state=IDLE; |
else |
next_state=WRITE_DAT; |
end |
|
WRITE_CRC: begin |
if (crc_status ==0) |
next_state= WRITE_BUSY; |
else |
next_state=WRITE_CRC; |
|
end |
WRITE_BUSY: begin |
if ( (busy_int ==1) & ack_transfer_int) |
next_state= IDLE; |
else |
next_state = WRITE_BUSY; |
end |
|
READ_WAIT: begin |
if (q_start_bit== 0 ) |
next_state= READ_DAT; |
else |
next_state=READ_WAIT; |
end |
|
READ_DAT: begin |
if ( ack_transfer_int) //Startbit consumed... |
next_state= IDLE; |
else if (start_dat == 2'b11) |
next_state=IDLE; |
else |
next_state=READ_DAT; |
end |
|
|
|
|
|
endcase |
end |
|
always @ (posedge sd_clk or posedge rst ) |
begin :START_SYNC |
if (rst ) begin |
q_start_bit<=1; |
end |
else begin |
q_start_bit <= DAT_dat_i[0]; |
end |
end |
|
|
//----------------Seq logic------------ |
always @ (posedge sd_clk or posedge rst ) |
begin : FSM_SEQ |
if (rst ) begin |
state <= #1 IDLE; |
end |
else begin |
state <= #1 next_state; |
end |
end |
|
reg [4:0] crc_c; |
reg [3:0] last_din; |
reg [2:0] crc_s ; |
reg [31:0] write_buf_0,write_buf_1, sd_data_out; |
reg out_buff_ptr,in_buff_ptr; |
reg [2:0] data_send_index; |
|
always @ (negedge sd_clk or posedge rst ) |
begin : FSM_OUT |
if (rst) begin |
write_buf_0<=0; |
write_buf_1<=0; |
DAT_oe_o<=0; |
crc_en<=0; |
crc_rst<=1; |
transf_cnt<=0; |
crc_c<=15; |
rd<=0; |
last_din<=0; |
crc_c<=0; |
crc_in<=0; |
DAT_dat_o<=0; |
crc_status<=7; |
crc_s<=0; |
transm_complete<=0; |
busy_n<=1; |
we<=0; |
data_out<=0; |
crc_ok<=0; |
busy_int<=0; |
data_send_index<=0; |
out_buff_ptr<=0; |
in_buff_ptr<=0; |
end |
else begin |
case(state) |
IDLE: begin |
DAT_oe_o<=0; |
DAT_dat_o<=4'b1111; |
crc_en<=0; |
crc_rst<=1; |
transf_cnt<=0; |
crc_c<=16; |
crc_status<=7; |
crc_s<=0; |
we<=0; |
rd<=0; |
busy_n<=1; |
data_send_index<=0; |
out_buff_ptr<=0; |
in_buff_ptr<=0; |
end |
WRITE_DAT: begin |
transm_complete <=0; |
busy_n<=0; |
crc_ok<=0; |
transf_cnt<=transf_cnt+1; |
rd<=0; |
|
|
|
if ( (in_buff_ptr != out_buff_ptr) || (!transf_cnt) ) begin |
rd <=1; |
if (!in_buff_ptr) |
write_buf_0<=data_in; |
else |
write_buf_1 <=data_in; |
|
in_buff_ptr<=in_buff_ptr+1; |
end |
|
if (!out_buff_ptr) |
sd_data_out<=write_buf_0; |
else |
sd_data_out<=write_buf_1; |
|
if (transf_cnt==1) begin |
|
crc_rst<=0; |
crc_en<=1; |
`ifdef LITLE_ENDIAN |
last_din <=write_buf_0[3:0]; |
crc_in<= write_buf_0[3:0]; |
`endif |
`ifdef BIG_ENDIAN |
last_din <=write_buf_0[31:28]; |
crc_in<= write_buf_0[31:28]; |
`endif |
|
DAT_oe_o<=1; |
DAT_dat_o<=0; |
|
data_send_index<=1; |
end |
else if ( (transf_cnt>=2) && (transf_cnt<=`BIT_BLOCK-`CRC_OFF )) begin |
DAT_oe_o<=1; |
case (data_send_index) |
`ifdef LITLE_ENDIAN |
0:begin |
last_din <=sd_data_out[3:0]; |
crc_in <=sd_data_out[3:0]; |
end |
1:begin |
last_din <=sd_data_out[7:4]; |
crc_in <=sd_data_out[7:4]; |
end |
2:begin |
last_din <=sd_data_out[11:8]; |
crc_in <=sd_data_out[11:8]; |
end |
3:begin |
last_din <=sd_data_out[15:12]; |
crc_in <=sd_data_out[15:12]; |
end |
4:begin |
last_din <=sd_data_out[19:16]; |
crc_in <=sd_data_out[19:16]; |
end |
5:begin |
last_din <=sd_data_out[23:20]; |
crc_in <=sd_data_out[23:20]; |
end |
6:begin |
last_din <=sd_data_out[27:24]; |
crc_in <=sd_data_out[27:24]; |
out_buff_ptr<=out_buff_ptr+1; |
end |
7:begin |
last_din <=sd_data_out[31:28]; |
crc_in <=sd_data_out[31:28]; |
end |
`endif |
`ifdef BIG_ENDIAN |
0:begin |
last_din <=sd_data_out[31:28]; |
crc_in <=sd_data_out[31:28]; |
end |
1:begin |
last_din <=sd_data_out[27:24]; |
crc_in <=sd_data_out[27:24]; |
end |
2:begin |
last_din <=sd_data_out[23:20]; |
crc_in <=sd_data_out[23:20]; |
end |
3:begin |
last_din <=sd_data_out[19:16]; |
crc_in <=sd_data_out[19:16]; |
end |
4:begin |
last_din <=sd_data_out[15:12]; |
crc_in <=sd_data_out[15:12]; |
end |
5:begin |
last_din <=sd_data_out[11:8]; |
crc_in <=sd_data_out[11:8]; |
end |
6:begin |
last_din <=sd_data_out[7:4]; |
crc_in <=sd_data_out[7:4]; |
out_buff_ptr<=out_buff_ptr+1; |
end |
7:begin |
last_din <=sd_data_out[3:0]; |
crc_in <=sd_data_out[3:0]; |
end |
`endif |
|
|
endcase |
data_send_index<=data_send_index+1; |
|
DAT_dat_o<= last_din; |
|
|
|
if ( transf_cnt >=`BIT_BLOCK-`CRC_OFF ) begin |
crc_en<=0; |
end |
end |
else if (transf_cnt>`BIT_BLOCK-`CRC_OFF & crc_c!=0) begin |
rd<=0; |
crc_en<=0; |
crc_c<=crc_c-1; |
DAT_oe_o<=1; |
DAT_dat_o[0]<=crc_out[0][crc_c-1]; |
DAT_dat_o[1]<=crc_out[1][crc_c-1]; |
DAT_dat_o[2]<=crc_out[2][crc_c-1]; |
DAT_dat_o[3]<=crc_out[3][crc_c-1]; |
end |
else if (transf_cnt==`BIT_BLOCK-2) begin |
DAT_oe_o<=1; |
DAT_dat_o<=4'b1111; |
rd<=0; |
end |
else if (transf_cnt !=0) begin |
DAT_oe_o<=0; |
rd<=0; |
end |
end |
WRITE_CRC : begin |
rd<=0; |
DAT_oe_o<=0; |
crc_status<=crc_status-1; |
if (( crc_status<=4) && ( crc_status>=2) ) |
crc_s[crc_status-2] <=DAT_dat_i[0]; |
end |
WRITE_BUSY : begin |
transm_complete <=1; |
if (crc_s == 3'b010) |
crc_ok<=1; |
else |
crc_ok<=0; |
|
busy_int<=DAT_dat_i[0]; |
|
|
end |
READ_WAIT:begin |
DAT_oe_o<=0; |
crc_rst<=0; |
crc_en<=1; |
crc_in<=0; |
crc_c<=15;// end |
busy_n<=0; |
transm_complete<=0; |
end |
|
READ_DAT: begin |
|
|
if (transf_cnt<`BIT_BLOCK_REC) begin |
we<=1; |
|
data_out<=DAT_dat_i; |
crc_in<=DAT_dat_i; |
crc_ok<=1; |
transf_cnt<=transf_cnt+1; |
|
end |
else if ( transf_cnt <= (`BIT_BLOCK_REC +`BIT_CRC_CYCLE)) begin |
transf_cnt<=transf_cnt+1; |
crc_en<=0; |
last_din <=DAT_dat_i; |
|
if (transf_cnt> `BIT_BLOCK_REC) begin |
crc_c<=crc_c-1; |
we<=0; |
`ifdef SD_BUS_WIDTH_1 |
if (crc_out[0][crc_status] == last_din[0]) |
crc_ok<=0; |
`endif |
|
`ifdef SD_BUS_WIDTH_4 |
if (crc_out[0][crc_c] != last_din[0]) |
crc_ok<=0; |
if (crc_out[1][crc_c] != last_din[1]) |
crc_ok<=0; |
if (crc_out[2][crc_c] != last_din[2]) |
crc_ok<=0; |
if (crc_out[3][crc_c] != last_din[3]) |
crc_ok<=0; |
|
`endif |
`ifdef SIM |
crc_ok<=1; |
`endif |
if (crc_c==0) begin |
transm_complete <=1; |
busy_n<=0; |
we<=0; |
end |
end |
end |
|
|
|
end |
|
|
|
endcase |
|
end |
|
end |
|
|
|
|
|
|
|
|
|
//Sync |
|
|
|
|
|
|
|
endmodule |
|
|
|
|
|
/sdc_dma/verilog/fifo/smii_rx_fifo.v
1,121 → 1,121
`include "SD_defines.v" |
|
module sd_rx_fifo |
( |
input [4-1:0] d, |
input wr, |
input wclk, |
output [32-1:0] q, |
input rd, |
output full, |
output empty, |
output [1:0] mem_empt, |
input rclk, |
input rst |
); |
reg [32-1:0] ram [0:`FIFO_RX_MEM_DEPTH-1]; |
reg [`FIFO_RX_MEM_ADR_SIZE-1:0] adr_i, adr_o; |
wire ram_we; |
wire [32-1:0] ram_din; |
reg [8-1:0] we; |
reg [4*(8)-1:0] tmp; |
reg ft; |
always @ (posedge wclk or posedge rst) |
if (rst) |
we <= 8'h1; |
else |
if (wr) |
we <= {we[8-2:0],we[8-1]}; |
|
always @ (posedge wclk or posedge rst) |
if (rst) begin |
tmp <= {4*(8-1){1'b0}}; |
ft<=0; |
end |
else |
begin |
`ifdef BIG_ENDIAN |
|
if (wr & we[7]) begin |
tmp[4*1-1:4*0] <= d; |
ft<=1; end |
if (wr & we[6]) |
tmp[4*2-1:4*1] <= d; |
if (wr & we[5]) |
tmp[4*3-1:4*2] <= d; |
if (wr & we[4]) |
tmp[4*4-1:4*3] <= d; |
if (wr & we[3]) |
tmp[4*5-1:4*4] <= d; |
if (wr & we[2]) |
tmp[4*6-1:4*5] <= d; |
if (wr & we[1]) |
tmp[4*7-1:4*6] <= d; |
if (wr & we[0]) |
tmp[4*8-1:4*7] <= d; |
`endif |
`ifdef LITTLE_ENDIAN |
if (wr & we[0]) |
tmp[4*1-1:4*0] <= d; |
if (wr & we[1]) |
tmp[4*2-1:4*1] <= d; |
if (wr & we[2]) |
tmp[4*3-1:4*2] <= d; |
if (wr & we[3]) |
tmp[4*4-1:4*3] <= d; |
if (wr & we[4]) |
tmp[4*5-1:4*4] <= d; |
if (wr & we[5]) |
tmp[4*6-1:4*5] <= d; |
if (wr & we[6]) |
tmp[4*7-1:4*6] <= d; |
if (wr & we[7]) begin |
tmp[4*8-1:4*7] <= d; |
ft<=1; |
end |
`endif |
end |
|
assign ram_we = wr & we[0] &ft; |
assign ram_din = tmp; |
always @ (posedge wclk) |
if (ram_we) |
ram[adr_i[`FIFO_RX_MEM_ADR_SIZE-2:0]] <= ram_din; |
always @ (posedge wclk or posedge rst) |
if (rst) |
adr_i <= `FIFO_RX_MEM_ADR_SIZE'h0; |
else |
if (ram_we) |
if (adr_i == `FIFO_RX_MEM_DEPTH-1) begin |
adr_i[`FIFO_RX_MEM_ADR_SIZE-2:0] <=0; |
adr_i[`FIFO_RX_MEM_ADR_SIZE-1]<=~adr_i[`FIFO_RX_MEM_ADR_SIZE-1]; |
end |
else |
adr_i <= adr_i + `FIFO_RX_MEM_ADR_SIZE'h1; |
|
always @ (posedge rclk or posedge rst) |
if (rst) |
adr_o <= `FIFO_RX_MEM_ADR_SIZE'h0; |
else |
if (!empty & rd) |
|
if (adr_o == `FIFO_RX_MEM_DEPTH-1) begin |
adr_o[`FIFO_RX_MEM_ADR_SIZE-2:0] <=0; |
adr_o[`FIFO_RX_MEM_ADR_SIZE-1] <=~adr_o[`FIFO_RX_MEM_ADR_SIZE-1]; |
end |
else |
adr_o <= adr_o + `FIFO_RX_MEM_ADR_SIZE'h1; |
|
//------------------------------------------------------------------ |
// Simplified version of the three necessary full-tests: |
// assign wfull_val=((wgnext[ADDRSIZE] !=wq2_rptr[ADDRSIZE] ) && |
// (wgnext[ADDRSIZE-1] !=wq2_rptr[ADDRSIZE-1]) && |
// (wgnext[ADDRSIZE-2:0]==wq2_rptr[ADDRSIZE-2:0])); |
//------------------------------------------------------------------ |
|
assign full = (adr_i[`FIFO_RX_MEM_ADR_SIZE-2:0] == adr_o[`FIFO_RX_MEM_ADR_SIZE-2:0] ) & (adr_i[`FIFO_RX_MEM_ADR_SIZE-1] ^ adr_o[`FIFO_RX_MEM_ADR_SIZE-1]) ; |
assign empty = (adr_i == adr_o) ; |
|
assign mem_empt = ( adr_i-adr_o); |
assign q = ram[adr_o[`FIFO_RX_MEM_ADR_SIZE-2:0]]; |
endmodule |
`include "SD_defines.v" |
`include "timescale.v" |
module sd_rx_fifo |
( |
input [4-1:0] d, |
input wr, |
input wclk, |
output [32-1:0] q, |
input rd, |
output full, |
output empty, |
output [1:0] mem_empt, |
input rclk, |
input rst |
); |
reg [32-1:0] ram [0:`FIFO_RX_MEM_DEPTH-1]; |
reg [`FIFO_RX_MEM_ADR_SIZE-1:0] adr_i, adr_o; |
wire ram_we; |
wire [32-1:0] ram_din; |
reg [8-1:0] we; |
reg [4*(8)-1:0] tmp; |
reg ft; |
always @ (posedge wclk or posedge rst) |
if (rst) |
we <= 8'h1; |
else |
if (wr) |
we <= {we[8-2:0],we[8-1]}; |
|
always @ (posedge wclk or posedge rst) |
if (rst) begin |
tmp <= {4*(8-1){1'b0}}; |
ft<=0; |
end |
else |
begin |
`ifdef BIG_ENDIAN |
|
if (wr & we[7]) begin |
tmp[4*1-1:4*0] <= d; |
ft<=1; end |
if (wr & we[6]) |
tmp[4*2-1:4*1] <= d; |
if (wr & we[5]) |
tmp[4*3-1:4*2] <= d; |
if (wr & we[4]) |
tmp[4*4-1:4*3] <= d; |
if (wr & we[3]) |
tmp[4*5-1:4*4] <= d; |
if (wr & we[2]) |
tmp[4*6-1:4*5] <= d; |
if (wr & we[1]) |
tmp[4*7-1:4*6] <= d; |
if (wr & we[0]) |
tmp[4*8-1:4*7] <= d; |
`endif |
`ifdef LITTLE_ENDIAN |
if (wr & we[0]) |
tmp[4*1-1:4*0] <= d; |
if (wr & we[1]) |
tmp[4*2-1:4*1] <= d; |
if (wr & we[2]) |
tmp[4*3-1:4*2] <= d; |
if (wr & we[3]) |
tmp[4*4-1:4*3] <= d; |
if (wr & we[4]) |
tmp[4*5-1:4*4] <= d; |
if (wr & we[5]) |
tmp[4*6-1:4*5] <= d; |
if (wr & we[6]) |
tmp[4*7-1:4*6] <= d; |
if (wr & we[7]) begin |
tmp[4*8-1:4*7] <= d; |
ft<=1; |
end |
`endif |
end |
|
assign ram_we = wr & we[0] &ft; |
assign ram_din = tmp; |
always @ (posedge wclk) |
if (ram_we) |
ram[adr_i[`FIFO_RX_MEM_ADR_SIZE-2:0]] <= ram_din; |
always @ (posedge wclk or posedge rst) |
if (rst) |
adr_i <= `FIFO_RX_MEM_ADR_SIZE'h0; |
else |
if (ram_we) |
if (adr_i == `FIFO_RX_MEM_DEPTH-1) begin |
adr_i[`FIFO_RX_MEM_ADR_SIZE-2:0] <=0; |
adr_i[`FIFO_RX_MEM_ADR_SIZE-1]<=~adr_i[`FIFO_RX_MEM_ADR_SIZE-1]; |
end |
else |
adr_i <= adr_i + `FIFO_RX_MEM_ADR_SIZE'h1; |
|
always @ (posedge rclk or posedge rst) |
if (rst) |
adr_o <= `FIFO_RX_MEM_ADR_SIZE'h0; |
else |
if (!empty & rd) |
|
if (adr_o == `FIFO_RX_MEM_DEPTH-1) begin |
adr_o[`FIFO_RX_MEM_ADR_SIZE-2:0] <=0; |
adr_o[`FIFO_RX_MEM_ADR_SIZE-1] <=~adr_o[`FIFO_RX_MEM_ADR_SIZE-1]; |
end |
else |
adr_o <= adr_o + `FIFO_RX_MEM_ADR_SIZE'h1; |
|
//------------------------------------------------------------------ |
// Simplified version of the three necessary full-tests: |
// assign wfull_val=((wgnext[ADDRSIZE] !=wq2_rptr[ADDRSIZE] ) && |
// (wgnext[ADDRSIZE-1] !=wq2_rptr[ADDRSIZE-1]) && |
// (wgnext[ADDRSIZE-2:0]==wq2_rptr[ADDRSIZE-2:0])); |
//------------------------------------------------------------------ |
|
assign full = (adr_i[`FIFO_RX_MEM_ADR_SIZE-2:0] == adr_o[`FIFO_RX_MEM_ADR_SIZE-2:0] ) & (adr_i[`FIFO_RX_MEM_ADR_SIZE-1] ^ adr_o[`FIFO_RX_MEM_ADR_SIZE-1]) ; |
assign empty = (adr_i == adr_o) ; |
|
assign mem_empt = ( adr_i-adr_o); |
assign q = ram[adr_o[`FIFO_RX_MEM_ADR_SIZE-2:0]]; |
endmodule |
/sdc_dma/verilog/fifo/smii_tx_fifo.v
1,6 → 1,6
|
`include "timescale.v" |
`include "SD_defines.v" |
|
|
module sd_tx_fifo |
( |
input [32-1:0] d, |
/sdc_dma/verilog/fifo/SD_defines.v
3,8 → 3,8
`define BIG_ENDIAN |
//`define LITLE_ENDIAN |
|
//`define SIM |
`define SYN |
`define SIM |
//`define SYN |
|
`define IRQ_ENABLE |
`define ACTEL |
/sdc_dma/verilog/SD_FIFO_TX_Filler.v
58,6 → 58,7
|
reg ackd; |
reg delay; |
|
always @(posedge clk or posedge rst )begin |
if (rst) begin |
offset <=0; |
/sdc_dma/verilog/SD_defines.v
3,8 → 3,8
`define BIG_ENDIAN |
//`define LITLE_ENDIAN |
|
//`define SIM |
`define SYN |
`define SIM |
//`define SYN |
|
`define IRQ_ENABLE |
`define ACTEL |
14,28 → 14,30
//`define XLINX |
//`define SIMULATOR |
|
`define RESEND_MAX_CNT 3 |
|
//MAX 255 BD |
//BD size/4 |
|
`ifdef ACTEL |
`define NR_O_BD_4 |
`define BD_WIDTH 5 |
`define BD_SIZE 32 |
`define NR_O_BD_4 |
`define BD_WIDTH 5 |
`define BD_SIZE 32 |
`define RAM_MEM_WIDTH_16 |
`define RAM_MEM_WIDTH 16 |
`define RAM_MEM_WIDTH 16 |
|
`endif |
|
`ifdef CUSTOM |
`define NR_O_BD_4 |
`define BD_WIDTH 5 |
`define BD_SIZE 32 |
`define RAM_MEM_WIDTH_32 |
`define RAM_MEM_WIDTH 32 |
`endif |
//`ifdef CUSTOM |
// `define NR_O_BD_4 |
// `define BD_WIDTH 5 |
// `define BD_SIZE 32 |
// `define RAM_MEM_WIDTH_32 |
// `define RAM_MEM_WIDTH 32 |
//`endif |
|
`define RESEND_MAX_CNT 3 |
|
|
`ifdef SYN |
`define RESET_CLK_DIV 1 |
`define MEM_OFFSET 4 |
43,7 → 45,7
|
`ifdef SIM |
`define RESET_CLK_DIV 0 |
`define MEM_OFFSET 1 |
`define MEM_OFFSET 4 |
`endif |
|
//SD-Clock Defines --------- |
/sdc_dma/verilog/SD_data_master.v
1,516 → 1,510
`include "SD_defines.v" |
|
module SD_DATA_MASTER ( |
input clk, |
input rst, |
//Tx Bd |
|
input [`RAM_MEM_WIDTH-1:0] dat_in_tx, |
input [`BD_WIDTH-1:0] free_tx_bd, |
input ack_i_s_tx, |
output reg re_s_tx, |
output reg a_cmp_tx, |
//Rx Bd |
|
input [`RAM_MEM_WIDTH-1:0] dat_in_rx, |
input [`BD_WIDTH-1:0] free_rx_bd, |
input ack_i_s_rx, |
output reg re_s_rx, |
output reg a_cmp_rx, |
//Input from SD-Host Reg |
input cmd_busy, //STATUS_REG[0] and mux |
//Output to SD-Host Reg |
output reg we_req, |
input we_ack, |
output reg d_write, |
output reg d_read, |
output reg [31:0] cmd_arg, |
output reg [15:0] cmd_set, |
input cmd_tsf_err, |
input [4:0] card_status, |
//To fifo filler |
output reg start_tx_fifo, |
output reg start_rx_fifo, |
output reg [31:0] sys_adr, |
input tx_empt, |
input tx_full, |
input rx_full, |
//SD-DATA_Host |
input busy_n , |
input transm_complete , |
input crc_ok, |
output reg ack_transfer, |
//status output |
output reg [7:0] Dat_Int_Status , |
input Dat_Int_Status_rst, |
output reg CIDAT |
|
|
); |
|
`ifdef RAM_MEM_WIDTH_32 |
`define READ_CYCLE 2 |
reg [1:0]bd_cnt ; |
`define BD_EMPTY (`BD_SIZE /2) |
`else `ifdef RAM_MEM_WIDTH_16 |
`define READ_CYCLE 4 |
reg [2:0] bd_cnt; |
`define BD_EMPTY (`BD_SIZE /4) |
`endif |
`endif |
|
reg send_done; |
reg rec_done; |
reg rec_failed; |
reg tx_cycle; |
reg rx_cycle; |
reg [2:0] resend_try_cnt; |
`ifdef SIM |
parameter CMD24 = 16'h181A ; //11000 0001 1010 |
parameter CMD17 = 16'h111A; //10001 0001 1010 |
parameter CMD12 = 16'hC1A ; //01100 0001 1010 |
`else |
parameter CMD24 = 16'h181A; |
parameter CMD17 = 16'h111A; |
parameter CMD12 = 16'hC1A ; |
`endif |
parameter SIZE = 9; |
reg [SIZE-1:0] state; |
reg [SIZE-1:0] next_state; |
parameter IDLE = 9'b000000001; |
parameter GET_TX_BD = 9'b000000010; |
parameter GET_RX_BD = 9'b000000100; |
parameter SEND_CMD = 9'b000001000; |
parameter RECIVE_CMD = 9'b000010000; |
parameter DATA_TRANSFER = 9'b000100000; |
parameter STOP = 9'b001000000; |
parameter STOP_SEND = 9'b010000000; |
parameter STOP_RECIVE_CMD = 9'b100000000; |
|
reg trans_done; |
reg trans_failed; |
reg internal_transm_complete; |
reg transm_complete_q; |
|
always @ (posedge clk or posedge rst ) |
begin |
if (rst) begin |
internal_transm_complete <=1'b0; |
transm_complete_q<=0; |
end |
else begin |
transm_complete_q<=transm_complete; |
internal_transm_complete<=transm_complete_q; |
end |
|
|
end |
|
|
|
|
always @ (state or resend_try_cnt or tx_full or free_tx_bd or free_rx_bd or bd_cnt or send_done or rec_done or rec_failed or trans_done or trans_failed) |
begin : FSM_COMBO |
next_state = 0; |
case(state) |
|
IDLE: begin |
if (free_tx_bd !=`BD_EMPTY)begin |
next_state = GET_TX_BD; |
end |
else if (free_rx_bd !=`BD_EMPTY) begin |
next_state = GET_RX_BD; |
end |
else begin |
next_state = IDLE; |
end |
end |
GET_TX_BD: begin |
if ( ( bd_cnt> `READ_CYCLE-1) && (tx_full==1) )begin |
next_state = SEND_CMD; |
end |
else begin |
next_state = GET_TX_BD; |
end |
end |
|
GET_RX_BD: begin |
if (bd_cnt >= (`READ_CYCLE-1))begin |
next_state = SEND_CMD; |
end |
else begin |
next_state = GET_RX_BD; |
end |
end |
|
SEND_CMD: begin |
if (send_done)begin |
next_state = RECIVE_CMD; |
end |
else begin |
next_state = SEND_CMD; |
end |
end |
|
|
RECIVE_CMD: begin |
if (rec_done) |
next_state = DATA_TRANSFER; |
else if (rec_failed) |
next_state = SEND_CMD; |
else |
next_state = RECIVE_CMD; |
end |
|
DATA_TRANSFER: begin |
if (trans_done) |
next_state = IDLE; |
else if (trans_failed) |
next_state = STOP; |
else |
next_state = DATA_TRANSFER; |
end |
|
STOP: begin |
next_state = STOP_SEND; |
end |
|
STOP_SEND: begin |
if (send_done)begin |
next_state = STOP_RECIVE_CMD; |
end |
else begin |
next_state = STOP_SEND; |
end |
end |
|
STOP_RECIVE_CMD : begin |
if (rec_done) |
next_state = SEND_CMD; |
else if (rec_failed) |
next_state = STOP; |
else if (resend_try_cnt>=`RESEND_MAX_CNT) |
next_state = IDLE; |
else |
next_state = STOP_RECIVE_CMD; |
end |
|
|
|
default : next_state = IDLE; |
endcase |
|
end |
|
//----------------Seq logic------------ |
always @ (posedge clk or posedge rst ) |
begin : FSM_SEQ |
if (rst ) begin |
state <= #1 IDLE; |
end |
else begin |
state <= #1 next_state; |
end |
end |
|
|
|
//Output logic----------------- |
|
|
always @ (posedge clk or posedge rst ) |
begin |
if (rst) begin |
send_done<=0; |
bd_cnt<=0; |
sys_adr<=0; |
cmd_arg<=0; |
rec_done<=0; |
start_tx_fifo<=0; |
start_rx_fifo<=0; |
send_done<=0; |
rec_failed<=0; |
d_write <=0; |
d_read <=0; |
trans_failed<=0; |
trans_done<=0; |
tx_cycle <=0; |
rx_cycle <=0; |
ack_transfer<=0; |
a_cmp_tx<=0; |
a_cmp_rx<=0; |
CIDAT<=0; |
Dat_Int_Status<=0; |
we_req<=0; |
re_s_tx<=0; |
re_s_rx<=0; |
cmd_set<=0; |
resend_try_cnt=0; |
end |
else begin |
case(state) |
IDLE: begin |
send_done<=0; |
bd_cnt<=0; |
sys_adr<=0; |
cmd_arg<=0; |
rec_done<=0; |
rec_failed<=0; |
start_tx_fifo<=0; |
start_rx_fifo<=0; |
send_done<=0; |
d_write <=0; |
d_read <=0; |
trans_failed<=0; |
trans_done<=0; |
tx_cycle <=0; |
rx_cycle <=0; |
ack_transfer<=0; |
a_cmp_tx<=0; |
a_cmp_rx<=0; |
resend_try_cnt=0; |
end |
|
GET_RX_BD: begin |
//0,1,2,3... |
re_s_rx <= 1; |
`ifdef RAM_MEM_WIDTH_32 |
if (ack_i_s_rx) begin |
if( bd_cnt == 2'b0) begin |
sys_adr <= dat_in_rx; |
bd_cnt <= bd_cnt+1; |
end |
else if ( bd_cnt == 2'b1) begin |
cmd_arg <= dat_in_rx; |
re_s_rx <= 0; |
end |
end |
`endif |
|
|
`ifdef RAM_MEM_WIDTH_16 |
if (ack_i_s_rx) begin |
if( bd_cnt == 2'b00) begin |
sys_adr [15:0] <= dat_in_rx; |
end |
else if ( bd_cnt == 2'b01) begin |
sys_adr [31:16] <= dat_in_rx; |
end |
else if ( bd_cnt == 2) begin |
cmd_arg [15:0] <= dat_in_rx; |
re_s_rx <= 0; |
end |
else if ( bd_cnt == 3) begin |
cmd_arg [31:16] <= dat_in_rx; |
re_s_rx <= 0; |
end |
bd_cnt <= bd_cnt+1; |
end |
`endif |
//Add Later Save last block addres for comparison with current (For multiple block cmd) |
//Add support for Pre-erased |
cmd_set <= CMD17; |
rx_cycle<=1; |
end |
|
GET_TX_BD: begin |
//0,1,2,3... |
re_s_tx <= 1; |
if ( bd_cnt == `READ_CYCLE) |
re_s_tx <= 0; |
|
`ifdef RAM_MEM_WIDTH_32 |
if (ack_i_s_tx) begin |
|
if( bd_cnt == 2'b0) begin |
sys_adr <= dat_in_tx; |
bd_cnt <= bd_cnt+1; |
end |
else if ( bd_cnt == 2'b1) begin |
cmd_arg <= dat_in_tx; |
re_s_tx <= 0; |
end |
end |
`endif |
|
`ifdef RAM_MEM_WIDTH_16 |
if (ack_i_s_tx) begin |
|
if( bd_cnt == 0) begin |
sys_adr [15:0] <= dat_in_tx; |
bd_cnt <= bd_cnt+1; end |
else if ( bd_cnt == 1) begin |
sys_adr [31:16] <= dat_in_tx; |
bd_cnt <= bd_cnt+1; end |
else if ( bd_cnt == 2) begin |
cmd_arg [15:0] <= dat_in_tx; |
re_s_tx <= 0; |
bd_cnt <= bd_cnt+1; end |
else if ( bd_cnt == 3) begin |
cmd_arg [31:16] <= dat_in_tx; |
re_s_tx <= 0; |
bd_cnt <= bd_cnt+1; |
end |
end |
`endif |
//Add Later Save last block addres for comparison with current (For multiple block cmd) |
//Add support for Pre-erased |
cmd_set <= CMD24; |
tx_cycle <=1; |
start_tx_fifo<=1; |
end |
|
SEND_CMD : begin |
rec_done<=0; |
if (rx_cycle) begin |
re_s_rx <=0; |
d_read<=1; |
end |
else begin |
re_s_tx <=0; |
d_write<=1; |
end |
start_rx_fifo<=0; //Reset FIFO |
// start_tx_fifo<=0; //Reset FIFO |
if (!cmd_busy) begin |
we_req <= 1; |
|
end //When send complete change state and wait for reply |
if (we_ack) begin |
send_done<=1; |
we_req <= 1; |
|
end |
end |
|
|
RECIVE_CMD : begin |
//When waiting for reply fill TX fifo |
if (rx_cycle) |
start_rx_fifo<=1; //start_fifo prebuffering |
//else |
//start_rx_fifo <=1; |
|
we_req <= 0; |
|
send_done<=0; |
if (!cmd_busy) begin //Means the sending is completed, |
d_read<=0; |
d_write<=0; |
if (!cmd_tsf_err) begin |
if (card_status[0]) begin |
`ifdef SYN |
if ( (card_status[4:1] == 4'b0100) || (card_status[4:1] == 4'b0110) || (card_status[4:1] == 4'b0101) ) |
rec_done<=1; |
else begin |
rec_failed<=1; |
Dat_Int_Status[4] <=1; |
start_tx_fifo<=0; |
end |
`endif |
|
|
//Check card_status[5:1] for state 4 or 6... |
//If wrong state change interupt status reg,so software can put card in |
// transfer state and restart/cancel Data transfer |
end |
`ifdef SIM |
rec_done<=1; |
start_tx_fifo<=1; |
`endif |
end |
else begin |
rec_failed<=1; //CRC-Error, CIC-Error or timeout |
start_tx_fifo<=0; |
`ifdef SIM |
rec_done<=1; |
start_tx_fifo<=1; |
`endif end |
end |
end |
|
DATA_TRANSFER: begin |
CIDAT<=1; |
if (tx_cycle) begin |
if (tx_empt) begin |
Dat_Int_Status[2] <=1; |
trans_failed<=1; |
end |
end |
else begin |
if (rx_full) begin |
Dat_Int_Status[2] <=1; |
trans_failed<=1; |
end |
end |
//Check for fifo underflow, |
//2 DO: if deteced stop transfer, reset data host |
if (internal_transm_complete) begin //Transfer complete |
ack_transfer<=1; |
|
if ((!crc_ok) && (busy_n)) begin //Wrong CRC and Data line free. |
Dat_Int_Status[5] <=1; |
trans_failed<=1; |
end |
else if ((crc_ok) && (busy_n)) begin //Data Line free |
trans_done <=1; |
Dat_Int_Status[0]<=1; |
if (tx_cycle) |
a_cmp_tx<=1; |
else |
a_cmp_rx<=1; |
end |
|
end |
|
end |
|
STOP: begin |
cmd_set <= CMD12; |
rec_done<=0; |
rec_failed<=0; |
send_done<=0; |
trans_failed<=0; |
trans_done<=0; |
d_read<=1; |
d_write<=1; |
start_rx_fifo <=0; |
start_tx_fifo <=0; |
|
end |
STOP_SEND: begin |
resend_try_cnt=resend_try_cnt+1; |
if (resend_try_cnt==`RESEND_MAX_CNT) |
Dat_Int_Status[1]<=1; |
if (!cmd_busy) |
we_req <= 1; |
if (we_ack) |
send_done<=1; |
end |
|
STOP_RECIVE_CMD: begin |
we_req <= 0; |
if (!cmd_busy) begin //Means the sending is completed, |
if (!cmd_tsf_err) begin |
rec_done<=1; |
send_done<=0; |
d_read<=0; |
d_write<=0; |
if (tx_cycle) |
cmd_set<= CMD24; |
else |
cmd_set <= CMD17; |
end |
else |
rec_failed<=1; |
end |
end |
|
endcase |
if (Dat_Int_Status_rst) |
Dat_Int_Status<=0; |
end |
|
end |
|
endmodule |
`include "SD_defines.v" |
|
module SD_DATA_MASTER ( |
input clk, |
input rst, |
//Tx Bd |
|
input [`RAM_MEM_WIDTH-1:0] dat_in_tx, |
input [`BD_WIDTH-1:0] free_tx_bd, |
input ack_i_s_tx, |
output reg re_s_tx, |
output reg a_cmp_tx, |
//Rx Bd |
|
input [`RAM_MEM_WIDTH-1:0] dat_in_rx, |
input [`BD_WIDTH-1:0] free_rx_bd, |
input ack_i_s_rx, |
output reg re_s_rx, |
output reg a_cmp_rx, |
//Input from SD-Host Reg |
input cmd_busy, //STATUS_REG[0] and mux |
//Output to SD-Host Reg |
output reg we_req, |
input we_ack, |
output reg d_write, |
output reg d_read, |
output reg [31:0] cmd_arg, |
output reg [15:0] cmd_set, |
input cmd_tsf_err, |
input [4:0] card_status, |
//To fifo filler |
output reg start_tx_fifo, |
output reg start_rx_fifo, |
output reg [31:0] sys_adr, |
input tx_empt, |
input tx_full, |
input rx_full, |
//SD-DATA_Host |
input busy_n , |
input transm_complete , |
input crc_ok, |
output reg ack_transfer, |
//status output |
output reg [7:0] Dat_Int_Status , |
input Dat_Int_Status_rst, |
output reg CIDAT |
|
|
); |
`define RESEND_MAX_CNT 3 |
`ifdef RAM_MEM_WIDTH_32 |
`define READ_CYCLE 2 |
reg [1:0]bd_cnt ; |
`define BD_EMPTY (`BD_SIZE /2) |
`else `ifdef RAM_MEM_WIDTH_16 |
`define READ_CYCLE 4 |
reg [2:0] bd_cnt; |
`define BD_EMPTY (`BD_SIZE /4) |
`endif |
`endif |
|
reg send_done; |
reg rec_done; |
reg rec_failed; |
reg tx_cycle; |
reg rx_cycle; |
reg [2:0] resend_try_cnt; |
`ifdef SIM |
parameter CMD24 = 16'h181A ; //11000 0001 1010 |
parameter CMD17 = 16'h111A; //10001 0001 1010 |
parameter CMD12 = 16'hC1A ; //01100 0001 1010 |
`else |
parameter CMD24 = 16'h181A; |
parameter CMD17 = 16'h111A; |
parameter CMD12 = 16'hC1A ; |
`endif |
parameter SIZE = 9; |
reg [SIZE-1:0] state; |
reg [SIZE-1:0] next_state; |
parameter IDLE = 9'b000000001; |
parameter GET_TX_BD = 9'b000000010; |
parameter GET_RX_BD = 9'b000000100; |
parameter SEND_CMD = 9'b000001000; |
parameter RECIVE_CMD = 9'b000010000; |
parameter DATA_TRANSFER = 9'b000100000; |
parameter STOP = 9'b001000000; |
parameter STOP_SEND = 9'b010000000; |
parameter STOP_RECIVE_CMD = 9'b100000000; |
|
reg trans_done; |
reg trans_failed; |
reg internal_transm_complete; |
reg transm_complete_q; |
|
always @ (posedge clk or posedge rst ) |
begin |
if (rst) begin |
internal_transm_complete <=1'b0; |
transm_complete_q<=0; |
end |
else begin |
transm_complete_q<=transm_complete; |
internal_transm_complete<=transm_complete_q; |
end |
|
|
end |
|
|
|
|
always @ (state or resend_try_cnt or tx_full or free_tx_bd or free_rx_bd or bd_cnt or send_done or rec_done or rec_failed or trans_done or trans_failed) |
begin : FSM_COMBO |
next_state = 0; |
case(state) |
|
IDLE: begin |
if (free_tx_bd !=`BD_EMPTY)begin |
next_state = GET_TX_BD; |
end |
else if (free_rx_bd !=`BD_EMPTY) begin |
next_state = GET_RX_BD; |
end |
else begin |
next_state = IDLE; |
end |
end |
GET_TX_BD: begin |
if ( ( bd_cnt> `READ_CYCLE-1) && (tx_full==1) )begin |
next_state = SEND_CMD; |
end |
else begin |
next_state = GET_TX_BD; |
end |
end |
|
GET_RX_BD: begin |
if (bd_cnt >= (`READ_CYCLE-1))begin |
next_state = SEND_CMD; |
end |
else begin |
next_state = GET_RX_BD; |
end |
end |
|
SEND_CMD: begin |
if (send_done)begin |
next_state = RECIVE_CMD; |
end |
else begin |
next_state = SEND_CMD; |
end |
end |
|
|
RECIVE_CMD: begin |
if (rec_done) |
next_state = DATA_TRANSFER; |
else if (rec_failed) |
next_state = SEND_CMD; |
else |
next_state = RECIVE_CMD; |
end |
|
DATA_TRANSFER: begin |
if (trans_done) |
next_state = IDLE; |
else if (trans_failed) |
next_state = STOP; |
else |
next_state = DATA_TRANSFER; |
end |
|
STOP: begin |
next_state = STOP_SEND; |
end |
|
STOP_SEND: begin |
if (send_done)begin |
next_state = STOP_RECIVE_CMD; |
end |
else begin |
next_state = STOP_SEND; |
end |
end |
|
STOP_RECIVE_CMD : begin |
if (rec_done) |
next_state = SEND_CMD; |
else if (rec_failed) |
next_state = STOP; |
else if (resend_try_cnt>=`RESEND_MAX_CNT) |
next_state = IDLE; |
else |
next_state = STOP_RECIVE_CMD; |
end |
|
|
|
default : next_state = IDLE; |
endcase |
|
end |
|
//----------------Seq logic------------ |
always @ (posedge clk or posedge rst ) |
begin : FSM_SEQ |
if (rst ) begin |
state <= #1 IDLE; |
end |
else begin |
state <= #1 next_state; |
end |
end |
|
|
|
//Output logic----------------- |
|
|
always @ (posedge clk or posedge rst ) |
begin |
if (rst) begin |
send_done<=0; |
bd_cnt<=0; |
sys_adr<=0; |
cmd_arg<=0; |
rec_done<=0; |
start_tx_fifo<=0; |
start_rx_fifo<=0; |
send_done<=0; |
rec_failed<=0; |
d_write <=0; |
d_read <=0; |
trans_failed<=0; |
trans_done<=0; |
tx_cycle <=0; |
rx_cycle <=0; |
ack_transfer<=0; |
a_cmp_tx<=0; |
a_cmp_rx<=0; |
CIDAT<=0; |
Dat_Int_Status<=0; |
we_req<=0; |
re_s_tx<=0; |
re_s_rx<=0; |
cmd_set<=0; |
resend_try_cnt=0; |
end |
else begin |
case(state) |
IDLE: begin |
send_done<=0; |
bd_cnt<=0; |
sys_adr<=0; |
cmd_arg<=0; |
rec_done<=0; |
rec_failed<=0; |
start_tx_fifo<=0; |
start_rx_fifo<=0; |
send_done<=0; |
d_write <=0; |
d_read <=0; |
trans_failed<=0; |
trans_done<=0; |
tx_cycle <=0; |
rx_cycle <=0; |
ack_transfer<=0; |
a_cmp_tx<=0; |
a_cmp_rx<=0; |
resend_try_cnt=0; |
end |
|
GET_RX_BD: begin |
//0,1,2,3... |
re_s_rx <= 1; |
`ifdef RAM_MEM_WIDTH_32 |
if (ack_i_s_rx) begin |
if( bd_cnt == 2'b0) begin |
sys_adr <= dat_in_rx; |
bd_cnt <= bd_cnt+1; |
end |
else if ( bd_cnt == 2'b1) begin |
cmd_arg <= dat_in_rx; |
re_s_rx <= 0; |
end |
end |
`endif |
|
|
`ifdef RAM_MEM_WIDTH_16 |
if (ack_i_s_rx) begin |
if( bd_cnt == 2'b00) begin |
sys_adr [15:0] <= dat_in_rx; |
end |
else if ( bd_cnt == 2'b01) begin |
sys_adr [31:16] <= dat_in_rx; |
end |
else if ( bd_cnt == 2) begin |
cmd_arg [15:0] <= dat_in_rx; |
re_s_rx <= 0; |
end |
else if ( bd_cnt == 3) begin |
cmd_arg [31:16] <= dat_in_rx; |
re_s_rx <= 0; |
end |
bd_cnt <= bd_cnt+1; |
end |
`endif |
//Add Later Save last block addres for comparison with current (For multiple block cmd) |
//Add support for Pre-erased |
cmd_set <= CMD17; |
rx_cycle<=1; |
end |
|
GET_TX_BD: begin |
//0,1,2,3... |
re_s_tx <= 1; |
if ( bd_cnt == `READ_CYCLE) |
re_s_tx <= 0; |
|
`ifdef RAM_MEM_WIDTH_32 |
if (ack_i_s_tx) begin |
|
if( bd_cnt == 2'b0) begin |
sys_adr <= dat_in_tx; |
bd_cnt <= bd_cnt+1; |
end |
else if ( bd_cnt == 2'b1) begin |
cmd_arg <= dat_in_tx; |
re_s_tx <= 0; |
end |
end |
`endif |
|
`ifdef RAM_MEM_WIDTH_16 |
if (ack_i_s_tx) begin |
|
if( bd_cnt == 0) begin |
sys_adr [15:0] <= dat_in_tx; |
bd_cnt <= bd_cnt+1; end |
else if ( bd_cnt == 1) begin |
sys_adr [31:16] <= dat_in_tx; |
bd_cnt <= bd_cnt+1; end |
else if ( bd_cnt == 2) begin |
cmd_arg [15:0] <= dat_in_tx; |
re_s_tx <= 0; |
bd_cnt <= bd_cnt+1; end |
else if ( bd_cnt == 3) begin |
cmd_arg [31:16] <= dat_in_tx; |
re_s_tx <= 0; |
bd_cnt <= bd_cnt+1; |
end |
end |
`endif |
//Add Later Save last block addres for comparison with current (For multiple block cmd) |
//Add support for Pre-erased |
cmd_set <= CMD24; |
tx_cycle <=1; |
start_tx_fifo<=1; |
end |
|
SEND_CMD : begin |
rec_done<=0; |
if (rx_cycle) begin |
re_s_rx <=0; |
d_read<=1; |
end |
else begin |
re_s_tx <=0; |
d_write<=1; |
end |
start_rx_fifo<=0; //Reset FIFO |
// start_tx_fifo<=0; //Reset FIFO |
if (!cmd_busy) begin |
we_req <= 1; |
|
end //When send complete change state and wait for reply |
if (we_ack) begin |
send_done<=1; |
we_req <= 1; |
|
end |
end |
|
|
RECIVE_CMD : begin |
//When waiting for reply fill TX fifo |
if (rx_cycle) |
start_rx_fifo<=1; //start_fifo prebuffering |
//else |
//start_rx_fifo <=1; |
|
we_req <= 0; |
|
send_done<=0; |
if (!cmd_busy) begin //Means the sending is completed, |
d_read<=0; |
d_write<=0; |
if (!cmd_tsf_err) begin |
if (card_status[0]) begin |
|
if ( (card_status[4:1] == 4'b0100) || (card_status[4:1] == 4'b0110) || (card_status[4:1] == 4'b0101) ) |
rec_done<=1; |
else begin |
rec_failed<=1; |
Dat_Int_Status[4] <=1; |
start_tx_fifo<=0; |
end |
|
|
|
//Check card_status[5:1] for state 4 or 6... |
//If wrong state change interupt status reg,so software can put card in |
// transfer state and restart/cancel Data transfer |
end |
|
end |
else begin |
rec_failed<=1; //CRC-Error, CIC-Error or timeout |
start_tx_fifo<=0; |
end |
end |
end |
|
DATA_TRANSFER: begin |
CIDAT<=1; |
if (tx_cycle) begin |
if (tx_empt) begin |
Dat_Int_Status[2] <=1; |
trans_failed<=1; |
end |
end |
else begin |
if (rx_full) begin |
Dat_Int_Status[2] <=1; |
trans_failed<=1; |
end |
end |
//Check for fifo underflow, |
//2 DO: if deteced stop transfer, reset data host |
if (internal_transm_complete) begin //Transfer complete |
ack_transfer<=1; |
|
if ((!crc_ok) && (busy_n)) begin //Wrong CRC and Data line free. |
Dat_Int_Status[5] <=1; |
trans_failed<=1; |
end |
else if ((crc_ok) && (busy_n)) begin //Data Line free |
trans_done <=1; |
Dat_Int_Status[0]<=1; |
if (tx_cycle) |
a_cmp_tx<=1; |
else |
a_cmp_rx<=1; |
end |
|
end |
|
end |
|
STOP: begin |
cmd_set <= CMD12; |
rec_done<=0; |
rec_failed<=0; |
send_done<=0; |
trans_failed<=0; |
trans_done<=0; |
d_read<=1; |
d_write<=1; |
start_rx_fifo <=0; |
start_tx_fifo <=0; |
|
end |
STOP_SEND: begin |
resend_try_cnt=resend_try_cnt+1; |
if (resend_try_cnt==`RESEND_MAX_CNT) |
Dat_Int_Status[1]<=1; |
if (!cmd_busy) |
we_req <= 1; |
if (we_ack) |
send_done<=1; |
end |
|
STOP_RECIVE_CMD: begin |
we_req <= 0; |
if (!cmd_busy) begin //Means the sending is completed, |
if (!cmd_tsf_err) begin |
rec_done<=1; |
send_done<=0; |
d_read<=0; |
d_write<=0; |
if (tx_cycle) |
cmd_set<= CMD24; |
else |
cmd_set <= CMD17; |
end |
else |
rec_failed<=1; |
end |
end |
|
endcase |
if (Dat_Int_Status_rst) |
Dat_Int_Status<=0; |
end |
|
end |
|
endmodule |