一.SPI协议简要介绍 SPI,是英语Serial Peripheral Interface的缩写,顾名思义就是串行外围设备接口。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。
* g; y6 f8 H) x& i9 W1 Y SPI总线是Motorola公司推出的三线同步接口,同步串行3线方式进行通信:一条时钟线SCK,一条数据输入线MOSI,一条数据输出线MISO;用于 CPU与各种外围器件进行全双工、同步串行通讯。SPI主要特点有:可以同时发出和接收串行数据;可以当作主机或从机工作;提供频率可编程时钟;发送结束中断标志;写冲突保护;总线竞争保护等。 SPI总线有四种工作方式(SP0, SP1, SP2, SP3),其中使用的最为广泛的是SPI0和SPI3方式。SPI模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性和相位可以进行配置,时钟极性(CPOL)对传输协议没有重大的影响。如果CPOL=0,串行同步时钟的空闲状态为低电平;如果CPOL=1,串行同步时钟的空闲状态为高电平。时钟相位(CPHA)能够配置用于选择两种不同的传输协议之一进行数据传输。如果 CPHA=0,在串行同步时钟的第一个跳变沿(上升或下降)数据被采样;如果CPHA=1,在串行同步时钟的第二个跳变沿(上升或下降)数据被采样。 SPI主模块和与之通信的外设时钟相位和极性应该一致。 以下是SPI时序图: 主要讲解一下广泛使用的两种方式设置: SPI0方式:CPOL=0,CPHA=0;SCK空闲状态为低电平,第一个跳变沿(上升沿)采样数据,无论对Master还是Slaver都是如此。 SPI3方式:CPOL=1,CPHA=1;SCK空闲状态为高电平,第二个跳变沿(上升沿采样数据,无论对Master还是Slaver都是如此。 其实对于SPI0和SPI1发送与接收数据,可以总结为一句话:上升沿采样数据,下降沿发送数据。全双工同时进行,当然,必须在CS拉低使能情况下。
3 B5 r+ v7 e7 c% a# F二.FPGA作为Slaver实现SPI3方式与STM32通信 1.STM32方面:用库函数配置SPI1,设置CPOL=1,CPHA=1. 2.FPGA方面: (1)通过边沿检测技术得出SCK上升沿与下降沿标志,用于下面状态机中的数据采样及发送。 (2)根据时序图,采用2个状态机分别在SCK上升沿实现数据采样,下降沿实现数据发送。无论是采样还是发送,都是高位在前,从Bit[7]到Bit[0],共8位数据。 (3)最后通过边沿检测技术得出数据采样完成标志,用于用户操作。 以下是SPI3的时序图: 三.Verilog代码部分 测试工程代码:实现了STM32每隔200ms发送流水灯数据给FPGA,使FPGA系统板上的4个LED灯实现流水操作;同时,FPGA每隔1s发送计数数据给STM32,并在STM32系统板上的LCD屏出来,即:显示0-9循环计数。 但下面的代码只是SPI作为从机的驱动部分,包括SPI发送数据与接收数据。
& g2 L8 E) F& y+ t- /***********************************************************************' ?! {5 d) U) f7 b; d M
- ****************** name:SPI_Slaver_Driver **************
. R4 w+ Q& u5 V - ********** author:made by zzuxzt **********$ ~: p8 X% w% D; L5 h
- ****************** time:2014.4.29 **********************5 Y U$ j4 c% |/ \. k3 n3 E
- ***********************************************************************/% Y% n! c3 E7 Y
- //use SPI 3 mode,CHOL = 1,CHAL = 1& e+ Z5 r0 T$ q7 ]' P6 P
- module spi(input clk,
3 s( e7 S( G3 S6 X- {! M6 J - input rst_n,. z5 n5 e3 T# \ ~# _; [
- input CS_N,
3 d6 g8 l) g6 d" x1 n - input SCK,7 D- |8 p8 K3 X9 U4 {
- input MOSI,
) [6 l* l: p$ ? - input [7:0] txd_data,
9 |8 b. K2 m6 V' S i - output reg MISO,# I, `0 c7 [3 u+ Y# X1 A0 C
- output reg [7:0] rxd_data,
& F* [5 \1 ]/ O5 p! h; t3 d% m - output rxd_flag); //recieve done,please transmit data
0 ]9 _$ t0 Z2 ^7 c( s
/ r; W% _( ]% ]- c, F- //-------------------------capture the sck-----------------------------
8 C+ d" y' V, S* y9 N! W - reg sck_r0,sck_r1;; f( C, z' U+ G% Z" w: g
- wire sck_n,sck_p;8 f$ |- [8 g# D' t2 D2 f& J
- always@(posedge clk or negedge rst_n)0 O9 U5 T9 N0 b8 R, U8 Q% V
- begin; T- A) M2 g& R) `
- if(!rst_n)
9 @( w T& P% }9 v& a" T7 w - begin$ N G6 J/ z: x4 |3 U3 |+ X
- sck_r0 <= 1'b1; //sck of the idle state is high
. m7 e& Y+ u. `/ F1 J9 ? - sck_r1 <= 1'b1;
- I* w9 a$ D, J2 Q - end
/ b( O- j8 T% M! l - else6 q$ w6 w4 g2 ]( F2 C+ L* F. [( ^
- begin
2 a- o0 k: Y& _ - sck_r0 <= SCK;* S3 T1 J3 ?) p0 K
- sck_r1 <= sck_r0;
8 n' b! a9 `3 Q4 q - end
7 A# M) `' Q' R- L4 N% L, j# c - end
6 b, p9 ~7 {' p. r' \) k - % `/ S9 W- @! M! _, H% O
- assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0; //capture the sck negedge
9 B. N4 w+ |+ g - assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0; //capture the sck posedge
% D7 O7 i# e: \ D - : P: R% j0 Q6 V0 P' M
- //-----------------------spi_slaver read data-------------------------------
* z# |: |& Z! u2 `, v& O - reg rxd_flag_r;1 h9 U+ S/ K9 M7 Q5 z; H
- reg [2:0] rxd_state;
# z6 P$ J/ G& C- ~, r" z5 u( d - always@(posedge clk or negedge rst_n)
K8 s, x$ S7 p0 H - begin) g& A( ]3 p/ e4 X+ E
- if(!rst_n)
0 q& B$ F- B1 c- X) s - begin
# b1 |2 ]2 b( I r; s! ~ - rxd_data <= 1'b0;# m6 C- d; m; ^8 K0 c8 a; F
- rxd_flag_r <= 1'b0;
% K/ }! H; Z* }' c: n; z2 R - rxd_state <= 1'b0;
3 [' V/ W: Z% Z+ _# t. A% r0 r - end$ u0 J7 Y2 b9 N: w
- else if(sck_p && !CS_N)& A" @% T# w# \0 f/ _8 R: K
- begin
/ A ~+ B, ]4 o$ \$ i: ?1 ` - case(rxd_state)
4 X# W: V6 M3 A - 3'd0:begin
7 `* Q* G! w. K3 D u - rxd_data[7] <= MOSI;6 q* x- g2 b6 l. M1 h1 ^
- rxd_flag_r <= 1'b0; //reset rxd_flag
9 }% g8 q- o9 l% w' { - rxd_state <= 3'd1;
* e3 `$ @6 t# S6 u - end
3 D5 S4 Z3 P: w" v - 3'd1:begin
6 V) O9 f0 }9 d - rxd_data[6] <= MOSI;+ h& O' u1 {6 `6 q( ]9 D
- rxd_state <= 3'd2;4 s& Q& [1 N* W, s# b2 r, `4 f
- end+ Y% `3 u$ A' c- v5 r ^* x
- 3'd2:begin
, V' i1 P" A. V1 z) v - rxd_data[5] <= MOSI;
" K( |, B! z% g0 r: t" g# [* Q - rxd_state <= 3'd3;
" _: Y: p9 _$ a5 H5 ~9 e - end, A' g6 e' c/ T7 D
- 3'd3:begin) `4 H$ C6 o& s% D* E' r
- rxd_data[4] <= MOSI;7 L3 J+ z& |. E+ W6 L! V8 E
- rxd_state <= 3'd4;1 O4 v1 a; m6 y$ i( @3 R
- end4 `" i( t" c( z* a; |
- 3'd4:begin5 S* |8 L7 m0 Y
- rxd_data[3] <= MOSI;
" R( s0 Z0 _: e* X - rxd_state <= 3'd5;
" S4 ~- [1 f# n7 i, S - end2 x5 ~ {! H' h$ o
- 3'd5:begin
2 Z: L) W- A0 A: g5 | - rxd_data[2] <= MOSI;+ h' E' e4 o7 |+ H
- rxd_state <= 3'd6;
4 H" Y! D$ }0 q3 t" H4 X/ F6 B - end
# r) d2 C' k; F; d5 ^ ` - 3'd6:begin
\) n" U8 m8 h" o - rxd_data[1] <= MOSI;) A, _" b L9 s# Q3 \
- rxd_state <= 3'd7;# _" G/ N* P+ @: U4 O6 [ l
- end, D2 F/ }5 i$ E8 b$ j4 F% J: p
- 3'd7:begin- f. b3 p5 k- L# H( [
- rxd_data[0] <= MOSI;
3 N' L5 n7 ~$ R; f. u - rxd_flag_r <= 1'b1; //set rxd_flag% P8 t& b4 W) c
- rxd_state <= 3'd0;
# Z% D! J& [' G- B- a9 s% f - end. ^: a8 P$ `: d. l
- default: ;+ }! {- i( E- U8 _9 @1 q* U
- endcase$ |2 V# D3 o2 n9 l: T5 O# k& N
- end+ c5 w4 b$ b8 [2 u$ D' M4 Y# _3 s
- end
3 o3 w# p( ?7 a1 \* z" F1 N8 L$ D! a - # A6 s/ v( }2 }3 C5 t q
- 0 a7 O/ f) V) U/ L& l8 Q$ o6 H
- //--------------------capture spi_flag posedge--------------------------------
* Y3 m2 S+ X5 w+ L1 S* t - reg rxd_flag_r0,rxd_flag_r1;
" a: k# n2 o) b5 E& g1 C3 s5 y' B - always@(posedge clk or negedge rst_n)
$ Q+ S0 m/ j+ ?) ] - begin6 |" q" o; s) Q. E$ u3 p! f
- if(!rst_n)
6 R+ `3 n/ f# K0 l5 Y - begin3 p# s9 X* f- u# x; \
- rxd_flag_r0 <= 1'b0;
8 K4 K7 o. U: R( p8 e* {9 X - rxd_flag_r1 <= 1'b0;
; |6 M( e7 W9 E' T; T5 b - end
! v/ k1 n5 V$ L- k6 T5 Z" D - else
4 K% i7 g# N& i& ~/ _% b - begin
; c- p2 q6 K# f, D6 X0 z - rxd_flag_r0 <= rxd_flag_r;& R6 w' n$ g, Z8 d
- rxd_flag_r1 <= rxd_flag_r0;
2 M* J; {6 J" b4 R7 @/ P: A4 _ - end/ N6 }, }+ `+ \4 g5 x0 p
- end
. |3 U3 `/ o2 Q U' u+ x
8 H+ d: l) ?7 e5 M% L- assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;. |8 t: `9 W' Y6 A) v& {* I
- 0 b# I0 q6 h& ~& J
- //---------------------spi_slaver send data---------------------------
) i: s+ C# q) F% X, W0 y - reg [2:0] txd_state;$ G# r5 n4 i2 H, }# S: z4 L2 W
- always@(posedge clk or negedge rst_n)
8 c# ], H) k" A2 p - begin
7 J% Y+ ]0 V f9 B - if(!rst_n)3 T' K" T% |! j k( o; b, q% U
- begin5 t" E% J9 w+ h/ s
- txd_state <= 1'b0;4 g5 Y9 D! f# K/ n! w6 y
- end
, p- n, k m& t. \, L k - else if(sck_n && !CS_N)* i8 e) l# O, ^/ k9 N! v
- begin0 l: b( @9 r- K6 n3 e% }
- case(txd_state)
) z% N( U* S/ a6 A+ r) F - 3'd0:begin- D& P5 ^ j& U' ?1 q% [; e
- MISO <= txd_data[7];
) |* S$ q& O$ n1 F4 N2 c! W/ B( U1 D - txd_state <= 3'd1;& e( v+ G! j" S7 ~3 z2 ]' a+ E
- end: f" c) r% K9 k7 i: B
- 3'd1:begin# m" E- A8 [6 B0 G" B1 a1 v& [/ J
- MISO <= txd_data[6];
/ \0 ?, t' h/ w) r0 z% B7 s - txd_state <= 3'd2;7 o& b1 S, e) a! ~/ w0 l
- end
7 [' c) v ?, r - 3'd2:begin
- {9 U' N; G8 b( i; Y! W$ C - MISO <= txd_data[5];- K {6 u% D* ?* _3 U+ o
- txd_state <= 3'd3;. l9 F0 W. p; E$ g5 k! T/ r
- end
$ @3 Q* N e' ~ - 3'd3:begin$ c6 k( Y C9 K# t
- MISO <= txd_data[4];0 i/ _! v* @9 J
- txd_state <= 3'd4;
7 p: b3 Y2 _# F/ \ - end0 B7 c) Q/ _* L* c: z8 A
- 3'd4:begin
5 @- n3 g! S& {6 ~" d - MISO <= txd_data[3];5 Q R: e. T2 S
- txd_state <= 3'd5;
+ y; p- G# v* u2 O - end& w1 x0 T* v% Q h. Z+ m+ q: M
- 3'd5:begin9 z: q' E5 m9 a* v& s- X
- MISO <= txd_data[2];& w+ z* s! s( \! ~( |
- txd_state <= 3'd6;8 E0 g9 I! g% D. i, P! d
- end
9 s6 c5 G: W; {" e) z - 3'd6:begin
8 D* S' h2 |) I L$ S8 ^4 _! Q - MISO <= txd_data[1];
+ |' k5 g( ?& j+ b9 j$ H - txd_state <= 3'd7;
, }" T+ Y$ j$ R6 w z - end, q% a3 T% f4 g* ^: D
- 3'd7:begin& i( `- m9 a2 A( {; S3 j
- MISO <= txd_data[0];
5 y$ _6 a9 u3 t/ C+ q" h5 E - txd_state <= 3'd0;: m8 B9 B+ u; ]' s/ p4 w0 R x% V4 @
- end! X" E! |' z1 f# y( h8 N
- default: ;
C4 x; N7 r$ s B - endcase
$ l3 K: y6 s) P, Z* [1 w* E5 q0 _ - end
( _ f* Q+ s8 I - end
& s% R k; u2 X; L( X - 7 r# @& z! A3 f2 O: k
- endmodule
复制代码 # J4 ]# ~9 O7 E& E" F/ v/ j
* n& r; u' s) R* r m& I/ c- K$ f% M6 z! u8 s
1 x6 b$ _; i9 f, d1 v |