📄 sd_data_master.v
字号:
`include "SD_defines.v"
module SD_DATA_MASTER (
input clk,
input rst,
//Tx Bd
input new_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 new_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 rx_full,
//SD-DATA_Host
input busy_n ,
input transm_complete ,
input crc_ok,
output reg ack_transfer,
//status output
output reg [7:0] bd_int_st ,
input bd_int_st_rst,
output reg CIDAT
);
`define BD_EMPTY (`BD_SIZE /4)
`ifdef RAM_MEM_WIDTH_32
`define READ_CYCLE 2
reg bd_cnt ;
`else `ifdef RAM_MEM_WIDTH_16
`define READ_CYCLE 4
reg [1:0] bd_cnt;
`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;
always @ (state 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))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;
bd_int_st<=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_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;
`ifdef RAM_MEM_WIDTH_16
if (ack_i_s_tx) begin
if( bd_cnt == 2'b00) begin
sys_adr [15:0] <= dat_in_tx; end
else if ( bd_cnt == 2'b01) begin
sys_adr [31:16] <= dat_in_tx; end
else if ( bd_cnt == 2) begin
cmd_arg [15:0] <= dat_in_tx;
re_s_tx <= 0; end
else if ( bd_cnt == 3) begin
cmd_arg [31:16] <= dat_in_tx;
re_s_tx <= 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 <= CMD24;
tx_cycle <=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 (tx_cycle)
start_tx_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;
bd_int_st[4] <=1;
end
`endif
`ifdef SIM
rec_done<=1;
`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
end
else
rec_failed<=1; //CRC-Error, CIC-Error or timeout
end
end
DATA_TRANSFER: begin
CIDAT<=1;
if (tx_cycle) begin
if (tx_empt) begin
bd_int_st[2] <=1;
trans_failed<=1;
end
end
else begin
if (rx_full) begin
bd_int_st[2] <=1;
trans_failed<=1;
end
end
//Check for fifo underflow,
//2 DO: if deteced stop transfer, reset data host
if (transm_complete) begin //Transfer complete
ack_transfer<=1;
if ((!crc_ok) && (busy_n)) begin //Wrong CRC and Data line free.
bd_int_st[5] <=1;
trans_failed<=1;
end
else if ((crc_ok) && (busy_n)) begin //Data Line free
trans_done <=1;
bd_int_st[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)
bd_int_st[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 (bd_int_st_rst)
bd_int_st<=0;
end
end
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -