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

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

[复制链接]
STMCU小助手 发布时间:2022-1-16 18:00
一.SPI协议简要介绍
SPI,是英语Serial Peripheral Interface的缩写,顾名思义就是串行外围设备接口。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。8 U+ P2 _2 K% u$ ~' p
  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拉低使能情况下。
: h* x) R! w6 d8 d; a
二.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发送数据与接收数据。
  M5 s3 B% |% e/ ]1 o3 z
  1. /***********************************************************************
    3 h, v3 j+ B; l6 {9 r6 y) c
  2.      ****************** name:SPI_Slaver_Driver **************
    $ e6 o7 {3 o  K7 O7 z
  3.             ********** author:made by zzuxzt **********
    2 r. M8 ?/ n# \3 }5 H+ O0 ^! [6 v
  4.      ****************** time:2014.4.29 **********************8 r% e% v- S- w9 y& N8 D$ r3 s+ ^
  5. ***********************************************************************/
    - i4 s1 u6 s1 M0 W
  6. //use SPI 3 mode,CHOL = 1,CHAL = 1
    - V; [+ N/ B1 m1 i" o( j  k3 q
  7. module spi(input clk,
    9 Y3 t0 {# ?2 x" x. u/ i1 e: v" G: N
  8.               input rst_n,9 N  G! Y( b  C) c
  9.               input CS_N,
    2 i; n7 G" Z) B3 F8 e
  10.               input SCK,
    ' k1 z* y2 {# ^
  11.               input MOSI,8 i# q6 a% A8 Q* n* p5 m1 J5 L! o3 f1 i. L
  12.               input [7:0] txd_data,/ b- z  u& C* u4 J2 x# O
  13.               output reg MISO,
    5 Z( A5 U3 n5 _/ [" `; f
  14.               output reg [7:0] rxd_data,
    8 j3 h" P5 [/ X) L. m' m6 l
  15.               output rxd_flag);   //recieve done,please transmit data
    5 R+ {! w$ d0 a/ b4 t+ u& g# w3 R
  16. 2 F' [" r2 [4 \7 O. f
  17. //-------------------------capture the sck-----------------------------
    ) [5 z- c  D- ~1 z) {
  18. reg sck_r0,sck_r1;
    7 P2 j" O, J" Z6 d+ v3 Y2 t
  19. wire sck_n,sck_p;& ^6 }5 t% a. P& d, C# ^. I* S2 P
  20. always@(posedge clk or negedge rst_n)
    . I/ {: v  x2 h/ ?
  21. begin
    0 X3 D3 d  R( ^8 B2 r' V
  22.     if(!rst_n)
    : k$ }9 ?0 G. _0 e2 M0 _
  23.         begin
    $ ]3 y" G; i- P
  24.             sck_r0 <= 1'b1;   //sck of the idle state is high3 Q% c$ [/ N  g8 W. f9 W$ ]- v) ^
  25.             sck_r1 <= 1'b1;3 R* h. K8 B8 t6 c& w" q+ A) e* \# X
  26.         end
    3 f, ?) Z1 U* u% Q
  27.     else
    / l' z% a, L4 B4 P9 [2 _# G
  28.         begin: _& _, |7 E3 i( ~7 ~
  29.             sck_r0 <= SCK;
    " F! F- R# R2 Z. F' a0 y
  30.             sck_r1 <= sck_r0;
    ! y( [' R# ?% [1 Q8 e# b3 @
  31.         end
    , i( `6 O7 v" a) m- F
  32. end7 z, k% v) ~2 K/ i/ f% X4 t. R

  33. 8 z4 C1 h7 b' Q5 r
  34. assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0;   //capture the sck negedge! F8 U. A$ B# \! ^
  35. assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0;   //capture the sck posedge4 J* ^9 e$ [% ^- d% |( [- z

  36. , q. S9 ]/ w1 k  w
  37. //-----------------------spi_slaver read data-------------------------------
    ( b4 A5 |% {% \/ t0 S+ x9 e, Q
  38. reg rxd_flag_r;
    ; |! l& a; F0 h1 [
  39. reg [2:0] rxd_state;
    2 n; |" _. K5 {. c
  40. always@(posedge clk or negedge rst_n)0 i9 s1 K& ^% f* X# U
  41. begin  j8 P6 B+ Y) k( H; U" k4 B
  42.     if(!rst_n)
    6 l, O7 P5 W+ B$ ]1 n/ I. W
  43.         begin3 I: f; z, k9 V3 r
  44.             rxd_data <= 1'b0;
    6 |4 P/ i* Q- I# }, d
  45.             rxd_flag_r <= 1'b0;% _* M% ^5 x6 C! x6 M  k  x9 r
  46.             rxd_state <= 1'b0;
    4 _8 F; d8 l1 p6 O) z# F* X
  47.         end
    7 Z1 L" B0 b& L+ q/ `6 Z
  48.     else if(sck_p && !CS_N)( B" a: e, q( R- ~4 Z! i
  49.         begin  J; x) Q2 f( ~
  50.             case(rxd_state)
    1 o, J# B) j0 D# h. B* K: `
  51.                 3'd0:begin
    8 V9 K* h! i  C3 m2 |5 M6 v. m% `
  52.                         rxd_data[7] <= MOSI;
    ' M6 w4 L8 `/ |& O# G- f
  53.                         rxd_flag_r <= 1'b0;   //reset rxd_flag
    + c- \$ q6 Q, _) k
  54.                         rxd_state <= 3'd1;  A% i' |2 E4 Z9 h; ?1 c8 }  \
  55.                       end
    5 C' p# F! \- J" ]( w' P
  56.                 3'd1:begin
      Q; d  W( p1 x) T0 c: r& f0 d
  57.                         rxd_data[6] <= MOSI;
    6 m. h9 y. u0 B, t- R) B
  58.                         rxd_state <= 3'd2;: C6 C' D! u" J
  59.                       end. Y1 u# v+ ]  i; ^8 |) I' c
  60.                 3'd2:begin
    + O7 E, r" {) |6 n& Z/ Z( g
  61.                         rxd_data[5] <= MOSI;
    % ~& Y. `8 P7 q- t) `' ?
  62.                         rxd_state <= 3'd3;% n! [  _. t% P, P
  63.                       end7 f+ u  {3 |: J
  64.                 3'd3:begin, j) @% y) |# K, c
  65.                         rxd_data[4] <= MOSI;, R3 R' k: t0 Y9 O
  66.                         rxd_state <= 3'd4;
      Z4 F7 ]9 X, a& E# d
  67.                       end
    ( u# s( s. j7 `$ J! g. J& |
  68.                 3'd4:begin+ c1 L( b* n$ N! F, J5 p0 x
  69.                         rxd_data[3] <= MOSI;
    2 A/ Q" a4 Q. T$ z% t) Q: n) j! W5 @
  70.                         rxd_state <= 3'd5;7 y+ l% C- P$ {/ w& U$ k
  71.                       end
    3 O8 C! f# d+ Y; ?  \
  72.                 3'd5:begin$ @- d- S, t) f# h5 N/ Y
  73.                         rxd_data[2] <= MOSI;* ^+ Q5 b2 ]5 @- |
  74.                         rxd_state <= 3'd6;
    4 B+ v# Q8 O: F. J  I7 m' y
  75.                       end
    & E1 w+ ?7 l% ?6 \5 x
  76.                 3'd6:begin
    # ?) {% [9 M. J) D; g& ?
  77.                         rxd_data[1] <= MOSI;" G" _9 ~" t! E  D- r1 W7 `
  78.                         rxd_state <= 3'd7;
    . ]" r, z$ d8 t% F( S7 F6 H8 k, h
  79.                       end
    ) {. ~8 b. k# ~9 }
  80.                 3'd7:begin, ]$ H2 C! ~% D' L6 E' p! b" Y
  81.                         rxd_data[0] <= MOSI;- a* P* o& N7 k0 d- F
  82.                         rxd_flag_r <= 1'b1;  //set rxd_flag3 }3 C3 x2 @. P  B
  83.                         rxd_state <= 3'd0;
    ' _6 v8 I2 G6 Y) [) z- |/ [
  84.                       end
    0 b) y$ A9 d$ \6 g) ^/ ~7 x( l2 n
  85.                 default: ;+ d6 [! G4 [' k3 F
  86.             endcase
    * i% n/ J, M' S& s  ?0 l
  87.         end6 U4 D3 }" p( D
  88. end$ j6 y/ Y( `! H) I5 H: F

  89. 0 @( Z7 @1 `& O7 E) g
  90. 8 b/ w5 a/ Z& h+ D5 R7 E; r
  91. //--------------------capture spi_flag posedge--------------------------------  c& ^0 @" L, A- T! N% h
  92. reg rxd_flag_r0,rxd_flag_r1;' f, H7 w5 b5 C! c6 E+ o
  93. always@(posedge clk or negedge rst_n)
    & a) S/ A& x8 l- Q; D9 E
  94. begin
      B8 u, `9 K& s5 t$ h/ ]5 _' s# w
  95.     if(!rst_n)
      [5 g$ P/ ^* }, K$ m* K( W! P) q
  96.         begin
    0 W" e* G, _/ N1 `0 X
  97.             rxd_flag_r0 <= 1'b0;( X$ H; n9 [/ v* r4 Q
  98.             rxd_flag_r1 <= 1'b0;
    # `3 `2 S* A* [5 Z( h
  99.         end% {8 B# M2 B% I9 ^) c
  100.     else- _" Q1 Q$ D% M1 I  i) d6 `9 B
  101.         begin" p# t# M; r7 m7 a
  102.             rxd_flag_r0 <= rxd_flag_r;
    + u) t! k1 a/ X4 l' U# o) ?
  103.             rxd_flag_r1 <= rxd_flag_r0;$ [& }' Y5 @5 ]' w' {  W% q
  104.         end/ V, U" h3 W5 B9 R: b* g  O/ |
  105. end& J: h: _7 u7 m) p, X0 s
  106. 1 ^* r! z5 Y( z# w+ `+ s8 t5 b2 t
  107. assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;
    : Q5 t8 c" E' ?. a7 @5 \& F$ l+ y
  108. * h7 H0 g* w8 T$ x8 I# q  h
  109. //---------------------spi_slaver send data---------------------------7 s8 K5 N1 c4 P* W
  110. reg [2:0] txd_state;* R/ B# c) |7 X% c! c
  111. always@(posedge clk or negedge rst_n)& w5 U4 x" X1 a+ j3 i+ k" q" B: A
  112. begin1 u) P1 i. Y5 f$ o) B6 Q6 K- M3 N
  113.     if(!rst_n)
    7 f( \; w* `9 S; x; ~
  114.         begin
    - {* D2 m0 u2 |3 Z5 R
  115.             txd_state <= 1'b0;
    & i, I5 y2 n: _7 J  \7 i
  116.         end
    0 \. h" C7 S$ `
  117.     else if(sck_n && !CS_N)% C( h. B3 X1 b: A# Y
  118.         begin. ^9 [& {5 D8 q' V8 K7 Y
  119.             case(txd_state)' d+ s, _# i: r
  120.                 3'd0:begin- \, Z# r1 W/ G6 g* M2 G
  121.                         MISO <= txd_data[7];
    ) p- U5 D0 _7 K, e9 f/ q0 Z
  122.                         txd_state <= 3'd1;& T( f1 m- L, s1 V
  123.                       end
    2 d$ d7 I" Z, m* K
  124.                 3'd1:begin  R: Y  X+ A  z9 ^& w
  125.                         MISO <= txd_data[6];# F8 M. b0 D& \
  126.                         txd_state <= 3'd2;
    - o% T. X! s" v( C) a$ [: O
  127.                       end
    ! T- n! F$ s5 A0 [/ R2 L/ _2 {
  128.                 3'd2:begin8 ^9 t4 `1 _- r8 i) F7 `
  129.                         MISO <= txd_data[5];
    . F: x$ x) R% F
  130.                         txd_state <= 3'd3;
    ' ~1 m. S3 v' S! r& G7 O
  131.                       end1 T0 h6 ^4 K8 V! R9 B6 {
  132.                 3'd3:begin# i+ V5 I. e. ^4 n5 V" |/ q; b$ \5 g
  133.                         MISO <= txd_data[4];% j0 Q/ a/ v9 L3 {1 e
  134.                         txd_state <= 3'd4;
    5 ]0 ~7 W0 P. }7 f1 R
  135.                       end8 Q9 I5 b( P* T( R1 R
  136.                 3'd4:begin
    0 Z& w  l/ f8 J. M
  137.                         MISO <= txd_data[3];
    9 \" g1 Q9 z4 v8 f1 S- z
  138.                         txd_state <= 3'd5;" Q0 ^/ a! {3 c; `1 o( V! M7 ], n
  139.                       end
    . c& f! i- f5 f' S7 A6 r
  140.                 3'd5:begin
    + i/ b1 S9 k# k/ a: ~
  141.                         MISO <= txd_data[2];4 ]" `, I) A; h- m9 ~
  142.                         txd_state <= 3'd6;
    & T$ s: ~+ W. D, p& z6 C
  143.                       end
    3 F+ Y3 l! K: g( ?
  144.                 3'd6:begin  T$ B- ?+ ~0 R
  145.                         MISO <= txd_data[1];
    - x; j7 I6 O% X0 e0 N, }
  146.                         txd_state <= 3'd7;" B6 s" ?$ W2 V& a( Q
  147.                       end. @" ^5 G' ?7 ~! Q0 V7 |
  148.                 3'd7:begin, \# d6 k: u7 N$ L) ?6 q
  149.                         MISO <= txd_data[0];' N& \$ n/ V; Z6 G
  150.                         txd_state <= 3'd0;
    % k& j+ D1 ^2 e9 g( [4 R; F
  151.                       end
    ' X! x+ m+ u: i+ t
  152.                 default: ;
    3 e; h' T, T* C
  153.             endcase" F: j# v( r" @
  154.         end' k$ x- Y. Y+ a( t9 E2 j; e, z$ v
  155. end/ g/ h6 O5 \4 I, d. K) ]

  156. / e& R7 E* N. G1 @  b+ X1 l
  157. endmodule
复制代码
7 f8 d) r5 h% V3 p; z) Z

6 t  @# y! T/ D( f0 s% p( C
) C! f' l. ]& L9 u* i, n

9 j; x( ^) Y) h. w" s8 F( s, y
赞 1 收藏 评论0 发布时间:2022-1-16 18:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版