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

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

[复制链接]
STMCU小助手 发布时间:2022-1-16 18:00
一.SPI协议简要介绍
SPI,是英语Serial Peripheral Interface的缩写,顾名思义就是串行外围设备接口。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。
4 E; q; N# g) J1 G! J: {  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拉低使能情况下。

2 I6 [% E: d( ]0 g
二.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发送数据与接收数据。
% @7 M( z1 {+ t0 H6 q
  1. /***********************************************************************
    # c) a% j0 G6 ?' n1 d7 e$ p6 @
  2.      ****************** name:SPI_Slaver_Driver **************
    * _9 D& F) f$ U7 C: l7 W  U
  3.             ********** author:made by zzuxzt **********
    6 B) e1 t' D4 Z: y2 O6 }
  4.      ****************** time:2014.4.29 **********************( F: D$ m6 _) |
  5. ***********************************************************************/
    ; _' V5 Z6 C: y$ c& y
  6. //use SPI 3 mode,CHOL = 1,CHAL = 12 p0 F$ r0 c1 `7 P5 n
  7. module spi(input clk,* B0 L; e/ [/ m* s4 b! v( P
  8.               input rst_n,
    2 R6 T/ }" i2 Z; c" }
  9.               input CS_N,
    7 P' m/ r7 }9 U! l" Z4 L
  10.               input SCK,! ]5 t4 C4 f, k0 @% Q/ r
  11.               input MOSI,
    - T" q9 b4 d; K8 ~
  12.               input [7:0] txd_data,
    % n" c+ R( A; N8 G7 y. N7 Z5 U
  13.               output reg MISO,  X% D# J5 B1 u
  14.               output reg [7:0] rxd_data,% e  W, f+ c8 |, z8 S
  15.               output rxd_flag);   //recieve done,please transmit data
    " L* V6 t7 n/ y6 Q- C" x5 ?* o

  16. * L+ T# I6 T# O  j: u2 ?4 t, Q
  17. //-------------------------capture the sck-----------------------------, G* ?/ W, p  I: m
  18. reg sck_r0,sck_r1;
    # E! t7 K; `$ X8 G9 Y4 M  _
  19. wire sck_n,sck_p;1 F" L/ I% x: Z' b* B9 t
  20. always@(posedge clk or negedge rst_n), i" Y1 P; q2 h# L( T
  21. begin
      b* r7 k9 R1 i* F# g7 b
  22.     if(!rst_n). r2 c4 A# v  E$ p; ]
  23.         begin
    , _- |1 d8 i5 H  |
  24.             sck_r0 <= 1'b1;   //sck of the idle state is high
    " ?* \- ^6 g' M4 M
  25.             sck_r1 <= 1'b1;% j2 R" A6 E. i& O4 L: \, w
  26.         end& Q6 N7 w4 [( z, q% o
  27.     else
    5 J" y( a7 F3 k( A7 d! }3 E
  28.         begin
    , ~) x1 W3 y8 d; d! W! n
  29.             sck_r0 <= SCK;- ]. o" n3 I7 @8 U
  30.             sck_r1 <= sck_r0;4 t5 h9 n+ m7 H- n
  31.         end# o6 R, Y+ k4 ]2 V1 E2 R
  32. end- E% S# |( L$ N( s1 k2 r' F# D/ \$ L: ~4 Z

  33. 9 X  N+ K9 R9 o; x; B
  34. assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0;   //capture the sck negedge9 M1 Y7 ?8 _5 @8 u7 \8 |5 ~
  35. assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0;   //capture the sck posedge
      o& S" c3 d3 N: L2 `

  36. " i( S  B" Z/ L/ Q' E/ z1 k
  37. //-----------------------spi_slaver read data-------------------------------
    7 C5 B. }5 A  w+ |7 `: D  m
  38. reg rxd_flag_r;
    0 s8 a( N9 }, w  u% O# e
  39. reg [2:0] rxd_state;
    7 o# z* O  t4 b; M6 ^0 ]! q" T
  40. always@(posedge clk or negedge rst_n)
    / J. [" W# }6 l- A8 L% u6 [# a
  41. begin
    5 E  E. C( D0 A: Z7 L
  42.     if(!rst_n)6 _4 h6 c% a% e! y5 _" [( H. P" R1 T7 T
  43.         begin6 `5 i  f* F1 r* C" ^- W  C
  44.             rxd_data <= 1'b0;
    2 U- g  ^& @7 O; y" q/ O  O5 W, Y1 s
  45.             rxd_flag_r <= 1'b0;5 @/ F$ Z! ?$ T- _; T3 V
  46.             rxd_state <= 1'b0;
    + h5 ]7 t9 Q$ q8 e- i/ \, [8 N1 r
  47.         end$ ]; V5 u/ y9 U/ I2 F3 n6 C. s; G
  48.     else if(sck_p && !CS_N)2 M; H* X$ i' t8 j
  49.         begin5 h- B5 N. z. \" m6 S1 {
  50.             case(rxd_state)$ D# o" E% m) i& L
  51.                 3'd0:begin- I8 w5 A2 f/ G' z' z, ~
  52.                         rxd_data[7] <= MOSI;, n7 Y7 d* j: g- X, v
  53.                         rxd_flag_r <= 1'b0;   //reset rxd_flag
    2 F9 b1 p3 s% A1 t
  54.                         rxd_state <= 3'd1;6 K% R. y7 e% Y1 O" }% |0 F
  55.                       end
    0 ~5 p" f8 J1 O) @' I
  56.                 3'd1:begin  |5 \  r1 r, E; o* a" Q
  57.                         rxd_data[6] <= MOSI;+ G) l3 t1 h) s" ]& G/ q9 L1 E2 S
  58.                         rxd_state <= 3'd2;
    6 U  }8 T% E0 b! }4 G' H4 A
  59.                       end5 [: o( u) m9 ~2 E4 p$ H
  60.                 3'd2:begin
    . N7 ]+ v+ _) G" o
  61.                         rxd_data[5] <= MOSI;
    $ r+ o3 Z& ]( \7 i6 h
  62.                         rxd_state <= 3'd3;! g& ^0 g* j/ l5 z/ w, G
  63.                       end! A; }; n8 j5 c) ?7 L; y! T! D
  64.                 3'd3:begin
    7 k" e, R3 K8 P' ^, N
  65.                         rxd_data[4] <= MOSI;
    % c( V5 p5 i; e& A
  66.                         rxd_state <= 3'd4;
    ) ~& }5 t, {- F
  67.                       end
    % `" N/ X& Y/ p: }2 e1 I
  68.                 3'd4:begin2 F% }9 p, a& v3 ~! G9 k
  69.                         rxd_data[3] <= MOSI;; \% \7 p" g8 M; F" y. Y! p! i
  70.                         rxd_state <= 3'd5;
    - n- R; A: c0 N9 f
  71.                       end
    ) P8 t+ {, Q9 a9 W0 e/ o5 w) _
  72.                 3'd5:begin
    6 P4 B; n0 {; F4 Z" D( U" @
  73.                         rxd_data[2] <= MOSI;6 C# V" u6 e( N. s
  74.                         rxd_state <= 3'd6;5 {- c, j# z) [" Q2 L
  75.                       end
    ! Z# Q" g" }/ |" B
  76.                 3'd6:begin& e2 x7 N& n* d
  77.                         rxd_data[1] <= MOSI;
    / Z. j7 B; T* q; y! N" a, [- V
  78.                         rxd_state <= 3'd7;
    + ~& d* c" p$ G8 e8 N# J- ?4 s
  79.                       end
    ( C( O3 D+ v, J$ ]% R
  80.                 3'd7:begin
    9 [6 z- L( I+ _7 P
  81.                         rxd_data[0] <= MOSI;
    6 I' t2 x7 A+ @* }) n
  82.                         rxd_flag_r <= 1'b1;  //set rxd_flag
    8 N1 a1 i9 B9 v$ \. v, _8 f' `
  83.                         rxd_state <= 3'd0;. W' \6 ?6 p4 ?: F; Q( B
  84.                       end
    8 Z  v# t- B- |, c  o" V
  85.                 default: ;
    7 E& b* x/ @' r% ~1 o; ^7 _# E6 m
  86.             endcase
    6 m; t+ q1 X+ Q. S+ |2 Q
  87.         end
    4 d6 }3 ^% ^6 V
  88. end- [! ]8 I0 e, I
  89. ( E8 N# W; x% d& l: A- {4 L" x
  90. 5 k5 _) K2 l5 v* I8 V: O
  91. //--------------------capture spi_flag posedge--------------------------------
    . X; g. w' s. K* n8 B
  92. reg rxd_flag_r0,rxd_flag_r1;
    $ L# |' b4 d5 R$ L
  93. always@(posedge clk or negedge rst_n)3 W1 n% u, l% @8 m. S$ i
  94. begin0 A3 y- ?6 E* _0 n3 Q4 Z' |. |! y
  95.     if(!rst_n)1 Q- G( x# \" B8 F9 {
  96.         begin
    % O3 l* ~$ w( W0 t  h4 Z; b% C% S
  97.             rxd_flag_r0 <= 1'b0;
    2 R/ e5 {  Z. U) @
  98.             rxd_flag_r1 <= 1'b0;0 {/ C' a5 Z% w5 j; J, R  g( ^9 ]' C1 h
  99.         end
    ) K7 X  I4 i; ^1 N
  100.     else
    : r9 I0 Q, F' E
  101.         begin
    , Q* n0 q5 c2 Y" S+ o
  102.             rxd_flag_r0 <= rxd_flag_r;
    ) f; t7 F( b+ s/ |4 k: P
  103.             rxd_flag_r1 <= rxd_flag_r0;; k5 Z- C. |+ s. g
  104.         end, u! @, L# Q& @0 m' U
  105. end
    # g5 |) _( T3 \1 U6 U  g5 p1 k

  106. 1 h1 p: ^* F2 m$ I# M1 R, O
  107. assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;" H* [5 K% N: ]7 t

  108. 7 Q, u7 R; I8 T5 N* P5 Y
  109. //---------------------spi_slaver send data---------------------------
    2 {2 l9 f3 e' H( U  Z
  110. reg [2:0] txd_state;
    4 c+ z1 J, L  ]
  111. always@(posedge clk or negedge rst_n)  B3 ?  K* Z4 X4 j4 I0 L6 b, \5 G
  112. begin. O# u) O6 S% m- V: h; b0 P8 Q
  113.     if(!rst_n)
    ; h0 N+ A% S( ?: o# @
  114.         begin% j0 R4 C/ x; L
  115.             txd_state <= 1'b0;2 d7 b7 Q8 ]2 \: F0 \
  116.         end
    4 T0 A  V: ~1 \7 }+ n2 r; ~2 r& d
  117.     else if(sck_n && !CS_N)
    $ j8 d0 ]/ z3 l  O" h* d7 k
  118.         begin
    * i2 U* C$ B- B1 w9 g2 u
  119.             case(txd_state)
    : s! M6 k2 U7 b
  120.                 3'd0:begin
    % I- v1 |" o& M! v! d' e- z; H6 R
  121.                         MISO <= txd_data[7];2 @) j8 P1 |, U7 T& M8 I4 ?: Y
  122.                         txd_state <= 3'd1;/ C! A) a5 `" T. v$ f
  123.                       end3 m& W6 z( l7 T
  124.                 3'd1:begin# k8 H  ^& W5 {
  125.                         MISO <= txd_data[6];6 `0 H% u1 Z- p7 M  Z- v
  126.                         txd_state <= 3'd2;
    0 Q8 }* n7 t8 ^/ x: r
  127.                       end
    ( l: r0 c$ Q3 U9 k: T* h- g/ H
  128.                 3'd2:begin- G& ]: D( X2 J5 z. ~7 Z
  129.                         MISO <= txd_data[5];
    " i6 Y! I* G' d1 x2 R6 S
  130.                         txd_state <= 3'd3;
    , a7 O4 D& q& I; R
  131.                       end0 O6 n" Q: W9 M* g5 @& q
  132.                 3'd3:begin5 Q6 Q4 Q2 t$ L7 c6 }
  133.                         MISO <= txd_data[4];  m1 u+ S$ T; `6 G- L- ]" [% e
  134.                         txd_state <= 3'd4;
    2 D+ \: J1 h( S1 {. n0 f1 m% y( G* i& w
  135.                       end
    3 Q3 U' n/ v( T0 C1 K* N$ X
  136.                 3'd4:begin
    3 `$ |# O/ j" a" h, j; q
  137.                         MISO <= txd_data[3];
    - O9 ?) I; ?0 L$ }; w+ P1 s- v9 P
  138.                         txd_state <= 3'd5;
      D! X# U2 s' w
  139.                       end
    4 b' e# ]% c9 J$ d" E' |% O
  140.                 3'd5:begin) _1 {# |* x, ?
  141.                         MISO <= txd_data[2];
    * c6 {$ V3 e; q
  142.                         txd_state <= 3'd6;
    ) S+ e% h/ U# `
  143.                       end
    4 p) O4 ?/ D, a4 b& Z! \
  144.                 3'd6:begin3 ~) x$ P) @, X( \
  145.                         MISO <= txd_data[1];
    ! W1 _/ E/ X4 Q% \- G
  146.                         txd_state <= 3'd7;
    " R% Y7 s) r% {5 E6 n
  147.                       end
    . P: P5 \% x: Q7 q9 _. K! k' V' d
  148.                 3'd7:begin
    ( \. O. l; i+ @# s% |
  149.                         MISO <= txd_data[0];
    ! ]# g0 ]  Z: I5 a% d' R
  150.                         txd_state <= 3'd0;1 `8 H% h% I1 b! a6 G4 ]0 }, I- ?
  151.                       end
    # [6 P6 A8 m5 d/ b9 U( B
  152.                 default: ;
    ) P5 h5 e6 @5 e' M' H1 Y$ U) \
  153.             endcase
    8 J* s% w5 q- s* i! ^, ^) |0 d
  154.         end. b  f0 z. O. k# {) F
  155. end
      l1 g: _6 D4 `( p) K( Z0 ]
  156. $ u$ _7 A8 n2 r) n
  157. endmodule
复制代码
3 I+ }2 u% Q: Z4 Y+ k7 q
# B2 {# S9 d) \. a+ v. _. \. j
; e3 l* w$ C9 N

. z' B; }( i5 j& |% l# S, ?
赞 1 收藏 评论0 发布时间:2022-1-16 18:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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