/// top file
`timescale 1ns / 1ps
////////////////////////////////////////////////////////////////////////////////
module sdcard_ctrl(
clk,rst_n,
spi_miso,spi_mosi,spi_clk,spi_cs_n,
sd_dout,sd_fifowr,sdwrad_clr
);
input clk;//FPAG輸入時鍾信號25MHz
input rst_n;//FPGA輸入復位信號
input spi_miso;//SPI主機輸入從機輸出數據信號
output spi_mosi;//SPI主機輸出從機輸入數據信號
output spi_clk;//SPI時鍾信號,由主機產生
output spi_cs_n;//SPI從設備使能信號,由主設備控制
output[7:0] sd_dout;//從SD讀出的待放入FIFO數據
output sd_fifowr;//sd讀出數據寫入FIFO使能信號,高有效
output sdwrad_clr;//SDRAM寫控制相關信號清零復位信號,高有效
//output[3:0] led;//調試使用
//----------------------------------------------------------------
wire spi_tx_en;//SPI數據發送使能信號,高有效
wire spi_tx_rdy;//SPI數據發送完成標志位,高有效
wire spi_rx_en;//SPI數據接收使能信號,高有效
wire spi_rx_rdy;//SPI數據接收完成標志位,高有效
wire[7:0] spi_tx_db;//SPI數據發送寄存器
wire[7:0] spi_rx_db;//SPI數據接收寄存器
//----------------------------------------------------------------
//例化SPI傳輸控制模塊
spi_ctrluut_spictrl(
.clk(clk),
.rst_n(rst_n),
.spi_miso(spi_miso),
.spi_mosi(spi_mosi),
.spi_clk(spi_clk),
.spi_tx_en(spi_tx_en),
.spi_tx_rdy(spi_tx_rdy),
.spi_rx_en(spi_rx_en),
.spi_rx_rdy(spi_rx_rdy),
.spi_tx_db(spi_tx_db),
.spi_rx_db(spi_rx_db)
);
//例化SD命令控制模塊
sd_ctrluut_sdctrl(
.clk(clk),
.rst_n(rst_n),
.spi_cs_n(spi_cs_n),
.spi_tx_en(spi_tx_en),
.spi_tx_rdy(spi_tx_rdy),
.spi_rx_en(spi_rx_en),
.spi_rx_rdy(spi_rx_rdy),
.spi_tx_db(spi_tx_db),
.spi_rx_db(spi_rx_db),
.sd_dout(sd_dout),
.sd_fifowr(sd_fifowr),
.sdwrad_clr(sdwrad_clr)
);
endmodule
// SPI讀寫時序
`timescale 1ns / 1ps
////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: 特權 franchises3
// Create Date: 2009.05.05
// Design Name:
// Module Name: spi_ctrl
// Project Name: sdrsvgaprj
// Target Device: Cyclone EP1C3T144C8
// Tool versions: Quartus II 8.1
// Description:
//
// Revision: V1.0
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////
module spi_ctrl(
clk,rst_n,
spi_miso,spi_mosi,spi_clk,
spi_tx_en,spi_tx_rdy,spi_rx_en,spi_rx_rdy,spi_tx_db,spi_rx_db
);
input clk;//FPAG輸入時鍾信號25MHz
input rst_n;//FPGA輸入復位信號
input spi_miso;//SPI主機輸入從機輸出數據信號
output spi_mosi;//SPI主機輸出從機輸入數據信號
output spi_clk;//SPI時鍾信號,由主機產生
input spi_tx_en;//SPI數據發送使能信號,高有效
output spi_tx_rdy;//SPI數據發送完成標志位,高有效
input spi_rx_en;//SPI數據接收使能信號,高有效
output spi_rx_rdy;//SPI數據接收完成標志位,高有效
input[7:0] spi_tx_db;//SPI數據發送寄存器
output[7:0] spi_rx_db;//SPI數據接收寄存器
//模擬SPI的時序模式為CPOL=1, CPHA=1,模擬速率為25Mbit
//-------------------------------------------------
//SPI時序控制計數器,所有SPI時序由該計數器值控制
reg[4:0] cnt8;//SPI時序控制計數器,計數范圍在0-18
always @(posedge clk or negedge rst_n)
if(!rst_n) cnt8 <= 5'd0;
else if(spi_tx_en || spi_rx_en) begin
if(cnt8 < 5'd18)cnt8 <= cnt8+1'b1;//SPI工作使能
else ;//計數到18停止,等待撤銷spi使能
end
else cnt8 <= 5'd0;//SPI關閉,計數停止
//-------------------------------------------------
//SPI時鍾信號產生
reg spi_clkr;//SPI時鍾信號,由主機產生
always @(posedge clk or negedge rst_n)
if(!rst_n) spi_clkr <= 1'b1;
else if(cnt8 > 5'd1 && cnt8 < 5'd18) spi_clkr <= ~spi_clkr;//在cnt8處於2-17時SPI時鍾有效翻轉
assign spi_clk = spi_clkr;
//-------------------------------------------------
//SPI主機輸出數據控制
reg spi_mosir;//SPI主機輸出從機輸入數據信號
always @(posedge clk or negedge rst_n)
if(!rst_n) spi_mosir <= 1'b1;
else if(spi_tx_en) begin
case(cnt8[4:1])//主機發送8bit數據
4'd1: spi_mosir <= spi_tx_db[7];//發送bit7
4'd2: spi_mosir <= spi_tx_db[6];//發送bit6
4'd3: spi_mosir <= spi_tx_db[5];//發送bit5
4'd4: spi_mosir <= spi_tx_db[4];//發送bit4
4'd5: spi_mosir <= spi_tx_db[3];//發送bit3
4'd6: spi_mosir <= spi_tx_db[2];//發送bit2
4'd7: spi_mosir <= spi_tx_db[1];//發送bit1
4'd8: spi_mosir <= spi_tx_db[0];//發送bit0
default: spi_mosir <= 1'b1;//spi_mosi沒有輸出時應保持高電平
endcase
end
else spi_mosir <= 1'b1;//spi_mosi沒有輸出時應保持高電平
assign spi_mosi = spi_mosir;
//-------------------------------------------------
//SPI主機輸入數據控制
reg[7:0] spi_rx_dbr;//SPI主機輸入從機輸出數據總線寄存器
always @(posedge clk or negedge rst_n)
if(!rst_n) spi_rx_dbr <= 8'hff;
else if(spi_rx_en) begin
case(cnt8)//主機接收並鎖存8bit數據
5'd3: spi_rx_dbr[7] <= spi_miso;//接收bit7
5'd5: spi_rx_dbr[6] <= spi_miso;//接收bit6
5'd7: spi_rx_dbr[5] <= spi_miso;//接收bit5
5'd9: spi_rx_dbr[4] <= spi_miso;//接收bit4
5'd11: spi_rx_dbr[3] <= spi_miso;//接收bit3
5'd13: spi_rx_dbr[2] <= spi_miso;//接收bit2
5'd15: spi_rx_dbr[1] <= spi_miso;//接收bit1
5'd17: spi_rx_dbr[0] <= spi_miso;//接收bit0
default: ;
endcase
end
assign spi_rx_db = spi_rx_dbr;
//-------------------------------------------------
//SPI數據發送完成標志位,高有效
assign spi_tx_rdy = (cnt8 == 5'd18)/* & spi_tx_en)*/;
//-------------------------------------------------
//SPI數據接收完成標志位,高有效
assign spi_rx_rdy = (cnt8 == 5'd18)/* & spi_rx_en)*/;
endmodule