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

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

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

5 P* w2 `0 ?& J4 j
二.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发送数据与接收数据。
& e, O/ |1 D' _0 [, C& K, i+ S
  1. /***********************************************************************6 N2 A8 E+ ^7 h  ~) b' w1 D
  2.      ****************** name:SPI_Slaver_Driver **************
    & w& K3 @6 q% g1 q7 R
  3.             ********** author:made by zzuxzt **********
    2 ~  s+ {4 P) x$ t  @
  4.      ****************** time:2014.4.29 **********************
    2 p( C/ z! C) Y; Y! s: J3 h2 o
  5. ***********************************************************************/' X/ W5 K! d5 p
  6. //use SPI 3 mode,CHOL = 1,CHAL = 1
    ' n2 H$ Z% P( v5 Y1 l
  7. module spi(input clk,
    5 i3 t  r) N. h) Y; \
  8.               input rst_n,. v4 R5 \+ V/ m) G. h( ]/ X
  9.               input CS_N,
    ) j6 q& V+ o) J) ^/ z0 M6 D' Q: n5 H
  10.               input SCK,! k4 i- H, g2 z5 l. a6 O" H
  11.               input MOSI,: r' f3 G' ^: {- v* R6 D
  12.               input [7:0] txd_data,# H8 y! q8 D2 p- H
  13.               output reg MISO,
    # A/ U1 z' L3 T1 b6 q
  14.               output reg [7:0] rxd_data,8 C+ I. \/ e* k! \% }( L" B* X% ~
  15.               output rxd_flag);   //recieve done,please transmit data
    2 y5 \) G" M9 \8 {' l
  16. & G: u4 H" r& j, o# x6 t
  17. //-------------------------capture the sck------------------------------ `' h0 ?9 _# e8 P+ @( Y
  18. reg sck_r0,sck_r1;
    : {7 w; B' ]- h, L) B9 V& B
  19. wire sck_n,sck_p;
    8 \2 M) _, l' J% j, \, }2 q
  20. always@(posedge clk or negedge rst_n); H( I1 y5 o" ?1 @- E8 V
  21. begin
    , _: e1 C5 `+ u/ f, t0 h" \" f
  22.     if(!rst_n)5 ]; u4 g2 f( h0 m
  23.         begin
    ; N- E( H0 ]  ^, i- u
  24.             sck_r0 <= 1'b1;   //sck of the idle state is high
    % ~' b2 K5 j/ x6 V" w
  25.             sck_r1 <= 1'b1;, x$ R9 _* x/ H! p' ~! `
  26.         end3 K4 R* Q' G( @9 K9 j  s, f% s
  27.     else, Z6 |$ K0 V* F) ?9 j
  28.         begin
    / ~5 D2 I( H% [
  29.             sck_r0 <= SCK;! ?6 u" P$ ^* q3 T2 Z% N, B
  30.             sck_r1 <= sck_r0;
    % U1 E* r4 o- b/ ~
  31.         end6 Z' T; R/ d, D+ m3 v! a
  32. end
    , w' y! k" _; Q5 j
  33. / V/ d2 a! N. p6 W6 U
  34. assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0;   //capture the sck negedge8 S0 }% G% ], `# v2 S- R2 I- F
  35. assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0;   //capture the sck posedge9 C# y1 |4 P1 }
  36. # q6 e( j5 l5 A+ n; z
  37. //-----------------------spi_slaver read data-------------------------------
    ! b% U" F* c3 N# F: ~' w5 \  i
  38. reg rxd_flag_r;
    1 J3 `1 P' \2 ?# G4 G0 ?, G7 X
  39. reg [2:0] rxd_state;
    ; t7 m7 W% w) [) J8 P4 D- ~% w
  40. always@(posedge clk or negedge rst_n)5 ~* a, X1 f/ {- I, l# ~% P
  41. begin
    ) o  B& G/ I& M$ f% a, }' r6 S
  42.     if(!rst_n): D* Z3 d0 Q* _1 s
  43.         begin
    ) c: J0 _2 J% T" F( ]
  44.             rxd_data <= 1'b0;2 U8 i  v1 t6 \7 W2 R
  45.             rxd_flag_r <= 1'b0;: T( ~' l$ \0 @4 W1 T  V/ b
  46.             rxd_state <= 1'b0;
    : S# F) \. j( J
  47.         end
    . `+ ~0 M0 @$ G4 r! W2 _
  48.     else if(sck_p && !CS_N)! t) y# Z: N; U3 Y. A
  49.         begin
    0 Q2 j- z/ U6 ^% S% S/ F* k4 F4 Y
  50.             case(rxd_state)- y( n! J! s" H: C+ u4 t# R
  51.                 3'd0:begin9 a) C9 c) Q5 f, x& A
  52.                         rxd_data[7] <= MOSI;5 B3 T" t3 M( \5 ~
  53.                         rxd_flag_r <= 1'b0;   //reset rxd_flag. a; a' f; x7 R) L5 S
  54.                         rxd_state <= 3'd1;
    * Z; `- L3 J$ J, P
  55.                       end
    3 W) D( p! v# Y
  56.                 3'd1:begin% n: u# T( ^3 `
  57.                         rxd_data[6] <= MOSI;1 B- O" R  _+ t. M: q8 \. `# Q
  58.                         rxd_state <= 3'd2;
    , A) C1 q5 C4 }7 z  n/ y
  59.                       end, a; `! x* X2 Q2 I& j
  60.                 3'd2:begin
      L; S6 `* {' J2 T
  61.                         rxd_data[5] <= MOSI;
    4 H0 g" Y' _  h8 v* P( {3 A
  62.                         rxd_state <= 3'd3;% p* s, i# Z' j2 K4 g
  63.                       end. b: }) b- }$ ^1 D
  64.                 3'd3:begin9 @. b5 ~0 ]9 M5 T
  65.                         rxd_data[4] <= MOSI;9 V, r" I8 F* L, H8 U
  66.                         rxd_state <= 3'd4;
    . v( S7 z2 L9 Q9 @! h% |$ f
  67.                       end3 c3 L$ D9 r. A& J) S5 i8 ~
  68.                 3'd4:begin: L7 Y- W) S0 l6 o9 e4 @$ x
  69.                         rxd_data[3] <= MOSI;* H1 w4 r! O$ o, F
  70.                         rxd_state <= 3'd5;& ?# S" J( X' Q! h0 l4 ]% D5 v
  71.                       end8 a7 v7 B3 ~+ Q# }  }" U
  72.                 3'd5:begin
    + D0 N8 y/ y5 E) p% b
  73.                         rxd_data[2] <= MOSI;
    1 \8 m6 ]( U3 t  z- a
  74.                         rxd_state <= 3'd6;6 O! e: |! v, ]( M3 a4 M0 v4 p0 g: T
  75.                       end
    ' j0 w- N) F. Q1 o% r' g/ i( J
  76.                 3'd6:begin) v( _2 t: B% Y
  77.                         rxd_data[1] <= MOSI;
    ( j, o0 _. e9 u6 W7 G8 I0 Q
  78.                         rxd_state <= 3'd7;
    % g- o# a: t9 z; \5 y% v
  79.                       end
    9 g- i3 C  S, O! Z9 Y
  80.                 3'd7:begin
    ' A5 F8 y% A, h, F# `- B  O
  81.                         rxd_data[0] <= MOSI;
    5 g; T- ~7 \  E. r- @
  82.                         rxd_flag_r <= 1'b1;  //set rxd_flag  {, }5 U, V2 [" `% h
  83.                         rxd_state <= 3'd0;+ q" {- X# }: m! C3 ]
  84.                       end2 D& }: h5 R0 u- c1 J
  85.                 default: ;
    5 b! l' o: U- ]
  86.             endcase) U: x  e/ f& }1 _+ N
  87.         end  ^. D( r* H1 Q- w; x& K2 i' z
  88. end, E* g: ]' `# A' `2 W, F7 f  ]3 r

  89. ( {0 p+ o: T+ f* M
  90. % a* A1 q" h& h! b, `; i& k
  91. //--------------------capture spi_flag posedge--------------------------------+ G& U) ^8 h; g* O& m; D) L  d. I
  92. reg rxd_flag_r0,rxd_flag_r1;; I+ Q6 [7 Z; b: g
  93. always@(posedge clk or negedge rst_n)
    5 Z3 E5 D, m9 r1 W4 K" d$ ~. ]
  94. begin  d" R' s& K& R7 b( Z
  95.     if(!rst_n)
    # `2 \; h/ C0 X, F5 C% k
  96.         begin
    3 p# h, O  W  u5 l* I8 n& X$ _( F, B- Z
  97.             rxd_flag_r0 <= 1'b0;
    / T+ g- A! j) K. s* D: U
  98.             rxd_flag_r1 <= 1'b0;
    % L5 q) X1 M3 |1 @) ?# H6 Z
  99.         end
      o1 ?- T- q' b  Q+ T
  100.     else
    / e) V' H; s* g' u# i( M
  101.         begin
    ; J. Q. G) k1 D/ b* P: d
  102.             rxd_flag_r0 <= rxd_flag_r;4 x+ E# ^3 B/ q5 y
  103.             rxd_flag_r1 <= rxd_flag_r0;
    2 D; N/ Q8 ?8 P+ W
  104.         end) d# O5 g( R) |( i  B2 b- J% u
  105. end
    # F0 ]# x8 I' p

  106. 1 J/ T8 w0 M$ ^# g1 W' J( Z
  107. assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;
    1 I7 k8 n! z" g
  108. ! ~( S+ i! x2 g  ?, N0 A+ `
  109. //---------------------spi_slaver send data---------------------------' Q8 V; P6 s8 S9 A$ n
  110. reg [2:0] txd_state;
    . N1 {" }7 R  a
  111. always@(posedge clk or negedge rst_n)% n- W! b' J) j$ c
  112. begin
    6 `. r% |6 D) C. P' P
  113.     if(!rst_n)" \- M* r3 h6 M* B; X7 D6 Q
  114.         begin
    0 K9 @% h! B6 G  J- V; Q( d; O
  115.             txd_state <= 1'b0;
    ! w/ A& w/ g/ {  m  W1 @
  116.         end3 e0 r$ |8 e1 z% L/ g: e
  117.     else if(sck_n && !CS_N)
    5 w- D. V- v3 M) D& l5 x8 P
  118.         begin* Q& m& i8 ?. j3 B+ ^
  119.             case(txd_state)* v& l' J; v6 i9 \# D* ?/ g
  120.                 3'd0:begin3 p9 }# }% |& P8 Z1 Y
  121.                         MISO <= txd_data[7];
    7 ~: P2 q1 Z) N$ f
  122.                         txd_state <= 3'd1;, m+ B& y, v3 P. ?% k; b0 U$ L
  123.                       end- I. ?. f: o/ F8 `0 U- p( {4 t
  124.                 3'd1:begin9 u+ U. z( L, ?7 Q/ _
  125.                         MISO <= txd_data[6];
    ' M: B. d8 }6 x
  126.                         txd_state <= 3'd2;
    ! x1 A. K4 u3 R( c3 j
  127.                       end  ]5 m: J7 U! B0 K1 t! W6 Q
  128.                 3'd2:begin: S3 O/ F' v" U% O0 c' s- j2 E
  129.                         MISO <= txd_data[5];
    ) T) Z& B/ b7 K9 C9 {
  130.                         txd_state <= 3'd3;
    ' U1 C& c, w' [$ p5 v2 q+ s0 r9 @4 q( T
  131.                       end+ f5 X; K' s' }% Z5 Q1 e1 d. [* j" l
  132.                 3'd3:begin: g/ y) m! O6 i1 U
  133.                         MISO <= txd_data[4];! h9 ~8 p% U8 c7 Z* D5 W& r
  134.                         txd_state <= 3'd4;
    ! }, r% O/ ~7 C; ^6 t/ w- W1 e$ y
  135.                       end7 R1 p, K9 B. j2 \" ^- C+ q5 p
  136.                 3'd4:begin
    # g  s0 `; A+ P& I: z" ^; ~2 P
  137.                         MISO <= txd_data[3];
    5 {. e& H1 z. m! L+ P; c2 d2 @& }
  138.                         txd_state <= 3'd5;2 y% u0 J- V9 q
  139.                       end) k5 _: e5 O1 G0 k
  140.                 3'd5:begin
    ; ^1 f2 x7 u/ b  G) a
  141.                         MISO <= txd_data[2];
    , F; O0 ^; [( z
  142.                         txd_state <= 3'd6;
    ! Z! h! p) z5 s: r3 _
  143.                       end/ k2 b  x: U. B' s! n$ s- o6 T
  144.                 3'd6:begin
    8 r5 Q. N( K2 @3 C+ s% `8 H$ O0 P
  145.                         MISO <= txd_data[1];
    7 W$ U! C; t4 ~1 K0 {: x- ~( z
  146.                         txd_state <= 3'd7;# O6 u1 g" C& @" s
  147.                       end, I+ S" M9 W8 ^: ~$ b
  148.                 3'd7:begin/ m5 _( q: v/ z3 ?, P# t
  149.                         MISO <= txd_data[0];
    4 t" P# {2 S5 e' H& I/ @; q
  150.                         txd_state <= 3'd0;
    : V1 R2 V) i( i4 I4 M
  151.                       end
    0 k8 m( U7 p+ i4 d: f: y) n# P
  152.                 default: ;
    4 C$ P$ l5 Y' m3 Q6 U' w
  153.             endcase
    9 F' ?; E9 X6 S, H7 \- ]7 [9 T, Z
  154.         end. Q( C1 V& {4 r  M* a
  155. end9 o7 G8 v7 }) e( K5 l- U# q

  156. : Z0 h/ X8 _2 s- M1 E  e
  157. endmodule
复制代码
3 V8 Z+ Q8 B4 E% l

7 u2 h3 x3 \* B" B# k! X7 w0 w/ I& k' N1 z1 D

! ~9 w  a* c, J! k: C
1 收藏 评论0 发布时间:2022-1-16 18:00

举报

0个回答

所属标签

相似分享

官网相关资源

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