Verilog SPI控制器


/// 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM