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

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

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

/ V/ M3 D) Q0 z* e  w: n
二.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发送数据与接收数据。

! L( R# U5 f- K9 g* g
  1. /***********************************************************************) q9 L# y7 ~* i+ Q( W
  2.      ****************** name:SPI_Slaver_Driver **************+ e) j  }/ @8 q/ g# \! i" L+ e, g
  3.             ********** author:made by zzuxzt **********! w* o, ^9 t" W, N
  4.      ****************** time:2014.4.29 **********************
    ; H7 j- A6 f1 F2 R; w
  5. ***********************************************************************/4 P8 O6 \% h% i1 V6 I
  6. //use SPI 3 mode,CHOL = 1,CHAL = 1
    1 K* k( h; |( w9 q$ _
  7. module spi(input clk,: s7 x2 W$ g4 I7 Q9 w, M) ]
  8.               input rst_n,
    ! \+ @# O2 t; S7 N7 b* y+ F
  9.               input CS_N,6 d; Y' j- s/ t' a- O
  10.               input SCK,# [/ h% i" _$ m- R0 f$ E8 _
  11.               input MOSI,
    ( F; W) ?* Y6 w# x& Z
  12.               input [7:0] txd_data,
    7 o8 c  `& d  \1 b7 f& v
  13.               output reg MISO,2 n" p& y4 W1 @! {. @7 {
  14.               output reg [7:0] rxd_data,4 L& E- B0 G  S6 F: {
  15.               output rxd_flag);   //recieve done,please transmit data5 U8 Z7 d9 n% f" b3 C& E# A
  16. 5 o; {& D0 f& y& k% H3 h
  17. //-------------------------capture the sck-----------------------------; h$ q/ H) Q8 I0 }- X8 k% l
  18. reg sck_r0,sck_r1;
    ; ^) `7 k1 k, v' E+ m+ [- [* V
  19. wire sck_n,sck_p;1 z! I* h8 h& k$ }5 q$ ?
  20. always@(posedge clk or negedge rst_n)
    0 f7 t' d& y. ?) I1 I
  21. begin
    ' [! k0 t0 ]5 ]" r, b/ q" s0 S
  22.     if(!rst_n)
    7 E' Z7 c# j* g2 [. T8 A. P; q
  23.         begin( V/ N, Q' A+ w
  24.             sck_r0 <= 1'b1;   //sck of the idle state is high
    / D+ Y: L" W% w  _9 W
  25.             sck_r1 <= 1'b1;
    * |3 k8 i. \' e7 l: J
  26.         end2 n& V; H( ?8 W9 b7 N
  27.     else
    , i9 J% K/ c9 I$ D) A, _8 g4 A$ ?
  28.         begin+ W/ w# C7 m$ e
  29.             sck_r0 <= SCK;: z- N7 i% T8 p4 Y  p& ]$ _) r
  30.             sck_r1 <= sck_r0;
    8 a# }7 ]2 s% y! _  {3 z% x
  31.         end
    # q+ n  ~0 i1 b  w: q( _
  32. end" F/ n  y1 U4 \- U7 l' G
  33. ( Q  A# z( A+ J  L
  34. assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0;   //capture the sck negedge/ O; s* y* T2 M5 ]+ f
  35. assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0;   //capture the sck posedge
    " T9 I. w5 Q3 m8 M  P
  36. - h6 J% n1 G% O% J$ H; W
  37. //-----------------------spi_slaver read data-------------------------------
    - X% L/ H2 B. i
  38. reg rxd_flag_r;% X- w; V6 M4 R# G# \7 v6 G
  39. reg [2:0] rxd_state;$ h: [  F: R5 w& e- R+ L
  40. always@(posedge clk or negedge rst_n)1 G" _! H( Y# U* g# a, }
  41. begin
    8 \$ J. `- ~) k# ~4 R+ V% K6 m
  42.     if(!rst_n)
    9 \, ?, t- K; Z( }% P* N6 |
  43.         begin
    0 i& X( Q' Y3 A/ S  T
  44.             rxd_data <= 1'b0;: j  D. b; {; w1 O8 p8 Y. S
  45.             rxd_flag_r <= 1'b0;  n+ F2 O! l* D- c2 @
  46.             rxd_state <= 1'b0;0 W3 I& P0 h; E1 n
  47.         end
    7 |# K" R$ j- a+ u0 C. G' h4 V5 T7 q
  48.     else if(sck_p && !CS_N)
    : ~1 G. S: h5 {! R7 f' l
  49.         begin7 K2 F& n1 s& o% e
  50.             case(rxd_state)+ \. f0 n% A, g- W) H/ U
  51.                 3'd0:begin' s# G2 ?! L1 e% Z+ J
  52.                         rxd_data[7] <= MOSI;
      i! x* ^4 k' U( w% }9 G& e. u
  53.                         rxd_flag_r <= 1'b0;   //reset rxd_flag
    1 m- x  D, p& Y2 B
  54.                         rxd_state <= 3'd1;
    5 X2 r# k3 E. y
  55.                       end
    0 D6 D* C, i6 {- G1 h3 h% }9 J
  56.                 3'd1:begin& G  O4 Z# ?$ @" l  i
  57.                         rxd_data[6] <= MOSI;$ J( a# v' F+ S
  58.                         rxd_state <= 3'd2;3 E0 @% u4 i3 v! E
  59.                       end6 [; S# l/ W" b& R. M" p/ C0 p
  60.                 3'd2:begin
    $ u- T. H" ]$ U2 G9 l' s  s
  61.                         rxd_data[5] <= MOSI;: v* q" r! A" Z' |
  62.                         rxd_state <= 3'd3;& K4 h7 h' g/ u# n1 S; ^' K% g
  63.                       end2 o5 |5 K2 C* ~+ ?3 S  ~
  64.                 3'd3:begin9 S0 E, L. h! v$ w8 A# A3 U) S
  65.                         rxd_data[4] <= MOSI;
    + u: j: Y2 s  ^% i; |
  66.                         rxd_state <= 3'd4;
    # t9 y+ H3 X& q# c9 a* P
  67.                       end, \$ l2 @4 E# r. ?* M6 M: ^. j+ ?6 J6 C
  68.                 3'd4:begin# x% `3 Z7 h' o% `* N- u
  69.                         rxd_data[3] <= MOSI;
    ! X- X$ ^: B% c2 l. {6 S  S
  70.                         rxd_state <= 3'd5;+ k; w$ J6 m& B2 F
  71.                       end; f( p- M5 F) T2 [- ^. j
  72.                 3'd5:begin" B) V, n3 f  z
  73.                         rxd_data[2] <= MOSI;# Y2 x8 a5 n7 T( S
  74.                         rxd_state <= 3'd6;
    " f$ n8 z$ o" I5 O0 l. s! f
  75.                       end
    6 R/ t1 d& w% ]" K7 Z" o, C. W
  76.                 3'd6:begin
    8 s. F% q8 H: y3 ]8 _- Q
  77.                         rxd_data[1] <= MOSI;
    , k; ]& L& H9 C7 z: `. z3 E2 {. X$ ?
  78.                         rxd_state <= 3'd7;
    : q$ X" K. z8 F) T, X) u" _/ x
  79.                       end& `- Q: M  t- _3 Z
  80.                 3'd7:begin; B" J! l5 T* c' D
  81.                         rxd_data[0] <= MOSI;
    + D, l$ C$ C1 l1 T2 q" W, U
  82.                         rxd_flag_r <= 1'b1;  //set rxd_flag
      ^) c7 ]+ N" X! q- s
  83.                         rxd_state <= 3'd0;( F9 t# q2 O7 q3 p) f! ]7 _$ s7 l4 a
  84.                       end
    " w. |& ?* F: n7 {, m' j; _6 v
  85.                 default: ;
    ( \9 ]# }- X0 L1 I3 D
  86.             endcase
    8 Z( A2 Y9 o$ s7 K  c
  87.         end4 B9 Y/ r5 t+ E5 b+ ~$ U
  88. end
    8 }# Z$ ~2 k6 e
  89. , J8 ]$ T; L, F, b5 c$ V4 x4 X
  90. + f( [3 U& `9 F# i2 t- [
  91. //--------------------capture spi_flag posedge--------------------------------
    4 F3 l: Z3 u% ?  Q0 S
  92. reg rxd_flag_r0,rxd_flag_r1;
    8 _  d5 K% @6 J7 I; p! V, t
  93. always@(posedge clk or negedge rst_n)
    - r2 Y  u; W! k7 u) Z9 Y2 D
  94. begin
    : U4 t7 p! b8 U0 H2 x* V& ]& I
  95.     if(!rst_n)
    , }* `8 M( A- }5 h: x
  96.         begin8 O: }% n+ v# B" h! c
  97.             rxd_flag_r0 <= 1'b0;4 a- A, U% j9 b+ I2 L
  98.             rxd_flag_r1 <= 1'b0;+ z7 i, x3 G6 c" s
  99.         end3 |) d* r8 J- X/ z( T* o
  100.     else4 \1 m3 u, d( j: s! p2 p$ G- h
  101.         begin
    , z# B- }9 a- ?8 W, s
  102.             rxd_flag_r0 <= rxd_flag_r;6 `' \% `9 h9 ^1 v1 N9 X8 h
  103.             rxd_flag_r1 <= rxd_flag_r0;
    3 j4 ?! O! w% V8 j" U: p. W
  104.         end0 C7 z( u0 v" f+ B/ F
  105. end
    2 }  X7 j8 B5 x  i+ n) |2 `
  106. " Y6 s0 y& o3 Y1 k. l- ~7 |
  107. assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;
    2 f6 M4 d* |5 F$ O
  108. 7 L1 F* N$ M5 h3 D$ M
  109. //---------------------spi_slaver send data---------------------------
    ( ?* F& C1 j( N
  110. reg [2:0] txd_state;2 d$ z5 o% S3 W3 g9 f6 F: a
  111. always@(posedge clk or negedge rst_n)  N6 p% }! Q3 N9 m
  112. begin
    * W. d% z  S% d! P- e
  113.     if(!rst_n)
      e4 ?9 j0 V( x/ h
  114.         begin7 u5 S4 X4 H' ?9 k" F3 c
  115.             txd_state <= 1'b0;! y6 S: L- L! l
  116.         end, u3 \' X0 s# ], z' I5 s# V
  117.     else if(sck_n && !CS_N)
    . }- ]: b$ g: }7 Q* Q- Q
  118.         begin, n, k- ^. B# Y( Z4 ?
  119.             case(txd_state)
    * F# w8 l; p0 T  c( W# K. A( {
  120.                 3'd0:begin' i0 b/ Y1 t# `  }" M% u' o; m3 W
  121.                         MISO <= txd_data[7];
    ; a3 K  |( X' U0 A0 m1 v7 G- h9 X
  122.                         txd_state <= 3'd1;
    - N' j( i* ]) l6 y
  123.                       end
    . r& |8 m. u: J  L
  124.                 3'd1:begin- x4 T8 Q7 O9 m: Z
  125.                         MISO <= txd_data[6];! N7 I# A) a( E1 J
  126.                         txd_state <= 3'd2;4 w$ K5 s1 Q) m; Z2 I
  127.                       end
    ! Y% I2 f/ X' G
  128.                 3'd2:begin
      q2 l9 y' V; W
  129.                         MISO <= txd_data[5];8 m$ B# y0 l" r
  130.                         txd_state <= 3'd3;# x" `7 q, T# E  Y
  131.                       end9 P. V5 N# ^" P$ q
  132.                 3'd3:begin. x2 o8 F. A& s. s7 A
  133.                         MISO <= txd_data[4];
      S# n1 _$ Q  f* Q% Q( {7 _9 w- Q
  134.                         txd_state <= 3'd4;
    ( I3 u3 [1 k7 U8 d) K
  135.                       end" g9 b! m- F, `- X
  136.                 3'd4:begin
    6 [% L/ l, |! G+ E
  137.                         MISO <= txd_data[3];! J- v- k/ ?4 v1 q" W
  138.                         txd_state <= 3'd5;
    4 @, `8 N4 \, d  e/ w7 Z
  139.                       end
    3 ~1 Q" k% E  q9 ~9 O! o" p
  140.                 3'd5:begin" ^% {9 E9 t: {6 @' n3 `$ m9 f" w
  141.                         MISO <= txd_data[2];
    3 _9 Y0 w+ m# m+ s, p# b
  142.                         txd_state <= 3'd6;
    3 ~2 z9 v8 L- X: A; G% J
  143.                       end- q2 C: m5 H( M3 Y  t
  144.                 3'd6:begin
    ) k+ R2 t3 b) B# Z! b/ A, D% K; C- N
  145.                         MISO <= txd_data[1];
    ! g/ K3 K2 g- s9 y1 O9 O
  146.                         txd_state <= 3'd7;* t, V: \# T6 ~( j2 s. v  S$ |
  147.                       end
      {4 }* X- O/ d
  148.                 3'd7:begin: S5 ?1 F9 @, u2 Z2 H2 k6 e2 e* H
  149.                         MISO <= txd_data[0];
    % G1 n; m  p9 \+ n" W, e
  150.                         txd_state <= 3'd0;
    - X( Z' z7 C4 N2 [% [
  151.                       end
    , [# f5 ~( j  ]3 @; A
  152.                 default: ;
    + i. o; ~. J, a# g
  153.             endcase; ~# {: @& g9 Y7 m% r4 ?: ]' P( p
  154.         end( |% h. ^9 @! i  i6 u7 p
  155. end
    ) O: b* d. E9 S7 l6 E) G$ u

  156. 8 i) F0 H, I# A& O
  157. endmodule
复制代码
8 ?1 R% X5 ?. e7 l- c0 D
8 c7 o3 p- F! t- [3 E6 ~+ k. i
* d, z0 \8 `, ^1 h; b
2 N/ B3 q, U0 d: ^$ g
1 收藏 评论0 发布时间:2022-1-16 18:00

举报

0个回答

所属标签

相似分享

官网相关资源

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