一.SPI协议简要介绍 SPI,是英语Serial Peripheral Interface的缩写,顾名思义就是串行外围设备接口。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。
" I- {! R, C6 f! u2 F$ Q3 l+ N 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拉低使能情况下。
. ~) c& L7 R5 C+ I二.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发送数据与接收数据。 9 x- E! v) y8 |8 S1 Y
- /***********************************************************************: @1 T1 h% \" g0 l" U
- ****************** name:SPI_Slaver_Driver **************7 G2 M! w+ H4 d" k7 e
- ********** author:made by zzuxzt **********4 S; R6 w. I# L7 {2 H
- ****************** time:2014.4.29 **********************
$ [1 H1 _% K/ }# x# H7 p - ***********************************************************************/
6 N- Q& m& ?% Y - //use SPI 3 mode,CHOL = 1,CHAL = 1% v v& [ u0 f5 j1 u# ^
- module spi(input clk,
6 i8 @ _7 a5 Q& T - input rst_n,
; i5 D0 d: |( S& H% P - input CS_N,, Q# z& Q! d p! \$ V) g. W5 p
- input SCK,
1 b" Q7 q6 m) k% C - input MOSI,) U' y1 G6 }8 [, m# o
- input [7:0] txd_data,) }; k2 a; m/ t& k$ _1 Q; j) W
- output reg MISO,
/ {- R7 L1 `# ^3 K S x# a, ]. d - output reg [7:0] rxd_data,1 H7 P6 P& F* \4 m+ G' \
- output rxd_flag); //recieve done,please transmit data* }9 ]4 s) T, b3 |. d& H
- ' d6 u# Z! U: }- z1 V K7 Z
- //-------------------------capture the sck-----------------------------
0 S. U3 n4 X2 i% B - reg sck_r0,sck_r1;
3 o- r- A7 R! T* J2 | - wire sck_n,sck_p;. P- U* g% ]4 y. C# q
- always@(posedge clk or negedge rst_n)3 k: e3 \/ U9 r# ^1 ?
- begin: M9 w# H7 ]; B- H* b1 }/ v+ A
- if(!rst_n)3 S! G5 K6 B6 W( s: b
- begin
3 d8 X3 X* A: @7 Y! R - sck_r0 <= 1'b1; //sck of the idle state is high
$ K6 Z2 k1 b+ F8 C' P2 q1 ]5 F: L - sck_r1 <= 1'b1;2 ]! [" T+ v6 @" L% H
- end v' C) n; M; j( I4 |
- else
# d# W: C. `, I5 d - begin3 \& M Y9 l( G" N
- sck_r0 <= SCK;
; D; h0 T8 N* {) o - sck_r1 <= sck_r0;
3 A! l& j# J7 f" Z! x) @( j% [0 F - end6 X* ?; j. `9 j7 R
- end
4 U! o8 v+ J1 O) b
/ u( B# u% H- z- k1 X+ o6 w+ Q- assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0; //capture the sck negedge0 k9 ^$ |) G7 {! i
- assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0; //capture the sck posedge
* W( Z! R% O) ^; h0 k* u
) d$ |: s+ }' h( B0 b! o( Q- //-----------------------spi_slaver read data-------------------------------
0 f( b0 v9 A3 J u$ D - reg rxd_flag_r;5 n; c* N: R, U
- reg [2:0] rxd_state;+ T9 n X% i0 b! ~4 r; A
- always@(posedge clk or negedge rst_n)
4 e1 u/ M8 ^" W' n* l - begin
/ x8 X* ^+ v' G4 I& i - if(!rst_n) b) m) V1 ~7 I2 f# f5 Q9 t
- begin
, B& R: d& O6 E6 @( {, n: D. O - rxd_data <= 1'b0;
T' Y; B4 Q$ X. I- f4 l5 e1 M' F9 O: Z6 Q - rxd_flag_r <= 1'b0;/ |1 m# p$ X0 O3 N! g
- rxd_state <= 1'b0;! Z& ?4 Z# Y: d$ _
- end9 ^# j8 a t: \
- else if(sck_p && !CS_N)
, F$ N# g$ S& K( h# s. { h; ] - begin2 A2 w9 w9 Y0 J. m- m& C' A8 n
- case(rxd_state): C! u5 M0 e. k2 k: I$ C1 c
- 3'd0:begin
6 l5 t# W$ @& f - rxd_data[7] <= MOSI;( I. ~4 a& @* N, u S
- rxd_flag_r <= 1'b0; //reset rxd_flag/ `, d4 E) m3 f. N* w
- rxd_state <= 3'd1;
1 ?/ }) A: L0 B. g% z5 P - end& G) Z7 p' n: m
- 3'd1:begin
/ H' |. `: W6 C: ]' r/ A - rxd_data[6] <= MOSI;
. c9 F9 j1 c# |, F' E - rxd_state <= 3'd2;
! ^! }8 L% a5 ] J8 I/ B+ J - end
0 X+ N! B4 i( E3 C, v5 Z - 3'd2:begin
' d4 L. C2 W2 A, J1 c/ P3 y - rxd_data[5] <= MOSI;2 V6 I7 a. T1 n9 T. Q
- rxd_state <= 3'd3;7 x8 } H) h) h' F% A' j( t8 e9 w
- end
" L- G- s( O% }0 [1 P* B - 3'd3:begin' u3 [, i; n5 C" Z$ e' c( G# X
- rxd_data[4] <= MOSI;
d+ T* T0 J+ b9 j - rxd_state <= 3'd4;
. k. w1 y2 `: v5 w( l - end
, K ~! v) R. y, v: C d - 3'd4:begin
5 h1 ^) _' L. Y+ u( ~ - rxd_data[3] <= MOSI;
+ C+ j6 d0 y O+ ~ ] - rxd_state <= 3'd5;0 {2 R% u9 ?" U: U; f& Q( Q
- end
) `6 \% v- M8 r: z/ I; s: x - 3'd5:begin7 @1 l$ A5 c0 |9 K1 c% P
- rxd_data[2] <= MOSI;# Y" C- e7 W6 z8 N2 B6 x
- rxd_state <= 3'd6;& B F0 q: ?2 q! ~$ }# Y
- end& Z5 k2 i. b. O2 K+ r/ _/ T. B
- 3'd6:begin
8 K- d9 ]/ }! r& y& C - rxd_data[1] <= MOSI;1 q# U9 [( B8 D: `! h
- rxd_state <= 3'd7;" c8 a+ M" \/ Q4 s- B# i
- end
: F, B# {# }( `. y - 3'd7:begin! d `7 a, E- u. v# u
- rxd_data[0] <= MOSI;
! R- i; x! y; g7 ^/ J" ^- l8 o - rxd_flag_r <= 1'b1; //set rxd_flag
9 L6 y1 `8 X' I1 a- ^ - rxd_state <= 3'd0;
' G @' Q7 R: `4 b; r( |5 j% ] - end
* G5 m$ \6 }1 v2 i8 q - default: ;6 t) ^# j6 l, e6 J# O+ N8 V: ]7 h
- endcase
7 u7 `! b# `: w! t$ ]$ g - end
, u4 k; A( Q. G6 ^6 D( l - end
; c% `; {" X8 {" T/ ?5 P- P - - a n5 p* n/ P& i; k: I
- L" X# k* n. x2 _5 `- _5 b- //--------------------capture spi_flag posedge--------------------------------0 Q0 i% \! I* @
- reg rxd_flag_r0,rxd_flag_r1;4 [2 v% V- Q, x7 o
- always@(posedge clk or negedge rst_n)
- t& E/ i! J" o' b, n( P- N - begin
8 b+ n/ \, k9 H - if(!rst_n)
+ m* @. _+ p9 ^1 G! T - begin3 I. h' @4 _2 X' L
- rxd_flag_r0 <= 1'b0;3 f0 V, c3 W/ ?5 f
- rxd_flag_r1 <= 1'b0;7 `6 \; ^ G2 X/ q7 H. v
- end
' \# _4 p+ p7 s* c+ ] - else
- s* u( `, `* ?2 L# I( R# V+ Y - begin
V0 ?1 i: T7 Y) g) \4 Z3 n - rxd_flag_r0 <= rxd_flag_r;
1 n; ^5 B" Z) `! ^ - rxd_flag_r1 <= rxd_flag_r0;
, r* M# \2 A! h4 h - end) w' g! g# P+ ~ @
- end- z5 C" w( t/ _, J) u7 Y
8 X+ ~/ u& G" i6 k' \+ |( u- assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;
2 {* s/ D9 r$ L
; Z% R6 a: n$ ^' h- C$ _- //---------------------spi_slaver send data---------------------------- Z. D9 j$ z H" ?2 q: w% b. E$ ^
- reg [2:0] txd_state;
( I* l2 ?+ ~7 e: S0 ? - always@(posedge clk or negedge rst_n)
1 a# t1 \( z- ^; ]7 l" e1 K - begin* x8 l# _1 ]" U) k, Q
- if(!rst_n)
7 I0 ^/ [6 T2 r/ q - begin
* Z4 F6 S9 ]/ O* H - txd_state <= 1'b0;# u: w: S5 C" d) E4 ]+ u) d1 _3 u
- end [) H" d4 r: X+ O7 ~* H% Z
- else if(sck_n && !CS_N)( Q4 m% e3 V8 I
- begin
, F9 B1 E( b) \ - case(txd_state)
5 t2 h6 }7 @% i# q7 \7 @! X5 g - 3'd0:begin
( b, V$ O( s6 k# r3 ^" m - MISO <= txd_data[7];
. A% y$ U8 y. j7 d V - txd_state <= 3'd1;3 j4 d8 g: k6 h& a7 }: ~) o& O* r9 c% a
- end0 e5 D3 {: P- S6 S* b
- 3'd1:begin# t$ X; k- h5 Z. X) }1 D
- MISO <= txd_data[6];
3 z4 R8 c. {, q - txd_state <= 3'd2;
' u- T4 `* f0 E" [ - end! v# [, P; ~; p7 x& ^5 f3 N
- 3'd2:begin- d; d5 {/ |: ^( j
- MISO <= txd_data[5];6 S. ]/ V- Z X: f( T3 D
- txd_state <= 3'd3;
3 ~* [) A& U& D- t2 _. u - end6 w8 ]2 o8 b5 I' h. H o
- 3'd3:begin: O# C" L+ x$ L
- MISO <= txd_data[4];
7 p+ w4 l& F" [2 ^: I - txd_state <= 3'd4;
3 X3 L0 ^4 W& d- G( w - end
d& ]9 _* b* k - 3'd4:begin. C( X8 d. x5 S
- MISO <= txd_data[3];
8 o* i! V6 y# H$ H) y7 n - txd_state <= 3'd5;
4 [% P5 x2 o' C# k9 H0 a V6 h - end' |# ?4 G. q: p9 F7 r& p5 L9 a
- 3'd5:begin4 J% ~; o& l$ p! A$ |2 m6 u' Q
- MISO <= txd_data[2];
6 _9 v: @8 K( C+ n- c - txd_state <= 3'd6;
3 ~+ H9 G2 k4 V - end: I( Z0 P8 ]# ^% d) F/ ~
- 3'd6:begin- H9 @. K# C5 ~2 g5 s
- MISO <= txd_data[1];
" K1 h2 Q, l. z6 f - txd_state <= 3'd7;" Q( H" ^$ [2 N; Z$ w
- end
8 N5 X( X- u! g5 z# o/ S8 B g - 3'd7:begin. t2 t# E0 [2 n3 ]# P/ V
- MISO <= txd_data[0];" G9 _. v( X: x1 I! |, ~# F
- txd_state <= 3'd0;
2 I& |! s! k Z+ |) n( ]. C; A% h - end
* o! b# h% U' K7 \4 [: c - default: ;" s: R( M( u( W" Z9 l7 v a6 O
- endcase
. Z2 t) j+ O2 k: A1 | - end
5 R3 n- j7 H5 N* z& b0 |) o - end
& u, M H" S/ Q% q% k: V
4 k) d. @1 z7 P" V- endmodule
复制代码 # t# w; F! z2 D1 h! _
$ s# R$ d0 H& ^+ a+ e% E- L8 `# g& ]/ u# L
' w) `4 x: D# j2 k. A( N& H4 e
|