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

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

[复制链接]
STMCU小助手 发布时间:2022-1-16 18:00
一.SPI协议简要介绍
SPI,是英语Serial Peripheral Interface的缩写,顾名思义就是串行外围设备接口。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。2 Q9 p% R/ n) U: X
  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拉低使能情况下。
% a# N3 A& b1 {! o8 e, c; F
二.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发送数据与接收数据。

) A. h& [- Z) C
  1. /***********************************************************************
    - V3 l8 H( Q& Y+ r! j  y
  2.      ****************** name:SPI_Slaver_Driver **************
    0 j4 B+ r" [: g) v/ w1 U; h
  3.             ********** author:made by zzuxzt **********2 z; c5 I0 q% G
  4.      ****************** time:2014.4.29 **********************
    ; b6 t6 k7 h1 m* [2 G* Q  u
  5. ***********************************************************************/
    8 I' w5 S! K( r5 U- I4 s
  6. //use SPI 3 mode,CHOL = 1,CHAL = 1
    0 \. E) m0 ^: f* }) g& W% I
  7. module spi(input clk,
    / X/ w+ x# a! s6 C  p+ r. ]2 E7 _: ~/ _
  8.               input rst_n,
    : d+ a, e0 y) i8 u
  9.               input CS_N,
    6 D5 P( R; I  m# W. ]4 _
  10.               input SCK,8 _4 z/ E% W6 X) I: r
  11.               input MOSI,
    7 Z/ _8 n& N, ]! x
  12.               input [7:0] txd_data,
    + ]& ~4 x# Z) z. n& W
  13.               output reg MISO,
    / G" U4 R/ v( N! v3 v1 B
  14.               output reg [7:0] rxd_data,
    0 l+ A# t& \5 x+ U: L% N
  15.               output rxd_flag);   //recieve done,please transmit data6 `( l9 ~6 U2 e/ {' b* z! g
  16. : K* M7 Z$ W+ C
  17. //-------------------------capture the sck-----------------------------
    . l  _8 s% ]+ P0 @! I
  18. reg sck_r0,sck_r1;
    , n* m1 q/ [, I& M# ^- E+ i
  19. wire sck_n,sck_p;
    ( H* E( m0 }; n/ e+ z4 M3 b
  20. always@(posedge clk or negedge rst_n); @9 K# W- \6 G) c: D. N& y  ^
  21. begin
    / j0 r4 _# s6 L0 f' @5 L9 q
  22.     if(!rst_n)' x9 E0 ]! b/ R. M, W
  23.         begin5 q/ r" b  l6 ~3 J$ t5 z
  24.             sck_r0 <= 1'b1;   //sck of the idle state is high
    ) \* ]& K4 W- b& o$ O8 ]& y: ^
  25.             sck_r1 <= 1'b1;
    % W7 u5 |7 H4 T6 h! [
  26.         end8 ?/ H5 j! ]  H" ?  {( U) E, V
  27.     else2 G' O5 b+ f  w- [2 ?) u
  28.         begin' s& \: D. e* D) c9 O
  29.             sck_r0 <= SCK;
    4 I# s- q# n- R! x1 s! L
  30.             sck_r1 <= sck_r0;
    / v, O6 d" ~7 ]5 E. C6 r8 Y, L: M
  31.         end- ?5 C, t; A! U3 B( \9 r0 A4 W- n
  32. end- W; A0 a6 q2 G" x. Y  p
  33. 4 U& k/ Y+ d5 c4 J$ F
  34. assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0;   //capture the sck negedge# R0 F5 s0 t% V4 w  T% ^1 Z6 n5 P
  35. assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0;   //capture the sck posedge
    , L1 h1 X5 I% _& l

  36. 4 _' @# l! e7 L/ t# |& P" f
  37. //-----------------------spi_slaver read data-------------------------------2 K, t+ f8 Z; `8 \
  38. reg rxd_flag_r;
    7 E$ U8 a* q! V
  39. reg [2:0] rxd_state;
    / n; {  p! l8 d& M% i+ h2 Y  {
  40. always@(posedge clk or negedge rst_n)  q: E% x" O1 l6 z. T! t, P; o! R! E* O& U
  41. begin3 l& s$ a6 y6 ^. y2 I$ q
  42.     if(!rst_n)! }* I# s& @2 f2 m1 Q
  43.         begin
    & I5 U4 V3 y2 I4 n% C
  44.             rxd_data <= 1'b0;
    8 {/ n- A1 F9 h
  45.             rxd_flag_r <= 1'b0;
    9 q& f7 Q, ~/ T; F5 i! m0 t7 u
  46.             rxd_state <= 1'b0;
    8 s0 p( m) V: ]8 s% r
  47.         end6 U4 j- u! \. F7 `0 N: R+ l
  48.     else if(sck_p && !CS_N)
    % u6 R2 U5 n3 {: m5 t  C' N
  49.         begin
    . S" V+ o) t$ ]( {6 s
  50.             case(rxd_state)) s( v4 T* F# V4 e  l1 h
  51.                 3'd0:begin' O0 N1 x0 j! N: h' D; F- z7 c
  52.                         rxd_data[7] <= MOSI;% Q" V5 F& ^* N( }+ B- V
  53.                         rxd_flag_r <= 1'b0;   //reset rxd_flag/ J. u" c  Q# ]8 Y6 }- |
  54.                         rxd_state <= 3'd1;" Q* E9 V5 n; T/ I1 \0 N* G
  55.                       end
    + Y0 m! O( ]) g0 x  o
  56.                 3'd1:begin0 `3 z; v; V1 B: w# F2 M+ `% p/ z
  57.                         rxd_data[6] <= MOSI;5 B- {$ \' h: p0 R7 W$ q
  58.                         rxd_state <= 3'd2;
    & |& {! v  Z$ \: u2 A8 s
  59.                       end
    $ l2 f! g/ d% \) z; J  e
  60.                 3'd2:begin/ m7 Y" C" D. R$ {7 Y
  61.                         rxd_data[5] <= MOSI;7 d/ y8 L8 A7 i+ U  L# f: K( G
  62.                         rxd_state <= 3'd3;
    0 I/ x6 `2 ?" B8 }
  63.                       end
    - r/ ^7 n& {6 b( |
  64.                 3'd3:begin
    ; i7 z' I2 o0 m! Z2 w
  65.                         rxd_data[4] <= MOSI;; ]' p1 q. p) P1 D
  66.                         rxd_state <= 3'd4;9 T$ y6 c2 j5 @4 p
  67.                       end8 L2 B& B& b0 P7 l0 n1 F
  68.                 3'd4:begin
    2 a  t# k& h6 Q8 b) b" D' g
  69.                         rxd_data[3] <= MOSI;* Y/ Q. W9 Y6 C+ k* C6 w6 A
  70.                         rxd_state <= 3'd5;
    / L) N% \; c( Z% K5 B3 G! I
  71.                       end/ S1 |# y/ J- v6 v# I! [
  72.                 3'd5:begin
    ! a1 h2 P  c$ w# ^1 G5 o* `" U. W
  73.                         rxd_data[2] <= MOSI;
      H- y6 s; b. @' D* j2 R5 R6 |8 z
  74.                         rxd_state <= 3'd6;1 ]( ?6 C+ @- j( `7 ?
  75.                       end
    ! h) A' {0 v, Z3 `4 y- S2 s& I
  76.                 3'd6:begin
    7 j2 f+ N7 P4 e* u
  77.                         rxd_data[1] <= MOSI;! G  r1 n- a' ]/ P: i: o; y
  78.                         rxd_state <= 3'd7;, M0 g* {/ S4 |6 H# @
  79.                       end
    " \7 K! I' g2 t& {$ d( s
  80.                 3'd7:begin
    4 `  W6 p$ z+ v# y
  81.                         rxd_data[0] <= MOSI;
    + F* W  F, G( I4 R0 s
  82.                         rxd_flag_r <= 1'b1;  //set rxd_flag* I- f# o0 O( r3 C* t
  83.                         rxd_state <= 3'd0;
    7 ^' L$ I" V# F& \* [* Z! \
  84.                       end# w) M: a; [9 ^
  85.                 default: ;
    " Z$ A' t6 y" K4 i, k
  86.             endcase
    $ A5 V$ _$ O4 A4 n" r
  87.         end
    3 Q" d- ]# J  m# M
  88. end
    8 U# ^" J3 k; {4 i" ^. b8 N5 u
  89. / m- w. r5 b% K& `1 M6 ^
  90. 8 d3 K* X  j  v% d, @. K8 \
  91. //--------------------capture spi_flag posedge--------------------------------7 w# r" X- Z: d( c- B6 f4 i
  92. reg rxd_flag_r0,rxd_flag_r1;8 _% Q9 k6 r4 C0 O5 Z* u1 r- u
  93. always@(posedge clk or negedge rst_n)
    0 h: Z: Q6 a0 Q; g: C* K. c
  94. begin8 w# [0 o6 }3 \! u9 ^, p
  95.     if(!rst_n)
    6 H  ~3 ^. N7 W0 P$ i
  96.         begin! \. Q4 P8 D/ _& Q! P( M
  97.             rxd_flag_r0 <= 1'b0;+ f* v- m" z" V7 R$ j% z. ]. t: |- Y
  98.             rxd_flag_r1 <= 1'b0;
    . B, f( ^. c) O: W9 `. R1 L" T- A1 @
  99.         end0 L2 h" t9 b. k+ K! |
  100.     else1 s( i0 z$ p. J, ~8 S
  101.         begin
    , h1 n0 ^: E! `. ~
  102.             rxd_flag_r0 <= rxd_flag_r;) @- S/ M% j9 |5 l& c3 R& o7 q7 o' ^
  103.             rxd_flag_r1 <= rxd_flag_r0;
    " h( N% Q' t8 d0 A. C0 l
  104.         end: j& x3 \+ j% a, o; y. K& g
  105. end  Q8 f) }" V' A4 \* Q

  106. ! I8 h2 a4 l3 f$ s0 ]$ T& j
  107. assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;
    # F6 e9 I( l5 a) s5 o  `0 S

  108. ; V3 a; H& d, x, x
  109. //---------------------spi_slaver send data---------------------------
    $ A3 s7 v- O7 A) h  r  N3 z
  110. reg [2:0] txd_state;+ i/ l& L& i9 j9 q0 ~
  111. always@(posedge clk or negedge rst_n)6 H) s: Z6 {4 _  K0 ], s
  112. begin
    5 U) G0 F; x3 l6 I3 x- ~
  113.     if(!rst_n)) r9 L( Y9 W6 R, s" u/ W" L
  114.         begin
    + J; i- J2 o! J) B7 @
  115.             txd_state <= 1'b0;( b; k: L" m! |8 ?: e8 b) a3 n
  116.         end! f; b, S+ ?0 h9 R% H
  117.     else if(sck_n && !CS_N)/ s4 g* h+ n; X" C
  118.         begin
    ( C! z, m/ v1 m4 `5 S% U
  119.             case(txd_state)2 d" `9 K& e8 u; v5 O2 q) K
  120.                 3'd0:begin- C# }2 Z' P& r: V
  121.                         MISO <= txd_data[7];
      P6 u) H  G- Y6 k% I
  122.                         txd_state <= 3'd1;3 m# U! h  B4 S# t* I
  123.                       end1 k+ i' x5 R, I3 m
  124.                 3'd1:begin; N7 e* I# C: f+ x/ Y
  125.                         MISO <= txd_data[6];
    & V7 u, l$ Z8 C2 z# E* J
  126.                         txd_state <= 3'd2;* w9 {; }$ y4 j+ [
  127.                       end
    & |! C' v: Q, h. c4 J9 T, U9 b
  128.                 3'd2:begin
    5 R+ W0 H3 U4 U4 m' ?( m
  129.                         MISO <= txd_data[5];: T3 m0 N* u$ D
  130.                         txd_state <= 3'd3;
    - q& R, w% ~! U1 @) d
  131.                       end/ w% o: _; J* f% ?9 C! a
  132.                 3'd3:begin
    $ N! p0 q1 q3 U+ u  Y
  133.                         MISO <= txd_data[4];
    ( V! @. y1 D1 v7 c7 G
  134.                         txd_state <= 3'd4;: ~! N0 P% W2 B3 j* V) E
  135.                       end2 ~* J4 R) C+ J, K
  136.                 3'd4:begin
    % C3 U* F# Y# @# B9 F: u
  137.                         MISO <= txd_data[3];& I1 S. g/ y8 V5 A5 \+ |( e
  138.                         txd_state <= 3'd5;
    3 K6 x' B6 t- L7 ~) q
  139.                       end
    8 L! m  e( }; K$ w8 K3 t/ D, \2 i
  140.                 3'd5:begin
    5 K  D0 p/ S% z6 [6 a
  141.                         MISO <= txd_data[2];' s2 b3 }, k; D8 L1 a9 a3 ?' N
  142.                         txd_state <= 3'd6;
    ! Y2 I* }' t5 `$ h
  143.                       end! H5 M1 U- Y0 u. Q. i0 L
  144.                 3'd6:begin% _. o6 [6 s8 B! ]1 S* ^0 i+ v# ^
  145.                         MISO <= txd_data[1];
    ( M. _. r& L: p  J# y/ I( a
  146.                         txd_state <= 3'd7;
    1 B, y, \: J5 [5 B
  147.                       end& B4 P2 D3 ~# O* ^  j
  148.                 3'd7:begin
    ) \& B2 p* m4 D& {# z3 ]! w5 [
  149.                         MISO <= txd_data[0];5 _# o/ k! X4 e; y4 ]  D% q* p
  150.                         txd_state <= 3'd0;
    * z$ C  Y* r  A# L6 G! @2 _* a
  151.                       end
    4 I; I& Y3 b- O: ]3 K/ m3 h; X
  152.                 default: ;; u$ }5 X! e6 [2 a% `* m
  153.             endcase
    4 }' p2 n3 d5 G  r! X' Z
  154.         end$ o+ ?% K0 h2 r
  155. end
    % Y5 \2 H4 y, D/ F# C
  156. 2 {$ C/ {% O8 H, [
  157. endmodule
复制代码
- a. ]8 w3 l  y7 m1 K0 b# M

8 k( h4 [7 A! t) X; g
, f9 M5 A7 C! u" a! z

. `; q/ Q; |( ?  b4 H
1 收藏 评论0 发布时间:2022-1-16 18:00

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版