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

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

[复制链接]
STMCU小助手 发布时间:2022-1-16 18:00
一.SPI协议简要介绍
SPI,是英语Serial Peripheral Interface的缩写,顾名思义就是串行外围设备接口。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。: j; T8 g" d, J8 G9 y/ ~; 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拉低使能情况下。
5 j6 }+ |; Z$ C$ O- m
二.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发送数据与接收数据。
2 }* e, ]1 m. U/ t7 \. [
  1. /***********************************************************************
      P9 n0 ?& Y, E) a8 z+ w
  2.      ****************** name:SPI_Slaver_Driver **************. M6 y9 W6 V. J' N
  3.             ********** author:made by zzuxzt **********% l- v% k4 J2 o  O9 S1 o
  4.      ****************** time:2014.4.29 **********************
    , \0 Q: t; d- J* E/ k" |6 I
  5. ***********************************************************************/9 N5 ]" p! x+ v( r  @% O" z
  6. //use SPI 3 mode,CHOL = 1,CHAL = 1
    - t/ M0 L7 x/ G. j
  7. module spi(input clk,1 \4 q; }5 v+ x, K1 s
  8.               input rst_n,
    7 Q! l0 j* ]. w
  9.               input CS_N,
    ( D5 x0 Y% o* u1 p. p
  10.               input SCK,; w  W# G/ {. W& c9 m
  11.               input MOSI,. _4 S5 L8 E5 q$ J6 I, p: B
  12.               input [7:0] txd_data,
    6 V' G) |# `, C5 \, ^
  13.               output reg MISO,& l, A9 L- @* g, y# x! U
  14.               output reg [7:0] rxd_data,
    0 z+ C. k% n  S
  15.               output rxd_flag);   //recieve done,please transmit data
    & N1 w. A- p* K. w" m' y

  16. 2 P+ D# u* B# f, L' j
  17. //-------------------------capture the sck-----------------------------. @; w  Y" z' }" R
  18. reg sck_r0,sck_r1;
    / _$ a" J0 \' G3 c8 P
  19. wire sck_n,sck_p;
    + E  l0 F4 P. Q' f# f/ n# I
  20. always@(posedge clk or negedge rst_n)
    * ?! ]2 M3 q6 ~: Y+ H
  21. begin  d- O( N1 i& P
  22.     if(!rst_n)
    % G9 t" L2 D, s2 u3 \& k1 F; g' B3 w
  23.         begin$ c' L' N& u+ p5 M
  24.             sck_r0 <= 1'b1;   //sck of the idle state is high
    % B( y3 c8 j, v
  25.             sck_r1 <= 1'b1;2 k  T, I/ x- M1 Y4 f; b* p9 A
  26.         end
    ' r- a1 C& E% r; e+ j
  27.     else
    ) r' D7 ]: C  T3 H2 w1 a
  28.         begin. _# y) R2 }  P# {+ O4 }2 T
  29.             sck_r0 <= SCK;
    , A* T* B5 ?  O) y# k
  30.             sck_r1 <= sck_r0;) W2 T/ X) Z+ u" @- ?' A
  31.         end
    / f2 U& c  w: O- r
  32. end+ p' t8 }4 B5 Q  d/ o/ b

  33. - J6 q; n; H# L- o) j
  34. assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0;   //capture the sck negedge) G/ z' G( F- ?- R* _- B0 P% k* |
  35. assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0;   //capture the sck posedge( U7 }5 N3 o( l" H# v2 e2 x
  36. / ^0 P: L, M( [& S4 o
  37. //-----------------------spi_slaver read data-------------------------------. Y& ?4 u8 Q1 D7 f2 Z* D4 x& o
  38. reg rxd_flag_r;
    ' M8 T1 @" u, ~' i* }2 y
  39. reg [2:0] rxd_state;
    ! a: Y- M- ^' Z- j. Y5 D) P! j
  40. always@(posedge clk or negedge rst_n)% [# j) M  n( u: M: _7 A8 L, e
  41. begin( ^! {8 d$ V) @3 Q; h
  42.     if(!rst_n)5 M/ z7 _& k- t1 _% \* ?
  43.         begin& q+ J* x& l) a% [4 Q
  44.             rxd_data <= 1'b0;8 z5 r/ w( i! L; o
  45.             rxd_flag_r <= 1'b0;
    2 x( Y, ?. e/ n7 Y
  46.             rxd_state <= 1'b0;9 ^2 i$ R) }: f" o7 v# J
  47.         end
    6 p, h! w4 m1 B
  48.     else if(sck_p && !CS_N)% U" i: }, {) u2 M6 s3 }6 s
  49.         begin
    3 k6 x4 R+ q0 F- {& k
  50.             case(rxd_state)
    7 s* q9 ^; M7 j- @
  51.                 3'd0:begin, A! F, |. [! g0 y
  52.                         rxd_data[7] <= MOSI;
    6 C$ D& h3 g; C" W
  53.                         rxd_flag_r <= 1'b0;   //reset rxd_flag6 {( O" ~& h  Q4 X% \! y3 t
  54.                         rxd_state <= 3'd1;
    9 h  O- Z' u4 R9 G3 |
  55.                       end
    % {7 G* `  @& X; G7 f8 F* _
  56.                 3'd1:begin- ?+ g& x2 ^6 [+ b
  57.                         rxd_data[6] <= MOSI;
    6 s( q; r- n% p3 {* w7 C: ]
  58.                         rxd_state <= 3'd2;, r- [% [7 [( M4 H9 A
  59.                       end4 _1 N5 K1 e% N, ?9 H; y' [
  60.                 3'd2:begin& J4 e2 c' G5 z, D, n9 F
  61.                         rxd_data[5] <= MOSI;! j! _  ^7 [. U4 z
  62.                         rxd_state <= 3'd3;3 A6 r$ n( G3 x9 |  k
  63.                       end
    , {' I! x% X! N8 _8 q( u
  64.                 3'd3:begin5 ~5 J! U5 ^1 |+ }6 _$ I
  65.                         rxd_data[4] <= MOSI;& |3 \* h7 d$ [. t) E5 p
  66.                         rxd_state <= 3'd4;
    6 ]- n# l1 ^+ _1 r: y) M; p
  67.                       end
    0 P( E# N7 u3 g$ {2 E4 w; t
  68.                 3'd4:begin8 x; m: Y7 ?7 e  [! ^/ J" u* x
  69.                         rxd_data[3] <= MOSI;0 N0 U+ ]+ b6 p# A4 `
  70.                         rxd_state <= 3'd5;
    5 C2 Y( V% ~/ _% `/ a/ n/ ]8 ^
  71.                       end* ^* I7 P; |* r3 B" a
  72.                 3'd5:begin; P/ c$ @, \  C7 |
  73.                         rxd_data[2] <= MOSI;
    # d. ?4 d. d7 m8 A7 V* u" B
  74.                         rxd_state <= 3'd6;+ x  L0 l, {* g" X; `
  75.                       end  v' A0 H1 G1 L& \+ ]  H. d
  76.                 3'd6:begin
      T9 x8 C' r! D1 L, a8 Q
  77.                         rxd_data[1] <= MOSI;; ^* R  C0 J" C# U+ u$ S1 Y/ F
  78.                         rxd_state <= 3'd7;' R$ u  f8 L5 u2 b  ]* X( O! i
  79.                       end
    ) K/ t2 @+ }3 P/ Z
  80.                 3'd7:begin8 o4 D" D) b/ v  e3 w. v# S
  81.                         rxd_data[0] <= MOSI;7 Q* @* h4 I- z$ p* v( v) Q
  82.                         rxd_flag_r <= 1'b1;  //set rxd_flag: v: L) V4 o# k5 D6 K
  83.                         rxd_state <= 3'd0;
    ( d- N7 E: _# Y! ?6 i# `0 F
  84.                       end
    " o' f9 u6 C, y$ Y) r- ?
  85.                 default: ;
    8 i  j2 W8 v, G- J; H0 O8 F- V$ |/ s
  86.             endcase$ X% y5 t$ K2 d$ V
  87.         end9 s; ?, M; Y; r7 Z+ ?. J2 b9 X
  88. end! }" f. G5 y, b3 i
  89. $ M0 X5 E, Z1 H( Y8 Z9 m3 d
  90. 2 \) h* v) R: M' K
  91. //--------------------capture spi_flag posedge--------------------------------
    - _( k) e: B: z$ K$ A
  92. reg rxd_flag_r0,rxd_flag_r1;
    3 Z6 M$ [" J2 w2 M4 k0 B8 a( ~2 v/ o
  93. always@(posedge clk or negedge rst_n)4 f3 i. C; t/ }4 z0 G5 k
  94. begin+ T: t) J  d/ V: m& F# E
  95.     if(!rst_n)
    & K' k' ~+ Z9 ~3 w% ]1 F
  96.         begin3 i9 @" _; h  D
  97.             rxd_flag_r0 <= 1'b0;
    3 ~, g+ @! O+ V3 U: N3 {7 p4 `2 l' X
  98.             rxd_flag_r1 <= 1'b0;
    0 `" j* Z% Y4 Y0 ?
  99.         end, _3 ~# F  V/ G# b* ^6 B8 E; O2 V
  100.     else9 V+ y8 o1 m8 L  ?" d7 M& X0 N" _
  101.         begin2 t% W8 [7 N: N1 I
  102.             rxd_flag_r0 <= rxd_flag_r;
    7 _3 F6 c  ^7 I# ~
  103.             rxd_flag_r1 <= rxd_flag_r0;0 ~( l. X* P4 m4 G4 F
  104.         end
      P( X' t" P/ J+ C
  105. end
    6 h( L. I* `2 v! A0 p: g
  106. + [  R+ b, Y$ \: ~/ E, b! I
  107. assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;  \1 Q4 F2 ^2 Y

  108. - \4 f8 S- v9 x$ k; C3 C
  109. //---------------------spi_slaver send data---------------------------
    . ^% n) x+ f' C; T, {
  110. reg [2:0] txd_state;
    6 |8 J3 ]3 k2 P4 J* O% j
  111. always@(posedge clk or negedge rst_n)6 `, U# j. z2 y, H' F5 K
  112. begin
    : A5 \8 Y) J4 @( K% `2 a
  113.     if(!rst_n)
    3 I2 @8 d! c4 d) @7 N
  114.         begin& G: N) Y( Y6 U/ @
  115.             txd_state <= 1'b0;# _* K% N& [0 N7 j
  116.         end
    $ _! b! I' s& W9 N0 e( a% X
  117.     else if(sck_n && !CS_N)
    % ]7 {  }6 w1 ]: t# [9 G
  118.         begin
    6 z) k1 X; S3 t4 r) K, o8 d) K" {
  119.             case(txd_state)( L9 a1 E; `! W3 @
  120.                 3'd0:begin7 @6 K  G  ?# U
  121.                         MISO <= txd_data[7];/ i# d, v+ H* f% n( X% H
  122.                         txd_state <= 3'd1;
    : `2 n1 P, `! w. W& d" ~' |
  123.                       end2 Y0 M: q. [; \8 `$ o
  124.                 3'd1:begin/ q9 u8 @- Z. T8 Z
  125.                         MISO <= txd_data[6];
    6 ~+ k% S4 W; t4 d! p
  126.                         txd_state <= 3'd2;
    : k. e; F" Y1 l' N  N5 T# T0 q# D
  127.                       end. a4 X/ u8 X6 k
  128.                 3'd2:begin4 @& f: }* V. ^" |5 R9 _
  129.                         MISO <= txd_data[5];- ^. ^/ B  l! f2 T  ^; C5 X; e
  130.                         txd_state <= 3'd3;( L6 K' }" F' I1 `# t/ D. w
  131.                       end- ?. y, n1 e- W! {0 I6 r2 Q
  132.                 3'd3:begin* _- y$ c- }% _+ n( \) x
  133.                         MISO <= txd_data[4];
    ( U, g) P' a1 o) Z! f
  134.                         txd_state <= 3'd4;
    * N/ Q8 b, Y4 [' Z2 v
  135.                       end4 ^1 B2 i2 v8 o
  136.                 3'd4:begin
    ) P7 Y" z- H! N
  137.                         MISO <= txd_data[3];7 |* U; n; ]2 `
  138.                         txd_state <= 3'd5;
    7 p! Q+ }6 W& _* J- ]3 {) R$ i
  139.                       end
    9 [% T1 W- C! X: M( I) X( M  F2 Z
  140.                 3'd5:begin: {2 m8 u" C$ C+ L* {$ |
  141.                         MISO <= txd_data[2];
    6 M7 K$ B& Z# T0 c+ a9 c
  142.                         txd_state <= 3'd6;0 h) ]4 A; {; e" k) R
  143.                       end
    6 D  o4 M; ^. E, H
  144.                 3'd6:begin
    - j) W2 x$ x3 p6 k
  145.                         MISO <= txd_data[1];; \) c4 a9 s' _  X
  146.                         txd_state <= 3'd7;
    , l% Y/ |1 T; G
  147.                       end
      z! m" h: O6 M
  148.                 3'd7:begin/ G  |" H, Q5 S
  149.                         MISO <= txd_data[0];5 I: L: O, t  A9 m: I
  150.                         txd_state <= 3'd0;
    ! f0 J& x& z6 i$ M& [; h) X) _" r1 R
  151.                       end
    # ^6 _% R- V* M3 r+ K4 @
  152.                 default: ;
    " B+ A2 U, E5 g4 ?
  153.             endcase' G# M( b/ s9 B" ~
  154.         end
    , u* Y& d6 c: Q# Q8 f6 z) m7 c
  155. end7 M% Y- |% p1 u
  156. ; N" M+ G7 ~+ @- M$ v9 f5 ?! S6 K
  157. endmodule
复制代码
7 h0 U' P- Y4 g2 h

+ q" d. L0 Z$ y4 k5 c
, ~9 J# j* H% ~5 w/ k8 P
! u* u* I4 Z4 B" R8 e0 F( r
收藏 评论0 发布时间:2022-1-16 18:00

举报

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