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

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

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

$ ?- F/ `% k' N5 d8 q' |" u: }
二.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发送数据与接收数据。

. Y- ?( F$ P: Q/ I- P' p
  1. /***********************************************************************
    ; I( m+ r  x' b1 [9 @4 K9 }8 c
  2.      ****************** name:SPI_Slaver_Driver **************  ~' Q" T( u7 u
  3.             ********** author:made by zzuxzt **********
    $ d2 u+ h3 {* w& N
  4.      ****************** time:2014.4.29 **********************
    2 R( y0 ]2 B+ c1 S( [
  5. ***********************************************************************/
    ; a9 _) r. |8 j+ Q7 O" v/ D5 p* Q
  6. //use SPI 3 mode,CHOL = 1,CHAL = 1' c* W) D0 X( a4 r, k3 v. m5 Q" C+ u
  7. module spi(input clk,( K: b  k2 A% J! a9 H4 \2 m6 W5 }
  8.               input rst_n,
    ( P- l( j8 q2 H0 ?, B
  9.               input CS_N,
    . K4 |7 [( o6 L* B1 v
  10.               input SCK,1 T% n( M7 K+ q
  11.               input MOSI,7 m6 w5 O# V: v9 n
  12.               input [7:0] txd_data,
    * Y2 e, ~# j# o: ]! I6 ?
  13.               output reg MISO,
    8 K2 X$ o  T2 M# y
  14.               output reg [7:0] rxd_data,
    # ]( k/ W" I: `7 L+ n9 U' ?+ O& q
  15.               output rxd_flag);   //recieve done,please transmit data
    5 }4 l4 L5 c$ j; ]4 a

  16. % V" N  A0 d6 f
  17. //-------------------------capture the sck-----------------------------
    3 \, d+ u! O7 B( g7 u
  18. reg sck_r0,sck_r1;
    3 [& |! N$ B% a6 q6 `# \" d
  19. wire sck_n,sck_p;0 L7 f  v( r0 J' _8 d6 g/ {* a# \( C
  20. always@(posedge clk or negedge rst_n)( a/ U; I; P: [
  21. begin
    9 Z! a8 v7 T/ w: r0 N' B% A
  22.     if(!rst_n)' U* v; U9 L5 X/ C4 G
  23.         begin$ k5 O$ ?1 G% D+ {- j7 E  F* _
  24.             sck_r0 <= 1'b1;   //sck of the idle state is high; n4 `& Z5 S$ Q
  25.             sck_r1 <= 1'b1;
    + V( i' g+ P0 _
  26.         end
    ( f% W. p! H; b/ r
  27.     else: e8 C0 O4 r5 e# w4 T/ f3 v) g, u/ m4 _
  28.         begin6 G4 b+ K$ p6 `  C0 [! t
  29.             sck_r0 <= SCK;! W" L, N3 Q& B2 H
  30.             sck_r1 <= sck_r0;
    , S0 t, u# ~+ |1 X, I* o& a; B- {
  31.         end" H8 g" A3 E7 }
  32. end  f# c3 G- }. s8 k9 E, t

  33. / {4 b/ C( X" O4 l" s+ u7 _
  34. assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0;   //capture the sck negedge2 I1 x- @6 |% g+ V
  35. assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0;   //capture the sck posedge& `) T' l) j; o6 e* t4 m$ q
  36. ( I1 D# r$ }9 O$ v$ W0 `; o
  37. //-----------------------spi_slaver read data-------------------------------4 `! j, H! Y, v1 P
  38. reg rxd_flag_r;6 Y% |% c, r2 h7 @0 g9 C" Z- f
  39. reg [2:0] rxd_state;1 h6 `* r7 h7 ^( A
  40. always@(posedge clk or negedge rst_n)* `6 t1 X/ W" H' P9 l  ?- f6 h8 b7 t
  41. begin
    ) }. g: J# Z9 F3 L
  42.     if(!rst_n)
    % s/ ^, E( g* T. s. Q1 o
  43.         begin& r8 O+ T9 |# _" p0 H
  44.             rxd_data <= 1'b0;
    ( l  u+ m5 j3 Q2 R
  45.             rxd_flag_r <= 1'b0;8 Y1 K" e6 M7 G& B; k8 J
  46.             rxd_state <= 1'b0;  c$ a5 J0 o2 j/ `7 f" L* D. r
  47.         end
    ) H# p, s; t! J9 q# w6 ?; F
  48.     else if(sck_p && !CS_N); ?$ t. a6 p7 n& H( `
  49.         begin4 y. x& {. R5 I0 u9 c" e
  50.             case(rxd_state)* [5 s/ P4 p1 `
  51.                 3'd0:begin" n4 h( q, A  n& Y6 H. l7 d6 W8 ]" E: e- U; i
  52.                         rxd_data[7] <= MOSI;2 g5 U2 M, j, e, u$ G
  53.                         rxd_flag_r <= 1'b0;   //reset rxd_flag0 u) }1 |4 w- n( C% m
  54.                         rxd_state <= 3'd1;+ x8 m# Z: U3 X: G% r. ^
  55.                       end, E# [1 n8 o1 g3 y2 M$ _' A
  56.                 3'd1:begin
    , v- S7 l! g+ E+ e: S' H# _! |
  57.                         rxd_data[6] <= MOSI;+ N$ l9 E' G0 _
  58.                         rxd_state <= 3'd2;
    , U2 v# O4 [6 i6 ^$ y% `6 V
  59.                       end
    ! K4 O3 y: i7 n5 f, n5 r0 J' B
  60.                 3'd2:begin
    % k: y" K' q  b9 P
  61.                         rxd_data[5] <= MOSI;
    5 R' ?; o9 Q6 ~2 a4 H: N, j
  62.                         rxd_state <= 3'd3;" k' w! ~/ [- s7 Z* A1 Q* [
  63.                       end
    7 F; R* O. {* C0 G1 m" {5 h, J
  64.                 3'd3:begin
    $ R. X- V8 `9 b! v
  65.                         rxd_data[4] <= MOSI;. J& q6 b2 Q3 b1 v. S6 s3 J% N. X
  66.                         rxd_state <= 3'd4;
    " H% }7 D/ H1 w; d- B9 Z
  67.                       end
    # h( X' k# l2 o* M
  68.                 3'd4:begin
    7 g" O/ d6 D+ F' R+ J. O
  69.                         rxd_data[3] <= MOSI;
    + F4 ^/ ?2 q" v7 u0 r& ?
  70.                         rxd_state <= 3'd5;
    + j3 {  }5 s7 j2 U
  71.                       end! h- [1 R% R& y: H' {9 O- y) n# ^
  72.                 3'd5:begin' C8 z( Q4 E' q2 _) ^
  73.                         rxd_data[2] <= MOSI;
    + {/ L( |! g" ]! a1 U, f9 v" L
  74.                         rxd_state <= 3'd6;( X$ l' z0 }, r1 u& ^3 O; e' [
  75.                       end
    ) J/ \5 w: L% B, s4 g
  76.                 3'd6:begin
    . m; m* O/ X+ Q; D  y- r/ O
  77.                         rxd_data[1] <= MOSI;
    ( a5 X( Q4 ~9 h' g7 O! ]$ d
  78.                         rxd_state <= 3'd7;* v; i4 F/ Q2 p6 ]& r
  79.                       end0 T1 D" C1 Y3 x
  80.                 3'd7:begin
    : i; S" `" ^& t5 D7 v
  81.                         rxd_data[0] <= MOSI;* g: P' Y2 X$ d3 {
  82.                         rxd_flag_r <= 1'b1;  //set rxd_flag
    / f0 r  s5 G+ ]4 H& h- v$ }, T' \
  83.                         rxd_state <= 3'd0;
    $ o7 i2 N% V5 H+ M6 S; D( P4 a7 Y) D  x6 h
  84.                       end7 c# s* u4 t$ Z' }6 {$ ]% h1 I3 M& R
  85.                 default: ;! t, U8 v' z) d. b* n9 e
  86.             endcase
    2 A) M% r4 @  R6 [/ i6 a; O5 E
  87.         end9 ~7 y5 C+ ^5 M0 _1 T
  88. end
    : O! f0 A3 s- j% S8 C3 ~" \' h
  89. ( {' t4 t4 Q# k6 b! d, W
  90. # C: R6 ~# V# w; Q4 M
  91. //--------------------capture spi_flag posedge--------------------------------
    4 \! T* U; J: b; t
  92. reg rxd_flag_r0,rxd_flag_r1;
    ) U3 V& ^6 ~5 O. w
  93. always@(posedge clk or negedge rst_n)1 E5 e( Y' q, j/ d3 F& P
  94. begin
    4 e- W* N7 _& G3 q& F) W+ X5 }
  95.     if(!rst_n)
    5 V% L1 W' P1 Z
  96.         begin% Z( g: i' E2 j: B/ @
  97.             rxd_flag_r0 <= 1'b0;! \* X0 T7 l$ \' F+ j  D; H6 R, n
  98.             rxd_flag_r1 <= 1'b0;
    # F7 T7 |" G) n% w4 b+ m& N0 [
  99.         end( ?  D/ e6 U8 f( a8 W8 r( y% \2 b
  100.     else2 h8 Q2 K, f4 F
  101.         begin5 [! j( D0 h# |
  102.             rxd_flag_r0 <= rxd_flag_r;
    " o9 n# ~) L4 _4 ^. d
  103.             rxd_flag_r1 <= rxd_flag_r0;- a1 t3 U" C4 k
  104.         end
    - K- s7 ~4 S8 C* [; v8 v# D
  105. end
    ( {0 Z- p! B2 `0 ^5 D" q
  106. ; D1 V# D6 g. N* r" u6 S' a
  107. assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;3 @, b. s0 [( C; n( t) x( g  Z
  108.   x% @  Y0 m. \* j
  109. //---------------------spi_slaver send data---------------------------8 \& \% w0 m0 f! N' g
  110. reg [2:0] txd_state;
    " I4 A* t2 C7 E& z) g5 n/ o4 m
  111. always@(posedge clk or negedge rst_n)
    2 s5 M% n: k# \7 g: ~
  112. begin
    : x# @: t4 {6 a9 K8 O: C5 J
  113.     if(!rst_n)
    + E* u2 k, [, L, h
  114.         begin
    2 j$ j0 v6 f, j4 O
  115.             txd_state <= 1'b0;& ~8 h9 z% X, d3 N
  116.         end; {" [. j2 L4 B+ y6 |. f+ Q
  117.     else if(sck_n && !CS_N)
    8 b( J7 D4 n; Q& F& V
  118.         begin8 Z1 J# @" Y$ E% m& S, f+ }
  119.             case(txd_state)
    # t$ A0 o- h) z# t4 i5 i: L/ o
  120.                 3'd0:begin
    8 i; Q0 B! n0 X
  121.                         MISO <= txd_data[7];  U, e6 W' }$ z" w5 c6 [, V
  122.                         txd_state <= 3'd1;6 u' q6 V0 ?/ j7 I! M5 N  i9 m) s
  123.                       end
    2 C8 {: s1 x: ]: W( K2 [8 u5 K
  124.                 3'd1:begin% V6 k  H/ _. t  b' W( J% o) V
  125.                         MISO <= txd_data[6];
    , r, d( b7 F2 R% H& Z8 y4 F
  126.                         txd_state <= 3'd2;$ k( ?, G  t, K6 m; X
  127.                       end
    % x, w9 E, u: S; d- R; m1 u! a; Q/ D
  128.                 3'd2:begin9 ]! J' j  @+ y& ^* A/ [7 q% ]0 j, h' m
  129.                         MISO <= txd_data[5];
    2 y; v+ @1 u* [% @" a
  130.                         txd_state <= 3'd3;
    2 e( v6 L+ ?0 y% N% u/ z
  131.                       end, L% I9 g3 Y1 D  \- x! {
  132.                 3'd3:begin
    , ]& t2 Y1 ]1 f3 }
  133.                         MISO <= txd_data[4];
    0 A1 @) @2 P! x7 z
  134.                         txd_state <= 3'd4;  Y/ k4 ?# \0 H  S" K$ K$ T
  135.                       end
    9 W5 M5 B' m1 t" f5 H  j
  136.                 3'd4:begin
    ( j( j& S6 J  [! |7 B2 L$ |
  137.                         MISO <= txd_data[3];
    & c6 q, x& v+ ]. ]* R
  138.                         txd_state <= 3'd5;
    5 |% {! k6 p7 P/ r4 r$ D
  139.                       end5 {+ ?( d* o# |) \) ~  _) D
  140.                 3'd5:begin
    7 R8 _+ T/ ]; F! d2 m3 z
  141.                         MISO <= txd_data[2];9 `9 N2 Q; \4 e) C
  142.                         txd_state <= 3'd6;
    6 u; t9 `, }/ d7 T
  143.                       end
    ; s7 z: p' e- T, A+ C- T- }8 x9 I
  144.                 3'd6:begin
    # j- e. N. M; ~
  145.                         MISO <= txd_data[1];
    7 Q0 n5 x/ V4 m
  146.                         txd_state <= 3'd7;
    ' S& v  ~) X6 ~0 x5 i" S" a
  147.                       end1 K8 K3 X) C$ k) V- B2 c
  148.                 3'd7:begin
    / d. n/ A. b. V/ C) V6 M3 |
  149.                         MISO <= txd_data[0];
    : q8 Z7 ?+ T5 V# E( N" r
  150.                         txd_state <= 3'd0;
    " ?; ]' T/ m" z6 w) X2 e
  151.                       end
    " N$ U0 g1 t; J- s+ w) E6 |
  152.                 default: ;7 c2 Q7 h5 \4 |7 b# t  Z
  153.             endcase0 }& H; n4 A( |  g" C
  154.         end0 T. L9 S7 m" w: g8 O& I
  155. end3 ^  e& ], N, a/ X2 U7 D

  156. $ H9 Q- m8 m. n. [& S5 h9 f
  157. endmodule
复制代码

3 R& Y# t. T: K/ H2 q* z/ q! X( n1 a+ f) f; \
4 u) w! u( q1 T

$ Z8 D0 g8 k# k2 E* \3 B" m
收藏 评论0 发布时间:2022-1-16 18:00

举报

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