摘要
本論文使用Verilog HDL硬件描述語言,結(jié)合野火可以FPGA征途Pro開發(fā)板,實現(xiàn)了SPI通信協(xié)議的全擦除,扇區(qū)擦除,讀數(shù)據(jù),頁寫,連續(xù)寫的驅(qū)動設(shè)計。在 Altera Cyclone Ⅳ 芯片上采用“自頂向下”的模塊化設(shè)計思想及 Verilog HDL 硬件描述語言,設(shè)計并實現(xiàn)串行外設(shè)接口(SPI)。在 Quartus II 13.0 軟件開發(fā)平臺上編譯、仿真后下載到 FPGA 芯片上,進行在線編程調(diào)試,實現(xiàn)了 SPI 總線通信功能?;?FPGA 的系統(tǒng)設(shè)計調(diào)試維護方便、可靠性高,而且設(shè)計具有靈活性,可以方便地進行擴展和移植。
關(guān)鍵詞:SPI;串口通信;FPGA;Verilog HDL
1 緒論
1.1研究背景
串行外設(shè)接口 (Serial peripheral interface, SPI) 是由Motorola 公司推出的一種同步串行外圍設(shè)備接口。SPI總線是一種高速、同步、全雙工的串行通信總線。SPI 總線接口只有四根外部接口線,結(jié)構(gòu)簡單、速度快、可靠性強。典型的 SPI 接口通信由四根信號線實現(xiàn),分別為:
SCS:從片選信號,邏輯 “0” 為有效狀態(tài),表示被選中與主設(shè)進行數(shù)據(jù)傳輸。
SCLK:串行時鐘線,由主設(shè)輸出,從設(shè)按照此時鐘進行數(shù)據(jù)的同步傳輸。
MOSI:數(shù)據(jù)傳輸線,由主設(shè)到從設(shè)。
MISO:數(shù)據(jù)傳輸線,由從設(shè)到主設(shè)。[1]
1.2 研究目的和意義
SPI 接口是一種全雙工、三線通信的系統(tǒng),是常用的工業(yè)標(biāo)準(zhǔn)同步串行接口,它允許主機處理器與各種外圍設(shè)備之間的通信方式是串行通信。在 SPI 接口中,主/從機之間數(shù)據(jù)的傳輸需要 1 個時鐘信號和 2 條數(shù)據(jù)線,所以 SPI 總線區(qū)分主機(Master)和從機(Slave)2 部分,結(jié)構(gòu)框圖如圖 1 所示。
主機和從機之間 SPI 總線由 4 根線構(gòu)成:①SCK。串行同步時鐘信號,用來同步主機和從機的數(shù)據(jù)傳輸,
由主機控制輸出,從機在 SCK 的邊沿接收或發(fā)送數(shù)據(jù)。②MOSI。主機輸出/從機輸入線,主機在上升沿(或下
降沿)通過該信號線發(fā)送數(shù)據(jù)給從機,從機在下降沿(或上升沿)通過該信號線接收該數(shù)據(jù)。③MISO。主
機輸入/從機輸出線,從機在上升沿(或下降沿)通過該信號線發(fā)送數(shù)據(jù)給主機,主機在下降沿(或上升沿)
通過該信號線接收該數(shù)據(jù)。④SS。從機片選信號線,它同樣是由主機控制輸出。[2]
1.2.1 SPI通信協(xié)議物理層簡介
(圖1-2-1-1:一主一從SPI通訊設(shè)備連接圖)
(Figure 1-2-1: One master and one slave SPI communication device connection diagram)
(圖1-2-1:一主多從SPI通訊設(shè)備連接圖)
(Figure 1-2-1-2: One master and multiple slave SPI communication device connection diagram)
SPI通信協(xié)議采用的是主從通信模式,通信雙方有主從之分,根據(jù)從機的設(shè)備個數(shù),SPI通信設(shè)備之間的連接方式可以分為一主一從和一主多從。
SPI通信協(xié)議包含1條時鐘信號線、2條數(shù)據(jù)總線和1條片選信號線,時鐘信號線為SCK、2條數(shù)據(jù)總線為MOSI和MISO,片選信號線為CS。它們的作用介紹如下:
1.SCK(Serial Clock) : 時鐘信號線,用于同步通信數(shù)據(jù)。由通信主機產(chǎn)生,決定了通信的速率,不同的設(shè)備支持的最高時鐘頻率不同,兩個設(shè)備通信時通信速率受限于低速設(shè)備。
2.MOSI(MasterOutput ,Slave Input) : 主設(shè)備輸出/從設(shè)備輸入引腳。主機的數(shù)據(jù)從這條信號線輸出,從機從這條信號線讀入主機發(fā)送的數(shù)據(jù),數(shù)據(jù)方向由主機到從機。
3.MISO(Master Input , Slave Output) : 主設(shè)備輸入/從設(shè)備輸出引腳。主機從這條信號線讀入數(shù)據(jù),從機的數(shù)據(jù)由這條信號線輸入到主機,數(shù)據(jù)方向由從機到主機。
。CS(Chip Select) : 片選信號線,也稱為CS_N。當(dāng)有多個從設(shè)備與主機相連時,設(shè)備的其他數(shù)據(jù)信號線SCK、MOSI、MISO同時并聯(lián)到相同的SPI總線上,即無論有多少從設(shè)備都使用這三條總線,每個從設(shè)備都有一條獨立的CS_N信號線,本數(shù)據(jù)線獨占主機的一個引腳,既有多少個從設(shè)備就有多少個片選信號線。I2C協(xié)議中通過設(shè)備地址來尋址,選中總線上的某個設(shè)備并與其進行通信;而SPI協(xié)議中沒有設(shè)備地址,它使用CS_N信號線來尋址,當(dāng)主機要選擇從設(shè)備時,把該設(shè)備的CS_N信號線設(shè)置為低電平,該設(shè)備即被選中,即片選信號有效,接著主機開始與被選中的從設(shè)備進行SPI通信。所以SPI通信以CS_N信號線置為低電平為開始信號,以CS_N信號線拉高為結(jié)束信號。
1.2.2 SPI 協(xié)議層
SPI通信協(xié)議一共有4種通信模式:模式0、模式1、模式2、模式3.這四種模式分由時鐘極性(CPLD,Clock Polarity)和時鐘相位(CPHA,ClockPhase)來定義,其中CPOL參數(shù)規(guī)定了空閑狀態(tài)(CS_N為高電平,設(shè)備未被選中時SCK時鐘信號的電平狀態(tài),CPHA規(guī)定了數(shù)據(jù)采樣是在SCK時鐘奇數(shù)邊沿還是偶數(shù)邊沿。
1.2.3 設(shè)計SPI總線接口要求
設(shè)計的 SPI 總線接口完成工作有:①將主機收到的 16 位并行數(shù)據(jù)轉(zhuǎn)換為串行數(shù)據(jù),并發(fā)送給從機;
②接收來自從機的串行數(shù)據(jù),將其轉(zhuǎn)換為并行數(shù)據(jù),通過并行端口輸出;③輸出從機所需要的輸入信號、
時鐘信號 SCK 和片選信號 SS
1.3 國內(nèi)外研究現(xiàn)狀(SPI接口的發(fā)展)
SPI 接口最早是由美國的Motorola 公司所定義的,它的中文名稱叫做串行外設(shè)接口,用于 Motorola 公司自己研發(fā)的產(chǎn)品之中。SPI 接口可以作為通信的橋梁,連接 CPU 等控制設(shè)備和外圍設(shè)備。SPI 接口能夠以串行、同步、高速的特點來傳輸通信數(shù)據(jù),具有簡單易用、節(jié)省面積等優(yōu)點,因此具有越來越廣泛的用途,并且逐漸應(yīng)用到其他場景,比如 SD 卡、液晶顯示屏、射頻通信卡等。傳統(tǒng)的 SPI 接口可以連接控制設(shè)備和外圍設(shè)備進行全雙工通信,隨著通信場景的需求,會引入設(shè)計半雙工、單工等通信方式,會根據(jù)功能設(shè)計更多的寄存器進行控制。在規(guī)模一般的芯片設(shè)計中,可能僅簡單設(shè)計 SPI 接口、滿足基本通信需求即可,但是在芯片性能不斷發(fā)展的今天,在設(shè)計 SPI 接口時需要考慮到 SPI 能否與其他各 IP 進行高效的通信與交互,能否在芯片 IP 復(fù)雜化的同時可以盡量復(fù)用之前的設(shè)計,能否適應(yīng)芯片設(shè)計中新的功能點和需求點。SPI 接口設(shè)計好后,會進行功能點的驗證。如果以傳統(tǒng)的 Verilog 語言驗證SPI,需要編寫大量激勵文件,以眾多定向驗證覆蓋到功能點。如果以單純的System Verilog 語言驗證SPI,可以實現(xiàn)隨機化的激勵輸入,達到高效的驗證,但是驗證平臺環(huán)境不容易得到復(fù)用,在項目迭代中具有一定的麻煩。所以需要尋求既可以高效驗證 SPI 功能點,又可以高效搭建實現(xiàn)驗證平臺環(huán)境的方式。[3]
1.4 研究內(nèi)容
1.5 研究方法及技術(shù)路線
2 設(shè)計SPI-FLASH全擦除實驗?zāi)K
2.1 設(shè)計SPI總線接口要求
2.2 設(shè)計SPI接口模塊結(jié)構(gòu)
2.3 SPI接口的子模塊設(shè)計
2.3.1 通訊模塊
2.3.2 控制模塊
2.3.3 FIFO模塊
2.3.4 數(shù)據(jù)收發(fā)模塊
2.4 設(shè)計過程波形圖繪制及各信號產(chǎn)生原因解析
2.5 設(shè)計的仿真、綜合與實現(xiàn)
module key_filter
#(
parameter CNT_20MS_MAX = 20'd999_999
)
(
input wire sys_clk ,
input wire sys_rst_n ,
input wire key_in ,
output reg key_flag
);
reg [19:0] cnt_20ms;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_20ms <= 20'd0;
else if(key_in == 1'b1)
cnt_20ms <= 20'd0;
else if(cnt_20ms == CNT_20MS_MAX && key_in == 1'b0)
cnt_20ms <= CNT_20MS_MAX;
else if(key_in == 1'b0)
cnt_20ms <= cnt_20ms + 20'd1;
else
cnt_20ms <= cnt_20ms;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
key_flag <= 1'b0;
else if(cnt_20ms == CNT_20MS_MAX - 20'd1)
key_flag <= 1'b1;
else
key_flag <= 1'b0;
endmodule
文章來源:http://www.zghlxwxcb.cn/news/detail-659271.html
module flash_be_ctrl
(
input wire sys_clk ,
input wire sys_rst_n ,
input wire key_flag ,
output reg cs_n ,
output reg sck ,
output reg mosi
);
parameter CNT_CLK_MAX = 5'd31;
parameter CNT_BYTE_MAX = 3'd6;
parameter CNT_SCK_MAX = 2'd3;
parameter CNT_BIT_MAX = 3'd7;
parameter IDLE = 4'b0001,
WREN = 4'b0010,
DELAY = 4'b0100,
BE = 4'b1000;
parameter WREN_IN = 8'b0000_0110;
parameter BE_IN = 8'b1100_0111;
reg [3:0] state;
reg [4:0] cnt_clk;
reg [2:0] cnt_byte;
reg [1:0] cnt_sck;
reg [2:0] cnt_bit;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
state <= IDLE;
else
case(state)
IDLE:
if(key_flag == 1'b1)
state <= WREN;
else
state <= IDLE;
WREN:
if(cnt_clk == CNT_CLK_MAX && cnt_byte == 3'd2)
state <= DELAY;
else
state <=WREN;
DELAY:
if(cnt_clk == CNT_CLK_MAX && cnt_byte == 3'd3)
state <= BE;
else
state <=DELAY;
BE :
if(cnt_clk == CNT_CLK_MAX && cnt_byte == CNT_BYTE_MAX)
state <= IDLE;
else
state <=BE;
default:state <= IDLE;
endcase
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_clk <= 5'd0;
else
case(state)
IDLE :cnt_clk <= 5'd0;
WREN :cnt_clk <= cnt_clk + 5'd1;//溢出清零
DELAY:cnt_clk <= cnt_clk + 5'd1;//溢出清零
BE :cnt_clk <= cnt_clk + 5'd1;//溢出清零
default:cnt_clk <= cnt_clk;
endcase
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_byte <= 3'd0;
else if(cnt_clk == CNT_CLK_MAX && cnt_byte == CNT_BYTE_MAX)
cnt_byte <= 3'd0;
else if(cnt_clk == CNT_CLK_MAX)
cnt_byte <= cnt_byte + 3'd1;
else
cnt_byte <= cnt_byte;
always@(posedge sys_clk or negedge sys_rst_n)//不同
if(sys_rst_n == 1'b0)
cnt_sck <= 2'd0;
else if((cnt_byte == 3'd1 || cnt_byte == 3'd5) && (cnt_sck == CNT_SCK_MAX))
cnt_sck <= 2'd0;
else if(cnt_byte == 3'd1 || cnt_byte == 3'd5)
cnt_sck <= cnt_sck + 2'd1;
else
cnt_sck <= 2'd0;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_bit <= 3'd0;
else if(cnt_sck == 2'd2 && cnt_bit == CNT_BIT_MAX)
cnt_bit <= 3'd0;
else if(cnt_sck == 2'd2)
cnt_bit <= cnt_bit + 3'd1;
else
cnt_bit <= cnt_bit;
/* always@(*)
case(state)
IDLE :cs_n <= 1'b1;
WREN :cs_n <= 1'b0;
DELAY:cs_n <= 1'b1;
BE :cs_n <= 1'b0;
default:cs_n <= 1'b1;
endcase */
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cs_n <= 1'b1;
else if(key_flag == 1'b1)
cs_n <= 1'b0;
else if(state == WREN && cnt_clk == CNT_CLK_MAX && cnt_byte == 3'd2)
cs_n <= 1'b1;
else if(state == DELAY && cnt_clk == CNT_CLK_MAX && cnt_byte == 3'd3)
cs_n <= 1'b0;
else if(state == BE && cnt_clk == CNT_CLK_MAX && cnt_byte == 3'd6)
cs_n <= 1'b1;
else
cs_n <= cs_n;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
sck <= 1'b0;
else if(cnt_sck == 2'd0)
sck <= 1'b0;
else if(cnt_sck == 2'd2)
sck <= 1'b1;
else
sck <= sck;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
mosi <= 1'b0;
else if(state == WREN && cnt_byte == 3'd2)
mosi <= 1'b0;
else if(state == BE && cnt_byte == 3'd6)
mosi <= 1'b0;
else if(state == WREN && cnt_byte == 3'd1 && cnt_sck == 2'd0)
mosi <= WREN_IN[7 - cnt_bit];
else if(state == BE && cnt_byte == 3'd5 && cnt_sck == 2'd0)
mosi <= BE_IN[7 - cnt_bit];
else
mosi <= mosi;
endmodule
module spi_flash_be
(
input wire sys_clk ,
input wire sys_rst_n ,
input wire key_in ,
output wire cs_n ,
output wire sck ,
output wire mosi
);
wire key_flag;
key_filter
#(
.CNT_20MS_MAX(20'd999_999)
)
key_filter_inst
(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n),
.key_in (key_in ),
.key_flag (key_flag )
);
flash_be_ctrl flash_be_ctrl_inst
(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n),
.key_flag (key_flag ),
.cs_n (cs_n ),
.sck (sck ),
.mosi (mosi )
);
endmodule
`timescale 1ns/1ns
module tb_flash_be_ctrl();
reg sys_clk ;
reg sys_rst_n ;
reg key_flag ;
wire cs_n ;
wire sck ;
wire mosi ;
initial
begin
sys_clk <= 1'b1;
sys_rst_n <= 1'b0;
key_flag <= 1'b0;
#20
sys_rst_n <= 1'b1;
#200
key_flag <= 1'b1;
#20
key_flag <= 1'b0;
end
always #10 sys_clk <= ~sys_clk;
defparam memory.mem_access.initfile = "initmemory.txt";
flash_be_ctrl flash_be_ctrl_inst
(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n),
.key_flag (key_flag ),
.cs_n (cs_n ),
.sck (sck ),
.mosi (mosi )
);
m25p16 memory
(
.c (sck ),
.data_in (mosi ),
.s (cs_n ),
.w (1'b1 ),
.hold (1'b1 ),
.data_out ( )
);
endmodule
2.5 模塊小結(jié)
參考文獻
[1]蔣國慶,顧軍.基于FPGA的LPC總線轉(zhuǎn)多路SPI總線設(shè)計[J].電子質(zhì)量,2022(10):39-45.
[2]楊梓鶴,彭秋雨,李湛藝,程曉迪.SPI接口仿真設(shè)計與實現(xiàn)[J].科技與創(chuàng)新,2022(19):121-123+126.DOI:10.15913/j.cnki.kjycx.2022.19.038.
[3]王大為. 基于UVM的SPI接口IP核的設(shè)計與驗證[D].北方工業(yè)學(xué),2022.DOI:10.26926/d.cnki.gbfgu.2022.000608.文章來源地址http://www.zghlxwxcb.cn/news/detail-659271.html
到了這里,關(guān)于FPGA實現(xiàn)基于SPI協(xié)議的Flash驅(qū)動控制(全擦除、頁擦除、讀數(shù)據(jù)、頁寫、連續(xù)寫—地址寫)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!