OpenCores
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

powered by: WebSVN 2.1.0

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