你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】FPGA作为从机与STM32进行SPI协议通信---Verilog实现

[复制链接]
STMCU小助手 发布时间:2022-1-16 18:00
一.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. /***********************************************************************: @1 T1 h% \" g0 l" U
  2.      ****************** name:SPI_Slaver_Driver **************7 G2 M! w+ H4 d" k7 e
  3.             ********** author:made by zzuxzt **********4 S; R6 w. I# L7 {2 H
  4.      ****************** time:2014.4.29 **********************
    $ [1 H1 _% K/ }# x# H7 p
  5. ***********************************************************************/
    6 N- Q& m& ?% Y
  6. //use SPI 3 mode,CHOL = 1,CHAL = 1% v  v& [  u0 f5 j1 u# ^
  7. module spi(input clk,
    6 i8 @  _7 a5 Q& T
  8.               input rst_n,
    ; i5 D0 d: |( S& H% P
  9.               input CS_N,, Q# z& Q! d  p! \$ V) g. W5 p
  10.               input SCK,
    1 b" Q7 q6 m) k% C
  11.               input MOSI,) U' y1 G6 }8 [, m# o
  12.               input [7:0] txd_data,) }; k2 a; m/ t& k$ _1 Q; j) W
  13.               output reg MISO,
    / {- R7 L1 `# ^3 K  S  x# a, ]. d
  14.               output reg [7:0] rxd_data,1 H7 P6 P& F* \4 m+ G' \
  15.               output rxd_flag);   //recieve done,please transmit data* }9 ]4 s) T, b3 |. d& H
  16. ' d6 u# Z! U: }- z1 V  K7 Z
  17. //-------------------------capture the sck-----------------------------
    0 S. U3 n4 X2 i% B
  18. reg sck_r0,sck_r1;
    3 o- r- A7 R! T* J2 |
  19. wire sck_n,sck_p;. P- U* g% ]4 y. C# q
  20. always@(posedge clk or negedge rst_n)3 k: e3 \/ U9 r# ^1 ?
  21. begin: M9 w# H7 ]; B- H* b1 }/ v+ A
  22.     if(!rst_n)3 S! G5 K6 B6 W( s: b
  23.         begin
    3 d8 X3 X* A: @7 Y! R
  24.             sck_r0 <= 1'b1;   //sck of the idle state is high
    $ K6 Z2 k1 b+ F8 C' P2 q1 ]5 F: L
  25.             sck_r1 <= 1'b1;2 ]! [" T+ v6 @" L% H
  26.         end  v' C) n; M; j( I4 |
  27.     else
    # d# W: C. `, I5 d
  28.         begin3 \& M  Y9 l( G" N
  29.             sck_r0 <= SCK;
    ; D; h0 T8 N* {) o
  30.             sck_r1 <= sck_r0;
    3 A! l& j# J7 f" Z! x) @( j% [0 F
  31.         end6 X* ?; j. `9 j7 R
  32. end
    4 U! o8 v+ J1 O) b

  33. / u( B# u% H- z- k1 X+ o6 w+ Q
  34. assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0;   //capture the sck negedge0 k9 ^$ |) G7 {! i
  35. assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0;   //capture the sck posedge
    * W( Z! R% O) ^; h0 k* u

  36. ) d$ |: s+ }' h( B0 b! o( Q
  37. //-----------------------spi_slaver read data-------------------------------
    0 f( b0 v9 A3 J  u$ D
  38. reg rxd_flag_r;5 n; c* N: R, U
  39. reg [2:0] rxd_state;+ T9 n  X% i0 b! ~4 r; A
  40. always@(posedge clk or negedge rst_n)
    4 e1 u/ M8 ^" W' n* l
  41. begin
    / x8 X* ^+ v' G4 I& i
  42.     if(!rst_n)  b) m) V1 ~7 I2 f# f5 Q9 t
  43.         begin
    , B& R: d& O6 E6 @( {, n: D. O
  44.             rxd_data <= 1'b0;
      T' Y; B4 Q$ X. I- f4 l5 e1 M' F9 O: Z6 Q
  45.             rxd_flag_r <= 1'b0;/ |1 m# p$ X0 O3 N! g
  46.             rxd_state <= 1'b0;! Z& ?4 Z# Y: d$ _
  47.         end9 ^# j8 a  t: \
  48.     else if(sck_p && !CS_N)
    , F$ N# g$ S& K( h# s. {  h; ]
  49.         begin2 A2 w9 w9 Y0 J. m- m& C' A8 n
  50.             case(rxd_state): C! u5 M0 e. k2 k: I$ C1 c
  51.                 3'd0:begin
    6 l5 t# W$ @& f
  52.                         rxd_data[7] <= MOSI;( I. ~4 a& @* N, u  S
  53.                         rxd_flag_r <= 1'b0;   //reset rxd_flag/ `, d4 E) m3 f. N* w
  54.                         rxd_state <= 3'd1;
    1 ?/ }) A: L0 B. g% z5 P
  55.                       end& G) Z7 p' n: m
  56.                 3'd1:begin
    / H' |. `: W6 C: ]' r/ A
  57.                         rxd_data[6] <= MOSI;
    . c9 F9 j1 c# |, F' E
  58.                         rxd_state <= 3'd2;
    ! ^! }8 L% a5 ]  J8 I/ B+ J
  59.                       end
    0 X+ N! B4 i( E3 C, v5 Z
  60.                 3'd2:begin
    ' d4 L. C2 W2 A, J1 c/ P3 y
  61.                         rxd_data[5] <= MOSI;2 V6 I7 a. T1 n9 T. Q
  62.                         rxd_state <= 3'd3;7 x8 }  H) h) h' F% A' j( t8 e9 w
  63.                       end
    " L- G- s( O% }0 [1 P* B
  64.                 3'd3:begin' u3 [, i; n5 C" Z$ e' c( G# X
  65.                         rxd_data[4] <= MOSI;
      d+ T* T0 J+ b9 j
  66.                         rxd_state <= 3'd4;
    . k. w1 y2 `: v5 w( l
  67.                       end
    , K  ~! v) R. y, v: C  d
  68.                 3'd4:begin
    5 h1 ^) _' L. Y+ u( ~
  69.                         rxd_data[3] <= MOSI;
    + C+ j6 d0 y  O+ ~  ]
  70.                         rxd_state <= 3'd5;0 {2 R% u9 ?" U: U; f& Q( Q
  71.                       end
    ) `6 \% v- M8 r: z/ I; s: x
  72.                 3'd5:begin7 @1 l$ A5 c0 |9 K1 c% P
  73.                         rxd_data[2] <= MOSI;# Y" C- e7 W6 z8 N2 B6 x
  74.                         rxd_state <= 3'd6;& B  F0 q: ?2 q! ~$ }# Y
  75.                       end& Z5 k2 i. b. O2 K+ r/ _/ T. B
  76.                 3'd6:begin
    8 K- d9 ]/ }! r& y& C
  77.                         rxd_data[1] <= MOSI;1 q# U9 [( B8 D: `! h
  78.                         rxd_state <= 3'd7;" c8 a+ M" \/ Q4 s- B# i
  79.                       end
    : F, B# {# }( `. y
  80.                 3'd7:begin! d  `7 a, E- u. v# u
  81.                         rxd_data[0] <= MOSI;
    ! R- i; x! y; g7 ^/ J" ^- l8 o
  82.                         rxd_flag_r <= 1'b1;  //set rxd_flag
    9 L6 y1 `8 X' I1 a- ^
  83.                         rxd_state <= 3'd0;
    ' G  @' Q7 R: `4 b; r( |5 j% ]
  84.                       end
    * G5 m$ \6 }1 v2 i8 q
  85.                 default: ;6 t) ^# j6 l, e6 J# O+ N8 V: ]7 h
  86.             endcase
    7 u7 `! b# `: w! t$ ]$ g
  87.         end
    , u4 k; A( Q. G6 ^6 D( l
  88. end
    ; c% `; {" X8 {" T/ ?5 P- P
  89. - a  n5 p* n/ P& i; k: I

  90. - L" X# k* n. x2 _5 `- _5 b
  91. //--------------------capture spi_flag posedge--------------------------------0 Q0 i% \! I* @
  92. reg rxd_flag_r0,rxd_flag_r1;4 [2 v% V- Q, x7 o
  93. always@(posedge clk or negedge rst_n)
    - t& E/ i! J" o' b, n( P- N
  94. begin
    8 b+ n/ \, k9 H
  95.     if(!rst_n)
    + m* @. _+ p9 ^1 G! T
  96.         begin3 I. h' @4 _2 X' L
  97.             rxd_flag_r0 <= 1'b0;3 f0 V, c3 W/ ?5 f
  98.             rxd_flag_r1 <= 1'b0;7 `6 \; ^  G2 X/ q7 H. v
  99.         end
    ' \# _4 p+ p7 s* c+ ]
  100.     else
    - s* u( `, `* ?2 L# I( R# V+ Y
  101.         begin
      V0 ?1 i: T7 Y) g) \4 Z3 n
  102.             rxd_flag_r0 <= rxd_flag_r;
    1 n; ^5 B" Z) `! ^
  103.             rxd_flag_r1 <= rxd_flag_r0;
    , r* M# \2 A! h4 h
  104.         end) w' g! g# P+ ~  @
  105. end- z5 C" w( t/ _, J) u7 Y

  106. 8 X+ ~/ u& G" i6 k' \+ |( u
  107. assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;
    2 {* s/ D9 r$ L

  108. ; Z% R6 a: n$ ^' h- C$ _
  109. //---------------------spi_slaver send data---------------------------- Z. D9 j$ z  H" ?2 q: w% b. E$ ^
  110. reg [2:0] txd_state;
    ( I* l2 ?+ ~7 e: S0 ?
  111. always@(posedge clk or negedge rst_n)
    1 a# t1 \( z- ^; ]7 l" e1 K
  112. begin* x8 l# _1 ]" U) k, Q
  113.     if(!rst_n)
    7 I0 ^/ [6 T2 r/ q
  114.         begin
    * Z4 F6 S9 ]/ O* H
  115.             txd_state <= 1'b0;# u: w: S5 C" d) E4 ]+ u) d1 _3 u
  116.         end  [) H" d4 r: X+ O7 ~* H% Z
  117.     else if(sck_n && !CS_N)( Q4 m% e3 V8 I
  118.         begin
    , F9 B1 E( b) \
  119.             case(txd_state)
    5 t2 h6 }7 @% i# q7 \7 @! X5 g
  120.                 3'd0:begin
    ( b, V$ O( s6 k# r3 ^" m
  121.                         MISO <= txd_data[7];
    . A% y$ U8 y. j7 d  V
  122.                         txd_state <= 3'd1;3 j4 d8 g: k6 h& a7 }: ~) o& O* r9 c% a
  123.                       end0 e5 D3 {: P- S6 S* b
  124.                 3'd1:begin# t$ X; k- h5 Z. X) }1 D
  125.                         MISO <= txd_data[6];
    3 z4 R8 c. {, q
  126.                         txd_state <= 3'd2;
    ' u- T4 `* f0 E" [
  127.                       end! v# [, P; ~; p7 x& ^5 f3 N
  128.                 3'd2:begin- d; d5 {/ |: ^( j
  129.                         MISO <= txd_data[5];6 S. ]/ V- Z  X: f( T3 D
  130.                         txd_state <= 3'd3;
    3 ~* [) A& U& D- t2 _. u
  131.                       end6 w8 ]2 o8 b5 I' h. H  o
  132.                 3'd3:begin: O# C" L+ x$ L
  133.                         MISO <= txd_data[4];
    7 p+ w4 l& F" [2 ^: I
  134.                         txd_state <= 3'd4;
    3 X3 L0 ^4 W& d- G( w
  135.                       end
      d& ]9 _* b* k
  136.                 3'd4:begin. C( X8 d. x5 S
  137.                         MISO <= txd_data[3];
    8 o* i! V6 y# H$ H) y7 n
  138.                         txd_state <= 3'd5;
    4 [% P5 x2 o' C# k9 H0 a  V6 h
  139.                       end' |# ?4 G. q: p9 F7 r& p5 L9 a
  140.                 3'd5:begin4 J% ~; o& l$ p! A$ |2 m6 u' Q
  141.                         MISO <= txd_data[2];
    6 _9 v: @8 K( C+ n- c
  142.                         txd_state <= 3'd6;
    3 ~+ H9 G2 k4 V
  143.                       end: I( Z0 P8 ]# ^% d) F/ ~
  144.                 3'd6:begin- H9 @. K# C5 ~2 g5 s
  145.                         MISO <= txd_data[1];
    " K1 h2 Q, l. z6 f
  146.                         txd_state <= 3'd7;" Q( H" ^$ [2 N; Z$ w
  147.                       end
    8 N5 X( X- u! g5 z# o/ S8 B  g
  148.                 3'd7:begin. t2 t# E0 [2 n3 ]# P/ V
  149.                         MISO <= txd_data[0];" G9 _. v( X: x1 I! |, ~# F
  150.                         txd_state <= 3'd0;
    2 I& |! s! k  Z+ |) n( ]. C; A% h
  151.                       end
    * o! b# h% U' K7 \4 [: c
  152.                 default: ;" s: R( M( u( W" Z9 l7 v  a6 O
  153.             endcase
    . Z2 t) j+ O2 k: A1 |
  154.         end
    5 R3 n- j7 H5 N* z& b0 |) o
  155. end
    & u, M  H" S/ Q% q% k: V

  156. 4 k) d. @1 z7 P" V
  157. 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
1 收藏 评论0 发布时间:2022-1-16 18:00

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版