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

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

[复制链接]
STMCU小助手 发布时间:2022-1-16 18:00
一.SPI协议简要介绍
SPI,是英语Serial Peripheral Interface的缩写,顾名思义就是串行外围设备接口。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。
+ C+ |# k4 E0 _4 N8 l# {! r  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拉低使能情况下。
' v1 A$ Z4 r" E: Q" y
二.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发送数据与接收数据。

; [3 V. `; l  y; S$ C6 \- q  K
  1. /***********************************************************************: W9 f' I$ G' k" }1 A: z& y, S
  2.      ****************** name:SPI_Slaver_Driver **************  L; J% t+ B8 t  J1 u& i
  3.             ********** author:made by zzuxzt **********  M/ N# S# X: J  V
  4.      ****************** time:2014.4.29 **********************
    6 I! x& W4 D! q
  5. ***********************************************************************/
    ' q% p& I6 X% N2 u0 W  |
  6. //use SPI 3 mode,CHOL = 1,CHAL = 1& Z  ^- K9 J6 Y0 o3 s& a
  7. module spi(input clk,% X- I$ k; S0 Y2 H0 O
  8.               input rst_n,
    ; Q: [4 n: h0 L  H
  9.               input CS_N,) M. D7 ^$ Y/ e3 R
  10.               input SCK,
    - L( N; {  j/ n+ h$ S, P% N6 y
  11.               input MOSI,; U' F! F7 O" F  y8 x2 E
  12.               input [7:0] txd_data,
    2 z4 C' {# [" \5 J0 C( v
  13.               output reg MISO,
    : A1 j* J5 y, U: n$ {
  14.               output reg [7:0] rxd_data,  J& E; y. V" Q& S$ }4 H2 M
  15.               output rxd_flag);   //recieve done,please transmit data# `# y5 I! M' _( N

  16. # @; }3 K# t, C! F: H
  17. //-------------------------capture the sck-----------------------------
    ! X. R' \# f, w
  18. reg sck_r0,sck_r1;
    $ I6 @+ Q1 r# ]& G
  19. wire sck_n,sck_p;
    ) H) ^/ d/ u9 C
  20. always@(posedge clk or negedge rst_n)
    4 x" l# u) o) W9 j8 C) y5 x8 Z
  21. begin
    , K0 S! ^$ P% [1 h# \% `; ^( V
  22.     if(!rst_n)
    ' }  Q% \& z9 S! R
  23.         begin
    % ^6 l4 a) G# n  h
  24.             sck_r0 <= 1'b1;   //sck of the idle state is high, F5 ]# Y( m8 w8 s
  25.             sck_r1 <= 1'b1;
    : G2 J! S3 c4 r0 t2 I* l
  26.         end
    + |. \  y/ _2 ?& C
  27.     else
    0 ?! J2 L6 I9 u+ p+ W3 X3 [
  28.         begin( u- [/ g# x( f$ }% Y, T6 A
  29.             sck_r0 <= SCK;$ Z  [1 @% a2 l, l7 V+ G  c, i
  30.             sck_r1 <= sck_r0;1 }! U0 o" c, h
  31.         end
    3 E$ C# q9 s5 Y) y
  32. end
    0 r7 W. e; e/ q

  33. 7 \2 y2 e" X" l9 e* R' x
  34. assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0;   //capture the sck negedge' a: I) v+ P( u
  35. assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0;   //capture the sck posedge- w- i& _+ I( _& `6 v2 j+ h9 r4 t
  36. & [* t9 X, q7 m1 g9 a( j7 d
  37. //-----------------------spi_slaver read data-------------------------------
    . c9 ?$ s4 ^0 ]4 \4 V4 n: b
  38. reg rxd_flag_r;, V# z% L8 o' _( w
  39. reg [2:0] rxd_state;
    + f* b! ]- Y* c1 x7 O
  40. always@(posedge clk or negedge rst_n)7 `6 k4 I" c0 |
  41. begin
    ' K* b% x/ D6 E$ _' I  ?
  42.     if(!rst_n)
    ) J; ~; c9 D$ s) N* ?/ s
  43.         begin+ e; i4 z6 ?( b' H
  44.             rxd_data <= 1'b0;
    " `0 V4 B/ I1 `0 S1 g" W* Z7 P# T& h# u
  45.             rxd_flag_r <= 1'b0;, @2 I3 U* v6 w6 V
  46.             rxd_state <= 1'b0;" W7 \  @) h3 s5 s: N; d3 r
  47.         end
    4 v0 m3 y. W( }5 |5 W
  48.     else if(sck_p && !CS_N)
    4 {2 W* U$ x: _3 O2 g- W% G* _  K' r
  49.         begin: Y0 O5 r/ f/ [9 H: `
  50.             case(rxd_state)4 D; k. Q/ v1 k: N
  51.                 3'd0:begin
    - i1 k& x. }0 s" \# y, V8 h
  52.                         rxd_data[7] <= MOSI;' l" {' O& Z3 T4 Q
  53.                         rxd_flag_r <= 1'b0;   //reset rxd_flag
    ! X' v1 s* ^; I! W/ O  D
  54.                         rxd_state <= 3'd1;- T  t4 C& Y, S. h
  55.                       end9 L$ O! B$ G) |" I
  56.                 3'd1:begin
    3 ^' \; p6 @! T( C0 o
  57.                         rxd_data[6] <= MOSI;
    ; a) I2 h* E  F( \
  58.                         rxd_state <= 3'd2;8 t' |# w" }7 s/ B" {* [: k
  59.                       end
    9 s8 ^) g& W5 _( D% w- A
  60.                 3'd2:begin
    1 G& c* F/ V7 |/ Z( a7 n
  61.                         rxd_data[5] <= MOSI;
    + L! S' R$ [: P. q. H' k* O
  62.                         rxd_state <= 3'd3;9 |* D5 G6 U3 w  H0 g
  63.                       end
    * B8 G$ g* K. p/ ~, ]: U
  64.                 3'd3:begin$ f/ M& q3 @; Q5 A$ q
  65.                         rxd_data[4] <= MOSI;! p% u  s( @9 {3 U4 d
  66.                         rxd_state <= 3'd4;  \) B( A6 ^+ T/ ?& Q; z% L9 r
  67.                       end3 H' f0 a5 I& j1 w( Q
  68.                 3'd4:begin3 }$ G- K/ V0 @
  69.                         rxd_data[3] <= MOSI;
    / F8 }2 g& t1 e2 H; Q
  70.                         rxd_state <= 3'd5;- `0 l/ Z! J" j8 W; H3 g
  71.                       end* j  d2 x- |- x
  72.                 3'd5:begin
    $ Q; m- e# z' G: X. g
  73.                         rxd_data[2] <= MOSI;  @  b" m, e9 G
  74.                         rxd_state <= 3'd6;
    7 q# O& p) M* q7 v& ]% \3 w
  75.                       end( t& h9 J: z: E% i3 f3 C
  76.                 3'd6:begin
    ; r  k2 N2 b6 ]+ Z3 X9 d; b1 `
  77.                         rxd_data[1] <= MOSI;
    5 X1 q* `' W4 k
  78.                         rxd_state <= 3'd7;
    - `  f9 c- y: R- {9 E2 g6 Y' p7 }
  79.                       end3 D, G  J5 y# X5 b* G5 _5 }" z
  80.                 3'd7:begin
    # [- f) g- u, L" E$ k. {
  81.                         rxd_data[0] <= MOSI;5 A/ N% q1 s, k" Y) L6 r/ |
  82.                         rxd_flag_r <= 1'b1;  //set rxd_flag
    ' ?& X. c  W5 S% |2 @
  83.                         rxd_state <= 3'd0;" {6 G' Q# U5 b  i& {6 j" B6 ?
  84.                       end( R  a* M2 E+ l  }, x6 z
  85.                 default: ;% W9 o7 ?( Z  s9 u$ n
  86.             endcase
    6 ^4 H( T# V+ W* h
  87.         end7 p* a4 T/ P" b2 ^' }8 ~. V/ N8 p
  88. end
    + ~3 [; Z- h2 {% {5 d+ ^" d
  89. % V$ f$ }7 I$ O" A' C- |4 T3 {

  90. + b& l& y) ]' b$ G- r& z* }
  91. //--------------------capture spi_flag posedge--------------------------------
    . \/ q; s# B- e7 l" Z
  92. reg rxd_flag_r0,rxd_flag_r1;
    5 |. `- `( V8 ?- v" A, w) {5 k! M9 v
  93. always@(posedge clk or negedge rst_n)
    ; j0 P. Z' d5 N- W
  94. begin
    # r; ?. n( i( E8 Q" q4 O) u' q
  95.     if(!rst_n)
    8 N$ J, l1 c. X5 `4 Z# `2 b/ T
  96.         begin
    ) a4 s; P3 s& ^/ @. `* E
  97.             rxd_flag_r0 <= 1'b0;' z% _. Y) j1 K0 [- h
  98.             rxd_flag_r1 <= 1'b0;( ^9 h' ~4 ?3 {0 Z) k: J
  99.         end
    8 X0 B  s7 i; K% u
  100.     else
      l8 b  P2 T& }5 P( E
  101.         begin
    4 _2 u3 D- t: L2 h+ e0 O* V9 n4 t1 B+ ?' L
  102.             rxd_flag_r0 <= rxd_flag_r;
    ; U. ]6 Y9 S% N2 [; e8 S* N
  103.             rxd_flag_r1 <= rxd_flag_r0;
    7 `# k" h' _( Y9 V& _3 I1 h8 z
  104.         end
    4 K1 W3 c/ w8 {2 \2 W. o# N: _4 _
  105. end8 O* ]$ L) M' T  U

  106. % r2 {/ V& R# \, u: W0 ~
  107. assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;/ D7 z3 `% U, K
  108. $ t0 v/ v+ J* W* o6 Z! L
  109. //---------------------spi_slaver send data---------------------------
    6 E: f( }3 G0 R: Q# m
  110. reg [2:0] txd_state;
    1 e! ~5 C3 \8 _0 q# z) Y
  111. always@(posedge clk or negedge rst_n)+ v' C6 k- T# g% I- R9 H( j( c
  112. begin
    3 C( s: n, y, P8 T4 H
  113.     if(!rst_n)
    / t9 ?$ s4 ?& M
  114.         begin* I# Y, H6 Z/ O4 A2 @4 @" Q  s
  115.             txd_state <= 1'b0;
    ; {) t; x3 ~6 o8 ?4 x
  116.         end1 @  ^. k( e! Y/ \0 t, ^7 z) h
  117.     else if(sck_n && !CS_N)
    . f% K: Z. D- u. u, L
  118.         begin" ]+ r. p" g" @6 q. a
  119.             case(txd_state)
    $ o' F: B2 }" U
  120.                 3'd0:begin
    6 l. A( C* U' m2 F& e! h( y# I
  121.                         MISO <= txd_data[7];
    , l3 H" ~7 h2 s# e) ~$ s7 i; k5 K
  122.                         txd_state <= 3'd1;1 i% D/ d5 F; W$ a3 p0 Q; X# s
  123.                       end
    9 r0 x' N' e+ e+ |% A
  124.                 3'd1:begin
    1 E7 o0 Z0 P! o
  125.                         MISO <= txd_data[6];
    9 B* i( Y+ G- a1 u- R
  126.                         txd_state <= 3'd2;
    / R9 X9 T5 \* ?  K  m9 o
  127.                       end) n; w8 O6 x% ~2 B% h
  128.                 3'd2:begin) X( E2 G0 m8 T1 H
  129.                         MISO <= txd_data[5];$ P' s0 c; u$ z6 F& o/ c9 i
  130.                         txd_state <= 3'd3;$ v6 l/ B4 F/ P+ h* b! W
  131.                       end. _; d3 M) T) D5 ~. \) I0 J5 [
  132.                 3'd3:begin9 F$ e% T: B" x8 ?
  133.                         MISO <= txd_data[4];+ H0 X3 g  i+ m1 a
  134.                         txd_state <= 3'd4;# }# ^  u- H2 x. G! ~
  135.                       end: ^( a! x" d4 Y$ F3 H
  136.                 3'd4:begin
    , b/ }, Z! e3 K& o& ^( _; S
  137.                         MISO <= txd_data[3];0 Y& q7 F. [0 a9 {& ^) ~
  138.                         txd_state <= 3'd5;& ^/ O8 {' k/ c, U/ s) h
  139.                       end, i- _7 v6 c3 f7 i$ u
  140.                 3'd5:begin
    : o/ O$ [! z0 `1 ?
  141.                         MISO <= txd_data[2];( Z  Z3 b2 S7 t. ^( \
  142.                         txd_state <= 3'd6;
    " y9 u" ?2 u% _9 F0 s9 {0 Q
  143.                       end2 \1 S  }  m2 ~% X" v- B1 Z& \- b
  144.                 3'd6:begin' Y9 ?3 b& A: b2 B, Q
  145.                         MISO <= txd_data[1];; t0 O) I! X3 {4 I# |
  146.                         txd_state <= 3'd7;
      ]! c3 C+ E' @) A% I3 J: D
  147.                       end8 M# D/ y7 k9 ~" ^
  148.                 3'd7:begin- U$ r+ B, M% S
  149.                         MISO <= txd_data[0];% Z5 ]9 ]7 j& j* S& j- p
  150.                         txd_state <= 3'd0;
    1 p8 u: r1 V6 h) N, X5 B
  151.                       end
    , x- a9 O: @1 G  X" }/ \
  152.                 default: ;
    1 B) l# h# @0 d& c5 Q4 n
  153.             endcase, E+ Q( u2 k1 C7 [- B  J
  154.         end
    / v4 v5 K5 f$ `) P+ S3 y- b
  155. end6 V9 \9 V8 ~7 [3 [, c& W3 a4 G1 U

  156. 0 n; c9 w8 z3 ]/ n
  157. endmodule
复制代码
+ i) f: {2 b5 n* i+ U: L: C9 ^9 y
+ X5 m9 Q0 l5 A+ g  x

! \4 d- N) M0 }% D

% i' g0 c, n3 F/ y
1 收藏 评论0 发布时间:2022-1-16 18:00

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版