|
一.SPI协议简要介绍 SPI,是英语Serial Peripheral Interface的缩写,顾名思义就是串行外围设备接口。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。
4 P( q- Z' k. Q- e+ A: |( r& D 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拉低使能情况下。 " T7 k+ {3 m$ G1 y# v- W. f# v
二.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发送数据与接收数据。
* h" y9 [3 O0 @! J6 D1 w2 k" @- /***********************************************************************
: d% L4 H/ a* S( b - ****************** name:SPI_Slaver_Driver **************8 l, N; @6 K8 {1 i4 r) K p
- ********** author:made by zzuxzt **********
3 J# P4 H5 f1 U7 A- x - ****************** time:2014.4.29 **********************$ p$ M/ q; d; {
- ***********************************************************************/) a: j2 I4 j4 U; c+ [1 `2 u# g
- //use SPI 3 mode,CHOL = 1,CHAL = 1
( @& J+ h* H3 `8 |7 ~) A - module spi(input clk,
; w1 F) @& c, O( g - input rst_n,
$ [, ^7 ~; g( U0 C/ _ - input CS_N,
. [) h6 q+ N7 y: r5 h - input SCK,/ ~" L# f1 w7 `; T6 {; W
- input MOSI,
+ A( P9 Y$ t4 n - input [7:0] txd_data,$ ~ N3 }5 c0 u: p9 x5 @" e- d" ]
- output reg MISO,: J0 A9 t7 G% {* y+ t6 T" S. e0 }/ C
- output reg [7:0] rxd_data," [% n0 O; b9 B
- output rxd_flag); //recieve done,please transmit data0 b, e& J* ^! B: ~5 z4 b- D# [
6 n! \4 D8 `; j5 W- //-------------------------capture the sck-----------------------------
3 ~* x- ?0 G4 S. u J& } - reg sck_r0,sck_r1;; h1 A% d) E2 _ k& G/ E# A
- wire sck_n,sck_p;- f- I, c# \& e; F
- always@(posedge clk or negedge rst_n)7 D7 _' |# B* o- R9 Y# n
- begin( L5 R1 ~' n. ~+ M
- if(!rst_n)" H! c, L V% l0 v
- begin6 f q+ ]0 M0 K$ }: Q$ r1 y
- sck_r0 <= 1'b1; //sck of the idle state is high. k3 ^; k% k" L f
- sck_r1 <= 1'b1;9 n; l% n$ ^& i' o0 q6 q* d
- end
7 s* C5 T, R3 d' ] - else
9 x4 W5 I; y8 C( ^7 S* T8 S: K i6 B - begin
& u2 a l! N; \' U - sck_r0 <= SCK;/ _: f. T: i* m% A
- sck_r1 <= sck_r0;
) _ h. J& X/ C1 r - end
6 X, A) R3 Y! x* `/ U% M - end) @- |. D" z0 B
- ( W" g0 N0 ^0 a3 C! m) u
- assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0; //capture the sck negedge" d( K( l% Q2 r, b
- assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0; //capture the sck posedge6 L7 o; z' m9 v
- p& K" l+ n% Y- R' l1 y- p+ d
- //-----------------------spi_slaver read data-------------------------------
* z8 T7 `6 }* G7 }5 Y( O; ^6 @ - reg rxd_flag_r;
* `2 P, _1 [' R* s" w4 ] - reg [2:0] rxd_state;2 X. v5 k4 ^7 d7 ~% o. j
- always@(posedge clk or negedge rst_n)
. h8 W6 g) W' i4 ~& X X - begin
$ r! B& i, N% F! _ - if(!rst_n)1 O: X2 r6 K) {
- begin/ d K) Z' M& w
- rxd_data <= 1'b0;
4 q% U- k' Z$ D3 i - rxd_flag_r <= 1'b0;2 l, x1 R; Q+ J& F
- rxd_state <= 1'b0;$ Y( G. X) R0 q( P
- end- t+ n, I" m6 Y B/ z: a
- else if(sck_p && !CS_N)
6 d7 z2 r5 Y3 L% k% J' h7 Q# N - begin
8 U: M# R6 L; h( o; n( l% f0 s - case(rxd_state)9 Q/ r: {9 I5 ^$ z& t c
- 3'd0:begin
( ]! i& \$ a$ y4 y2 L0 \ - rxd_data[7] <= MOSI;2 {+ E, W" |# u2 O' R) l( g7 L
- rxd_flag_r <= 1'b0; //reset rxd_flag3 ~. R0 u0 z) `- k
- rxd_state <= 3'd1; N) [. T2 t/ j% v+ |
- end
: m G7 L: ~5 J2 r - 3'd1:begin. z" w E% ], o7 G9 K' a
- rxd_data[6] <= MOSI;
% C; a x5 q( Z2 ]7 r; d - rxd_state <= 3'd2;
/ }, H5 h# }$ s - end
2 O" x0 c+ s, J5 w d - 3'd2:begin1 j* ?; s! @- Y; w% v2 L
- rxd_data[5] <= MOSI;
# a4 q, G# \, S7 F4 u - rxd_state <= 3'd3;
; c9 B. ~5 V$ o7 u/ } - end& v# [+ _! l/ ~0 [ B$ O
- 3'd3:begin& a4 m$ m6 U" q6 M' `3 s
- rxd_data[4] <= MOSI;
* \% V2 A6 U6 c9 i - rxd_state <= 3'd4;4 @9 Y5 N2 f5 K. E, O
- end6 d9 g1 _' Z+ O) {* w8 x
- 3'd4:begin# C2 \6 m. W* `6 v" z
- rxd_data[3] <= MOSI;
. |& n$ y9 N9 O2 r$ Y - rxd_state <= 3'd5;+ h+ x7 X5 i7 r: K2 J- R
- end* L7 G2 R* a$ L) L' t
- 3'd5:begin3 q9 n, d4 r% R, B
- rxd_data[2] <= MOSI;
) Y8 J- v+ S5 J - rxd_state <= 3'd6;+ T, y: ]! s* X8 Y6 C
- end
* s' n. y& `/ L t - 3'd6:begin1 [8 z* T( v# j" v; U% Z/ T5 g
- rxd_data[1] <= MOSI;8 ~0 F) U2 |8 o# m7 N5 M
- rxd_state <= 3'd7;6 O; A* S0 M1 c, l
- end7 k* f7 H7 c7 R3 ^: M
- 3'd7:begin, [4 b" d- d" P! g: U* W
- rxd_data[0] <= MOSI;
* s/ S) Y; [) I5 d. [: i' v - rxd_flag_r <= 1'b1; //set rxd_flag6 Y- F- v& [+ V5 K; O- o
- rxd_state <= 3'd0;
/ f" z) f9 E, E/ V - end' k4 ~+ a0 k$ H% f% y0 t& F. t
- default: ;
. }& Y$ n/ ]3 j7 Y - endcase
* j+ k/ x7 a" H - end
/ b2 y- \- j* V* N% Q B* v% Y - end3 j5 Q; P7 s$ T4 @) j7 v1 Q
# R( `$ t! {& k7 L; h- 9 S, `% g! `$ N! |% s' W
- //--------------------capture spi_flag posedge--------------------------------
' r- s/ m0 Q! E: e( W/ a - reg rxd_flag_r0,rxd_flag_r1;. O. L+ V, T+ a/ A
- always@(posedge clk or negedge rst_n)
. c% i7 e5 I9 T - begin
9 }: G: a. j( i6 i - if(!rst_n)6 i: C ^* B$ y) G: w
- begin
& H' Q+ J- {2 n9 Q$ X5 h - rxd_flag_r0 <= 1'b0;) M2 X. T1 Q0 Q. M, F: N
- rxd_flag_r1 <= 1'b0;: O1 x. C* d5 \4 ]0 b' R
- end1 H/ Q: c+ l! n2 \ X/ B- I- O
- else
* u5 U; r: Y; z G. n% V - begin6 v8 F5 f" X% T6 ~" f# C
- rxd_flag_r0 <= rxd_flag_r;
* D; X; }6 L; z( e: k - rxd_flag_r1 <= rxd_flag_r0;
+ S# l2 G5 z3 D [" |2 R1 X - end3 a! O7 g1 k+ c. w1 o
- end4 J( `( t& h# _0 a; Y4 ?
- - n5 ~& ~0 B+ O9 `: o# N
- assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;4 [+ O" ?4 x$ y) q
- " u) y( h% L i" t( ~
- //---------------------spi_slaver send data---------------------------4 k3 |2 u. R j0 A) Q' Z W
- reg [2:0] txd_state;
5 W: e. F5 C' ]- H& c% R* W! d - always@(posedge clk or negedge rst_n); @' v' b# `3 D
- begin
6 q; G3 g6 W* B/ `$ q3 c - if(!rst_n)
& `0 G" F. |" X/ C& m6 S - begin' \- @$ K% K6 J9 N
- txd_state <= 1'b0;
+ E8 g: I1 V7 `' W& X - end
! |0 L8 U, ?9 `9 y, q; P' c - else if(sck_n && !CS_N), ^, P9 P+ Y, q3 o
- begin
X! \8 d( \" V$ J - case(txd_state)
7 K3 c; V8 W8 _7 }1 r; K - 3'd0:begin
/ A( D. s7 U6 s4 R - MISO <= txd_data[7];
6 `3 x T+ l+ f( g) w8 ?6 B j' f - txd_state <= 3'd1;
3 z7 v7 m- Y, I - end2 A" J2 G# A+ y5 @" p
- 3'd1:begin
! K$ C* {1 R, d0 y9 f6 U - MISO <= txd_data[6];
3 B2 Q, C. X; d f2 p9 D - txd_state <= 3'd2;9 B3 T0 \4 [2 ]4 {
- end4 ]) p& C) W/ J; [1 k4 N1 M9 U$ g+ r4 P
- 3'd2:begin5 z; ?! q8 C( N G0 ?
- MISO <= txd_data[5];' m0 i! y* h* ^5 \! t* W: X* Z
- txd_state <= 3'd3;
5 S+ E8 K' l: b% f" s5 I+ U8 u$ Y8 L; Q - end" Q8 \( o; O" I! \% G5 E' d# E
- 3'd3:begin4 a" M" G& i2 Y5 v) W& H9 G
- MISO <= txd_data[4];
9 z; J9 E6 A3 c- z7 W! {! Y8 G - txd_state <= 3'd4;
1 w# \/ Z3 ^2 w* h8 D- z9 I - end
2 k6 o1 j1 B- U0 I$ v0 l0 t f - 3'd4:begin
4 _( ]. l; Q9 D" K( A, @. _ - MISO <= txd_data[3];
1 F: b/ f3 l- Q - txd_state <= 3'd5;
5 h9 w9 E' U' G% g9 D1 h - end8 K; i* F/ l0 O8 o; `6 e- h
- 3'd5:begin t5 Z( z$ F$ C0 `& G: a
- MISO <= txd_data[2];! d& _7 @; g8 E# M6 V
- txd_state <= 3'd6;
8 g3 ^1 i! Q0 I - end
( T2 i) K/ T2 q2 M* _; _ - 3'd6:begin
! Z1 W6 \/ Z( m# t) \1 \3 r' { - MISO <= txd_data[1];. {# H4 c `0 e0 O) a8 s
- txd_state <= 3'd7;) L. t ?6 D; s) p$ R5 w, ?
- end! G. C3 Y# R- g& N, \+ s
- 3'd7:begin
" i# q# O6 e; U+ @( q. ~) c - MISO <= txd_data[0];
. P1 C: Q! e+ y/ V9 b; b - txd_state <= 3'd0;
& D# Q+ b3 E! }# A0 j - end' j/ _" Z8 d( G6 I! p
- default: ;
6 q$ t; H7 E; y5 F2 ]2 T - endcase! M$ u# q% ^2 ` e
- end
- K! B" O- e4 K& {! G- | P' ~; C% F - end4 |! K) T- R3 w1 _" q. a3 C
- ; _* \8 b& L0 \6 E
- endmodule
复制代码 + `8 t! B# Y4 Y: ]% |0 V7 ^
0 ~9 y, G# S7 S8 ~/ c) ?
% G- a: b5 w3 Y8 {! z0 Y+ s, I9 e$ j+ d2 d
. o2 H. a) n# }+ V0 k
|