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

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

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

7 ?. f! V" Z1 W3 \4 f3 j
二.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发送数据与接收数据。
. J3 Z1 q" B# d/ ?6 W5 x7 J
  1. /***********************************************************************( J, s  c5 k( i) D4 i- @$ e
  2.      ****************** name:SPI_Slaver_Driver **************
    8 g4 M  K) ^" @. j( _- s
  3.             ********** author:made by zzuxzt **********
    # ?- Q: H, |8 W# `; d) q
  4.      ****************** time:2014.4.29 *********************** E0 w0 o( |4 f
  5. ***********************************************************************/, W, u+ A! A* B  z3 K
  6. //use SPI 3 mode,CHOL = 1,CHAL = 1
    ; j4 S9 W8 O6 c
  7. module spi(input clk,
    & G$ l1 F4 _& s2 Q3 ]6 h" N# e
  8.               input rst_n,! }# Y# ^( J+ P% [
  9.               input CS_N,
    0 `# i  p2 g" f
  10.               input SCK,
    , h9 Q& m- o5 P% `# S8 j
  11.               input MOSI,
    ) [$ e8 V, j3 y( T) ^
  12.               input [7:0] txd_data,
    2 L; T# ]# e2 _, E2 N! {
  13.               output reg MISO,* z9 V8 d$ x$ f
  14.               output reg [7:0] rxd_data,  w0 r* w/ u6 p7 d. b( C
  15.               output rxd_flag);   //recieve done,please transmit data
    ) |1 H: Z7 a: [& L- V% X, O
  16. 3 s8 z" d1 V1 C& j9 l. {
  17. //-------------------------capture the sck-----------------------------
    ' x* B; P2 }& A8 Z* Y
  18. reg sck_r0,sck_r1;
    2 f1 A: u8 F& A
  19. wire sck_n,sck_p;
    2 ]; }# g$ r: W+ A, K
  20. always@(posedge clk or negedge rst_n)
    $ W+ v! [4 S/ M' t- d0 g
  21. begin
      p* v" R. `, s$ V8 t) h& `
  22.     if(!rst_n)
    & P% A" z& L. N+ b+ c2 u1 F5 S
  23.         begin/ L( t: l6 B9 Y3 r
  24.             sck_r0 <= 1'b1;   //sck of the idle state is high6 ]5 q7 p% e( _6 F% v: F6 s
  25.             sck_r1 <= 1'b1;9 n: @4 k' }! J; I! K  {! U+ B
  26.         end
    2 C) |& d% A/ j6 f' C9 k1 H$ z
  27.     else, f' X2 |4 r; Y( w
  28.         begin
    * ]+ t7 {: n# O9 k* L5 j" L7 F( [
  29.             sck_r0 <= SCK;/ O& I& ^. u6 x1 g. s9 e( X& a3 I
  30.             sck_r1 <= sck_r0;
    ' a, d% W# w( H4 j* i
  31.         end
    1 e6 T4 M* o6 S1 T1 T6 U  a( a9 G0 x
  32. end
    1 t+ c8 F# o1 v( E" A
  33. 7 o$ L- u$ O/ v9 l' n, d
  34. assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0;   //capture the sck negedge1 z% J+ b# m) \, u
  35. assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0;   //capture the sck posedge
    # N1 P8 w% b% f

  36. 0 Z2 D6 t$ Y6 G: t" A2 X
  37. //-----------------------spi_slaver read data-------------------------------& O4 a, b! ]; j6 o/ p- t
  38. reg rxd_flag_r;% j7 z/ z( L6 V5 e: n1 l
  39. reg [2:0] rxd_state;
    ! [! R% A9 Y/ x+ W9 f- Y
  40. always@(posedge clk or negedge rst_n)
    , ^% L5 Z; d: k7 V( ?
  41. begin
    % O" k% s. i4 Z; q: I: F/ a& C8 o3 C
  42.     if(!rst_n)
    - T! d+ I: _# p% F/ n# n5 J
  43.         begin
    . G5 X5 a- j" m
  44.             rxd_data <= 1'b0;8 A) V( ?$ D7 F! a+ N* D! z
  45.             rxd_flag_r <= 1'b0;
    / W6 ^5 n; {, d7 Z! C2 E5 C" V0 R( L
  46.             rxd_state <= 1'b0;
    $ R, K7 X. M. `0 k  U0 x! p2 z9 p
  47.         end# h9 B) Z4 r' l2 s
  48.     else if(sck_p && !CS_N)
    6 M# m- O* F2 D8 l2 b. a$ `
  49.         begin/ W5 c  G6 g/ P- ^% u5 @
  50.             case(rxd_state)1 v/ G: \7 h  ^2 @4 C. W2 \
  51.                 3'd0:begin
    ; q" W6 h/ l; d5 O$ e
  52.                         rxd_data[7] <= MOSI;
    3 L6 _+ R# x( X
  53.                         rxd_flag_r <= 1'b0;   //reset rxd_flag
    + }( a0 q$ a0 b% B+ p) M' j; m
  54.                         rxd_state <= 3'd1;! a$ _% w& b  v# i- y
  55.                       end7 D% D) H( n( P; E0 o' Z: n% a& y; [
  56.                 3'd1:begin- X) Y: g' P4 L2 o5 p) |# j
  57.                         rxd_data[6] <= MOSI;
    2 b3 U8 M! M* i, v' t
  58.                         rxd_state <= 3'd2;
    & c" V) Y, m- b9 ^6 N4 l
  59.                       end0 G8 F0 }& a+ ], l* D% v: y
  60.                 3'd2:begin
    - |  }3 r0 q- p9 R9 k" \
  61.                         rxd_data[5] <= MOSI;4 L- r$ p* w" }! `1 {, z( S
  62.                         rxd_state <= 3'd3;
    * g; X: ~3 d5 l% f. y$ B; U/ x* N5 x
  63.                       end
    + |6 d9 `5 t% u& b# r( E. x
  64.                 3'd3:begin
    % ^$ k% F/ g8 v2 n7 P$ R
  65.                         rxd_data[4] <= MOSI;' l6 \+ E3 R4 q5 T
  66.                         rxd_state <= 3'd4;$ H. r4 e$ W% m0 i3 j
  67.                       end
      j0 x; _9 e+ L
  68.                 3'd4:begin' o$ k; Y, N- C4 m1 \2 S, b
  69.                         rxd_data[3] <= MOSI;$ O& \3 z% s8 H5 p# W+ Z. W
  70.                         rxd_state <= 3'd5;
    / t. P; `8 {3 H
  71.                       end
    # F  E6 y) H, l( z
  72.                 3'd5:begin
    " T1 H3 c5 p2 Y3 o- k7 b% v, N3 [1 Q* K
  73.                         rxd_data[2] <= MOSI;
    ( F& M) N) k) M* P
  74.                         rxd_state <= 3'd6;& Z* f4 Q/ B! R
  75.                       end
      {& {5 L0 \# R! X: |( J  b' `
  76.                 3'd6:begin
    / {4 g6 E7 j3 @% o  [. \( b
  77.                         rxd_data[1] <= MOSI;% G2 y0 }# A+ b2 D
  78.                         rxd_state <= 3'd7;! J; l- {+ i  x( o$ s6 a3 _  c
  79.                       end
    " S, T8 p* o# Y, f7 K* d
  80.                 3'd7:begin
    . ^1 M7 B& q, r9 ^
  81.                         rxd_data[0] <= MOSI;
    0 w1 N) C6 z: c! }  a
  82.                         rxd_flag_r <= 1'b1;  //set rxd_flag4 ]& o- ~$ j$ h* l) v! L/ s
  83.                         rxd_state <= 3'd0;1 h1 J+ r5 I) o9 u
  84.                       end2 v  J( X; A- b$ x! T
  85.                 default: ;0 y, ~8 P8 q: J& G$ Y6 v
  86.             endcase1 [/ R6 c; r6 h( h; i- M
  87.         end) W9 [1 ?% X5 n
  88. end" k  Q: G+ M6 \3 a6 d
  89. 3 l$ \2 z1 `) ]) E' \1 L

  90. : y8 t2 Q8 [& h7 R: ~7 t3 Z9 ]
  91. //--------------------capture spi_flag posedge--------------------------------* v7 j  X( M* y. Z. \& u
  92. reg rxd_flag_r0,rxd_flag_r1;
    " W  s& d. ~/ d$ d" D
  93. always@(posedge clk or negedge rst_n)5 s$ d! Q& v, m  I
  94. begin
    " n4 ^5 c1 g6 [6 f2 ?) X
  95.     if(!rst_n). y0 Z% B' W+ d8 Z" J* K" j# G- f
  96.         begin/ }/ M3 o2 F) A$ ?$ V
  97.             rxd_flag_r0 <= 1'b0;
    3 p2 d0 a( C# }
  98.             rxd_flag_r1 <= 1'b0;
    : v: F3 R+ ]1 W$ m4 E
  99.         end
    : l8 j3 V" N$ N
  100.     else
    ' i" B& w0 \( n: x
  101.         begin8 N" C2 G: [  Y6 s
  102.             rxd_flag_r0 <= rxd_flag_r;
    $ k" C( z6 y5 z; `5 e6 ~
  103.             rxd_flag_r1 <= rxd_flag_r0;
    + Q/ J+ Y: ~& s2 O) A9 _/ T; z
  104.         end
    8 `2 k$ j) F# G! ^% i. _* T. \
  105. end
    ' r+ W. T- V/ v( w; z+ k3 k+ r

  106. : ~: a5 T8 ]4 ~, o! @6 W' Z$ h- _
  107. assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;3 T/ V0 a, p( G( r5 }
  108. $ j- l: k" O  q+ z. q+ `% ?2 X0 S- J
  109. //---------------------spi_slaver send data---------------------------
    # b) D* g4 ~: N* A4 e5 x9 R
  110. reg [2:0] txd_state;0 L8 R) n- m' A! b9 S" c
  111. always@(posedge clk or negedge rst_n)
    2 l% \$ E* W2 ]5 y  e5 Y
  112. begin+ M0 B3 A# K; g3 @5 D, c8 ?
  113.     if(!rst_n)+ @9 M# e3 h2 }( I1 J
  114.         begin1 c$ ~8 ?( w0 A% p+ J0 S
  115.             txd_state <= 1'b0;% Y' E  ?/ g7 Q
  116.         end8 F- N+ p+ E# X3 b* d! c; X: w; R
  117.     else if(sck_n && !CS_N)5 q5 s& O: g; x& M, ~$ H/ |- n, p3 J
  118.         begin
    : [1 o2 y- [  N5 _! y7 X
  119.             case(txd_state)
    " I( e& A. |. y
  120.                 3'd0:begin2 j# J  f( I+ m
  121.                         MISO <= txd_data[7];
    ! _6 d1 c" G( o. j2 ~6 P
  122.                         txd_state <= 3'd1;
      Z6 v8 \/ i* j
  123.                       end
    8 p3 \0 Q2 F" _" h( Q6 i2 j2 N& ~
  124.                 3'd1:begin3 @8 U% |" ~1 h# w  b7 z6 k: ]6 }
  125.                         MISO <= txd_data[6];
    ! Z+ C1 p$ B8 ~2 q0 [
  126.                         txd_state <= 3'd2;
    ( ~9 U$ n1 Z8 E, \; i
  127.                       end
    1 i- i+ ]( W+ M$ W. @
  128.                 3'd2:begin! [: I  h8 I8 {) K- M
  129.                         MISO <= txd_data[5];4 y3 h! g( ^: E# {! u" n' X0 B
  130.                         txd_state <= 3'd3;
    ( P* e8 s7 V) h* }% g
  131.                       end
    ' x( G2 F7 ]# ?$ ~
  132.                 3'd3:begin8 a0 z2 Q) n/ U! e/ G  q1 H; r
  133.                         MISO <= txd_data[4];6 ~5 W8 X, {/ L+ |$ m. o
  134.                         txd_state <= 3'd4;7 ?# s9 G, F* R2 N) b6 R
  135.                       end
    $ L5 W/ v0 V' ?- Z
  136.                 3'd4:begin
    : J6 h7 @( K+ {4 t+ M- O/ C6 k  t8 Y
  137.                         MISO <= txd_data[3];; z8 L$ E. N5 q% l' |" v& G% v
  138.                         txd_state <= 3'd5;
    - |7 f6 O, s5 Z( K0 J
  139.                       end2 i0 p4 k2 u8 {. p0 T, _$ E
  140.                 3'd5:begin3 c6 I: e  j% T( _5 R! l
  141.                         MISO <= txd_data[2];
    $ D+ l& A" V! {! x8 x5 H$ |  P: P* y
  142.                         txd_state <= 3'd6;/ z- L3 b  b4 f4 d3 `$ T
  143.                       end
    1 Y" q$ v8 [/ T+ H# }
  144.                 3'd6:begin
    , m( X8 M$ z& v2 N+ L( `
  145.                         MISO <= txd_data[1];7 o' m, |  M. v* }* k. {
  146.                         txd_state <= 3'd7;, ]- V, T3 p  s
  147.                       end6 r2 G: q9 L- `7 l2 {
  148.                 3'd7:begin
    ) t' r7 i$ Q* B5 G4 Z5 x
  149.                         MISO <= txd_data[0];
    % S; A! |) h" Q
  150.                         txd_state <= 3'd0;
    4 e! K( ^# P% Z7 Q
  151.                       end
    ' E% E' }2 V' o4 P( z/ \# Z; g
  152.                 default: ;
    ( P; a2 d. J0 H* u0 x4 o, o/ O; L( z
  153.             endcase
      @2 \7 s0 P3 J) T5 Z
  154.         end
    - O2 B( b7 I% Y9 t$ h2 }
  155. end
    - G* ?1 {: V+ _# b( d6 I6 I$ c
  156. + R) K! D/ h1 c0 L; D7 }3 e
  157. endmodule
复制代码

8 V- }8 `5 ?& F" j% R) V" d9 n; `! Z( m5 E$ w7 j
- l. G& [* z0 f* K

5 i1 V- z. e3 N& m9 C! I7 i
1 收藏 评论0 发布时间:2022-1-16 18:00

举报

0个回答

所属标签

相似分享

官网相关资源

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