请选择 进入手机版 | 继续访问电脑版

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

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

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

% R/ `+ A# r% X% f' x% L
  1. /***********************************************************************0 ]7 r2 r% E1 z4 w1 s9 B& r
  2.      ****************** name:SPI_Slaver_Driver **************. p4 `# P+ C$ j# o) d. ^) h% T
  3.             ********** author:made by zzuxzt **********
    8 E4 _2 L. e8 H9 D/ P
  4.      ****************** time:2014.4.29 **********************3 n0 W- a: f: H3 m! ~
  5. ***********************************************************************/( Y6 }/ b9 g, q7 Y  l% z* r$ w/ _
  6. //use SPI 3 mode,CHOL = 1,CHAL = 10 b$ K0 o, c5 M. K
  7. module spi(input clk,  o: V, T9 @& w3 @5 [% m) e
  8.               input rst_n,
    " h% [/ C* S6 a( g6 |' q) t5 k2 z
  9.               input CS_N,
    # j) ?! c, e8 J. r9 Y' ]
  10.               input SCK,2 H0 o5 q& v' U# b7 u4 H# z
  11.               input MOSI,0 w3 r5 D) [% a% L. N( V
  12.               input [7:0] txd_data,
      V- _4 F. l- L' W9 @1 {3 X
  13.               output reg MISO,4 i; B1 i3 S4 @  i- U+ U
  14.               output reg [7:0] rxd_data,
    / E' n# i6 s# E$ b+ N. c/ s9 T
  15.               output rxd_flag);   //recieve done,please transmit data
    + U3 F7 j5 t  w+ I9 R

  16. * v8 Z) d; `  H0 x
  17. //-------------------------capture the sck-----------------------------
    $ `# ^) d+ r4 Y2 h: O* n2 L
  18. reg sck_r0,sck_r1;
    : \4 i+ k- E- o$ e
  19. wire sck_n,sck_p;
    ( n0 S2 r' u+ }9 p
  20. always@(posedge clk or negedge rst_n)) }) x+ U  q: T8 F5 ~- T
  21. begin
    5 m! O6 l  q& a5 z; e4 Q. k
  22.     if(!rst_n)
    1 E3 G) f  g) e" t
  23.         begin
    $ s- K+ c/ U  b" \) @
  24.             sck_r0 <= 1'b1;   //sck of the idle state is high' ]) y! A- u; ]; K9 V
  25.             sck_r1 <= 1'b1;/ g" v0 o/ P9 n" d
  26.         end
    9 a8 ?. m. O( w& s" s6 W* w
  27.     else
    $ k- ^" B5 Z3 E5 ~4 `1 w
  28.         begin: j/ C2 l( x7 E$ K$ T3 P
  29.             sck_r0 <= SCK;
    7 g. e& @# P* q1 n
  30.             sck_r1 <= sck_r0;3 c, ?  Q  ~: c
  31.         end
    ) P+ l3 F, J4 V6 w4 z3 j3 U" o8 E
  32. end9 {1 [. y: J/ B( G* h& F/ P# J
  33. ; Y$ h. E- c/ D) s5 H
  34. assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0;   //capture the sck negedge
    ) o, Y  W5 P* X6 D  _: g- K
  35. assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0;   //capture the sck posedge, a" Y  G8 X; Z! \5 m

  36. / K* w! x4 G; w$ N, j# d
  37. //-----------------------spi_slaver read data-------------------------------
    ; }% y$ i+ e# Z* r; m2 X
  38. reg rxd_flag_r;! r* K! M8 O- `2 r. U* z8 H8 q
  39. reg [2:0] rxd_state;+ O3 m2 ~; T3 b* J. M
  40. always@(posedge clk or negedge rst_n)7 O6 F8 \  i- d6 ^" I; `
  41. begin  m. b; a( I/ g
  42.     if(!rst_n)0 u+ E4 Q# \/ A8 i& |# A
  43.         begin; |% v, f' m4 W: z. v
  44.             rxd_data <= 1'b0;
    ! b& c- _5 u; Z2 `' x1 P. `
  45.             rxd_flag_r <= 1'b0;" J. O5 g) R0 O5 X8 t' S
  46.             rxd_state <= 1'b0;
    " q3 r, I( [2 ?2 N* j$ h6 D/ {& _
  47.         end
    " d0 _6 L, ~$ v) Y
  48.     else if(sck_p && !CS_N)! D5 {6 ?9 [) ?& J0 a: n
  49.         begin
    3 H! v! L- j  o7 [: Q1 [# G9 G
  50.             case(rxd_state)
    6 w! h* ~# S4 F) Y
  51.                 3'd0:begin9 I5 D4 e! d) T6 f' o
  52.                         rxd_data[7] <= MOSI;
    , b1 x9 T3 Q4 N
  53.                         rxd_flag_r <= 1'b0;   //reset rxd_flag
    # x1 k1 F" H* _! E
  54.                         rxd_state <= 3'd1;) W2 h: T" Y/ x
  55.                       end
    ! [3 i6 ^: _" P/ D' J  H$ ?
  56.                 3'd1:begin
    # E5 o4 f, e9 a, i9 c) |$ ~
  57.                         rxd_data[6] <= MOSI;, p  k. h# {/ D( I3 a
  58.                         rxd_state <= 3'd2;
    ; m( D; Z4 X7 J1 u' N3 o
  59.                       end
    % Q  e$ R, I0 @; K3 s* d- p
  60.                 3'd2:begin
    ' {9 b8 F: L# Q
  61.                         rxd_data[5] <= MOSI;
    % C+ }6 u0 L; W3 `3 c* ]
  62.                         rxd_state <= 3'd3;. B0 [3 j; H9 m* Y9 E) T- g7 j
  63.                       end
    ' |! s/ ^: R, |; B5 F+ s1 l
  64.                 3'd3:begin
    8 n7 H5 m* @0 J3 ^5 T/ N% h# l2 I' l
  65.                         rxd_data[4] <= MOSI;
    " i. k7 S  K: _
  66.                         rxd_state <= 3'd4;
    ! B) O" z5 \, p1 x8 h8 K  e' _
  67.                       end" v# i2 n7 z& b% Q" {
  68.                 3'd4:begin0 N/ a9 `+ u9 G, r3 i: V5 j; X! ~
  69.                         rxd_data[3] <= MOSI;$ ^3 @2 y, f# P/ N% }% r) f
  70.                         rxd_state <= 3'd5;  J9 ~# t9 E9 |$ l, A$ B' Y
  71.                       end; w8 O7 V" A8 \0 a3 c3 o
  72.                 3'd5:begin
    , _2 }2 f* u5 o8 z& h: {
  73.                         rxd_data[2] <= MOSI;2 _" ]9 x1 e6 c$ l# n+ H- ?; b
  74.                         rxd_state <= 3'd6;: ^& `; E! d: s4 |0 C* i# y
  75.                       end
    ( g% ]. i; M7 j& A
  76.                 3'd6:begin2 u- p$ J( P; g; `
  77.                         rxd_data[1] <= MOSI;( `8 R7 o0 Y; C5 J. t) q% p" b0 H
  78.                         rxd_state <= 3'd7;4 e) M; s9 ]* p, e
  79.                       end' A4 l9 G8 I+ s# ~+ `& W/ n
  80.                 3'd7:begin/ \. Z) l2 B* U" b0 I
  81.                         rxd_data[0] <= MOSI;
    + l8 G* S4 X, Z" k
  82.                         rxd_flag_r <= 1'b1;  //set rxd_flag; B1 a9 M3 y, P7 d8 g( q4 B7 _
  83.                         rxd_state <= 3'd0;, m' S8 f( @) @) z" X
  84.                       end* I. e+ \' @) F& }5 I! o
  85.                 default: ;
    " ]! b& h, Y# |$ h
  86.             endcase3 i* P: j3 I8 z% Z
  87.         end! y" B# M! C4 m5 W
  88. end/ M; y8 x: x# }/ Y
  89. , x) l$ o9 s6 ]
  90. , S+ n- r' O6 X% B5 Z( y* q
  91. //--------------------capture spi_flag posedge--------------------------------
    5 `* e' [. d1 _" Q( A- h
  92. reg rxd_flag_r0,rxd_flag_r1;% Z6 U- M  ~5 L# m- y3 i7 ~
  93. always@(posedge clk or negedge rst_n)4 W9 [" r" J1 `2 p) o
  94. begin
    9 `1 s' j) ^* p& r& _  l
  95.     if(!rst_n)
    ' {. X+ N5 m& Y) ?
  96.         begin) W: o  k* C- ~% n8 {6 }
  97.             rxd_flag_r0 <= 1'b0;+ j- p1 v0 K1 |% a5 i7 W
  98.             rxd_flag_r1 <= 1'b0;
    7 f% h) Z$ H! ^5 Q1 X+ d' j( w: ^
  99.         end$ I+ ]$ e" h) ]: O: M( X! k
  100.     else) _5 A$ W$ G5 |5 N5 `! @' n1 ?
  101.         begin4 j. c7 G: {+ G
  102.             rxd_flag_r0 <= rxd_flag_r;
    $ Y* }- ?4 z- y$ P6 b0 B
  103.             rxd_flag_r1 <= rxd_flag_r0;& _, s" c+ b# @# W8 i' v+ j* D
  104.         end' N& F* q( x- Z" k* j- @
  105. end4 l2 I# k6 U& o  }  ^

  106. 0 ]5 y( v' \, Y8 q! m% s5 I8 w% _
  107. assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;& d$ n- ^9 |$ S$ H2 R4 L$ D3 d& Z- a
  108. % w1 N  k+ x1 l. R2 i* q: t& `
  109. //---------------------spi_slaver send data---------------------------
    2 r% d9 I  r4 g; U4 Q
  110. reg [2:0] txd_state;! e6 D& M' v6 y2 X3 A3 _- M5 [
  111. always@(posedge clk or negedge rst_n)
    4 t. ~/ J6 }; w7 b
  112. begin( h4 A, R* H6 p; |6 V
  113.     if(!rst_n)% F1 p! [) ~5 V0 |
  114.         begin* `8 d* L* t1 T/ o& z
  115.             txd_state <= 1'b0;0 r2 j5 e# ~9 k- e
  116.         end
    4 o0 D/ v! ^2 g0 y  y! q4 A
  117.     else if(sck_n && !CS_N)' l* v. O& Q1 E% V! `& l, K; r
  118.         begin& |4 y8 I1 u& |0 E
  119.             case(txd_state)
    ( n  Q: Z4 @! v
  120.                 3'd0:begin
    * |& E* D# I; H5 _( d3 P# ~  l) G
  121.                         MISO <= txd_data[7];4 y6 Y( m" Q: N. l( Z: C9 \
  122.                         txd_state <= 3'd1;; r# ?9 d8 Z! Y. ~. x- A0 i
  123.                       end+ Q+ O6 S, H8 y  d; |7 j- R
  124.                 3'd1:begin$ K8 y5 M7 z- E% ~
  125.                         MISO <= txd_data[6];
    8 Z. }# |9 I9 k* Z/ m4 b
  126.                         txd_state <= 3'd2;2 J* _. {# E0 H* O4 b
  127.                       end
    6 o# n9 v7 l6 J
  128.                 3'd2:begin% ~& T/ X! K) k! W
  129.                         MISO <= txd_data[5];
    6 W4 f" q" R) r2 J
  130.                         txd_state <= 3'd3;
    . t! U2 x) M1 Q6 R; F6 [0 |
  131.                       end
    - R* ]$ `- ~, G4 A  i
  132.                 3'd3:begin
    8 Q. {) J. o9 {9 o# q  q# G
  133.                         MISO <= txd_data[4];
    5 Q4 ~5 g1 V3 F) }
  134.                         txd_state <= 3'd4;1 B4 O- \* ?2 K3 \
  135.                       end5 }: `' f  W5 R6 m9 p3 z
  136.                 3'd4:begin* t' \' |0 q  g0 _3 `  [
  137.                         MISO <= txd_data[3];7 n% C$ `+ d$ R: }9 }! T; `
  138.                         txd_state <= 3'd5;& c9 E& X. P/ o) m
  139.                       end
    . g2 g( K6 u! ?1 {1 ~# @1 g
  140.                 3'd5:begin
    9 J0 r/ |, T; k0 Q7 s
  141.                         MISO <= txd_data[2];$ b  V! K$ ~6 J8 @7 _2 J! F
  142.                         txd_state <= 3'd6;
    7 I2 G) N6 Y7 |* C6 Z
  143.                       end+ I8 f  Y' Q  @* C8 P0 d
  144.                 3'd6:begin
    ' [( G# u8 |1 i6 s( n: U
  145.                         MISO <= txd_data[1];) `' O5 P( r1 V+ L2 \) e' u
  146.                         txd_state <= 3'd7;: |& o  N% f8 ]% d+ z
  147.                       end
    : Y5 A8 J) B; H, e6 x& c
  148.                 3'd7:begin
    ! K1 p/ w: n! u/ o( O$ E9 t
  149.                         MISO <= txd_data[0];9 a% S  u2 F( R# j  Q7 ^1 I
  150.                         txd_state <= 3'd0;
    4 g2 f" T- e  l! B/ Z
  151.                       end
    1 O" @, G* ]. l
  152.                 default: ;
    1 V1 ]: ~0 L, l' r/ o8 c+ N
  153.             endcase6 W5 @  j8 |4 M9 V: K
  154.         end
    0 A" Y) {" q& b2 k; s
  155. end
    * W/ N8 p% a+ v( [5 N

  156. * N0 M) H# ~( X7 R
  157. endmodule
复制代码
  W# d5 ]5 q: t" k& f/ Q) m
! ?) [6 ~$ f( D+ }$ h
5 e* T- Q2 a# s
, W! x+ y  i: X1 m) p
1 收藏 评论0 发布时间:2022-1-16 18:00

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版