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

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

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

3 e3 H. O* Z- M  X9 T) a
二.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发送数据与接收数据。

! Q' Q  L5 ?$ ?! w, O- e
  1. /***********************************************************************
    , V7 N4 L0 ?  }; u2 k1 v  ^
  2.      ****************** name:SPI_Slaver_Driver **************' p3 b4 V" `/ l5 n+ D% P
  3.             ********** author:made by zzuxzt **********
    0 L) L* z% v$ u0 D
  4.      ****************** time:2014.4.29 **********************
    3 d" F0 L. L6 H  o9 Y6 u4 ^  z
  5. ***********************************************************************/
    1 r. T$ ?; N/ @; t$ y+ m( I
  6. //use SPI 3 mode,CHOL = 1,CHAL = 1
    - G- M8 i) J1 _8 p3 w, d0 L
  7. module spi(input clk,1 M! J% ~9 J; u
  8.               input rst_n,
    ' n# N) F1 e- M# x2 D2 k- t
  9.               input CS_N,
    % r& y2 G+ h& k" M- E7 P) @
  10.               input SCK,2 }8 v) V  X5 M6 q' z3 o4 b
  11.               input MOSI,8 O/ y% r2 U0 Z( T3 [5 `( i
  12.               input [7:0] txd_data,! v0 @( p% t( ^
  13.               output reg MISO,0 K, {) |8 y# D* W$ I; D6 J
  14.               output reg [7:0] rxd_data,! Z1 U$ w9 V5 W* u8 I' s* S
  15.               output rxd_flag);   //recieve done,please transmit data
    9 V0 K% W% w4 @2 {4 j+ @% t  Z7 E! A* h

  16. ) O, V( c6 P9 i
  17. //-------------------------capture the sck-----------------------------
    ) m6 r5 }; H# x0 x5 M3 N
  18. reg sck_r0,sck_r1;* e" s% S0 Z6 j5 Y/ ]7 q! J; n$ v0 R
  19. wire sck_n,sck_p;5 x* C4 c3 H4 G2 f! b
  20. always@(posedge clk or negedge rst_n)8 X3 p* n: L6 }2 g+ j
  21. begin
    " |7 a$ f0 S- n8 s6 s# p% G6 K' U' }
  22.     if(!rst_n); f' T5 ?6 J7 s) F
  23.         begin) S; [9 f9 G% N8 A- H
  24.             sck_r0 <= 1'b1;   //sck of the idle state is high1 ~7 Q7 F9 I" q; Q' g+ v0 o/ j0 G
  25.             sck_r1 <= 1'b1;; w+ V1 H9 d" {5 S0 F$ I4 z
  26.         end
    7 z" `! ~3 H9 U& y6 F
  27.     else
    - l5 M- I4 }) p% \0 [  Y
  28.         begin* H- K7 C6 Z- R/ g
  29.             sck_r0 <= SCK;
    0 J3 Q" B; f" p6 C2 T+ D7 Q
  30.             sck_r1 <= sck_r0;2 x# d! H# c( k0 a4 l4 i
  31.         end: D" D% S& _0 m) p& j  V
  32. end9 i  L& _; N, e; e& X
  33. 5 H/ K" x4 E# k3 C3 c( h6 D6 t  h3 _
  34. assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0;   //capture the sck negedge
    9 V5 l2 X7 {- D, a; {6 x6 j
  35. assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0;   //capture the sck posedge8 ]: w' d* A$ x$ {
  36. 8 I. {( `; M5 O& r: j
  37. //-----------------------spi_slaver read data-------------------------------8 k5 R7 d+ T& p/ }1 u& B# Q4 F
  38. reg rxd_flag_r;  _7 y, x. f# i, w6 s6 `& q  o
  39. reg [2:0] rxd_state;0 L9 p' I/ V' B9 d' F/ b
  40. always@(posedge clk or negedge rst_n)+ J7 @' d4 w1 u6 a8 p4 V
  41. begin, l- s" i! `6 T9 |. n/ O
  42.     if(!rst_n)8 J; t# @3 `, n7 @, M5 i+ _- m' h% }
  43.         begin+ C6 [+ m6 P# H
  44.             rxd_data <= 1'b0;" |6 b2 ?$ a. \- _( Q! `
  45.             rxd_flag_r <= 1'b0;& D* B; w; o0 S
  46.             rxd_state <= 1'b0;
    - R9 X8 x/ F9 V) S% c3 U' E
  47.         end
    3 m2 ~( J& h& m1 t: L
  48.     else if(sck_p && !CS_N)2 T, q9 U7 i; V4 s) p9 B+ c
  49.         begin
    ' V) R& U. v. d5 @% W# T4 O
  50.             case(rxd_state)
    . H  S/ A! h, R1 o# O
  51.                 3'd0:begin+ L) q' |: `% o( s; b
  52.                         rxd_data[7] <= MOSI;
    9 x" k- R' B( n' w$ J* B3 @
  53.                         rxd_flag_r <= 1'b0;   //reset rxd_flag
    6 c/ W0 V+ h8 `% ^& N7 d
  54.                         rxd_state <= 3'd1;0 M5 C% V& |# }% z: C
  55.                       end- B$ y$ Y; P- [3 q/ A  k
  56.                 3'd1:begin
    * j# G6 ^- t1 a. Y0 E/ d
  57.                         rxd_data[6] <= MOSI;
    0 T3 @- w- h* e9 e: R
  58.                         rxd_state <= 3'd2;
    : Z+ Z2 U$ A4 a- ]. Q1 {
  59.                       end9 \+ B2 K1 M6 ?6 H1 f  R# O9 Y
  60.                 3'd2:begin: ]" V9 O  Y9 l4 ?! j' U+ Y( x
  61.                         rxd_data[5] <= MOSI;* n# O3 s2 f2 s8 z/ j8 W4 s) }  E
  62.                         rxd_state <= 3'd3;6 q* F- }* a9 A8 L9 A
  63.                       end
    9 c( j2 L) z1 _1 G% u/ H+ b
  64.                 3'd3:begin
    , F  d" c2 W5 s. e
  65.                         rxd_data[4] <= MOSI;2 ~  L. ~7 b2 L; E4 r
  66.                         rxd_state <= 3'd4;
    . j% I6 M3 ^* l, d/ S
  67.                       end
    7 a! n: y  C2 q: U$ e0 H# X
  68.                 3'd4:begin2 U9 i& j' u4 x, a  X
  69.                         rxd_data[3] <= MOSI;
    . z+ O5 F% H- @8 E9 Q
  70.                         rxd_state <= 3'd5;& u" W! a# ]4 H+ p5 d- D6 a
  71.                       end  p) ]% e+ M; H+ p
  72.                 3'd5:begin
      _' w2 H: B& [7 R2 \' X4 h7 Q. K$ Z
  73.                         rxd_data[2] <= MOSI;- E- Z/ }8 i4 F3 @( a5 }
  74.                         rxd_state <= 3'd6;, l% X/ l& [5 [8 i. e2 \
  75.                       end
      D- c# Y3 j) \/ \
  76.                 3'd6:begin/ d- l6 l" m9 c) R4 g" ~) P
  77.                         rxd_data[1] <= MOSI;
    - V& S- C3 I0 |
  78.                         rxd_state <= 3'd7;$ |3 n+ J/ k$ {% ]# p& A
  79.                       end
    8 ~" w; b* @. x/ S: B! d+ R( I1 c
  80.                 3'd7:begin
    & R3 Q, \$ x; I( L0 l
  81.                         rxd_data[0] <= MOSI;0 n* ^& B! S3 U" ^* d9 Y
  82.                         rxd_flag_r <= 1'b1;  //set rxd_flag- ?3 x9 a7 ~# i* X# U
  83.                         rxd_state <= 3'd0;6 z7 d2 M' ^! y) J* b7 j5 ]
  84.                       end( L0 W% Y& ~. q$ F2 z
  85.                 default: ;
    4 L7 L9 d3 g: T. [' v
  86.             endcase
    5 ?$ |8 t) [3 Z' w
  87.         end( _% z( f& G! e5 G
  88. end
    2 l2 g' j" ^6 z
  89. : x8 e& D; L% I% f
  90. 9 H- ?( Q9 W7 g1 @
  91. //--------------------capture spi_flag posedge--------------------------------
    8 Y' K# c( v  I3 L
  92. reg rxd_flag_r0,rxd_flag_r1;, S5 j  @: b8 q% x5 E. S- ]7 b
  93. always@(posedge clk or negedge rst_n)
    , M! |- q' W- c9 s  H' n
  94. begin
    - s5 D) ]& s' |& L
  95.     if(!rst_n)
    0 W5 v) L& Y3 V1 O, h, [% y
  96.         begin6 s% X* h/ {$ c; T* G' i) j
  97.             rxd_flag_r0 <= 1'b0;; d- Q+ f; P7 }
  98.             rxd_flag_r1 <= 1'b0;
    & I3 W1 w1 ^+ X+ }: f/ ~9 m9 \: r* Z
  99.         end4 _2 f2 F# N3 t: o5 B
  100.     else
    4 Y" |4 S0 Y- A" H
  101.         begin% y+ H! P0 j, ^8 n) J6 \
  102.             rxd_flag_r0 <= rxd_flag_r;1 ^! l4 ^4 ^* G& R* o1 ~$ j
  103.             rxd_flag_r1 <= rxd_flag_r0;
    / V. f% q8 h; X& J/ g2 [) p
  104.         end7 U$ D% t4 L2 N: w7 U8 H2 {
  105. end+ P6 i' ?: U5 J& N3 C7 c$ {( b

  106. 4 B7 ?8 [  p3 P, J. w# v* l. m4 E
  107. assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;0 U! r0 L3 l) {
  108. 1 ?! l1 t2 T3 h' ]6 m' G, g
  109. //---------------------spi_slaver send data---------------------------
    ! J/ |# n7 b+ Z8 e  o  p6 w
  110. reg [2:0] txd_state;
    & L; g9 K" m$ o: Z) m/ B
  111. always@(posedge clk or negedge rst_n)
    ( z4 |# n, F% p1 d$ _  b+ R
  112. begin. s' c# E, A, f: B8 E
  113.     if(!rst_n)
    6 R8 p2 l' r8 @) R; ?; @, r
  114.         begin
    , w3 @' i2 |' ]6 f2 T
  115.             txd_state <= 1'b0;
    6 @7 s3 ?+ s6 W4 k# W; `% |! t
  116.         end
    3 ^  U( H+ q7 |
  117.     else if(sck_n && !CS_N)
    ( h$ W5 k" g/ O/ R: e! H
  118.         begin! q- T+ n5 {+ a3 d, y3 U
  119.             case(txd_state)
    2 f. j$ O6 f& ]6 g) b- x7 ^, U
  120.                 3'd0:begin0 {' x/ t( }5 q' K; }
  121.                         MISO <= txd_data[7];2 _( d- f  K( l! [% K5 w: A3 h
  122.                         txd_state <= 3'd1;
    # j$ E8 e) J; l
  123.                       end  G$ ^+ R( J, L$ P! P! s" Q
  124.                 3'd1:begin
    7 }0 f- |4 ?% N# P5 m$ V
  125.                         MISO <= txd_data[6];) E- M* S: x+ r# Q6 F3 @8 l* a/ l
  126.                         txd_state <= 3'd2;
    . i8 g: W0 ]" H' V, B
  127.                       end; r/ f2 @$ ]  Y; y' F/ ?$ W! P. O) q
  128.                 3'd2:begin1 p  X) h. n; |: T
  129.                         MISO <= txd_data[5];; u: p& Y* d7 A5 [% C$ E' O5 H
  130.                         txd_state <= 3'd3;5 L8 J5 a3 z+ i
  131.                       end
    8 U) W- b7 z, c- k' @' V
  132.                 3'd3:begin, r& j. I& I" e3 P4 W3 C8 y; P. L
  133.                         MISO <= txd_data[4];
    , U5 Z2 d  S& ~' l1 F
  134.                         txd_state <= 3'd4;
    8 M$ n2 P; J0 S) L, o; M. |
  135.                       end  i/ e0 R0 O# S& z  l
  136.                 3'd4:begin4 P7 p$ m- f! J1 u" ^  |* h
  137.                         MISO <= txd_data[3];
    ' r" M; ]5 d/ B8 k
  138.                         txd_state <= 3'd5;
    ' M+ p" T$ H( D: s8 Z
  139.                       end' P. s; v/ Y8 ]
  140.                 3'd5:begin
    5 \2 h1 v) T- I$ U6 k
  141.                         MISO <= txd_data[2];$ k+ Q( W: ?$ m4 P, D& r
  142.                         txd_state <= 3'd6;" E6 Y4 g9 z& F" `' Y3 O
  143.                       end
    ) e4 u5 \7 o' _( L0 o
  144.                 3'd6:begin5 y8 N. f1 p% b6 {5 H  f8 d5 _
  145.                         MISO <= txd_data[1];
    / e3 u: K9 X7 J
  146.                         txd_state <= 3'd7;
      m7 ?  Z  ]) C! D" e1 z
  147.                       end
    2 u0 P7 F; Z/ y/ S5 n" w1 w
  148.                 3'd7:begin. E2 \  D6 C5 E. L, B
  149.                         MISO <= txd_data[0];. g  N' L1 a- u5 C
  150.                         txd_state <= 3'd0;
    % u/ ~! E' n2 x( g: J
  151.                       end
    4 \& p2 b# ], g% O; a3 U4 R' V
  152.                 default: ;9 A  W+ G1 I4 d' W
  153.             endcase, ~; ?1 ~0 G( o7 H1 ?5 G
  154.         end
    ; ^2 p% _8 z" q8 p/ h8 v! C
  155. end
    + k' b5 F- o# j  |' F. _8 ^
  156. ' j2 k+ q) N! ?( n6 V& M
  157. endmodule
复制代码
* u! D  a  O5 W
" H/ L* p2 B2 `

' Z3 d/ e' [, T- `9 u4 c( ]

3 |1 ]. C& ~" |* n9 W, S
1 收藏 评论0 发布时间:2022-1-16 18:00

举报

0个回答

所属标签

相似分享

官网相关资源

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