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

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

[复制链接]
STMCU小助手 发布时间:2022-1-16 18:00
一.SPI协议简要介绍
SPI,是英语Serial Peripheral Interface的缩写,顾名思义就是串行外围设备接口。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。
; a3 b/ j$ E7 H3 c  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 P& T$ N" K% l$ d! B0 F, Z7 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发送数据与接收数据。
$ l! X! f) B% n: _
  1. /***********************************************************************
    : w) n- t( q, a
  2.      ****************** name:SPI_Slaver_Driver **************
    3 ^0 P7 r6 E& h- r
  3.             ********** author:made by zzuxzt **********# Y7 A3 i' a. R
  4.      ****************** time:2014.4.29 **********************
    4 U7 k0 y/ Q2 E5 j. p
  5. ***********************************************************************/
    / ?+ v1 v6 u6 H; w6 k
  6. //use SPI 3 mode,CHOL = 1,CHAL = 13 M6 A( S  [( Z" E
  7. module spi(input clk,, T3 G: B% g9 f  W1 e
  8.               input rst_n,
    ; z; w5 _2 y* g5 }
  9.               input CS_N,- u5 |  _( o' L/ X! K2 f& @3 ?
  10.               input SCK,
    2 j9 h" e3 V- U& E+ H
  11.               input MOSI,
    / g. w) V% K2 X# Y
  12.               input [7:0] txd_data,+ I: ?8 l9 N, w
  13.               output reg MISO,
    : N7 v- [2 O! G: W# S5 l
  14.               output reg [7:0] rxd_data,
    0 s  ~8 ~0 `0 y: T- X" Z8 N
  15.               output rxd_flag);   //recieve done,please transmit data
    * J5 A/ O2 w) Z6 t* H
  16. + s* C- ^; A' h
  17. //-------------------------capture the sck-----------------------------6 z3 x; h$ O) Q5 |4 s; g
  18. reg sck_r0,sck_r1;
    % A7 i1 S. M/ B  ^: T( K3 a" V4 x
  19. wire sck_n,sck_p;
    2 q/ S5 F# M- g+ ~7 Z- U
  20. always@(posedge clk or negedge rst_n)
    7 K% L" S  ~: [" s2 b; x0 i
  21. begin) V; b' [+ K0 _) _' r% v/ p% a; i5 \
  22.     if(!rst_n)
    ! Z# q- ]$ K6 r% o+ ~
  23.         begin
    / _! t: w/ g0 s  c; P5 j& h
  24.             sck_r0 <= 1'b1;   //sck of the idle state is high6 {* \5 V  S# g1 E( W0 z; C
  25.             sck_r1 <= 1'b1;$ q& e1 l! k4 H2 }! {) {3 {7 c
  26.         end
    6 s) h: t+ {# ?: n) \$ J
  27.     else
    $ s' P0 U+ ?# [: u; a
  28.         begin& r" v/ K/ Z& |- T& L3 k
  29.             sck_r0 <= SCK;
    ; ~; V3 ]3 m$ K$ e: b/ U  o: J& W
  30.             sck_r1 <= sck_r0;  r; _" k. p7 o& t6 ?3 G
  31.         end
    - K/ P, x4 G3 g5 X4 y  G
  32. end
    0 k3 @4 E( d4 t: P  n4 B5 d

  33. 0 J1 ]+ A# u2 z5 R/ ]7 G1 N, \5 D
  34. assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0;   //capture the sck negedge: I+ l5 ]# I8 P6 A0 R! i& p2 o. o
  35. assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0;   //capture the sck posedge+ X# F4 @7 `# `9 ], g
  36. 7 U0 v$ G0 T0 B6 O0 A+ [
  37. //-----------------------spi_slaver read data-------------------------------
    / Z$ R2 u$ y4 @8 h3 m* f& ?9 j
  38. reg rxd_flag_r;6 B& I: [$ b; c
  39. reg [2:0] rxd_state;, t1 ?7 t' q6 F0 i
  40. always@(posedge clk or negedge rst_n), J2 I  x, I0 e, D! M1 D. j
  41. begin
    9 X+ R, w: l5 _( N+ i
  42.     if(!rst_n)
    : I( p2 {/ r9 s1 ?
  43.         begin
    9 r4 W7 I) u9 V# I
  44.             rxd_data <= 1'b0;# B1 g* B$ Z# F' T4 d) D& E  R
  45.             rxd_flag_r <= 1'b0;
    ' y2 l) q# D7 G5 b. P6 @! u: e$ i
  46.             rxd_state <= 1'b0;
    ; J3 L5 M9 q9 S  y( G! N1 @
  47.         end; O# N) N$ S1 h/ @
  48.     else if(sck_p && !CS_N)  ?+ b$ ~' d* s
  49.         begin
    8 R5 z; f! o9 J( d
  50.             case(rxd_state)4 U6 B) @' Y4 f+ ~4 A: ~5 W" F
  51.                 3'd0:begin
    2 j. C% }) z: h$ n3 j7 `) P. ^
  52.                         rxd_data[7] <= MOSI;
    ! L; e$ D6 b, @, @
  53.                         rxd_flag_r <= 1'b0;   //reset rxd_flag
    + ]8 @6 ^- q+ ^' K* g
  54.                         rxd_state <= 3'd1;
    2 z9 V/ B1 a0 D5 M) v+ K
  55.                       end
      Q, U* `5 j( L) ~1 J7 R5 G' I
  56.                 3'd1:begin7 Y1 X. |; t5 q0 z# R1 l: A
  57.                         rxd_data[6] <= MOSI;" f3 Q4 X& D1 o) Z0 S- |
  58.                         rxd_state <= 3'd2;
    " o+ n- S" G* o) t% k5 Y, z
  59.                       end/ q" A3 v. S, z/ I2 n
  60.                 3'd2:begin
    4 P$ [* {; O6 E
  61.                         rxd_data[5] <= MOSI;9 p" }, J7 s# Y
  62.                         rxd_state <= 3'd3;: `6 [' x0 _. u2 {
  63.                       end* Z2 m) \7 z5 t3 W4 X" Y0 ~! g
  64.                 3'd3:begin
    ' r$ N" J% F2 B8 g. O. N* q
  65.                         rxd_data[4] <= MOSI;, ~: l% R! c) Q0 C6 h& n( c
  66.                         rxd_state <= 3'd4;
    - s# b% M* Q7 R  F  L$ o' @
  67.                       end
    & m' d' n* s& b0 B0 s; `" p* w
  68.                 3'd4:begin6 K- M; n5 R& A: I- H8 g
  69.                         rxd_data[3] <= MOSI;1 k6 S, Q( \3 F6 b( W* ?9 ~2 V
  70.                         rxd_state <= 3'd5;7 L0 x% Y# X2 W
  71.                       end
    1 {' ^9 [4 d' S9 d% B0 X
  72.                 3'd5:begin+ y, c4 w# Z2 a
  73.                         rxd_data[2] <= MOSI;" X& j& Y6 B. _4 X
  74.                         rxd_state <= 3'd6;* @! q% [: |& ^) x
  75.                       end
    # I6 r$ T" N. p1 Y
  76.                 3'd6:begin( y4 G: @3 z- D& P( q8 Q5 u. C: I9 X
  77.                         rxd_data[1] <= MOSI;
    9 X% _) @1 y. z7 k2 A, C4 i
  78.                         rxd_state <= 3'd7;. o. _( j/ {8 ~! q8 s
  79.                       end
    4 ]9 ]& q% h! F7 ]7 G# @, D
  80.                 3'd7:begin
    " s4 a+ h" y: }$ u4 |
  81.                         rxd_data[0] <= MOSI;
    - q, {( G' h0 ?! J6 L. j8 H
  82.                         rxd_flag_r <= 1'b1;  //set rxd_flag
    9 L3 m& N# l( }
  83.                         rxd_state <= 3'd0;
    / K- i9 U) P0 Z& A( @2 \& i% C4 f
  84.                       end  q0 Q# Y% C' U
  85.                 default: ;
    / n7 o5 u1 E* O  \& _7 u
  86.             endcase9 X2 t* z( `5 y2 Y7 s4 M
  87.         end
    + e/ N1 R" P1 ~5 e5 F
  88. end
    6 c! ]8 y1 q& y8 Q4 U" z

  89. 3 B* q  E- M2 [8 y

  90. * k3 O  g, ?6 y4 C. }2 m' m
  91. //--------------------capture spi_flag posedge--------------------------------0 l  f* g2 i$ n0 o+ ]
  92. reg rxd_flag_r0,rxd_flag_r1;
    , E) d# A  o5 N; \3 @- [- |4 C
  93. always@(posedge clk or negedge rst_n)
    / h/ ]  b3 S# b& Q0 _3 I8 t: }( ^
  94. begin
    ) {# C' {5 F% i9 R* n! D
  95.     if(!rst_n)
    7 c: p5 O* s5 \  C
  96.         begin
    9 [/ C0 S0 {% m+ o$ q
  97.             rxd_flag_r0 <= 1'b0;0 M) q/ g( M6 n& ]( b0 j2 a2 H
  98.             rxd_flag_r1 <= 1'b0;
    0 x$ }3 G0 Q0 ~  Q
  99.         end" N5 k! T. ]4 G, g
  100.     else
    - p( E) T: T1 w$ J) a
  101.         begin
    $ d$ b- A8 f! J
  102.             rxd_flag_r0 <= rxd_flag_r;
    , {3 N2 E) x8 X9 Q, g  a1 Z* v) Q  ~
  103.             rxd_flag_r1 <= rxd_flag_r0;- J8 j+ _: a; G- h) x" v
  104.         end
    ' b: s4 M( b' A! w8 @& M7 n5 r
  105. end
    0 ?, }# M# {2 I/ G9 J# h/ I

  106. ' M+ \8 g: F0 v9 d1 ]+ `' c1 e
  107. assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;( V7 e; Y3 b+ O. c

  108. * M1 @1 A3 @: ^- L. v+ d3 \1 }0 W- Y
  109. //---------------------spi_slaver send data---------------------------
    3 g2 c/ f% g/ [# Y; s
  110. reg [2:0] txd_state;
    4 W  K% V4 ?0 H1 S/ @2 @/ c: z
  111. always@(posedge clk or negedge rst_n)3 _" A3 A) v7 d6 x2 ?3 k
  112. begin
    2 o3 G2 p  b: |+ u* G: m* X
  113.     if(!rst_n)' t* r: C4 b" I
  114.         begin- J: P7 e  q0 m) m% t
  115.             txd_state <= 1'b0;
    7 h7 c, W# N* j% d1 K* c; B$ L
  116.         end2 e6 ]1 f; r6 b) [
  117.     else if(sck_n && !CS_N)
    - E6 u" L% m7 I( z" J
  118.         begin
    5 N: q3 W  f( W6 P7 Y: K
  119.             case(txd_state)) `- }. A+ s+ I
  120.                 3'd0:begin5 a0 F) R1 @# X! s- b0 [1 z: o, Y
  121.                         MISO <= txd_data[7];& y, C1 [; ]: ~) z. X. V1 m
  122.                         txd_state <= 3'd1;) S6 p0 W. }7 A
  123.                       end
    2 q8 y' X. {" K. t8 ]  ]; z
  124.                 3'd1:begin
    3 v% k% i  |- E$ \4 L: Q
  125.                         MISO <= txd_data[6];
    / X0 n" R( E" O7 y+ z, o6 M$ o9 c1 _
  126.                         txd_state <= 3'd2;
    . s( i" ]- A1 F/ K
  127.                       end  N$ t  t$ e! o7 X/ v% A
  128.                 3'd2:begin
    ( r6 e1 z4 d, a6 K: ]5 A# ~
  129.                         MISO <= txd_data[5];
    3 }7 h$ o3 Z& |( M9 e
  130.                         txd_state <= 3'd3;5 s8 e( p2 i# f6 l8 Z
  131.                       end
    8 B* p* p8 E- L* S) _; t
  132.                 3'd3:begin& c0 k+ I( u; w5 T, u
  133.                         MISO <= txd_data[4];
    2 J5 _- H6 A, t% Y5 T/ V* Y
  134.                         txd_state <= 3'd4;
    $ P. L* w& J" d6 t: m! H
  135.                       end) b4 g( [0 p* W' i; `
  136.                 3'd4:begin
    7 j2 F2 ?' |; v: P3 ]: I* p$ a
  137.                         MISO <= txd_data[3];& [+ m7 f& o+ H0 |3 w
  138.                         txd_state <= 3'd5;1 @' x2 `2 s3 m8 o4 T4 s  v
  139.                       end
    3 j7 g- n% @0 @# x- b
  140.                 3'd5:begin6 }7 p7 {! N- e9 ~+ |4 E
  141.                         MISO <= txd_data[2];
    ' J0 Z4 ^- @  W0 T, V: G0 K+ ]$ n
  142.                         txd_state <= 3'd6;6 Z; z9 u/ {; c. a
  143.                       end/ X, |8 J2 `" X9 m
  144.                 3'd6:begin: s# @! }' X: z, M# Q$ Q
  145.                         MISO <= txd_data[1];
    1 a, r: O) ^( A' M2 R- S
  146.                         txd_state <= 3'd7;
    " @' x% C1 w" K! s" \) b% |+ \! Q
  147.                       end
    6 p# k$ `3 d) Q. h8 A2 @
  148.                 3'd7:begin+ m$ Z: p6 \$ k5 o6 o. D2 [
  149.                         MISO <= txd_data[0];
    - `% U( D; i; n; \+ L8 n% r+ `
  150.                         txd_state <= 3'd0;
    ; i" K- D5 w6 Z0 d2 \, c  T
  151.                       end
    0 K1 I" d: o! {* V3 o, a
  152.                 default: ;
    0 `7 \! I6 ?$ w! e- s$ ^2 _
  153.             endcase" K7 h& f+ l3 [
  154.         end
    % X' Q$ |: O) p4 |
  155. end  V+ ^. d; M: b% C

  156. % k$ i; E. I- }# c/ {; d) Z4 w
  157. endmodule
复制代码

' ?$ W, T" w- T; Q
6 R6 Q6 t/ m9 U  `- J
6 S0 x4 U, @# x. s
" i- x+ r* z" h6 E6 q: o
1 收藏 评论0 发布时间:2022-1-16 18:00

举报

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