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

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

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

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

: `& M8 @1 P; l+ J7 m5 y1 |
  1. /***********************************************************************9 u" l5 R& d( V, j
  2.      ****************** name:SPI_Slaver_Driver **************
    ( W6 `1 i7 C2 H" w+ }- O
  3.             ********** author:made by zzuxzt **********
    8 F% n* z7 [$ y. G  `
  4.      ****************** time:2014.4.29 **********************
    6 ~8 L( m6 G7 E0 i4 ~% I( ~6 {3 x  I
  5. ***********************************************************************/9 ]4 O$ L7 v) T  C4 o7 B
  6. //use SPI 3 mode,CHOL = 1,CHAL = 1
    ; x4 w% ]" _; d6 e& j$ r
  7. module spi(input clk,# [3 X$ Q3 F% c) H- M! E% [3 [2 r
  8.               input rst_n,
    ( s+ o6 H+ u" {/ u) F9 x) e
  9.               input CS_N,& t( |' o' r1 r  f( ~
  10.               input SCK,7 h0 f8 U0 H+ S0 }
  11.               input MOSI,! O% ^1 ~6 B8 M
  12.               input [7:0] txd_data,* J5 m4 b. A  k3 A6 i& `
  13.               output reg MISO," S. X( X- [/ f7 [9 C3 t3 q
  14.               output reg [7:0] rxd_data,
    . J( z" r  S8 ?) y; a) D7 h9 }
  15.               output rxd_flag);   //recieve done,please transmit data2 k: i6 a7 ~3 Z2 p4 m

  16. 6 v! T4 \$ ], d
  17. //-------------------------capture the sck-----------------------------
    " A+ @2 [, ~, d4 R4 ~; q. p
  18. reg sck_r0,sck_r1;; k$ [; j+ H" k, H
  19. wire sck_n,sck_p;0 d. l  c; r% K- J0 P
  20. always@(posedge clk or negedge rst_n)
    4 [* |& J' r0 `- K8 R; G
  21. begin
    * L. }1 I, P( v  `
  22.     if(!rst_n)2 R8 U2 p9 T' p1 q) l! J
  23.         begin
    . {9 H6 u. o+ y6 ]) {" Q+ O# |2 J
  24.             sck_r0 <= 1'b1;   //sck of the idle state is high
    : Q3 d9 I" a. E$ `( T/ V5 s8 n% G
  25.             sck_r1 <= 1'b1;9 B- Q% f! ~  S0 l" V; _& A9 y
  26.         end
    9 K) j# z; w6 F. `" ^& |8 b
  27.     else
    0 {* L4 u# Z9 C/ X8 Q8 U
  28.         begin
    # V3 c: G. t. D/ r3 y3 \+ J) B
  29.             sck_r0 <= SCK;; J. c7 \  o$ m1 M) d3 {' H9 Z
  30.             sck_r1 <= sck_r0;
    ) \  a! M0 j# P( ]  J
  31.         end. m1 g6 b6 n' _3 D4 x! j) L
  32. end
    ; `: G9 x, X  }+ |" d, f' E
  33. ; x+ i! S: j6 R6 x
  34. assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0;   //capture the sck negedge3 n& |+ ], u) f
  35. assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0;   //capture the sck posedge. ~8 j: w- ^. W3 a" M- g

  36. 1 U% Q' I8 V$ V0 B9 k. X
  37. //-----------------------spi_slaver read data-------------------------------: A2 x; M2 ~: i* m( B7 m
  38. reg rxd_flag_r;
    ' h$ p7 ]7 N7 J" ]  r( P
  39. reg [2:0] rxd_state;
    2 ^" e2 k+ M% Z
  40. always@(posedge clk or negedge rst_n)$ E' ~8 Z0 \3 m
  41. begin
    ) d  R4 d$ m8 T
  42.     if(!rst_n)
    , e6 l# ?6 u" d+ A3 ?" T
  43.         begin
      j1 C. x" R( `; s, v1 q0 m% G
  44.             rxd_data <= 1'b0;: d* G7 d  S0 O) I7 d2 p- l
  45.             rxd_flag_r <= 1'b0;7 D1 D: W) ~, l
  46.             rxd_state <= 1'b0;/ _4 ^' x' J: v0 K, a; k/ |
  47.         end4 o; a7 B: Y2 q. ^( }# v( b8 P, \; r- M
  48.     else if(sck_p && !CS_N)
    / \3 E5 T, o: a% j6 c. Z" E/ O
  49.         begin- ^$ B' \# Y! w: Z. X4 w1 E
  50.             case(rxd_state)  h5 b2 W+ @* @( g0 M1 r: S, V
  51.                 3'd0:begin
    3 Q. L6 e& ^/ P
  52.                         rxd_data[7] <= MOSI;
    8 Y. W- t& W( ~( z+ i& |
  53.                         rxd_flag_r <= 1'b0;   //reset rxd_flag
    4 w0 D5 Y0 [7 r
  54.                         rxd_state <= 3'd1;
    5 S! V, [3 f, M# H7 m) i
  55.                       end) f* Y. P4 u; Y- x+ y
  56.                 3'd1:begin" I8 D* [- C5 \8 Z4 W% ^
  57.                         rxd_data[6] <= MOSI;
    4 l. Z& w6 L5 {, q+ F4 a5 n
  58.                         rxd_state <= 3'd2;- H: p& f( k3 [2 @0 [  R0 J  x  a
  59.                       end
    0 ^* V- x6 V' A: u# u
  60.                 3'd2:begin1 D0 s" l* t" K9 y7 d
  61.                         rxd_data[5] <= MOSI;
    / a$ `6 w% }& D8 o% F
  62.                         rxd_state <= 3'd3;5 _, l4 f, W  k% G+ l+ {
  63.                       end
    7 X+ W/ {) Y. _
  64.                 3'd3:begin
    8 i$ P; j8 u8 t% z3 y
  65.                         rxd_data[4] <= MOSI;
    * @/ w! ]; `1 Y' C+ J; g
  66.                         rxd_state <= 3'd4;" u6 @: |0 ~1 t1 f
  67.                       end6 [! z4 t: q* w
  68.                 3'd4:begin1 R8 K, Y3 D+ V. a! Q) c- b
  69.                         rxd_data[3] <= MOSI;8 j3 M( K& m. k3 H) |% O' W. Y
  70.                         rxd_state <= 3'd5;) w, g# \5 k1 ~/ @- }9 ~
  71.                       end
    ) x* n: W, ^, t. G
  72.                 3'd5:begin
    6 `7 v' Y5 K1 E3 P& A0 o7 z
  73.                         rxd_data[2] <= MOSI;
    / e, ^6 {: Q  C7 M: \& x
  74.                         rxd_state <= 3'd6;& q0 [6 v4 e, R2 F- K$ a
  75.                       end5 W( j' \% J  [& R) z
  76.                 3'd6:begin  u, G( `* C- t3 u2 A
  77.                         rxd_data[1] <= MOSI;
    & O1 o, k6 G. d8 g( r  \$ ?
  78.                         rxd_state <= 3'd7;
    4 b& _# h/ I1 ^6 M
  79.                       end
    # m9 \3 q8 I$ S( z1 k/ {8 s
  80.                 3'd7:begin
    % N' {. Z# R, c
  81.                         rxd_data[0] <= MOSI;
    & I5 B' E5 V& |% l3 f
  82.                         rxd_flag_r <= 1'b1;  //set rxd_flag
    % z$ ~9 G$ G& z# ^6 |. \( s1 u/ Q
  83.                         rxd_state <= 3'd0;
    . v' }% [. G& {2 j( |' F& L
  84.                       end' D  X+ ^; D' M/ F
  85.                 default: ;
    - ^( }5 M. v. z; S' u" ^
  86.             endcase
    . P5 u: E; O: R4 i! t. ]- o/ v; U
  87.         end# u9 G( l& @* D# u6 d2 R) i( ]
  88. end
    * ]  f/ @7 Q; g% k7 _' j
  89. . ?1 ?$ @* k! r
  90. 2 ]3 }( E# Q1 _* U
  91. //--------------------capture spi_flag posedge--------------------------------4 ~5 J: W- O- V) o3 V" P& [) d
  92. reg rxd_flag_r0,rxd_flag_r1;% U& _4 ~: k. O+ i, j
  93. always@(posedge clk or negedge rst_n)
    7 X0 r6 Q7 A, C
  94. begin
    . I5 ~& v5 z! u1 i! X
  95.     if(!rst_n)
    ! f  F' s' p1 H# G2 f: A# X8 N- H
  96.         begin
    ) F7 M- g9 ?6 L2 t) P$ v
  97.             rxd_flag_r0 <= 1'b0;1 c- l: ^2 _9 c9 K' }' \. t
  98.             rxd_flag_r1 <= 1'b0;
    8 c4 }0 E  i& R
  99.         end$ [9 G% L& f2 t/ D- C4 T
  100.     else& D& j! D+ H  ~- F6 X( N1 q
  101.         begin
    8 x# j+ @) G6 Y# B8 l1 r
  102.             rxd_flag_r0 <= rxd_flag_r;: c5 Q8 s/ d' b' F: C  E
  103.             rxd_flag_r1 <= rxd_flag_r0;
    6 ~3 K- c  ]/ E# O; ~
  104.         end
    ; P+ Q- R9 X  ~* B& @; S
  105. end6 s% q! B! }' T2 z+ o

  106. . W9 G; Y: r5 I
  107. assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;5 J# k4 Q5 P( [+ v/ X" r7 H6 }

  108. - `& s; ~2 E& F. u5 u2 {
  109. //---------------------spi_slaver send data---------------------------
    6 r2 n& N2 l, b
  110. reg [2:0] txd_state;; A) N9 U9 t- a9 N, N7 e
  111. always@(posedge clk or negedge rst_n)
    & E' z( u) C& p' G% s0 C
  112. begin
    1 u! t- ]1 U* U8 c% C' U
  113.     if(!rst_n)
    - ]2 y9 g! }5 n% h
  114.         begin" n" M6 s8 {) Y2 {" v1 ~3 B
  115.             txd_state <= 1'b0;
    7 Z7 I: T# [- e. O6 a' d' E
  116.         end
      J8 j. q0 q- ?$ D' v" c
  117.     else if(sck_n && !CS_N)
    % x- D; ~7 l7 {
  118.         begin" I/ @2 R2 @* _0 {* |) N, X! i8 N
  119.             case(txd_state)
    : K: r$ f! }; ]0 @0 f% L* o
  120.                 3'd0:begin3 B& M1 D( N8 v$ ?
  121.                         MISO <= txd_data[7];0 {9 n1 r+ w( [! I2 {! S* F6 \
  122.                         txd_state <= 3'd1;% ?  Y! {' w  m2 J$ j( i
  123.                       end' o# K6 {8 }5 j2 B- E9 Y2 u
  124.                 3'd1:begin
    # t7 E* x) [" W/ X; E+ a
  125.                         MISO <= txd_data[6];
    / v7 Q% D& G# X, B
  126.                         txd_state <= 3'd2;" C, S4 h# }, r1 \/ i
  127.                       end
    7 e, ^6 V& J! L7 C+ b
  128.                 3'd2:begin+ z: u5 B2 W! [
  129.                         MISO <= txd_data[5];
    " H  Q; |+ u0 y, e4 z
  130.                         txd_state <= 3'd3;
    : {( u6 Z$ V6 v2 ?( t4 Y. y
  131.                       end
    " x2 L7 U( N- L% D& ]# m7 H
  132.                 3'd3:begin; L0 }  K# p  _/ j# t# Y& |* ~
  133.                         MISO <= txd_data[4];6 T7 G' P5 N* h% g: R
  134.                         txd_state <= 3'd4;( a) @  S. Z$ S) h# |$ i. {( Y
  135.                       end7 L$ R& g& {8 t; y- n
  136.                 3'd4:begin# ~; @. i$ `3 q! S. c
  137.                         MISO <= txd_data[3];2 M# }9 N! Y+ ?8 J, {+ F, L: [7 d
  138.                         txd_state <= 3'd5;- b# C7 I$ y$ J. A( y/ t* ?
  139.                       end
    ) I/ m$ m% W) U) |% `2 ?( n; l
  140.                 3'd5:begin- B" t0 o8 q) R8 K
  141.                         MISO <= txd_data[2];5 c% y1 t" Z' M6 W2 v+ G
  142.                         txd_state <= 3'd6;
    % D8 ?( t+ s: K# X; u# k
  143.                       end
    ' ^" K- ?) R1 M- y" b3 D+ E
  144.                 3'd6:begin
    ! F2 I! M* |1 `* g. D
  145.                         MISO <= txd_data[1];" f" h4 Q6 J5 ]
  146.                         txd_state <= 3'd7;
      }# U- N9 ^0 X) v/ o6 x, R
  147.                       end5 {* b3 v3 L1 B" D0 N5 J. G( x5 T
  148.                 3'd7:begin
    + ?' N/ H1 n! @, K( V6 G; a" p
  149.                         MISO <= txd_data[0];
    + ^$ A6 O+ L' \, M7 c1 Q
  150.                         txd_state <= 3'd0;  r+ J$ @+ H& ]% b7 P* T; v  g) b& ?
  151.                       end
    5 O* r/ Q+ |; s) G0 l: _: W
  152.                 default: ;2 m" U7 a, v& P
  153.             endcase
    * r- _4 Y5 v, \8 J, r7 c2 ?: ~3 R
  154.         end, W# d6 z8 R  ^. f; J+ Z
  155. end
    3 H/ A' z3 I9 S: a9 f
  156. ! B. j: d1 Z8 T% _
  157. endmodule
复制代码

/ x4 D- \8 e2 G$ T$ i+ B
8 N3 p7 F+ _9 `- ?. _3 I# j. x& ~
3 H( V; ?9 U; A, [, W/ V4 X# F

8 }: _; a/ X8 ~1 H
收藏 评论0 发布时间:2022-1-16 18:00

举报

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