日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

FPGA实现SPI 协议

發(fā)布時(shí)間:2023/12/20 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 FPGA实现SPI 协议 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

SPI 協(xié)議是由摩托羅拉公司提出的通訊協(xié)議(Serial Peripheral Interface),即串行外圍設(shè)備接口,是一種高速全雙工的通信總線(xiàn)。它被廣泛地使用在 ADC、LCD 等設(shè)備與 MCU 間,要求通訊速率較高的場(chǎng)合。

SPI 通訊設(shè)備之間的常用連接方式見(jiàn)圖 1。

SPI 通訊使用3 條總線(xiàn)及片選線(xiàn),3 條總線(xiàn)分別為SCK、MOSI、MISO,片選線(xiàn)為 SS
,它們的作用介紹如下:
(1) SS ( Slave Select):從設(shè)備選擇信號(hào)線(xiàn),常稱(chēng)為片選信號(hào)線(xiàn),也稱(chēng)為NSS、CS,以下用NSS 表示。當(dāng)有多個(gè)SPI 從設(shè)備與SPI 主機(jī)相連時(shí),設(shè)備的其它信號(hào)線(xiàn)SCK、MOSI及MISO 同時(shí)并聯(lián)到相同的SPI 總線(xiàn)上,即無(wú)論有多少個(gè)從設(shè)備,都共同只使用這3 條總線(xiàn);而每個(gè)從設(shè)備都有獨(dú)立的這一條NSS 信號(hào)線(xiàn),本信號(hào)線(xiàn)獨(dú)占主機(jī)的一個(gè)引腳,即有多少個(gè)從設(shè)備,就有多少條片選信號(hào)線(xiàn)。I2C 協(xié)議中通過(guò)設(shè)備地址來(lái)尋址、選中總線(xiàn)上的某個(gè)設(shè)備并與其進(jìn)行通訊;而SPI 協(xié)議中沒(méi)有設(shè)備地址,它使用NSS 信號(hào)線(xiàn)
來(lái)尋址,當(dāng)主機(jī)要選擇從設(shè)備時(shí),把該從設(shè)備的NSS 信號(hào)線(xiàn)設(shè)置為低電平,該從設(shè)備即被選中,即片選有效,接著主機(jī)開(kāi)始與被選中的從設(shè)備進(jìn)行SPI 通訊。所以SPI 通訊以NSS 線(xiàn)置低電平為開(kāi)始信號(hào),以NSS 線(xiàn)被拉高作為結(jié)束信號(hào)。
(2) SCK (Serial Clock):時(shí)鐘信號(hào)線(xiàn),用于通訊數(shù)據(jù)同步。它由通訊主機(jī)產(chǎn)生,決定了通訊的速率,不同的設(shè)備支持的最高時(shí)鐘頻率不一樣,如STM32 的SPI 時(shí)鐘頻率最大為fpclk/2,兩個(gè)設(shè)備之間通訊時(shí),通訊速率受限于低速設(shè)備。
(3) MOSI (Master Output, Slave Input):主設(shè)備輸出/從設(shè)備輸入引腳。主機(jī)的數(shù)據(jù)從這條信號(hào)線(xiàn)輸出,從機(jī)由這條信號(hào)線(xiàn)讀入主機(jī)發(fā)送的數(shù)據(jù),即這條線(xiàn)上數(shù)據(jù)的方向?yàn)橹鳈C(jī)到從機(jī)。
(4) MISO(Master Input,,Slave Output):主設(shè)備輸入/從設(shè)備輸出引腳。主機(jī)從這條信號(hào)線(xiàn)讀入數(shù)據(jù),從機(jī)的數(shù)據(jù)由這條信號(hào)線(xiàn)輸出到主機(jī),即在這條線(xiàn)上數(shù)據(jù)的方向?yàn)閺臋C(jī)到主機(jī)。

協(xié)議層
與I2C 的類(lèi)似,SPI 協(xié)議定義了通訊的起始和停止信號(hào)、數(shù)據(jù)有效性、時(shí)鐘同步等環(huán)節(jié)。
SPI 基本通訊過(guò)程先看看SPI 通訊的通訊時(shí)序,見(jiàn)圖 2。

這是一個(gè)主機(jī)的通訊時(shí)序。NSS、SCK、MOSI 信號(hào)都由主機(jī)控制產(chǎn)生,而MISO 的信號(hào)由從機(jī)產(chǎn)生,主機(jī)通過(guò)該信號(hào)線(xiàn)讀取從機(jī)的數(shù)據(jù)。MOSI 與MISO 的信號(hào)只在NSS 為低電平的時(shí)候才有效,在SCK 的每個(gè)時(shí)鐘周期MOSI 和MISO 傳輸一位數(shù)據(jù)。以上通訊流程中包含的各個(gè)信號(hào)分解如下:
3. 通訊的起始和停止信號(hào)
在圖 2 中的標(biāo)號(hào)處,NSS 信號(hào)線(xiàn)由高變低,是SPI 通訊的起始信號(hào)。NSS 是每個(gè)從機(jī)各自獨(dú)占的信號(hào)線(xiàn),當(dāng)從機(jī)在自己的NSS 線(xiàn)檢測(cè)到起始信號(hào)后,就知道自己被主機(jī)選中了,開(kāi)始準(zhǔn)備與主機(jī)通訊。在圖中的標(biāo)號(hào)?處,NSS 信號(hào)由低變高,是SPI 通訊的停止信號(hào),表示本次通訊結(jié)束,從機(jī)的選中狀態(tài)被取消。
4. 數(shù)據(jù)有效性
SPI 使用MOSI 及MISO 信號(hào)線(xiàn)來(lái)傳輸數(shù)據(jù),使用SCK信號(hào)線(xiàn)進(jìn)行數(shù)據(jù)同步。MOSI 及MISO 數(shù)據(jù)線(xiàn)在SCK 的每個(gè)時(shí)鐘周期傳輸一位數(shù)據(jù),且數(shù)據(jù)輸入輸出是同時(shí)進(jìn)行的。數(shù)據(jù)傳輸時(shí),MSB 先行或LSB 先行并沒(méi)有作硬性規(guī)定,但要保證兩個(gè)SPI 通訊設(shè)備之間使用同樣的協(xié)定,一般都會(huì)采用圖 2 中的MSB 先行模式。MOSI 及MISO 的數(shù)據(jù)在SCK的上升沿期間變化輸出,在SCK 的下降沿時(shí)被采樣。即在SCK 的下降沿時(shí)刻,MOSI 及MISO 的數(shù)據(jù)有效,高電平時(shí)表示數(shù)據(jù)“1”,為低電平時(shí)表示數(shù)據(jù)“0”。在其它時(shí)刻,數(shù)據(jù)無(wú)效,MOSI 及MISO 為下一次表示數(shù)據(jù)做準(zhǔn)備。SPI 每次數(shù)據(jù)傳輸可以8 位或16 位為單位,每次傳輸?shù)膯挝粩?shù)不受限制。
5. CPOL/CPHA 及通訊模式
上面講述的圖 25-2 中的時(shí)序只是SPI 中的其中一種通訊模式,SPI 一共有四種通訊模式,它們的主要區(qū)別是總線(xiàn)空閑時(shí)SCK 的時(shí)鐘狀態(tài)以及數(shù)據(jù)采樣時(shí)刻。為方便說(shuō)明,在此引入“時(shí)鐘極性CPOL”和“時(shí)鐘相位CPHA”的概念。時(shí)鐘極性CPOL 是指SPI 通訊設(shè)備處于空閑狀態(tài)時(shí),SCK 信號(hào)線(xiàn)的電平信號(hào)(即SPI 通
訊開(kāi)始前、 NSS 線(xiàn)為高電平時(shí)SCK 的狀態(tài))。CPOL=0 時(shí), SCK 在空閑狀態(tài)時(shí)為低電平,CPOL=1 時(shí),則相反。時(shí)鐘相位CPHA 是指數(shù)據(jù)的采樣的時(shí)刻,當(dāng)CPHA=0 時(shí),MOSI 或MISO 數(shù)據(jù)線(xiàn)上的信號(hào)將會(huì)在SCK 時(shí)鐘線(xiàn)的“奇數(shù)邊沿”被采樣。當(dāng)CPHA=1 時(shí),數(shù)據(jù)線(xiàn)在SCK 的“偶數(shù)邊沿”采樣。見(jiàn)圖 3 及圖 4。

我們來(lái)分析這個(gè)CPHA=0 的時(shí)序圖。首先,根據(jù)SCK在空閑狀態(tài)時(shí)的電平,分為兩種情況。SCK 信號(hào)線(xiàn)在空閑狀態(tài)為低電平時(shí),CPOL=0;空閑狀態(tài)為高電平時(shí),CPOL=1。無(wú)論CPOL=0 還是=1,因?yàn)槲覀兣渲玫臅r(shí)鐘相位CPHA=0,在圖中可以看到,采樣時(shí)刻都是在SCK 的奇數(shù)邊沿。注意當(dāng)CPOL=0 的時(shí)候,時(shí)鐘的奇數(shù)邊沿是上升沿,而CPOL=1 的時(shí)候,時(shí)鐘的奇數(shù)邊沿是下降沿。所以SPI 的采樣時(shí)刻不是由上升/下降沿決定的。MOSI 和MISO 數(shù)據(jù)線(xiàn)的有效信號(hào)在SCK 的奇數(shù)邊沿保持不變,數(shù)據(jù)信號(hào)將在SCK 奇數(shù)邊沿時(shí)被采樣,在非采樣時(shí)刻,MOSI 和MISO 的有效信號(hào)才發(fā)生切換。類(lèi)似地,當(dāng)CPHA=1 時(shí),不受CPOL 的影響,數(shù)據(jù)信號(hào)在SCK的偶數(shù)邊沿被采樣,見(jiàn)圖 4。

圖 4 CPHA=1 時(shí)的SPI 通訊模式
由CPOL 及CPHA 的不同狀態(tài),SPI 分成了四種模式,見(jiàn)表 1,主機(jī)與從機(jī)需要工
作在相同的模式下才可以正常通訊,實(shí)際中采用較多的是“模式0”與“模式3”。
表 1 SPI 的四種模式
SPI 模式 CPOL CPHA 空閑時(shí)SCK 時(shí)鐘 采樣時(shí)刻
0 0 0 低電平 奇數(shù)邊沿
1 0 1 低電平 偶數(shù)邊沿
2 1 0 高電平 奇數(shù)邊沿
3 1 1 高電平 偶數(shù)邊沿

3 FPGA實(shí)現(xiàn)從機(jī)收發(fā)SPI數(shù)據(jù)

在實(shí)現(xiàn)SPI時(shí)需要完成通信協(xié)議和數(shù)據(jù)長(zhǎng)度的約定,這個(gè)代碼實(shí)現(xiàn)的協(xié)議如下圖所示

代碼如下所示,代碼通過(guò)多時(shí)鐘上升沿的變化來(lái)讀寫(xiě)數(shù)據(jù)的

`timescale 1ns / 1ps // // Company: // Engineer: // // module SPI_data( input wire clk_100m , input wire clk_125m , input wire rst_n ,input wire spi_sclk0 , //mast input wire spi_cs0 , input wire spi_din0 , output reg spi_dout0 ,output reg spi_wr_flag , output reg spi_rd_flag , output reg [1:0] spi_rd_data_id ,input wire data_in_en , input wire [15:0] data_in , output reg data_out_en , output reg [15:0] data_out );// //SPI1parameter spi_data_dlc = 14 ; parameter spi_data_dlc_t = 13 ; parameter spi_dlc = 16 ; parameter spi_half_dlc = 8 ;reg spi_sclk0_t ; reg spi_cs0_t ; reg spi_din0_t ; reg spi_sclk0_t_t ; reg spi_cs0_t_t ; reg spi_din0_t_t ; reg spi_cs0_t_t_t ;reg data_din_flag ; reg one_data_flag ; reg one_data_flag_t ;reg data_dout_flag ;reg [6:0] spi_bit_cont ;reg [4:0] spi_cs0_cont ; reg [7:0] spi_first_data0 ; reg [7:0] spi_last_data0 ;reg [15:0] spi_sum_in ; reg [15:0] spi_sum_out ;always @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin spi_sclk0_t <= 'b0 ; spi_cs0_t <= 'b0 ; spi_din0_t <= 'b0 ; spi_sclk0_t_t <= 'b0 ; spi_cs0_t_t <= 'b0 ; spi_din0_t_t <= 'b0 ; spi_cs0_t_t_t <= 'b0 ; end else begin spi_sclk0_t <= spi_sclk0 ; spi_cs0_t <= spi_cs0 ; spi_din0_t <= spi_din0 ; spi_sclk0_t_t <= spi_sclk0_t ; spi_cs0_t_t <= spi_cs0_t ; spi_cs0_t_t_t <= spi_cs0_t_t ; spi_din0_t_t <= spi_din0_t ; end end SPI modle 0 16 bitalways @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin spi_cs0_cont <= 'b0 ; end else if ((spi_cs0_t_t==1'b0)&&((spi_sclk0_t_t==1'b0)&&(spi_sclk0_t==1'b1))) begin spi_cs0_cont <= spi_cs0_cont + 1'b1 ; end else if ((spi_cs0_t_t==1'b1)||(spi_cs0_cont>=spi_half_dlc)) begin spi_cs0_cont <= 'b0 ; end end always @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin one_data_flag <= 'b0 ; end else if ((spi_cs0_t_t==1'b0)&&((spi_sclk0_t_t==1'b0)&&(spi_sclk0_t==1'b1))&&(spi_cs0_cont==5'b00111)) begin one_data_flag <= 1'b1 ; end else begin one_data_flag <= 'b0 ; end end always @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin one_data_flag_t <= 'b0 ; end else begin one_data_flag_t <= one_data_flag ; end end always @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin spi_bit_cont <= 'b0 ; end else if ((spi_cs0_t_t_t==1'b0)&&(spi_cs0_cont==spi_half_dlc)) begin spi_bit_cont <= spi_bit_cont+ 1'b1 ; end else if ((spi_cs0_t_t_t==1'b1)) begin spi_bit_cont <= 'b0 ; end end always @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin spi_first_data0 <= 'b0 ; end else if ((spi_cs0_t_t==1'b0)&&((spi_sclk0_t_t==1'b0)&&(spi_sclk0_t==1'b1))&&(spi_cs0_cont<spi_half_dlc)) begin spi_first_data0 <= {spi_first_data0[6:0],spi_din0_t} ; end else if ((spi_cs0_t_t_t==1'b1)||(spi_cs0_cont==spi_half_dlc)) begin spi_first_data0 <= 'b0 ; end end always @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin spi_wr_flag <= 'b0 ; spi_rd_flag <= 'b0 ; spi_rd_data_id<= 'b0 ; end else if ((spi_cs0_t_t==1'b0)&&(spi_bit_cont==1'b0)&&(spi_cs0_cont==3)&&((spi_first_data0[2:1]==2'b10))&&((spi_sclk0_t_t==1'b0)&&(spi_sclk0_t==1'b1))) begin spi_wr_flag <= 'b1 ; spi_rd_flag <= 'b0 ; spi_rd_data_id<= 'b0 ; end else if ((spi_cs0_t_t==1'b0)&&(spi_bit_cont==1'b0)&&(spi_cs0_cont==3)&&((spi_first_data0[2:1]==2'b01))&&((spi_sclk0_t_t==1'b0)&&(spi_sclk0_t==1'b1))) begin spi_wr_flag <= 'b0 ; spi_rd_flag <= 'b1 ; spi_rd_data_id<= {spi_first_data0[0],spi_din0_t} ; end else if ((spi_cs0_t_t==1'b0)&&(spi_bit_cont==1'b0)&&(spi_cs0_cont==3)&&((spi_first_data0[2:1]==2'b00))&&((spi_sclk0_t_t==1'b0)&&(spi_sclk0_t==1'b1))) begin spi_wr_flag <= 'b1 ; spi_rd_flag <= 'b1 ; spi_rd_data_id<= {spi_first_data0[0],spi_din0_t} ; end else if ((spi_cs0_t_t_t==1'b1)) begin spi_wr_flag <= 'b0 ; spi_rd_flag <= 'b0 ; spi_rd_data_id<= 'b0 ; end end //spi_rd_data_idalways @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin data_out_en <= 'b0 ; end else if ((spi_cs0_cont==spi_half_dlc)&&(spi_bit_cont==spi_data_dlc_t)&&(spi_wr_flag==1'b1)&&(spi_rd_flag==1'b0)) begin data_out_en <= 1'b1 ; end else if ((spi_cs0_cont==spi_half_dlc)&&(spi_bit_cont==spi_data_dlc_t)&&(spi_wr_flag==1'b1)&&(spi_rd_flag==1'b1)) begin data_out_en <= 1'b1 ; end else begin data_out_en <= 'b0 ; end end always @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin data_out <= 'b0 ; end else if ((spi_cs0_cont==spi_half_dlc)&&(spi_wr_flag==1'b1)&&(spi_rd_flag==1'b0)) begin data_out <= {data_out[199:0],spi_first_data0} ; end else if ((spi_cs0_cont==spi_half_dlc)&&(spi_wr_flag==1'b1)&&(spi_rd_flag==1'b1)) begin data_out <= {data_out[199:0],spi_first_data0} ; end else if ((spi_cs0_t_t_t==1'b1)) begin data_out <= 'b0 ; end end always @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin spi_last_data0 <= 'b0 ; end else if ((spi_cs0_t_t==1'b0)&&((spi_sclk0_t_t==1'b0)&&(spi_sclk0_t==1'b1))&&(spi_cs0_cont<spi_half_dlc)&&(data_dout_flag==1'b1)) begin spi_last_data0 <= {spi_last_data0[6:0],spi_dout0} ; end else if ((spi_cs0_t_t_t==1'b1)||(spi_cs0_cont==spi_half_dlc)) begin spi_last_data0 <= 'b0 ; end end //data_dout_flagalways @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin data_dout_flag <= 'b0 ; end else if ((spi_cs0_t_t==1'b0)&&(spi_bit_cont==1'b0)&&(one_data_flag==1'b1)&&(spi_rd_flag==1'b1)&&(spi_wr_flag==1'b0)) begin data_dout_flag <= 1'b1 ; end else if ((spi_cs0_t_t==1'b0)&&(spi_bit_cont==1'b0)&&(one_data_flag==1'b1)&&(spi_rd_flag==1'b1)&&(spi_wr_flag==1'b1)) begin data_dout_flag <= 1'b1 ; end else if ((spi_cs0_t_t_t==1'b1)) begin data_dout_flag <= 'b0 ; end end reg [191:0] spi_data_in ; reg [7:0] last_sum ;always @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin last_sum <= 'b0 ; end else if ((spi_cs0_t_t==1'b0)&&(spi_bit_cont==spi_data_dlc_t)&&(one_data_flag_t==1'b1)&&(spi_rd_flag==1'b1)&&(spi_wr_flag==1'b0)) begin last_sum <= spi_sum_out[7:0] ; end else if ((spi_cs0_t_t==1'b0)&&(spi_bit_cont==spi_data_dlc_t)&&(one_data_flag_t==1'b1)&&(spi_rd_flag==1'b1)&&(spi_wr_flag==1'b1)) begin last_sum <= spi_sum_out[7:0] ; end else if ((spi_cs0_t_t==1'b0)&&((spi_sclk0_t_t==1'b1)&&(spi_sclk0_t==1'b0))&&(spi_bit_cont==spi_data_dlc_t)&&(spi_rd_flag==1'b1)&&(spi_wr_flag==1'b0)) begin last_sum <= {last_sum[6:0],1'b0} ; end else if ((spi_cs0_t_t==1'b0)&&((spi_sclk0_t_t==1'b1)&&(spi_sclk0_t==1'b0))&&(spi_bit_cont==spi_data_dlc_t)&&(spi_rd_flag==1'b1)&&(spi_wr_flag==1'b1)) begin last_sum <= {last_sum[6:0],1'b0} ; end else if ((spi_cs0_t_t_t==1'b1)) begin last_sum <= 'b0 ; end end always @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin spi_data_in <= 'b0 ; end else if (data_in_en==1'b1) begin spi_data_in <= data_in ; end else if ((spi_cs0_t_t==1'b0)&&((spi_sclk0_t_t==1'b1)&&(spi_sclk0_t==1'b0))&&(data_dout_flag==1'b1)&&(spi_rd_flag==1'b1)&&(spi_wr_flag==1'b0)) begin spi_data_in <= {spi_data_in[190:0],1'b0} ; end else if ((spi_cs0_t_t==1'b0)&&((spi_sclk0_t_t==1'b1)&&(spi_sclk0_t==1'b0))&&(data_dout_flag==1'b1)&&(spi_rd_flag==1'b1)&&(spi_wr_flag==1'b1)) begin spi_data_in <= {spi_data_in[190:0],1'b0} ; end else if ((spi_cs0_t_t_t==1'b1)) begin spi_data_in <= 'b0 ; end end always @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin spi_dout0 <= 'b0 ; end else if ((spi_cs0_t_t==1'b0)&&((spi_sclk0_t_t==1'b1)&&(spi_sclk0_t==1'b0))&&(spi_bit_cont<1)) begin //spi_dout0 <= spi_data_in[191] ; spi_dout0 <= spi_din0_t ; end else if ((spi_cs0_t_t==1'b0)&&((spi_sclk0_t_t==1'b1)&&(spi_sclk0_t==1'b0))&&(spi_rd_flag==1'b1)&&(spi_wr_flag==1'b0)&&(spi_bit_cont<spi_data_dlc_t)&&(spi_bit_cont>0)) begin spi_dout0 <= spi_data_in[191] ; end else if ((spi_cs0_t_t==1'b0)&&((spi_sclk0_t_t==1'b1)&&(spi_sclk0_t==1'b0))&&(spi_rd_flag==1'b1)&&(spi_wr_flag==1'b1)&&(spi_bit_cont<spi_data_dlc_t)&&(spi_bit_cont>0)) begin spi_dout0 <= spi_data_in[191] ; end else if ((spi_cs0_t_t==1'b0)&&((spi_sclk0_t_t==1'b1)&&(spi_sclk0_t==1'b0))&&(spi_rd_flag==1'b1)&&(spi_wr_flag==1'b0)&&(spi_bit_cont==spi_data_dlc_t)&&(spi_bit_cont>0)) begin spi_dout0 <= last_sum[7] ; end else if ((spi_cs0_t_t==1'b0)&&((spi_sclk0_t_t==1'b1)&&(spi_sclk0_t==1'b0))&&(spi_rd_flag==1'b1)&&(spi_wr_flag==1'b1)&&(spi_bit_cont==spi_data_dlc_t)&&(spi_bit_cont>0)) begin spi_dout0 <= last_sum[7] ; end else if ((spi_cs0_t_t==1'b1)) begin spi_dout0 <= 'b0 ; end end /always @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin spi_sum_in <= 'b0 ; end else if (((spi_bit_cont<spi_data_dlc)&&(spi_bit_cont>1'b0))&&(spi_cs0_cont==spi_half_dlc)&&(spi_wr_flag==1'b1)&&(spi_rd_flag==1'b0)) begin spi_sum_in <= spi_sum_in + spi_first_data0 ; end else if (((spi_bit_cont<spi_data_dlc)&&(spi_bit_cont>1'b0))&&(spi_cs0_cont==spi_half_dlc)&&(spi_wr_flag==1'b1)&&(spi_rd_flag==1'b1)) begin spi_sum_in <= spi_sum_in + spi_first_data0 ; end else if ((spi_cs0_t_t==1'b1)) begin spi_sum_in <= 'b0 ; end end always @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin spi_sum_out <= 'b0 ; end else if (((spi_bit_cont<spi_data_dlc)&&(spi_bit_cont>1'b0))&&(spi_cs0_cont==spi_half_dlc)&&(spi_wr_flag==1'b0)&&(spi_rd_flag==1'b1)) begin spi_sum_out <= spi_sum_out + spi_last_data0 ; end else if (((spi_bit_cont<spi_data_dlc)&&(spi_bit_cont>1'b0))&&(spi_cs0_cont==spi_half_dlc)&&(spi_wr_flag==1'b1)&&(spi_rd_flag==1'b1)) begin spi_sum_out <= spi_sum_out + spi_last_data0 ; end else if ((spi_cs0_t_t==1'b1)) begin spi_sum_out <= 'b0 ; end end endmodule

4、FPGA實(shí)現(xiàn)主機(jī)SPI數(shù)據(jù)的收發(fā)

作為主機(jī)時(shí)實(shí)現(xiàn)時(shí)鐘的發(fā)送和數(shù)據(jù)傳輸?shù)目刂啤?/p> `timescale 1ns / 1ps // // Company: // Engineer: // module SPI_slv_data( input wire clk_100m , input wire clk_125m , input wire rst_n ,output wire spi_sclk1 , //slv output reg spi_cs1 , input wire spi_din1 , output reg spi_dout1 ,///input wire data_fram_sof , input wire data_fram_eof ,input wire data_in_en , input wire [15:0] data_in ,output reg data_one_flag );/ reg [3:0] spi_div ; reg spi_clk ; reg bit_flag ; reg [4:0] bit_cont ; reg [15:0] spi_data_in ;always @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin spi_cs1 <= 'b1 ; end else if(data_fram_sof==1'b1) begin spi_cs1 <= 1'b0 ; end else begin spi_cs1 <= 'b1 ; end end always @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin spi_div <= 'b0 ; end else if((spi_div<12)&&(data_fram_eof==1'b1)) begin spi_div <= spi_div + 1'b1 ; end else begin spi_div <= 'b0 ; end end always @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin spi_clk <= 'b1 ; end else if (spi_div<=5) begin spi_clk <= 1'b1 ; end else spi_clk <= 'b0 ; end 時(shí)鐘經(jīng)過(guò)BUFG緩沖 wire spi_clk_o ; BUFG spi_clk_obuf (.I(spi_clk), .O(spi_sclk1)); // always @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin spi_data_in <= 'b1 ; end else if (data_in_en==1'b1) begin spi_data_in <= data_in ; end else if (bit_flag==1'b1) begin spi_data_in <= {spi_data_in[14:0],1'b1} ; end end always @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin bit_flag <= 'b0 ; end else if (spi_div==6) begin bit_flag <= 1'b1 ; end else bit_flag <= 'b0 ; end always @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin spi_dout1 <= 'b0 ; end else if (bit_flag==1'b1) begin spi_dout1 <= spi_data_in[15] ; end end always @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin bit_cont <= 'b0 ; end else if (bit_flag==1'b1) begin bit_cont <= bit_cont + 1'b1 ; end else if (bit_cont>=16) begin bit_cont <= 'b0 ; end end always @(posedge clk_100m or negedge rst_n )begin if(rst_n==1'b0) begin data_one_flag <= 'b0 ; end else if (bit_cont==16) begin data_one_flag <= 1'b1 ; end else data_one_flag <= 'b0 ; end endmodu

總體來(lái)說(shuō)FPGA實(shí)現(xiàn)SPI相對(duì)簡(jiǎn)單。

總結(jié)

以上是生活随笔為你收集整理的FPGA实现SPI 协议的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。