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

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

[复制链接]
STMCU小助手 发布时间:2022-1-16 18:00
一.SPI协议简要介绍
SPI,是英语Serial Peripheral Interface的缩写,顾名思义就是串行外围设备接口。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。
* g; y6 f8 H) x& i9 W1 Y  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 B5 r+ v7 e7 c% a# 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发送数据与接收数据。

& g2 L8 E) F& y+ t
  1. /***********************************************************************' ?! {5 d) U) f7 b; d  M
  2.      ****************** name:SPI_Slaver_Driver **************
    . R4 w+ Q& u5 V
  3.             ********** author:made by zzuxzt **********$ ~: p8 X% w% D; L5 h
  4.      ****************** time:2014.4.29 **********************5 Y  U$ j4 c% |/ \. k3 n3 E
  5. ***********************************************************************/% Y% n! c3 E7 Y
  6. //use SPI 3 mode,CHOL = 1,CHAL = 1& e+ Z5 r0 T$ q7 ]' P6 P
  7. module spi(input clk,
    3 s( e7 S( G3 S6 X- {! M6 J
  8.               input rst_n,. z5 n5 e3 T# \  ~# _; [
  9.               input CS_N,
    3 d6 g8 l) g6 d" x1 n
  10.               input SCK,7 D- |8 p8 K3 X9 U4 {
  11.               input MOSI,
    ) [6 l* l: p$ ?
  12.               input [7:0] txd_data,
    9 |8 b. K2 m6 V' S  i
  13.               output reg MISO,# I, `0 c7 [3 u+ Y# X1 A0 C
  14.               output reg [7:0] rxd_data,
    & F* [5 \1 ]/ O5 p! h; t3 d% m
  15.               output rxd_flag);   //recieve done,please transmit data
    0 ]9 _$ t0 Z2 ^7 c( s

  16. / r; W% _( ]% ]- c, F
  17. //-------------------------capture the sck-----------------------------
    8 C+ d" y' V, S* y9 N! W
  18. reg sck_r0,sck_r1;; f( C, z' U+ G% Z" w: g
  19. wire sck_n,sck_p;8 f$ |- [8 g# D' t2 D2 f& J
  20. always@(posedge clk or negedge rst_n)0 O9 U5 T9 N0 b8 R, U8 Q% V
  21. begin; T- A) M2 g& R) `
  22.     if(!rst_n)
    9 @( w  T& P% }9 v& a" T7 w
  23.         begin$ N  G6 J/ z: x4 |3 U3 |+ X
  24.             sck_r0 <= 1'b1;   //sck of the idle state is high
    . m7 e& Y+ u. `/ F1 J9 ?
  25.             sck_r1 <= 1'b1;
    - I* w9 a$ D, J2 Q
  26.         end
    / b( O- j8 T% M! l
  27.     else6 q$ w6 w4 g2 ]( F2 C+ L* F. [( ^
  28.         begin
    2 a- o0 k: Y& _
  29.             sck_r0 <= SCK;* S3 T1 J3 ?) p0 K
  30.             sck_r1 <= sck_r0;
    8 n' b! a9 `3 Q4 q
  31.         end
    7 A# M) `' Q' R- L4 N% L, j# c
  32. end
    6 b, p9 ~7 {' p. r' \) k
  33. % `/ S9 W- @! M! _, H% O
  34. assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0;   //capture the sck negedge
    9 B. N4 w+ |+ g
  35. assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0;   //capture the sck posedge
    % D7 O7 i# e: \  D
  36. : P: R% j0 Q6 V0 P' M
  37. //-----------------------spi_slaver read data-------------------------------
    * z# |: |& Z! u2 `, v& O
  38. reg rxd_flag_r;1 h9 U+ S/ K9 M7 Q5 z; H
  39. reg [2:0] rxd_state;
    # z6 P$ J/ G& C- ~, r" z5 u( d
  40. always@(posedge clk or negedge rst_n)
      K8 s, x$ S7 p0 H
  41. begin) g& A( ]3 p/ e4 X+ E
  42.     if(!rst_n)
    0 q& B$ F- B1 c- X) s
  43.         begin
    # b1 |2 ]2 b( I  r; s! ~
  44.             rxd_data <= 1'b0;# m6 C- d; m; ^8 K0 c8 a; F
  45.             rxd_flag_r <= 1'b0;
    % K/ }! H; Z* }' c: n; z2 R
  46.             rxd_state <= 1'b0;
    3 [' V/ W: Z% Z+ _# t. A% r0 r
  47.         end$ u0 J7 Y2 b9 N: w
  48.     else if(sck_p && !CS_N)& A" @% T# w# \0 f/ _8 R: K
  49.         begin
    / A  ~+ B, ]4 o$ \$ i: ?1 `
  50.             case(rxd_state)
    4 X# W: V6 M3 A
  51.                 3'd0:begin
    7 `* Q* G! w. K3 D  u
  52.                         rxd_data[7] <= MOSI;6 q* x- g2 b6 l. M1 h1 ^
  53.                         rxd_flag_r <= 1'b0;   //reset rxd_flag
    9 }% g8 q- o9 l% w' {
  54.                         rxd_state <= 3'd1;
    * e3 `$ @6 t# S6 u
  55.                       end
    3 D5 S4 Z3 P: w" v
  56.                 3'd1:begin
    6 V) O9 f0 }9 d
  57.                         rxd_data[6] <= MOSI;+ h& O' u1 {6 `6 q( ]9 D
  58.                         rxd_state <= 3'd2;4 s& Q& [1 N* W, s# b2 r, `4 f
  59.                       end+ Y% `3 u$ A' c- v5 r  ^* x
  60.                 3'd2:begin
    , V' i1 P" A. V1 z) v
  61.                         rxd_data[5] <= MOSI;
    " K( |, B! z% g0 r: t" g# [* Q
  62.                         rxd_state <= 3'd3;
    " _: Y: p9 _$ a5 H5 ~9 e
  63.                       end, A' g6 e' c/ T7 D
  64.                 3'd3:begin) `4 H$ C6 o& s% D* E' r
  65.                         rxd_data[4] <= MOSI;7 L3 J+ z& |. E+ W6 L! V8 E
  66.                         rxd_state <= 3'd4;1 O4 v1 a; m6 y$ i( @3 R
  67.                       end4 `" i( t" c( z* a; |
  68.                 3'd4:begin5 S* |8 L7 m0 Y
  69.                         rxd_data[3] <= MOSI;
    " R( s0 Z0 _: e* X
  70.                         rxd_state <= 3'd5;
    " S4 ~- [1 f# n7 i, S
  71.                       end2 x5 ~  {! H' h$ o
  72.                 3'd5:begin
    2 Z: L) W- A0 A: g5 |
  73.                         rxd_data[2] <= MOSI;+ h' E' e4 o7 |+ H
  74.                         rxd_state <= 3'd6;
    4 H" Y! D$ }0 q3 t" H4 X/ F6 B
  75.                       end
    # r) d2 C' k; F; d5 ^  `
  76.                 3'd6:begin
      \) n" U8 m8 h" o
  77.                         rxd_data[1] <= MOSI;) A, _" b  L9 s# Q3 \
  78.                         rxd_state <= 3'd7;# _" G/ N* P+ @: U4 O6 [  l
  79.                       end, D2 F/ }5 i$ E8 b$ j4 F% J: p
  80.                 3'd7:begin- f. b3 p5 k- L# H( [
  81.                         rxd_data[0] <= MOSI;
    3 N' L5 n7 ~$ R; f. u
  82.                         rxd_flag_r <= 1'b1;  //set rxd_flag% P8 t& b4 W) c
  83.                         rxd_state <= 3'd0;
    # Z% D! J& [' G- B- a9 s% f
  84.                       end. ^: a8 P$ `: d. l
  85.                 default: ;+ }! {- i( E- U8 _9 @1 q* U
  86.             endcase$ |2 V# D3 o2 n9 l: T5 O# k& N
  87.         end+ c5 w4 b$ b8 [2 u$ D' M4 Y# _3 s
  88. end
    3 o3 w# p( ?7 a1 \* z" F1 N8 L$ D! a
  89. # A6 s/ v( }2 }3 C5 t  q
  90. 0 a7 O/ f) V) U/ L& l8 Q$ o6 H
  91. //--------------------capture spi_flag posedge--------------------------------
    * Y3 m2 S+ X5 w+ L1 S* t
  92. reg rxd_flag_r0,rxd_flag_r1;
    " a: k# n2 o) b5 E& g1 C3 s5 y' B
  93. always@(posedge clk or negedge rst_n)
    $ Q+ S0 m/ j+ ?) ]
  94. begin6 |" q" o; s) Q. E$ u3 p! f
  95.     if(!rst_n)
    6 R+ `3 n/ f# K0 l5 Y
  96.         begin3 p# s9 X* f- u# x; \
  97.             rxd_flag_r0 <= 1'b0;
    8 K4 K7 o. U: R( p8 e* {9 X
  98.             rxd_flag_r1 <= 1'b0;
    ; |6 M( e7 W9 E' T; T5 b
  99.         end
    ! v/ k1 n5 V$ L- k6 T5 Z" D
  100.     else
    4 K% i7 g# N& i& ~/ _% b
  101.         begin
    ; c- p2 q6 K# f, D6 X0 z
  102.             rxd_flag_r0 <= rxd_flag_r;& R6 w' n$ g, Z8 d
  103.             rxd_flag_r1 <= rxd_flag_r0;
    2 M* J; {6 J" b4 R7 @/ P: A4 _
  104.         end/ N6 }, }+ `+ \4 g5 x0 p
  105. end
    . |3 U3 `/ o2 Q  U' u+ x

  106. 8 H+ d: l) ?7 e5 M% L
  107. assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;. |8 t: `9 W' Y6 A) v& {* I
  108. 0 b# I0 q6 h& ~& J
  109. //---------------------spi_slaver send data---------------------------
    ) i: s+ C# q) F% X, W0 y
  110. reg [2:0] txd_state;$ G# r5 n4 i2 H, }# S: z4 L2 W
  111. always@(posedge clk or negedge rst_n)
    8 c# ], H) k" A2 p
  112. begin
    7 J% Y+ ]0 V  f9 B
  113.     if(!rst_n)3 T' K" T% |! j  k( o; b, q% U
  114.         begin5 t" E% J9 w+ h/ s
  115.             txd_state <= 1'b0;4 g5 Y9 D! f# K/ n! w6 y
  116.         end
    , p- n, k  m& t. \, L  k
  117.     else if(sck_n && !CS_N)* i8 e) l# O, ^/ k9 N! v
  118.         begin0 l: b( @9 r- K6 n3 e% }
  119.             case(txd_state)
    ) z% N( U* S/ a6 A+ r) F
  120.                 3'd0:begin- D& P5 ^  j& U' ?1 q% [; e
  121.                         MISO <= txd_data[7];
    ) |* S$ q& O$ n1 F4 N2 c! W/ B( U1 D
  122.                         txd_state <= 3'd1;& e( v+ G! j" S7 ~3 z2 ]' a+ E
  123.                       end: f" c) r% K9 k7 i: B
  124.                 3'd1:begin# m" E- A8 [6 B0 G" B1 a1 v& [/ J
  125.                         MISO <= txd_data[6];
    / \0 ?, t' h/ w) r0 z% B7 s
  126.                         txd_state <= 3'd2;7 o& b1 S, e) a! ~/ w0 l
  127.                       end
    7 [' c) v  ?, r
  128.                 3'd2:begin
    - {9 U' N; G8 b( i; Y! W$ C
  129.                         MISO <= txd_data[5];- K  {6 u% D* ?* _3 U+ o
  130.                         txd_state <= 3'd3;. l9 F0 W. p; E$ g5 k! T/ r
  131.                       end
    $ @3 Q* N  e' ~
  132.                 3'd3:begin$ c6 k( Y  C9 K# t
  133.                         MISO <= txd_data[4];0 i/ _! v* @9 J
  134.                         txd_state <= 3'd4;
    7 p: b3 Y2 _# F/ \
  135.                       end0 B7 c) Q/ _* L* c: z8 A
  136.                 3'd4:begin
    5 @- n3 g! S& {6 ~" d
  137.                         MISO <= txd_data[3];5 Q  R: e. T2 S
  138.                         txd_state <= 3'd5;
    + y; p- G# v* u2 O
  139.                       end& w1 x0 T* v% Q  h. Z+ m+ q: M
  140.                 3'd5:begin9 z: q' E5 m9 a* v& s- X
  141.                         MISO <= txd_data[2];& w+ z* s! s( \! ~( |
  142.                         txd_state <= 3'd6;8 E0 g9 I! g% D. i, P! d
  143.                       end
    9 s6 c5 G: W; {" e) z
  144.                 3'd6:begin
    8 D* S' h2 |) I  L$ S8 ^4 _! Q
  145.                         MISO <= txd_data[1];
    + |' k5 g( ?& j+ b9 j$ H
  146.                         txd_state <= 3'd7;
    , }" T+ Y$ j$ R6 w  z
  147.                       end, q% a3 T% f4 g* ^: D
  148.                 3'd7:begin& i( `- m9 a2 A( {; S3 j
  149.                         MISO <= txd_data[0];
    5 y$ _6 a9 u3 t/ C+ q" h5 E
  150.                         txd_state <= 3'd0;: m8 B9 B+ u; ]' s/ p4 w0 R  x% V4 @
  151.                       end! X" E! |' z1 f# y( h8 N
  152.                 default: ;
      C4 x; N7 r$ s  B
  153.             endcase
    $ l3 K: y6 s) P, Z* [1 w* E5 q0 _
  154.         end
    ( _  f* Q+ s8 I
  155. end
    & s% R  k; u2 X; L( X
  156. 7 r# @& z! A3 f2 O: k
  157. endmodule
复制代码
# J4 ]# ~9 O7 E& E" F/ v/ j

* n& r; u' s) R* r  m& I/ c- K$ f% M6 z! u8 s

1 x6 b$ _; i9 f, d1 v
1 收藏 评论0 发布时间:2022-1-16 18:00

举报

0个回答

所属标签

相似分享

官网相关资源

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