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

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

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

# J$ v  l% j% ^0 Q9 \1 j3 |
二.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发送数据与接收数据。

0 q& j1 `3 g( m6 Y
  1. /***********************************************************************2 T- Y& \3 m) w
  2.      ****************** name:SPI_Slaver_Driver **************
    % {: [/ Y* j! D% E! _; B; |
  3.             ********** author:made by zzuxzt **********
    ' q+ {1 D% q  \  s! M, r
  4.      ****************** time:2014.4.29 **********************5 G  {  U* D0 T" }
  5. ***********************************************************************/
    ( J1 U+ O% Y% c% o) E) P
  6. //use SPI 3 mode,CHOL = 1,CHAL = 1% s% O* t1 L- q) Y8 V
  7. module spi(input clk,
    7 L% x! t5 ]3 O' x0 Y% x
  8.               input rst_n,4 h. p2 O# @" b, p
  9.               input CS_N,1 ^7 Y! e! J$ w8 ?" o
  10.               input SCK,
    ) V' d9 u) v# ~2 R0 K0 j9 s
  11.               input MOSI,
    ) n" e) S7 v5 _* }) L
  12.               input [7:0] txd_data,9 j+ Z7 `4 F" K% |- M
  13.               output reg MISO,
    % W' T. S2 s- v
  14.               output reg [7:0] rxd_data,+ i& V/ b) ~2 v, n" h
  15.               output rxd_flag);   //recieve done,please transmit data
    ) C+ u+ _/ N8 ^5 C7 T' M! c& `

  16. 0 w) U/ K+ K; u' O; m6 S
  17. //-------------------------capture the sck-----------------------------
    : P; J& f7 X0 ^; n6 ]1 G
  18. reg sck_r0,sck_r1;0 l& L/ X# x& R$ J1 u
  19. wire sck_n,sck_p;
    ( Q/ Z) P( t$ T6 B
  20. always@(posedge clk or negedge rst_n)
      s4 _" S" J6 [% |- I6 E
  21. begin
    ( q" o% q8 N5 Q5 Y
  22.     if(!rst_n)* H+ u7 c7 ^' r1 f& i5 M7 t3 ]
  23.         begin
    9 I$ ~; _" j/ O8 f
  24.             sck_r0 <= 1'b1;   //sck of the idle state is high& _8 r9 T# S  d( |
  25.             sck_r1 <= 1'b1;
    . c( ^' L3 g) i+ }
  26.         end
    7 Y7 H# {6 F: o/ P2 S
  27.     else
    - o/ E8 Q. |  ]2 Q6 P
  28.         begin
    # }0 @* u- a( h/ n8 K
  29.             sck_r0 <= SCK;
    1 f) j: d& ], i& q
  30.             sck_r1 <= sck_r0;
      U/ ^! o  f* `$ s0 [$ A
  31.         end
    ) W7 }# c6 H9 l
  32. end4 E+ x' e- h. B5 n9 g8 s) p% i

  33. ' ]& {! s4 i+ y
  34. assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0;   //capture the sck negedge
    ! A. c+ m0 M) w. J, o
  35. assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0;   //capture the sck posedge' \$ J0 b* H2 T  b

  36. - @5 s8 d+ h; }  X. s
  37. //-----------------------spi_slaver read data-------------------------------$ C& x3 b) l9 b! ?5 I2 y
  38. reg rxd_flag_r;
    ( S2 X6 {! f7 L( M( @9 T$ C
  39. reg [2:0] rxd_state;2 i9 P; ]$ {4 s8 [
  40. always@(posedge clk or negedge rst_n)
    2 E! ?8 a% m% o% \! I8 S" I, q
  41. begin
    + w/ ]  u8 C4 s! n% \
  42.     if(!rst_n)
    6 b$ [/ f7 p3 L+ n) n6 f
  43.         begin1 I' z: c0 E  _* b) ?/ c8 f
  44.             rxd_data <= 1'b0;5 m% g- Q# I0 t* X
  45.             rxd_flag_r <= 1'b0;) }7 t$ D! o+ T  R* z% W* x4 Q
  46.             rxd_state <= 1'b0;* k. F4 N6 z+ X- J0 {
  47.         end
      c0 P: j" N# T( v
  48.     else if(sck_p && !CS_N)6 B/ x! H, W# r0 [' f8 p
  49.         begin
    2 f$ `8 \% \( z0 D( D
  50.             case(rxd_state)
    5 R+ S7 q1 K+ r2 D9 n) L! i
  51.                 3'd0:begin8 V( H: ^" K4 g" h( i  {+ B- o8 k+ D
  52.                         rxd_data[7] <= MOSI;
    ) ~0 h2 L3 C% r" j; s; L) ?
  53.                         rxd_flag_r <= 1'b0;   //reset rxd_flag5 d" X3 @2 Q  a
  54.                         rxd_state <= 3'd1;
    $ c: |0 D+ e) E6 t+ f
  55.                       end+ E* }/ p! [2 p
  56.                 3'd1:begin: E. `' P7 E3 \( {# c# @/ T* b
  57.                         rxd_data[6] <= MOSI;
    7 x6 G7 x4 p% w  }: i9 }' Q
  58.                         rxd_state <= 3'd2;* f' J9 k' V6 U" |$ p  J0 z$ u
  59.                       end
    " D* z+ @  C8 c+ X
  60.                 3'd2:begin
    9 k9 X! S- h9 B: _
  61.                         rxd_data[5] <= MOSI;2 M* y' L( M% L/ T
  62.                         rxd_state <= 3'd3;
    & J5 b1 w% u6 U: z. Z: A
  63.                       end
    6 u$ b' m! H; K9 f8 b# e
  64.                 3'd3:begin
    + V: e8 @' T5 A: J. I2 d* B* I
  65.                         rxd_data[4] <= MOSI;
    # p: b- F5 E* V  c6 e% x- E% a
  66.                         rxd_state <= 3'd4;, ~; U2 ]6 t( H. F6 r# \
  67.                       end
    4 L! z% U  R* i  u6 d
  68.                 3'd4:begin* v* B9 t" F1 o" Z
  69.                         rxd_data[3] <= MOSI;/ j5 y5 f$ A0 `2 V: m
  70.                         rxd_state <= 3'd5;7 B; o- [3 F: |. p, b
  71.                       end
    ! _2 ]2 [9 ]4 i! l4 n1 w& r
  72.                 3'd5:begin- c* A* z4 L& `& ~2 @
  73.                         rxd_data[2] <= MOSI;4 W! @  z  \8 E! [; B! ]
  74.                         rxd_state <= 3'd6;
    . L( j% e0 L0 _8 F5 R! \: T+ K
  75.                       end
    2 x6 N! g0 t  |; i
  76.                 3'd6:begin
    5 z) Z( J5 I, Z2 K* l0 K+ `# L
  77.                         rxd_data[1] <= MOSI;7 g, B% a4 M! K- A' \
  78.                         rxd_state <= 3'd7;4 D% g, _4 B2 _# T
  79.                       end
      Q/ l! p$ K0 V' g+ n
  80.                 3'd7:begin/ z$ S+ ^8 T; q
  81.                         rxd_data[0] <= MOSI;* k$ p% }3 c6 U$ z& x
  82.                         rxd_flag_r <= 1'b1;  //set rxd_flag
    - L6 F4 W( i5 Q) ~  a
  83.                         rxd_state <= 3'd0;
    4 ~& J6 X* N$ x% e: D. F
  84.                       end2 @. p! A# k: m8 Z4 p" s
  85.                 default: ;
    ; ?/ K) \% A1 y
  86.             endcase
    - a. O' [% @7 x, m, Y
  87.         end
    & N" x) Z. {  c1 C. u# a/ i& }
  88. end# c1 j& x/ b0 N  Q. s5 w

  89. * Z  {- u( K# |/ k6 d2 R, l0 n6 J
  90. 8 l' X5 P( ^% N, {: y4 G
  91. //--------------------capture spi_flag posedge--------------------------------# @. E1 P; p( }2 W6 @
  92. reg rxd_flag_r0,rxd_flag_r1;
    " ~' l- q" W% u" N8 Q
  93. always@(posedge clk or negedge rst_n)
    : S, v' |) f! e3 Y" ?7 u
  94. begin6 m9 H- a" F$ e. d# e
  95.     if(!rst_n)
    / T3 m3 H/ ^# i# m( V
  96.         begin' X' {/ v  n2 D8 z8 f0 n  w
  97.             rxd_flag_r0 <= 1'b0;
    $ g4 p, D8 {) g
  98.             rxd_flag_r1 <= 1'b0;
    3 I  |3 r3 p' B! {/ w9 n
  99.         end
    1 \; W1 P0 H' j- q
  100.     else% i7 G$ F; G, H' i" a- K: n
  101.         begin& n+ Y, c7 d( Y- ]4 t. {2 G
  102.             rxd_flag_r0 <= rxd_flag_r;
    * M: P/ ^6 [3 L
  103.             rxd_flag_r1 <= rxd_flag_r0;
    0 o" u, N- `5 _* _* ]# Z
  104.         end
    & s% c( q/ D3 `  Z
  105. end
    2 H# p7 W$ c0 ~: D( S* G
  106. * W5 t: H& ]! }2 E3 o0 j! ^% h' t; u
  107. assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;9 {% T) t2 H* R6 R) h" |% s
  108. 3 _# g2 m1 \( m
  109. //---------------------spi_slaver send data---------------------------
      J9 O1 W/ K9 ]* o
  110. reg [2:0] txd_state;. g; o! X2 s8 _( Q0 i
  111. always@(posedge clk or negedge rst_n)% A) _2 X3 B! u5 j( G: [
  112. begin. s3 }. D4 M  k* w0 O
  113.     if(!rst_n)  ^) T2 l  o3 K5 `* u; a
  114.         begin
    6 H0 O9 u4 P$ n4 F3 o. G& u
  115.             txd_state <= 1'b0;" [$ B" R7 R- }& {1 v
  116.         end/ E% W) s: I+ U
  117.     else if(sck_n && !CS_N)
    5 k: j9 ]5 }9 X2 ~5 N' a$ E
  118.         begin2 ]; |) S0 ^5 u3 E( w- E/ N
  119.             case(txd_state)
      m/ N4 M1 b8 g. V3 G6 }" a9 I
  120.                 3'd0:begin
    7 X" u! i: G# Z5 L" P
  121.                         MISO <= txd_data[7];' T8 E& G8 I* S  f3 C
  122.                         txd_state <= 3'd1;$ D( v4 J3 F! ^
  123.                       end
    5 X, i- E' L8 P0 `6 J/ i/ K# Z
  124.                 3'd1:begin6 r' c* X: q2 E1 \6 B( u
  125.                         MISO <= txd_data[6];
    4 _$ H2 o+ J/ F8 p" R1 A! x
  126.                         txd_state <= 3'd2;
    , Q  p' P  Y% S$ z1 B, x) X6 d
  127.                       end3 `1 d# O/ S1 }9 Z1 m2 I
  128.                 3'd2:begin" D: B6 `4 A7 v. w6 ^$ z, q9 a
  129.                         MISO <= txd_data[5];
    $ v. S' \# q) C
  130.                         txd_state <= 3'd3;, Q1 Z) r- @: _0 ]  |4 a3 m. b
  131.                       end" z4 j) ~0 s# ^. g8 t$ h; q2 _; W  O
  132.                 3'd3:begin
    / W" ^) ]; x, p9 _' V
  133.                         MISO <= txd_data[4];
    ! n) @% `" n$ {( X7 p6 @8 W
  134.                         txd_state <= 3'd4;$ o3 H; p, c# a( T8 i
  135.                       end
    % j; [) W8 Z4 m) Y$ V0 b7 }4 \
  136.                 3'd4:begin) z9 p+ ^! a# ~2 }
  137.                         MISO <= txd_data[3];. ^) K. q1 p* n- U+ A) W
  138.                         txd_state <= 3'd5;
    # p  g, }# b8 N7 X, E1 Z
  139.                       end% e0 |9 f& |7 S5 `0 {2 o
  140.                 3'd5:begin+ l8 t& ~3 I5 N8 S! L
  141.                         MISO <= txd_data[2];% n% u& V8 Q' d: |) Y; b
  142.                         txd_state <= 3'd6;
    / k, j% ~; j/ P) R3 x0 y' \% P
  143.                       end  m6 c/ w9 K$ t8 I& b4 `
  144.                 3'd6:begin: f5 [5 h& W  |3 u
  145.                         MISO <= txd_data[1];, Z4 `" ^- |% g! ^
  146.                         txd_state <= 3'd7;
    8 V+ H" K7 w  L4 D+ N1 m
  147.                       end+ y+ p* S$ F2 V
  148.                 3'd7:begin- C8 g( A% Z& W) Q/ q( M
  149.                         MISO <= txd_data[0];
    # e" U6 C: g* T" x
  150.                         txd_state <= 3'd0;
    & M& i+ n$ H$ Y9 S
  151.                       end
    . \& a! R1 c" C: j* p" {
  152.                 default: ;
    ' o" R1 e  {2 i1 w
  153.             endcase5 p& u  s0 a8 F; C# G3 \# {
  154.         end
    " U9 @) y3 v! t- r
  155. end
    8 R' D; F$ k* ^9 q; `
  156. * |; p" J* A( Q
  157. endmodule
复制代码

' ?5 I* ?  G0 ?) S5 ]8 e+ J9 j) y1 T" j' O6 a. {' _) \4 m8 A

; ], q, |, r9 ~, G

- _6 g$ O2 p1 d: W; |+ O
赞 1 收藏 评论0 发布时间:2022-1-16 18:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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