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/sdc_dma
- from Rev 107 to Rev 108
- ↔ Reverse comparison
Rev 107 → Rev 108
/verilog/SD_controller_top.v
1,600 → 1,463
`include "SD_defines.v" |
module SD_CONTROLLER_TOP( |
|
// WISHBONE common |
wb_clk_i, wb_rst_i, wb_dat_i, wb_dat_o, |
|
// WISHBONE slave |
wb_adr_i, wb_sel_i, wb_we_i, wb_cyc_i, wb_stb_i, wb_ack_o, |
|
// WISHBONE master |
m_wb_adr_o, m_wb_sel_o, m_wb_we_o, |
m_wb_dat_o, m_wb_dat_i, m_wb_cyc_o, |
m_wb_stb_o, m_wb_ack_i, |
m_wb_cti_o, m_wb_bte_o, |
//SD BUS |
sd_cmd_dat_i,sd_cmd_out_o, sd_cmd_oe_o, |
sd_dat_dat_i, sd_dat_out_o , sd_dat_oe_o, sd_clk_o_pad |
`ifdef SD_CLK_SEP |
,sd_clk_i_pad |
`endif |
`ifdef IRQ_ENABLE |
,int_a, int_b, int_c |
`endif |
); |
|
|
|
// WISHBONE common |
input wb_clk_i; // WISHBONE clock |
input wb_rst_i; // WISHBONE reset |
input [31:0] wb_dat_i; // WISHBONE data input |
output reg [31:0] wb_dat_o; // WISHBONE data output |
// WISHBONE error output |
|
// WISHBONE slave |
input [7:0] wb_adr_i; // WISHBONE address input |
input [3:0] wb_sel_i; // WISHBONE byte select input |
input wb_we_i; // WISHBONE write enable input |
input wb_cyc_i; // WISHBONE cycle input |
input wb_stb_i; // WISHBONE strobe input |
|
output wb_ack_o; // WISHBONE acknowledge output |
|
// WISHBONE master |
output [31:0] m_wb_adr_o; |
output [3:0] m_wb_sel_o; |
output m_wb_we_o; |
|
input [31:0] m_wb_dat_i; |
output [31:0] m_wb_dat_o; |
output m_wb_cyc_o; |
output m_wb_stb_o; |
input m_wb_ack_i; |
output [2:0] m_wb_cti_o; |
output [1:0] m_wb_bte_o; |
//SD port |
|
input wire [3:0] sd_dat_dat_i; //Data in from SDcard |
output wire [3:0] sd_dat_out_o; //Data out to SDcard |
output wire sd_dat_oe_o; //SD Card tristate Data Output enable (Connects on the SoC TopLevel) |
|
input wire sd_cmd_dat_i; //Command in from SDcard |
output wire sd_cmd_out_o; //Command out to SDcard |
output wire sd_cmd_oe_o; //SD Card tristate CMD Output enable (Connects on the SoC TopLevel) |
|
//IRQ |
|
|
`ifdef IRQ_ENABLE |
output int_a, int_b, int_c ; |
`endif |
|
reg wb_ack_o; |
reg wb_inta_o; |
reg new_cmd; |
|
|
`define SUPPLY_VOLTAGE_3_3 |
`define SD_CARD_2_0 |
|
//Register Addreses |
`define argument 8'h00 |
`define command 8'h04 |
`define status 8'h08 |
`define resp1 8'h0c |
`define controller 8'h1c |
`define block 8'h20 |
`define power 8'h24 |
`define software 8'h28 |
`define timeout 8'h2c |
`define normal_isr 8'h30 |
`define error_isr 8'h34 |
`define normal_iser 8'h38 |
`define error_iser 8'h3c |
`define capa 8'h48 |
`define clock_d 8'h4c |
`define bd_status 8'h50 |
`define bd_isr 8'h54 |
`define bd_iser 8'h58 |
`define bd_rx 8'h60 |
`define bd_tx 8'h80 |
|
|
assign m_wb_sel_o = 4'b1111; |
`ifdef SUPPLY_VOLTAGE_3_3 |
parameter power_controll_reg = 8'b0000_111_1; |
`elsif SUPPLY_VOLTAGE_3_0 |
parameter power_controll_reg = 8'b0000_110_1; |
`elsif SUPPLY_VOLTAGE_1_8 |
parameter power_controll_reg = 8'b0000_101_1; |
`endif |
|
parameter block_size_reg = `BLOCK_SIZE ; //512-Bytes |
|
`ifdef SD_BUS_WIDTH_4 |
parameter controll_setting_reg =16'b0000_0000_0000_0010; |
`else |
parameter controll_setting_reg =16'b0000_0000_0000_0000; |
`endif |
parameter capabilies_reg =16'b0000_0000_0000_0000; |
|
//Buss accessible registers |
reg [31:0] argument_reg; |
reg [15:0] cmd_setting_reg; |
reg [15:0] status_reg; |
reg [31:0] cmd_resp_1; |
reg [7:0] software_reset_reg; |
reg [15:0] time_out_reg; |
reg [15:0]normal_int_status_reg; |
reg [15:0]error_int_status_reg; |
reg [15:0]normal_int_signal_enable_reg; |
reg [15:0]error_int_signal_enable_reg; |
reg [7:0] clock_divider; |
reg [15:0] Bd_Status_reg; |
reg [7:0] Bd_isr_reg; |
reg [7:0] Bd_isr_enable_reg; |
|
//Register Controll |
reg Bd_isr_reset; |
reg normal_isr_reset; |
reg error_isr_reset; |
|
//Wires from SD_CMD_MASTER Module |
wire [15:0] status_reg_w; |
wire [31:0] cmd_resp_1_w; |
wire [15:0]normal_int_status_reg_w; |
wire [15:0]error_int_status_reg_w; |
|
|
|
//Internal Delayed Ack |
reg int_ack; |
|
//Rx Buffer Descriptor internal signals |
reg we_m_rx_bd; //Write enable Master side Rx_bd |
reg re_m_rx_bd; //Read enable Master side Rx_bd |
reg [`RAM_MEM_WIDTH-1:0] dat_in_m_rx_bd; //Data in to Rx_bd from Master |
wire [`RAM_MEM_WIDTH-1:0] dat_out_m_rx_bd; //Data out from Rx_bd to Master |
wire [`BD_WIDTH-1 :0] free_bd_rx_bd; //NO free Rx_bd |
wire new_rx_bd; // New Bd writen |
reg re_s_rx_bd; // Read enable Slave side Rx_bd |
reg a_cmp_rx_bd; //A Completed transmison of a Bd |
wire [`RAM_MEM_WIDTH-1:0] dat_out_s_rx_bd; //Data out from Rx_bd to Slave |
|
//Tx Buffer Descriptor internal signals |
reg we_m_tx_bd; |
reg re_m_tx_bd; |
reg [`RAM_MEM_WIDTH-1:0] dat_in_m_tx_bd; |
wire [`RAM_MEM_WIDTH-1:0] dat_out_m_tx_bd; |
wire [`BD_WIDTH-1 :0] free_bd_tx_bd; |
wire new_tx_bd; |
reg re_s_tx_bd; |
reg a_cmp_tx_bd; |
wire [`RAM_MEM_WIDTH-1:0] dat_out_s_tx_bd; |
reg [1:0] we; |
wire [7:0] bd_int_st_w; //Wire to BD status register |
|
//Wires for connecting Bd registers with the SD_Data_master module |
wire re_s_tx_bd_w; |
wire a_cmp_tx_bd_w; |
wire re_s_rx_bd_w; |
wire a_cmp_rx_bd_w; |
|
wire write_req_s; //SD_Data_master want acces to the CMD line. |
wire cmd_busy; //CMD line busy no access granted |
reg we_ack; //CMD acces granted |
wire [31:0] cmd_arg_s; //SD_Data_master CMD Argument |
wire [31:0] cmd_set_s; //SD_Data_master Settings Argument |
wire [31:0] sys_adr; //System addres the DMA whil Read/Write to/from |
wire [1:0]start_dat_t; //Start data transfer |
|
//Signals to Syncronize busy signaling betwen Wishbone access and SD_Data_master access to the CMD line (Also manage the status reg uppdate) |
reg int_busy; |
assign cmd_busy = int_busy | status_reg[0]; |
wire status_reg_busy; |
reg cmd_int_busy; |
|
//Wires from SD_DATA_SERIAL_HOST_1 to the FIFO |
wire [`SD_BUS_W -1 : 0 ]data_in_rx_fifo; |
wire [31: 0 ] data_fout_tx_fifo; |
wire [31:0] m_wb_dat_o_rx; |
wire [3:0] m_wb_sel_o_tx; |
wire [31:0] m_wb_adr_o_tx; |
wire [31:0] m_wb_adr_o_rx; |
|
//SD clock |
wire sd_clk_i; //Sd_clk provided to the system |
wire sd_clk_o; //Sd_clk used in the system |
output sd_clk_o_pad; |
//sd_clk_o to be used i set here |
`ifdef SD_CLK_BUS_CLK |
assign sd_clk_i = wb_clk_i; |
`endif |
`ifdef SD_CLK_SEP |
sd_clk_i = sd_clk_i_pad |
`endif |
|
`ifdef SD_CLK_STATIC |
assign sd_clk_o = sd_clk_i; |
`endif |
|
`ifdef SD_CLK_DYNAMIC |
SD_CLOCK_DIVIDER CLOCK_DIVIDER_1 ( |
.CLK (sd_clk_i), |
.DIVIDER (clock_divider), |
.RST (wb_rst_i | software_reset_reg[0]), |
.SD_CLK (sd_clk_o) |
); |
`endif |
assign sd_clk_o_pad = sd_clk_o ; |
|
|
SD_CMD_MASTER cmd_master_1 |
( |
.CLK_PAD_IO (wb_clk_i), |
.SD_CLK_I (sd_clk_o), |
.RST_PAD_I (wb_rst_i | software_reset_reg[0]), |
.New_CMD (new_cmd), |
.data_write (d_write), |
.data_read (d_read), |
.cmd_dat_i (sd_cmd_dat_i), |
.cmd_out_o (sd_cmd_out_o), |
.cmd_oe_o ( sd_cmd_oe_o), |
.ARG_REG (argument_reg), |
.CMD_SET_REG (cmd_setting_reg), |
.STATUS_REG (status_reg_w), |
.TIMEOUT_REG (time_out_reg), |
.RESP_1_REG (cmd_resp_1_w), |
.ERR_INT_REG (error_int_status_reg_w), |
.NORMAL_INT_REG (normal_int_status_reg_w), |
.ERR_INT_RST (error_isr_reset), |
.NORMAL_INT_RST (normal_isr_reset), |
.CLK_DIVIDER (clock_divider), |
.st_dat_t (start_dat_t) |
); |
|
|
SD_DATA_MASTER data_master_1 |
( |
.clk (wb_clk_i), |
.rst (wb_rst_i | software_reset_reg[0]), |
.new_tx_bd (new_tx_bd), |
.dat_in_tx (dat_out_s_tx_bd), |
.free_tx_bd (free_bd_tx_bd), |
.ack_i_s_tx ( ack_o_s_tx ), |
.re_s_tx (re_s_tx_bd_w), |
.a_cmp_tx (a_cmp_tx_bd_w), |
.new_rx_bd (new_rx_bd), |
.dat_in_rx (dat_out_s_rx_bd), |
.free_rx_bd (free_bd_rx_bd), |
.ack_i_s_rx ( ack_o_s_rx ), |
.re_s_rx (re_s_rx_bd_w), |
.a_cmp_rx (a_cmp_rx_bd_w), |
.cmd_busy (cmd_busy), |
.we_req (write_req_s), |
.we_ack (we_ack), |
.d_write ( d_write ), |
.d_read ( d_read ), |
.cmd_arg ( cmd_arg_s), |
.cmd_set ( cmd_set_s), |
.cmd_tsf_err (normal_int_status_reg[15]) , |
.card_status (cmd_resp_1[12:8]) , |
.start_tx_fifo (start_w), |
.start_rx_fifo (start_r), |
.sys_adr (sys_adr), |
.tx_empt (tx_e ), |
.tx_full (tx_f ), |
.rx_full(full_rx ), |
.busy_n (busy_n), |
.transm_complete (trans_complete ), |
.crc_ok (crc_ok), |
.ack_transfer (ack_transfer), |
.bd_int_st (bd_int_st_w), |
.bd_int_st_rst (Bd_isr_reset), |
.CIDAT (cidat_w) |
); |
|
wire [31:0] data_out_tx_fifo; |
SD_DATA_SERIAL_HOST SD_DATA_SERIAL_HOST_1( |
.sd_clk (sd_clk_o), |
.rst (wb_rst_i | software_reset_reg[0]), |
.data_in (data_out_tx_fifo), |
.rd (rd), |
.data_out (data_in_rx_fifo), |
.we (we_rx), |
.DAT_oe_o (sd_dat_oe_o), |
.DAT_dat_o (sd_dat_out_o), |
.DAT_dat_i (sd_dat_dat_i), |
.start_dat (start_dat_t), |
.ack_transfer (ack_transfer), |
.busy_n (busy_n), |
.transm_complete (trans_complete ), |
.crc_ok (crc_ok) |
); |
|
|
SD_Bd rx_bd |
( |
.clk (wb_clk_i), |
.rst (wb_rst_i | software_reset_reg[0]), |
.we_m (we_m_rx_bd), |
.re_m (re_m_rx_bd), |
.dat_in_m (dat_in_m_rx_bd), |
.dat_out_m (dat_out_m_rx_bd), |
.free_bd (free_bd_rx_bd), |
.new_bw (new_rx_bd), |
.re_s (re_s_rx_bd), |
.ack_o_s (ack_o_s_rx), |
.a_cmp (a_cmp_rx_bd), |
.dat_out_s (dat_out_s_rx_bd) |
|
); |
|
SD_Bd tx_bd |
( |
.clk (wb_clk_i), |
.rst (wb_rst_i | software_reset_reg[0]), |
.we_m (we_m_tx_bd), |
.re_m (re_m_tx_bd), |
.dat_in_m (dat_in_m_tx_bd), |
.dat_out_m (dat_out_m_tx_bd), |
.free_bd (free_bd_tx_bd), |
.new_bw (new_tx_bd), |
.ack_o_s (ack_o_s_tx), |
.re_s (re_s_tx_bd), |
.a_cmp (a_cmp_tx_bd), |
.dat_out_s (dat_out_s_tx_bd) |
|
); |
|
|
SD_FIFO_TX_FILLER FIFO_filer_tx ( |
.clk (wb_clk_i), |
.rst (wb_rst_i | software_reset_reg[0]), |
.m_wb_adr_o (m_wb_adr_o_tx), |
|
.m_wb_we_o (m_wb_we_o_tx), |
|
.m_wb_dat_i (m_wb_dat_i), |
.m_wb_cyc_o (m_wb_cyc_o_tx), |
.m_wb_stb_o (m_wb_stb_o_tx), |
.m_wb_ack_i ( m_wb_ack_i), |
.en (start_w), |
.adr (sys_adr), |
.sd_clk (sd_clk_o), |
.dat_o (data_out_tx_fifo ), |
.rd ( rd ), |
.empty (tx_e), |
.fe (tx_f) |
); |
|
SD_FIFO_RX_FILLER FIFO_filer_rx ( |
.clk (wb_clk_i), |
.rst (wb_rst_i | software_reset_reg[0]), |
.m_wb_adr_o (m_wb_adr_o_rx), |
|
.m_wb_we_o (m_wb_we_o_rx), |
.m_wb_dat_o (m_wb_dat_o_rx), |
.m_wb_cyc_o (m_wb_cyc_o_rx), |
.m_wb_stb_o (m_wb_stb_o_rx), |
.m_wb_ack_i ( m_wb_ack_i), |
.en (start_r), |
.adr (sys_adr), |
.sd_clk (sd_clk_o), |
.dat_i (data_in_rx_fifo ), |
.wr ( we_rx ), |
.full (full_rx) |
); |
|
//MUX For WB master acces granted to RX or TX FIFO filler |
assign m_wb_cyc_o = start_w ? m_wb_cyc_o_tx :start_r ?m_wb_cyc_o_rx: 0; |
assign m_wb_stb_o = start_w ? m_wb_stb_o_tx :start_r ?m_wb_stb_o_rx: 0; |
assign m_wb_dat_o = m_wb_dat_o_rx; |
assign m_wb_we_o = start_w ? m_wb_we_o_tx :start_r ?m_wb_we_o_rx: 0; |
assign m_wb_adr_o = start_w ? m_wb_adr_o_tx :start_r ?m_wb_adr_o_rx: 0; |
|
`ifdef IRQ_ENABLE |
assign int_a =normal_int_status_reg & normal_int_signal_enable_reg; |
assign int_b = error_int_status_reg & error_int_signal_enable_reg; |
assign int_c = Bd_isr_reg & Bd_isr_enable_reg; |
`endif |
|
always @ (re_s_tx_bd_w or a_cmp_tx_bd_w or re_s_rx_bd_w or a_cmp_rx_bd_w or write_req_s) begin |
re_s_tx_bd<=re_s_tx_bd_w; |
a_cmp_tx_bd <=a_cmp_tx_bd_w; |
re_s_rx_bd <=re_s_rx_bd_w; |
a_cmp_rx_bd<=a_cmp_rx_bd_w; |
end |
|
//Set Bd_Status_reg |
always @ ( free_bd_tx_bd or free_bd_rx_bd ) begin |
Bd_Status_reg[15:8]=free_bd_rx_bd; |
Bd_Status_reg[7:0]=free_bd_tx_bd; |
end |
|
always @( cmd_resp_1_w or error_int_status_reg_w or normal_int_status_reg_w ) begin |
cmd_resp_1<= cmd_resp_1_w; |
normal_int_status_reg<= normal_int_status_reg_w ; |
error_int_status_reg<= error_int_status_reg_w ; |
end |
|
always @ ( cidat_w or cmd_int_busy or status_reg_w or status_reg_busy or bd_int_st_w) begin |
status_reg[0]<= status_reg_busy; |
status_reg[15:1]<= status_reg_w[15:1]; |
status_reg[1] <= cidat_w; |
Bd_isr_reg<=bd_int_st_w; |
end |
|
//cmd_int_busy is set when an internal access to the CMD buss is granted then immidetly uppdate the status busy bit to prevent buss access to cmd |
assign status_reg_busy = cmd_int_busy ? 1'b1: status_reg_w[0]; |
|
//WB write |
always @(posedge wb_clk_i or posedge wb_rst_i) |
begin |
we_m_rx_bd <= 0; |
we_m_tx_bd <= 0; |
new_cmd<= 1'b0 ; |
we_ack <= 0; |
int_ack = 1; |
cmd_int_busy<=0; |
if ( wb_rst_i )begin |
argument_reg <=0; |
cmd_setting_reg <= 0; |
software_reset_reg <= 0; |
time_out_reg <= 0; |
normal_int_signal_enable_reg <= 0; |
error_int_signal_enable_reg <= 0; |
clock_divider <=`RESET_CLK_DIV; |
int_ack=1 ; |
we<=0; |
int_busy <=0; |
we_ack <=0; |
wb_ack_o=0; |
cmd_int_busy<=0; |
Bd_isr_reset<=0; |
dat_in_m_tx_bd<=0; |
dat_in_m_rx_bd<=0; |
Bd_isr_enable_reg<=0; |
normal_isr_reset<=0; |
error_isr_reset<=0; |
end |
else if ((wb_stb_i & wb_cyc_i) || wb_ack_o )begin |
Bd_isr_reset<=0; |
normal_isr_reset<= 0; |
error_isr_reset<= 0; |
if (wb_we_i) begin |
case (wb_adr_i) |
`argument: begin |
argument_reg <= wb_dat_i; |
new_cmd <= 1'b1 ; |
end |
`command : begin |
cmd_setting_reg <= wb_dat_i; |
int_busy <= 1; |
end |
`software : software_reset_reg <= wb_dat_i; |
`timeout : time_out_reg <= wb_dat_i; |
`normal_iser : normal_int_signal_enable_reg <= wb_dat_i; |
`error_iser : error_int_signal_enable_reg <= wb_dat_i; |
`normal_isr : normal_isr_reset<= 1; |
`error_isr: error_isr_reset<= 1; |
`clock_d: clock_divider <= wb_dat_i; |
`bd_isr: Bd_isr_reset<= 1; |
`bd_iser : Bd_isr_enable_reg <= wb_dat_i ; |
`ifdef RAM_MEM_WIDTH_32 |
`bd_rx: begin |
we <= we+1; |
we_m_rx_bd <= 1; |
int_ack = 0; |
if (we[1:0]==2'b00) |
we_m_rx_bd <= 0; |
else if (we[1:0]==2'b01) |
dat_in_m_rx_bd <= wb_dat_i; |
else begin |
int_ack = 1; |
we<= 0; |
we_m_rx_bd <= 0; |
end |
|
end |
`bd_tx: begin |
we <= we+1; |
we_m_tx_bd <= 1; |
int_ack = 0; |
if (we[1:0]==2'b00) |
we_m_tx_bd <= 0; |
else if (we[1:0]==2'b01) |
dat_in_m_tx_bd <= wb_dat_i; |
else begin |
int_ack = 1; |
we<= 0; |
we_m_tx_bd <= 0; |
end |
end |
|
`endif |
`ifdef RAM_MEM_WIDTH_16 |
`bd_rx: begin |
we <= we+1; |
we_m_rx_bd <= 1; |
int_ack = 0; |
if (we[1:0]==2'b00) |
we_m_rx_bd <= 0; |
else if (we[1:0]==2'b01) |
dat_in_m_rx_bd <= wb_dat_i[15:0]; |
else if ( we[1:0]==2'b10) |
dat_in_m_rx_bd <= wb_dat_i[31:16]; |
else begin |
int_ack = 1; |
we<= 0; |
we_m_rx_bd <= 0; |
end |
|
end |
`bd_tx: begin |
we <= we+1; |
we_m_tx_bd <= 1; |
int_ack = 0; |
if (we[1:0]==2'b00) |
we_m_tx_bd <= 0; |
else if (we[1:0]==2'b01) |
dat_in_m_tx_bd <= wb_dat_i[15:0]; |
else if ( we[1:0]==2'b10) |
dat_in_m_tx_bd <= wb_dat_i[31:16]; |
else begin |
int_ack = 1; |
we<= 0; |
we_m_tx_bd <= 0; |
end |
end |
`endif |
|
endcase |
end |
wb_ack_o = wb_cyc_i & wb_stb_i & ~wb_ack_o & int_ack; |
end |
else if (write_req_s) begin |
new_cmd <= 1'b1 ; |
cmd_setting_reg <= cmd_set_s; |
argument_reg <= cmd_arg_s ; |
cmd_int_busy<= 1; |
we_ack <= 1; |
end |
|
if (status_reg[0]) |
int_busy <= 0; |
|
//wb_ack_o = wb_cyc_i & wb_stb_i & ~wb_ack_o & int_ack; |
end |
|
always @(posedge wb_clk_i )begin |
if (wb_stb_i & wb_cyc_i) begin //CS |
case (wb_adr_i) |
`argument: wb_dat_o <= argument_reg ; |
`command : wb_dat_o <= cmd_setting_reg ; |
`status : wb_dat_o <= status_reg ; |
`resp1 : wb_dat_o <= cmd_resp_1 ; |
|
`controller : wb_dat_o <= controll_setting_reg ; |
`block : wb_dat_o <= block_size_reg ; |
`power : wb_dat_o <= power_controll_reg ; |
`software : wb_dat_o <= software_reset_reg ; |
`timeout : wb_dat_o <= time_out_reg ; |
`normal_isr : wb_dat_o <= normal_int_status_reg ; |
`error_isr : wb_dat_o <= error_int_status_reg ; |
`normal_iser : wb_dat_o <= normal_int_signal_enable_reg ; |
`error_iser : wb_dat_o <= error_int_signal_enable_reg ; |
|
`capa : wb_dat_o <= capabilies_reg ; |
`bd_status : wb_dat_o <= Bd_Status_reg; |
`bd_isr : wb_dat_o <= Bd_isr_reg ; |
`bd_iser : wb_dat_o <= Bd_isr_enable_reg ; |
endcase |
end |
end |
|
|
|
|
`include "SD_defines.v" |
module SD_CONTROLLER_TOP( |
|
// WISHBONE common |
wb_clk_i, wb_rst_i, wb_dat_i, wb_dat_o, |
|
// WISHBONE slave |
wb_adr_i, wb_sel_i, wb_we_i, wb_cyc_i, wb_stb_i, wb_ack_o, |
|
// WISHBONE master |
m_wb_adr_o, m_wb_sel_o, m_wb_we_o, |
m_wb_dat_o, m_wb_dat_i, m_wb_cyc_o, |
m_wb_stb_o, m_wb_ack_i, |
m_wb_cti_o, m_wb_bte_o, |
//SD BUS |
sd_cmd_dat_i,sd_cmd_out_o, sd_cmd_oe_o, |
sd_dat_dat_i, sd_dat_out_o , sd_dat_oe_o, sd_clk_o_pad |
`ifdef SD_CLK_SEP |
,sd_clk_i_pad |
`endif |
`ifdef IRQ_ENABLE |
,int_a, int_b, int_c |
`endif |
); |
|
|
|
// WISHBONE common |
input wb_clk_i; // WISHBONE clock |
input wb_rst_i; // WISHBONE reset |
input [31:0] wb_dat_i; // WISHBONE data input |
output [31:0] wb_dat_o; // WISHBONE data output |
// WISHBONE error output |
|
// WISHBONE slave |
input [7:0] wb_adr_i; // WISHBONE address input |
input [3:0] wb_sel_i; // WISHBONE byte select input |
input wb_we_i; // WISHBONE write enable input |
input wb_cyc_i; // WISHBONE cycle input |
input wb_stb_i; // WISHBONE strobe input |
|
output wb_ack_o; // WISHBONE acknowledge output |
|
// WISHBONE master |
output [31:0] m_wb_adr_o; |
output [3:0] m_wb_sel_o; |
output m_wb_we_o; |
|
input [31:0] m_wb_dat_i; |
output [31:0] m_wb_dat_o; |
output m_wb_cyc_o; |
output m_wb_stb_o; |
input m_wb_ack_i; |
output [2:0] m_wb_cti_o; |
output [1:0] m_wb_bte_o; |
//SD port |
|
input wire [3:0] sd_dat_dat_i; //Data in from SDcard |
output wire [3:0] sd_dat_out_o; //Data out to SDcard |
output wire sd_dat_oe_o; //SD Card tristate Data Output enable (Connects on the SoC TopLevel) |
|
input wire sd_cmd_dat_i; //Command in from SDcard |
output wire sd_cmd_out_o; //Command out to SDcard |
output wire sd_cmd_oe_o; //SD Card tristate CMD Output enable (Connects on the SoC TopLevel) |
|
//IRQ |
|
|
`ifdef IRQ_ENABLE |
output int_a, int_b, int_c ; |
`endif |
|
wire int_busy; |
|
|
|
//Wires from SD_CMD_MASTER Module |
wire [15:0] status_reg_w; |
wire [31:0] cmd_resp_1_w; |
wire [15:0]normal_int_status_reg_w; |
wire [15:0]error_int_status_reg_w; |
|
|
wire[31:0] argument_reg; |
wire[15:0] cmd_setting_reg; |
reg[15:0] status_reg; |
reg[31:0] cmd_resp_1; |
wire[7:0] software_reset_reg; |
wire[15:0] time_out_reg; |
reg[15:0]normal_int_status_reg; |
reg[15:0]error_int_status_reg; |
wire[15:0]normal_int_signal_enable_reg; |
wire[15:0]error_int_signal_enable_reg; |
wire[7:0] clock_divider; |
reg[15:0] Bd_Status_reg; |
reg[7:0] Bd_isr_reg; |
wire[7:0] Bd_isr_enable_reg; |
|
|
//Rx Buffer Descriptor internal signals |
|
|
wire [`RAM_MEM_WIDTH-1:0] dat_out_m_rx_bd; //Data out from Rx_bd to Master |
wire [`BD_WIDTH-1 :0] free_bd_rx_bd; //NO free Rx_bd |
wire new_rx_bd; // New Bd writen |
reg re_s_rx_bd; // Read enable Slave side Rx_bd |
reg a_cmp_rx_bd; //A Completed transmison of a Bd |
wire [`RAM_MEM_WIDTH-1:0] dat_out_s_rx_bd; //Data out from Rx_bd to Slave |
|
//Tx Buffer Descriptor internal signals |
wire [`RAM_MEM_WIDTH-1:0] dat_in_m_rx_bd; //Data in to Rx_bd from Master |
wire [`RAM_MEM_WIDTH-1:0] dat_in_m_tx_bd; |
wire [`RAM_MEM_WIDTH-1:0] dat_out_m_tx_bd; |
wire [`BD_WIDTH-1 :0] free_bd_tx_bd; |
wire new_tx_bd; |
reg re_s_tx_bd; |
reg a_cmp_tx_bd; |
wire [`RAM_MEM_WIDTH-1:0] dat_out_s_tx_bd; |
|
wire [7:0] bd_int_st_w; //Wire to BD status register |
|
//Wires for connecting Bd registers with the SD_Data_master module |
wire re_s_tx_bd_w; |
wire a_cmp_tx_bd_w; |
wire re_s_rx_bd_w; |
wire a_cmp_rx_bd_w; |
|
wire write_req_s; //SD_Data_master want acces to the CMD line. |
wire cmd_busy; //CMD line busy no access granted |
|
wire [31:0] cmd_arg_s; //SD_Data_master CMD Argument |
wire [15:0] cmd_set_s; //SD_Data_master Settings Argument |
wire [31:0] sys_adr; //System addres the DMA whil Read/Write to/from |
wire [1:0]start_dat_t; //Start data transfer |
|
//Signals to Syncronize busy signaling betwen Wishbone access and SD_Data_master access to the CMD line (Also manage the status reg uppdate) |
|
assign cmd_busy = int_busy | status_reg[0]; |
wire status_reg_busy; |
|
|
//Wires from SD_DATA_SERIAL_HOST_1 to the FIFO |
wire [`SD_BUS_W -1 : 0 ]data_in_rx_fifo; |
wire [31: 0 ] data_fout_tx_fifo; |
wire [31:0] m_wb_dat_o_rx; |
wire [3:0] m_wb_sel_o_tx; |
wire [31:0] m_wb_adr_o_tx; |
wire [31:0] m_wb_adr_o_rx; |
|
//SD clock |
wire sd_clk_i; //Sd_clk provided to the system |
wire sd_clk_o; //Sd_clk used in the system |
output sd_clk_o_pad; |
//sd_clk_o to be used i set here |
`ifdef SD_CLK_BUS_CLK |
assign sd_clk_i = wb_clk_i; |
`endif |
`ifdef SD_CLK_SEP |
sd_clk_i = sd_clk_i_pad |
`endif |
|
`ifdef SD_CLK_STATIC |
assign sd_clk_o = sd_clk_i; |
`endif |
|
`ifdef SD_CLK_DYNAMIC |
SD_CLOCK_DIVIDER CLOCK_DIVIDER_1 ( |
.CLK (sd_clk_i), |
.DIVIDER (clock_divider), |
.RST (wb_rst_i | software_reset_reg[0]), |
.SD_CLK (sd_clk_o) |
); |
`endif |
assign sd_clk_o_pad = sd_clk_o ; |
wire [15:0] settings; |
wire [15:0] serial_status; |
wire [39:0] cmd_out_master; |
wire [39:0] cmd_in_host; |
|
SD_CMD_MASTER cmd_master_1 |
( |
.CLK_PAD_IO (wb_clk_i), |
|
.RST_PAD_I (wb_rst_i | software_reset_reg[0]), |
.New_CMD (new_cmd), |
.data_write (d_write), |
.data_read (d_read), |
.ARG_REG (argument_reg), |
.CMD_SET_REG (cmd_setting_reg), |
.STATUS_REG (status_reg_w), |
.TIMEOUT_REG (time_out_reg), |
.RESP_1_REG (cmd_resp_1_w), |
.ERR_INT_REG (error_int_status_reg_w), |
.NORMAL_INT_REG (normal_int_status_reg_w), |
.ERR_INT_RST (error_isr_reset), |
.NORMAL_INT_RST (normal_isr_reset), |
|
|
.settings (settings), |
.go_idle_o (go_idle), |
.cmd_out ( cmd_out_master ), |
.req_out ( req_out_master ), |
.ack_out ( ack_out_master ), |
.req_in (req_in_host), |
.ack_in (ack_in_host), |
.cmd_in (cmd_in_host), |
.serial_status (serial_status) |
|
); |
|
|
SD_CMD_SERIAL_HOST CMD_SERIAL_HOST_1( |
.SD_CLK_IN (sd_clk_o), |
.RST_IN (wb_rst_i | software_reset_reg[0]), |
.SETTING_IN (settings), |
.GO_IDLE (go_idle), |
.CMD_IN (cmd_out_master), |
.REQ_IN (req_out_master), |
.ACK_IN (ack_out_master), |
.REQ_OUT (req_in_host), |
.ACK_OUT (ack_in_host), |
.CMD_OUT (cmd_in_host), |
.STATUS (serial_status), |
.cmd_dat_i (sd_cmd_dat_i), |
.cmd_out_o (sd_cmd_out_o), |
.cmd_oe_o ( sd_cmd_oe_o), |
.st_dat_t (start_dat_t) |
); |
|
|
SD_DATA_MASTER data_master_1 |
( |
.clk (wb_clk_i), |
.rst (wb_rst_i | software_reset_reg[0]), |
|
.dat_in_tx (dat_out_s_tx_bd), |
.free_tx_bd (free_bd_tx_bd), |
.ack_i_s_tx ( ack_o_s_tx ), |
.re_s_tx (re_s_tx_bd_w), |
.a_cmp_tx (a_cmp_tx_bd_w), |
|
.dat_in_rx (dat_out_s_rx_bd), |
.free_rx_bd (free_bd_rx_bd), |
.ack_i_s_rx ( ack_o_s_rx ), |
.re_s_rx (re_s_rx_bd_w), |
.a_cmp_rx (a_cmp_rx_bd_w), |
.cmd_busy (cmd_busy), |
.we_req (write_req_s), |
.we_ack (we_ack), |
.d_write ( d_write ), |
.d_read ( d_read ), |
.cmd_arg ( cmd_arg_s), |
.cmd_set ( cmd_set_s), |
.cmd_tsf_err (normal_int_status_reg[15]) , |
.card_status (cmd_resp_1[12:8]) , |
.start_tx_fifo (start_w), |
.start_rx_fifo (start_r), |
.sys_adr (sys_adr), |
.tx_empt (tx_e ), |
.tx_full (tx_f ), |
.rx_full(full_rx ), |
.busy_n (busy_n), |
.transm_complete (trans_complete ), |
.crc_ok (crc_ok), |
.ack_transfer (ack_transfer), |
.Dat_Int_Status (bd_int_st_w), |
.Dat_Int_Status_rst (Bd_isr_reset), |
.CIDAT (cidat_w) |
); |
|
wire [31:0] data_out_tx_fifo; |
SD_DATA_SERIAL_HOST SD_DATA_SERIAL_HOST_1( |
.sd_clk (sd_clk_o), |
.rst (wb_rst_i | software_reset_reg[0]), |
.data_in (data_out_tx_fifo), |
.rd (rd), |
.data_out (data_in_rx_fifo), |
.we (we_rx), |
.DAT_oe_o (sd_dat_oe_o), |
.DAT_dat_o (sd_dat_out_o), |
.DAT_dat_i (sd_dat_dat_i), |
.start_dat (start_dat_t), |
.ack_transfer (ack_transfer), |
.busy_n (busy_n), |
.transm_complete (trans_complete ), |
.crc_ok (crc_ok) |
); |
|
|
SD_Bd rx_bd |
( |
.clk (wb_clk_i), |
.rst (wb_rst_i | software_reset_reg[0]), |
.we_m (we_m_rx_bd), |
.re_m (re_m_rx_bd), |
.dat_in_m (dat_in_m_rx_bd), |
.dat_out_m (dat_out_m_rx_bd), |
.free_bd (free_bd_rx_bd), |
|
.re_s (re_s_rx_bd), |
.ack_o_s (ack_o_s_rx), |
.a_cmp (a_cmp_rx_bd), |
.dat_out_s (dat_out_s_rx_bd) |
|
); |
|
SD_Bd tx_bd |
( |
.clk (wb_clk_i), |
.rst (wb_rst_i | software_reset_reg[0]), |
.we_m (we_m_tx_bd), |
.re_m (re_m_tx_bd), |
.dat_in_m (dat_in_m_tx_bd), |
.dat_out_m (dat_out_m_tx_bd), |
.free_bd (free_bd_tx_bd), |
|
.ack_o_s (ack_o_s_tx), |
.re_s (re_s_tx_bd), |
.a_cmp (a_cmp_tx_bd), |
.dat_out_s (dat_out_s_tx_bd) |
|
); |
|
|
SD_FIFO_TX_FILLER FIFO_filer_tx ( |
.clk (wb_clk_i), |
.rst (wb_rst_i | software_reset_reg[0]), |
.m_wb_adr_o (m_wb_adr_o_tx), |
|
.m_wb_we_o (m_wb_we_o_tx), |
|
.m_wb_dat_i (m_wb_dat_i), |
.m_wb_cyc_o (m_wb_cyc_o_tx), |
.m_wb_stb_o (m_wb_stb_o_tx), |
.m_wb_ack_i ( m_wb_ack_i), |
.en (start_w), |
.adr (sys_adr), |
.sd_clk (sd_clk_o), |
.dat_o (data_out_tx_fifo ), |
.rd ( rd ), |
.empty (tx_e), |
.fe (tx_f) |
); |
|
SD_FIFO_RX_FILLER FIFO_filer_rx ( |
.clk (wb_clk_i), |
.rst (wb_rst_i | software_reset_reg[0]), |
.m_wb_adr_o (m_wb_adr_o_rx), |
|
.m_wb_we_o (m_wb_we_o_rx), |
.m_wb_dat_o (m_wb_dat_o), |
.m_wb_cyc_o (m_wb_cyc_o_rx), |
.m_wb_stb_o (m_wb_stb_o_rx), |
.m_wb_ack_i ( m_wb_ack_i), |
.en (start_r), |
.adr (sys_adr), |
.sd_clk (sd_clk_o), |
.dat_i (data_in_rx_fifo ), |
.wr ( we_rx ), |
.full (full_rx) |
|
); |
|
SD_CONTROLLER_WB SD_CONTROLLER_WB0 |
( |
.wb_clk_i(wb_clk_i), |
.wb_rst_i(wb_rst_i), |
.wb_dat_i(wb_dat_i), |
.wb_dat_o(wb_dat_o), |
.wb_adr_i(wb_adr_i[7:0]), |
.wb_sel_i(wb_sel_i), |
.wb_we_i(wb_we_i), |
.wb_stb_i(wb_stb_i), |
.wb_cyc_i(wb_cyc_i), |
.wb_ack_o(wb_ack_o), |
|
.we_m_tx_bd( we_m_tx_bd ), |
.re_m_tx_bd( re_m_tx_bd ), |
.new_cmd( new_cmd ), |
.we_m_rx_bd( we_m_rx_bd ) , |
.re_m_rx_bd( re_m_rx_bd ) , |
|
.we_ack( we_ack ) , |
.int_ack( int_ack ) , |
.cmd_int_busy( cmd_int_busy ) , |
.Bd_isr_reset( Bd_isr_reset ) , |
.normal_isr_reset( normal_isr_reset ) , |
.error_isr_reset( error_isr_reset ) , |
.int_busy( int_busy ) , |
.dat_in_m_tx_bd( dat_in_m_tx_bd ) , |
.dat_in_m_rx_bd( dat_in_m_rx_bd ) , |
.write_req_s( write_req_s ) , |
.cmd_set_s( cmd_set_s ) , |
.cmd_arg_s( cmd_arg_s ) , |
.argument_reg( argument_reg ) , |
.cmd_setting_reg( cmd_setting_reg ) , |
.status_reg( status_reg ) , |
.cmd_resp_1( cmd_resp_1 ) , |
.software_reset_reg( software_reset_reg ) , |
.time_out_reg( time_out_reg ) , |
.normal_int_status_reg( normal_int_status_reg ) , |
.error_int_status_reg( error_int_status_reg ) , |
.normal_int_signal_enable_reg( normal_int_signal_enable_reg ) , |
.error_int_signal_enable_reg( error_int_signal_enable_reg ) , |
.clock_divider( clock_divider ) , |
.Bd_Status_reg( Bd_Status_reg ) , |
.Bd_isr_reg( Bd_isr_reg ) , |
.Bd_isr_enable_reg( Bd_isr_enable_reg ) |
|
); |
|
|
|
|
|
//MUX For WB master acces granted to RX or TX FIFO filler |
assign m_wb_cyc_o = start_w ? m_wb_cyc_o_tx :start_r ?m_wb_cyc_o_rx: 0; |
assign m_wb_stb_o = start_w ? m_wb_stb_o_tx :start_r ?m_wb_stb_o_rx: 0; |
//assign m_wb_dat_o = m_wb_dat_o_rx; |
assign m_wb_we_o = start_w ? m_wb_we_o_tx :start_r ?m_wb_we_o_rx: 0; |
assign m_wb_adr_o = start_w ? m_wb_adr_o_tx :start_r ?m_wb_adr_o_rx: 0; |
|
`ifdef IRQ_ENABLE |
assign int_a =normal_int_status_reg & normal_int_signal_enable_reg; |
assign int_b = error_int_status_reg & error_int_signal_enable_reg; |
assign int_c = Bd_isr_reg & Bd_isr_enable_reg; |
`endif |
|
always @ (re_s_tx_bd_w or a_cmp_tx_bd_w or re_s_rx_bd_w or a_cmp_rx_bd_w or write_req_s) begin |
re_s_tx_bd<=re_s_tx_bd_w; |
a_cmp_tx_bd <=a_cmp_tx_bd_w; |
re_s_rx_bd <=re_s_rx_bd_w; |
a_cmp_rx_bd<=a_cmp_rx_bd_w; |
end |
|
//Set Bd_Status_reg |
always @ ( free_bd_tx_bd or free_bd_rx_bd ) begin |
Bd_Status_reg[15:8]=free_bd_rx_bd; |
Bd_Status_reg[7:0]=free_bd_tx_bd; |
end |
|
always @( cmd_resp_1_w or error_int_status_reg_w or normal_int_status_reg_w ) begin |
cmd_resp_1<= cmd_resp_1_w; |
normal_int_status_reg<= normal_int_status_reg_w ; |
error_int_status_reg<= error_int_status_reg_w ; |
end |
|
always @ ( cidat_w or cmd_int_busy or status_reg_w or status_reg_busy or bd_int_st_w) begin |
status_reg[0]<= status_reg_busy; |
status_reg[15:1]<= status_reg_w[15:1]; |
status_reg[1] <= cidat_w; |
Bd_isr_reg<=bd_int_st_w; |
end |
|
//cmd_int_busy is set when an internal access to the CMD buss is granted then immidetly uppdate the status busy bit to prevent buss access to cmd |
assign status_reg_busy = cmd_int_busy ? 1'b1: status_reg_w[0]; |
|
|
|
|
|
|
endmodule |
/verilog/SD_data_host.v
1,417 → 1,411
//------------------------- |
//------------------------- |
|
|
|
|
`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 |
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 |
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 |
if (rst) begin |
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; |
last_din <=write_buf_0[3:0]; |
DAT_oe_o<=1; |
DAT_dat_o<=0; |
crc_in<= write_buf_0[3: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) |
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 |
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]; |
|
`ifdef SIM |
crc_ok<=1; |
`endif |
/* `ifdef NO_CRC_CHECK_ON_WRITE_DATA |
crc_ok<=1; |
`endif |
*/ |
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 |
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; |
last_din <=write_buf_0[3:0]; |
DAT_oe_o<=1; |
DAT_dat_o<=0; |
crc_in<= write_buf_0[3: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) |
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 |
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 |
|
|
|
/verilog/SD_FIFO_RX_Filler.v
1,97 → 1,99
`include "SD_defines.v" |
module SD_FIFO_RX_FILLER |
( |
input clk, |
input rst, |
//WB Signals |
output [31:0] m_wb_adr_o, |
|
output reg m_wb_we_o, |
|
output reg [31:0] m_wb_dat_o, |
output reg m_wb_cyc_o, |
output reg m_wb_stb_o, |
input m_wb_ack_i, |
//output [2:0] m_wb_cti_o, |
//output [1:0] m_wb_bte_o, |
|
//Data Master Control signals |
input en, |
input [31:0] adr, |
|
//Data Serial signals |
input sd_clk, |
input [`SD_BUS_W-1:0] dat_i, |
input wr, |
output full |
// |
|
); |
wire [31:0] dat_o; |
reg rd; |
reg reset_rx_fifo; |
sd_rx_fifo Rx_Fifo ( |
.d ( dat_i ), |
.wr ( wr ), |
.wclk (sd_clk), |
.q ( dat_o), |
.rd (rd), |
.full (full), |
.empty (empty), |
.mem_empt (), |
.rclk (clk), |
.rst (rst | reset_rx_fifo) |
); |
|
//reg [31:0] tmp_dat; |
reg [8:0] offset; |
assign m_wb_adr_o = adr+offset; |
//assign m_wb_dat_o = dat_o; |
reg ackd; |
always @(posedge clk or posedge rst )begin |
|
if (rst) begin |
offset<=0; |
m_wb_we_o <=0; |
m_wb_cyc_o <= 0; |
m_wb_stb_o <= 0; |
ackd<=1; |
m_wb_dat_o<=0; |
rd<=0; |
reset_rx_fifo<=1; |
end |
else if (en) begin//Start filling the TX buffer |
rd<=0; |
reset_rx_fifo<=0; |
if (!empty & ackd) begin |
rd<=1; |
|
m_wb_dat_o<=dat_o; |
m_wb_we_o <=1; |
m_wb_cyc_o <= 1; |
m_wb_stb_o <= 1; |
ackd<=0; |
|
end |
if( !ackd & m_wb_ack_i) begin |
m_wb_we_o <=0; |
m_wb_cyc_o <= 0; |
m_wb_stb_o <= 0; |
offset<=offset+`MEM_OFFSET; |
ackd<=1; |
end |
end |
else begin |
reset_rx_fifo<=1; |
rd<=0; |
offset<=0; |
m_wb_cyc_o <= 0; |
m_wb_stb_o <= 0; |
m_wb_we_o <=0; |
ackd<=1; |
end |
|
end |
endmodule |
|
|
`include "SD_defines.v" |
`include "timescale.v" |
module SD_FIFO_RX_FILLER |
( |
input clk, |
input rst, |
//WB Signals |
output [31:0] m_wb_adr_o, |
|
output reg m_wb_we_o, |
|
output reg [31:0] m_wb_dat_o, |
output reg m_wb_cyc_o, |
output reg m_wb_stb_o, |
input m_wb_ack_i, |
//output [2:0] m_wb_cti_o, |
//output [1:0] m_wb_bte_o, |
|
//Data Master Control signals |
input en, |
input [31:0] adr, |
|
//Data Serial signals |
input sd_clk, |
input [`SD_BUS_W-1:0] dat_i, |
input wr, |
output full |
// |
|
); |
wire [31:0] dat_o; |
reg rd; |
reg reset_rx_fifo; |
sd_rx_fifo Rx_Fifo ( |
.d ( dat_i ), |
.wr ( wr ), |
.wclk (sd_clk), |
.q ( dat_o), |
.rd (rd), |
.full (full), |
.empty (empty), |
.mem_empt (), |
.rclk (clk), |
.rst (rst | reset_rx_fifo) |
); |
|
//reg [31:0] tmp_dat; |
reg [8:0] offset; |
assign m_wb_adr_o = adr+offset; |
//assign m_wb_dat_o = dat_o; |
|
reg ackd; |
always @(posedge clk or posedge rst )begin |
|
if (rst) begin |
offset<=0; |
m_wb_we_o <=0; |
m_wb_cyc_o <= 0; |
m_wb_stb_o <= 0; |
ackd<=1; |
m_wb_dat_o<=0; |
rd<=0; |
reset_rx_fifo<=1; |
end |
else if (en) begin//Start filling the TX buffer |
rd<=0; |
reset_rx_fifo<=0; |
if (!empty & ackd) begin |
rd<=1; |
|
m_wb_dat_o<=#1 dat_o; |
m_wb_we_o <=#1 1; |
m_wb_cyc_o <=#1 1; |
m_wb_stb_o <=#1 1; |
ackd<=0; |
|
end |
if( !ackd & m_wb_ack_i) begin |
m_wb_we_o <=0; |
m_wb_cyc_o <= 0; |
m_wb_stb_o <= 0; |
offset<=offset+`MEM_OFFSET; |
ackd<=1; |
end |
end |
else begin |
reset_rx_fifo<=1; |
rd<=0; |
offset<=0; |
m_wb_cyc_o <= 0; |
m_wb_stb_o <= 0; |
m_wb_we_o <=0; |
ackd<=1; |
end |
|
end |
endmodule |
|
|
/verilog/SD_FIFO_TX_Filler.v
1,122 → 1,123
`include "SD_defines.v" |
module SD_FIFO_TX_FILLER |
( |
input clk, |
input rst, |
//WB Signals |
output [31:0] m_wb_adr_o, |
|
output reg m_wb_we_o, |
input [31:0] m_wb_dat_i, |
|
output reg m_wb_cyc_o, |
output reg m_wb_stb_o, |
input m_wb_ack_i, |
//output [2:0] m_wb_cti_o, |
//output [1:0] m_wb_bte_o, |
|
//Data Master Control signals |
input en, |
input [31:0] adr, |
|
|
//Data Serial signals |
input sd_clk, |
output [31:0] dat_o, |
input rd, |
output empty, |
output fe |
// |
|
); |
reg reset_tx_fifo; |
|
reg [31:0] din; |
reg wr_tx; |
reg [8:0] we; |
reg [8:0] offset; |
wire [5:0]mem_empt; |
sd_tx_fifo Tx_Fifo ( |
.d ( din ), |
.wr ( wr_tx ), |
.wclk (clk), |
.q ( dat_o), |
.rd (rd), |
.full (fe), |
.empty (empty), |
.mem_empt (mem_empt), |
.rclk (sd_clk), |
.rst (rst | reset_tx_fifo) |
); |
|
reg [3:0] t_c_buffer_0; |
reg [3:0] t_c_buffer_1; |
assign m_wb_adr_o = adr+offset; |
|
|
reg first; |
|
reg ackd; |
reg delay; |
always @(posedge clk or posedge rst )begin |
if (rst) begin |
offset <=0; |
we <= 8'h1; |
m_wb_we_o <=0; |
m_wb_cyc_o <= 0; |
m_wb_stb_o <= 0; |
wr_tx<=0; |
ackd <=1; |
delay<=0; |
reset_tx_fifo<=1; |
|
first<=1; |
din<=0; |
|
end |
else if (en) begin //Start filling the TX buffer |
reset_tx_fifo<=0; |
if (m_wb_ack_i) begin |
|
wr_tx <=1; |
din <=m_wb_dat_i; |
|
m_wb_cyc_o <= 0; |
m_wb_stb_o <= 0; |
delay<=~ delay; |
end |
|
else begin |
wr_tx <=0; |
|
end |
|
if (delay)begin |
offset<=offset+`MEM_OFFSET; |
ackd<=ackd+1; |
delay<=~ delay; |
wr_tx <=0; |
end |
if ( !m_wb_ack_i & !fe & ackd ) begin //If not full And no Ack |
m_wb_we_o <=0; |
m_wb_cyc_o <= 1; |
m_wb_stb_o <= 1; |
ackd<=0; |
end |
|
|
end |
else begin |
offset <=0; |
reset_tx_fifo<=1; |
m_wb_cyc_o <= 0; |
m_wb_stb_o <= 0; |
m_wb_we_o <=0; |
|
|
end |
end |
|
endmodule |
|
|
`include "SD_defines.v" |
`include "timescale.v" |
module SD_FIFO_TX_FILLER |
( |
input clk, |
input rst, |
//WB Signals |
output [31:0] m_wb_adr_o, |
|
output reg m_wb_we_o, |
input [31:0] m_wb_dat_i, |
|
output reg m_wb_cyc_o, |
output reg m_wb_stb_o, |
input m_wb_ack_i, |
//output [2:0] m_wb_cti_o, |
//output [1:0] m_wb_bte_o, |
|
//Data Master Control signals |
input en, |
input [31:0] adr, |
|
|
//Data Serial signals |
input sd_clk, |
output [31:0] dat_o, |
input rd, |
output empty, |
output fe |
// |
|
); |
reg reset_tx_fifo; |
|
reg [31:0] din; |
reg wr_tx; |
reg [8:0] we; |
reg [8:0] offset; |
wire [5:0]mem_empt; |
sd_tx_fifo Tx_Fifo ( |
.d ( din ), |
.wr ( wr_tx ), |
.wclk (clk), |
.q ( dat_o), |
.rd (rd), |
.full (fe), |
.empty (empty), |
.mem_empt (mem_empt), |
.rclk (sd_clk), |
.rst (rst | reset_tx_fifo) |
); |
|
reg [3:0] t_c_buffer_0; |
reg [3:0] t_c_buffer_1; |
assign m_wb_adr_o = adr+offset; |
|
|
reg first; |
|
reg ackd; |
reg delay; |
always @(posedge clk or posedge rst )begin |
if (rst) begin |
offset <=0; |
we <= 8'h1; |
m_wb_we_o <=0; |
m_wb_cyc_o <= 0; |
m_wb_stb_o <= 0; |
wr_tx<=0; |
ackd <=1; |
delay<=0; |
reset_tx_fifo<=1; |
|
first<=1; |
din<=0; |
|
end |
else if (en) begin //Start filling the TX buffer |
reset_tx_fifo<=0; |
if (m_wb_ack_i) begin |
|
wr_tx <=1; |
din <=m_wb_dat_i; |
|
m_wb_cyc_o <= 0; |
m_wb_stb_o <= 0; |
delay<=~ delay; |
end |
else begin |
wr_tx <=0; |
|
end |
|
if (delay)begin |
offset<=offset+`MEM_OFFSET; |
ackd<=~ackd; |
delay<=~ delay; |
wr_tx <=0; |
end |
|
if ( !m_wb_ack_i & !fe & ackd ) begin //If not full And no Ack |
m_wb_we_o <=0; |
m_wb_cyc_o <= 1; |
m_wb_stb_o <= 1; |
ackd<=0; |
end |
|
|
end |
else begin |
offset <=0; |
reset_tx_fifo<=1; |
m_wb_cyc_o <= 0; |
m_wb_stb_o <= 0; |
m_wb_we_o <=0; |
|
|
end |
end |
|
endmodule |
|
|
/verilog/SD_defines.v
9,7 → 9,7
//`define IRQ_ENABLE |
`define ACTEL |
|
//`define CUSTOM |
`define CUSTOM |
//`define ALTERA |
//`define XLINX |
//`define SIMULATOR |
26,10 → 26,18
|
`endif |
|
`ifdef CUSTOM |
`define NR_O_BD_4 |
`define BD_WIDTH 4 |
`define BD_SIZE 16 |
`define RAM_MEM_WIDTH_16 |
`define RAM_MEM_WIDTH 16 |
`endif |
|
`define RESEND_MAX_CNT 3 |
|
`ifdef SYN |
`define RESET_CLK_DIV 2 |
`define RESET_CLK_DIV 0 |
`define MEM_OFFSET 4 |
`endif |
|
/verilog/SD_data_master.v
4,7 → 4,7
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, |
11,7 → 11,7
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, |
41,8 → 41,8
input crc_ok, |
output reg ack_transfer, |
//status output |
output reg [7:0] bd_int_st , |
input bd_int_st_rst, |
output reg [7:0] Dat_Int_Status , |
input Dat_Int_Status_rst, |
output reg CIDAT |
|
|
238,7 → 238,7
a_cmp_tx<=0; |
a_cmp_rx<=0; |
CIDAT<=0; |
bd_int_st<=0; |
Dat_Int_Status<=0; |
we_req<=0; |
re_s_tx<=0; |
re_s_rx<=0; |
394,7 → 394,7
rec_done<=1; |
else begin |
rec_failed<=1; |
bd_int_st[4] <=1; |
Dat_Int_Status[4] <=1; |
start_tx_fifo<=0; |
end |
`endif |
423,13 → 423,13
CIDAT<=1; |
if (tx_cycle) begin |
if (tx_empt) begin |
bd_int_st[2] <=1; |
Dat_Int_Status[2] <=1; |
trans_failed<=1; |
end |
end |
else begin |
if (rx_full) begin |
bd_int_st[2] <=1; |
Dat_Int_Status[2] <=1; |
trans_failed<=1; |
end |
end |
439,12 → 439,12
ack_transfer<=1; |
|
if ((!crc_ok) && (busy_n)) begin //Wrong CRC and Data line free. |
bd_int_st[5] <=1; |
Dat_Int_Status[5] <=1; |
trans_failed<=1; |
end |
else if ((crc_ok) && (busy_n)) begin //Data Line free |
trans_done <=1; |
bd_int_st[0]<=1; |
Dat_Int_Status[0]<=1; |
if (tx_cycle) |
a_cmp_tx<=1; |
else |
471,7 → 471,7
STOP_SEND: begin |
resend_try_cnt=resend_try_cnt+1; |
if (resend_try_cnt==`RESEND_MAX_CNT) |
bd_int_st[1]<=1; |
Dat_Int_Status[1]<=1; |
if (!cmd_busy) |
we_req <= 1; |
if (we_ack) |
497,8 → 497,8
end |
|
endcase |
if (bd_int_st_rst) |
bd_int_st<=0; |
if (Dat_Int_Status_rst) |
Dat_Int_Status<=0; |
end |
|
end |