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

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

[复制链接]
STMCU小助手 发布时间:2022-1-16 18:00
一.SPI协议简要介绍
SPI,是英语Serial Peripheral Interface的缩写,顾名思义就是串行外围设备接口。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。
4 P( q- Z' k. Q- e+ A: |( r& D  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拉低使能情况下。
" T7 k+ {3 m$ G1 y# v- W. f# v
二.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发送数据与接收数据。

* h" y9 [3 O0 @! J6 D1 w2 k" @
  1. /***********************************************************************
    : d% L4 H/ a* S( b
  2.      ****************** name:SPI_Slaver_Driver **************8 l, N; @6 K8 {1 i4 r) K  p
  3.             ********** author:made by zzuxzt **********
    3 J# P4 H5 f1 U7 A- x
  4.      ****************** time:2014.4.29 **********************$ p$ M/ q; d; {
  5. ***********************************************************************/) a: j2 I4 j4 U; c+ [1 `2 u# g
  6. //use SPI 3 mode,CHOL = 1,CHAL = 1
    ( @& J+ h* H3 `8 |7 ~) A
  7. module spi(input clk,
    ; w1 F) @& c, O( g
  8.               input rst_n,
    $ [, ^7 ~; g( U0 C/ _
  9.               input CS_N,
    . [) h6 q+ N7 y: r5 h
  10.               input SCK,/ ~" L# f1 w7 `; T6 {; W
  11.               input MOSI,
    + A( P9 Y$ t4 n
  12.               input [7:0] txd_data,$ ~  N3 }5 c0 u: p9 x5 @" e- d" ]
  13.               output reg MISO,: J0 A9 t7 G% {* y+ t6 T" S. e0 }/ C
  14.               output reg [7:0] rxd_data," [% n0 O; b9 B
  15.               output rxd_flag);   //recieve done,please transmit data0 b, e& J* ^! B: ~5 z4 b- D# [

  16. 6 n! \4 D8 `; j5 W
  17. //-------------------------capture the sck-----------------------------
    3 ~* x- ?0 G4 S. u  J& }
  18. reg sck_r0,sck_r1;; h1 A% d) E2 _  k& G/ E# A
  19. wire sck_n,sck_p;- f- I, c# \& e; F
  20. always@(posedge clk or negedge rst_n)7 D7 _' |# B* o- R9 Y# n
  21. begin( L5 R1 ~' n. ~+ M
  22.     if(!rst_n)" H! c, L  V% l0 v
  23.         begin6 f  q+ ]0 M0 K$ }: Q$ r1 y
  24.             sck_r0 <= 1'b1;   //sck of the idle state is high. k3 ^; k% k" L  f
  25.             sck_r1 <= 1'b1;9 n; l% n$ ^& i' o0 q6 q* d
  26.         end
    7 s* C5 T, R3 d' ]
  27.     else
    9 x4 W5 I; y8 C( ^7 S* T8 S: K  i6 B
  28.         begin
    & u2 a  l! N; \' U
  29.             sck_r0 <= SCK;/ _: f. T: i* m% A
  30.             sck_r1 <= sck_r0;
    ) _  h. J& X/ C1 r
  31.         end
    6 X, A) R3 Y! x* `/ U% M
  32. end) @- |. D" z0 B
  33. ( W" g0 N0 ^0 a3 C! m) u
  34. assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0;   //capture the sck negedge" d( K( l% Q2 r, b
  35. assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0;   //capture the sck posedge6 L7 o; z' m9 v
  36.   p& K" l+ n% Y- R' l1 y- p+ d
  37. //-----------------------spi_slaver read data-------------------------------
    * z8 T7 `6 }* G7 }5 Y( O; ^6 @
  38. reg rxd_flag_r;
    * `2 P, _1 [' R* s" w4 ]
  39. reg [2:0] rxd_state;2 X. v5 k4 ^7 d7 ~% o. j
  40. always@(posedge clk or negedge rst_n)
    . h8 W6 g) W' i4 ~& X  X
  41. begin
    $ r! B& i, N% F! _
  42.     if(!rst_n)1 O: X2 r6 K) {
  43.         begin/ d  K) Z' M& w
  44.             rxd_data <= 1'b0;
    4 q% U- k' Z$ D3 i
  45.             rxd_flag_r <= 1'b0;2 l, x1 R; Q+ J& F
  46.             rxd_state <= 1'b0;$ Y( G. X) R0 q( P
  47.         end- t+ n, I" m6 Y  B/ z: a
  48.     else if(sck_p && !CS_N)
    6 d7 z2 r5 Y3 L% k% J' h7 Q# N
  49.         begin
    8 U: M# R6 L; h( o; n( l% f0 s
  50.             case(rxd_state)9 Q/ r: {9 I5 ^$ z& t  c
  51.                 3'd0:begin
    ( ]! i& \$ a$ y4 y2 L0 \
  52.                         rxd_data[7] <= MOSI;2 {+ E, W" |# u2 O' R) l( g7 L
  53.                         rxd_flag_r <= 1'b0;   //reset rxd_flag3 ~. R0 u0 z) `- k
  54.                         rxd_state <= 3'd1;  N) [. T2 t/ j% v+ |
  55.                       end
    : m  G7 L: ~5 J2 r
  56.                 3'd1:begin. z" w  E% ], o7 G9 K' a
  57.                         rxd_data[6] <= MOSI;
    % C; a  x5 q( Z2 ]7 r; d
  58.                         rxd_state <= 3'd2;
    / }, H5 h# }$ s
  59.                       end
    2 O" x0 c+ s, J5 w  d
  60.                 3'd2:begin1 j* ?; s! @- Y; w% v2 L
  61.                         rxd_data[5] <= MOSI;
    # a4 q, G# \, S7 F4 u
  62.                         rxd_state <= 3'd3;
    ; c9 B. ~5 V$ o7 u/ }
  63.                       end& v# [+ _! l/ ~0 [  B$ O
  64.                 3'd3:begin& a4 m$ m6 U" q6 M' `3 s
  65.                         rxd_data[4] <= MOSI;
    * \% V2 A6 U6 c9 i
  66.                         rxd_state <= 3'd4;4 @9 Y5 N2 f5 K. E, O
  67.                       end6 d9 g1 _' Z+ O) {* w8 x
  68.                 3'd4:begin# C2 \6 m. W* `6 v" z
  69.                         rxd_data[3] <= MOSI;
    . |& n$ y9 N9 O2 r$ Y
  70.                         rxd_state <= 3'd5;+ h+ x7 X5 i7 r: K2 J- R
  71.                       end* L7 G2 R* a$ L) L' t
  72.                 3'd5:begin3 q9 n, d4 r% R, B
  73.                         rxd_data[2] <= MOSI;
    ) Y8 J- v+ S5 J
  74.                         rxd_state <= 3'd6;+ T, y: ]! s* X8 Y6 C
  75.                       end
    * s' n. y& `/ L  t
  76.                 3'd6:begin1 [8 z* T( v# j" v; U% Z/ T5 g
  77.                         rxd_data[1] <= MOSI;8 ~0 F) U2 |8 o# m7 N5 M
  78.                         rxd_state <= 3'd7;6 O; A* S0 M1 c, l
  79.                       end7 k* f7 H7 c7 R3 ^: M
  80.                 3'd7:begin, [4 b" d- d" P! g: U* W
  81.                         rxd_data[0] <= MOSI;
    * s/ S) Y; [) I5 d. [: i' v
  82.                         rxd_flag_r <= 1'b1;  //set rxd_flag6 Y- F- v& [+ V5 K; O- o
  83.                         rxd_state <= 3'd0;
    / f" z) f9 E, E/ V
  84.                       end' k4 ~+ a0 k$ H% f% y0 t& F. t
  85.                 default: ;
    . }& Y$ n/ ]3 j7 Y
  86.             endcase
    * j+ k/ x7 a" H
  87.         end
    / b2 y- \- j* V* N% Q  B* v% Y
  88. end3 j5 Q; P7 s$ T4 @) j7 v1 Q

  89. # R( `$ t! {& k7 L; h
  90. 9 S, `% g! `$ N! |% s' W
  91. //--------------------capture spi_flag posedge--------------------------------
    ' r- s/ m0 Q! E: e( W/ a
  92. reg rxd_flag_r0,rxd_flag_r1;. O. L+ V, T+ a/ A
  93. always@(posedge clk or negedge rst_n)
    . c% i7 e5 I9 T
  94. begin
    9 }: G: a. j( i6 i
  95.     if(!rst_n)6 i: C  ^* B$ y) G: w
  96.         begin
    & H' Q+ J- {2 n9 Q$ X5 h
  97.             rxd_flag_r0 <= 1'b0;) M2 X. T1 Q0 Q. M, F: N
  98.             rxd_flag_r1 <= 1'b0;: O1 x. C* d5 \4 ]0 b' R
  99.         end1 H/ Q: c+ l! n2 \  X/ B- I- O
  100.     else
    * u5 U; r: Y; z  G. n% V
  101.         begin6 v8 F5 f" X% T6 ~" f# C
  102.             rxd_flag_r0 <= rxd_flag_r;
    * D; X; }6 L; z( e: k
  103.             rxd_flag_r1 <= rxd_flag_r0;
    + S# l2 G5 z3 D  [" |2 R1 X
  104.         end3 a! O7 g1 k+ c. w1 o
  105. end4 J( `( t& h# _0 a; Y4 ?
  106. - n5 ~& ~0 B+ O9 `: o# N
  107. assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;4 [+ O" ?4 x$ y) q
  108. " u) y( h% L  i" t( ~
  109. //---------------------spi_slaver send data---------------------------4 k3 |2 u. R  j0 A) Q' Z  W
  110. reg [2:0] txd_state;
    5 W: e. F5 C' ]- H& c% R* W! d
  111. always@(posedge clk or negedge rst_n); @' v' b# `3 D
  112. begin
    6 q; G3 g6 W* B/ `$ q3 c
  113.     if(!rst_n)
    & `0 G" F. |" X/ C& m6 S
  114.         begin' \- @$ K% K6 J9 N
  115.             txd_state <= 1'b0;
    + E8 g: I1 V7 `' W& X
  116.         end
    ! |0 L8 U, ?9 `9 y, q; P' c
  117.     else if(sck_n && !CS_N), ^, P9 P+ Y, q3 o
  118.         begin
      X! \8 d( \" V$ J
  119.             case(txd_state)
    7 K3 c; V8 W8 _7 }1 r; K
  120.                 3'd0:begin
    / A( D. s7 U6 s4 R
  121.                         MISO <= txd_data[7];
    6 `3 x  T+ l+ f( g) w8 ?6 B  j' f
  122.                         txd_state <= 3'd1;
    3 z7 v7 m- Y, I
  123.                       end2 A" J2 G# A+ y5 @" p
  124.                 3'd1:begin
    ! K$ C* {1 R, d0 y9 f6 U
  125.                         MISO <= txd_data[6];
    3 B2 Q, C. X; d  f2 p9 D
  126.                         txd_state <= 3'd2;9 B3 T0 \4 [2 ]4 {
  127.                       end4 ]) p& C) W/ J; [1 k4 N1 M9 U$ g+ r4 P
  128.                 3'd2:begin5 z; ?! q8 C( N  G0 ?
  129.                         MISO <= txd_data[5];' m0 i! y* h* ^5 \! t* W: X* Z
  130.                         txd_state <= 3'd3;
    5 S+ E8 K' l: b% f" s5 I+ U8 u$ Y8 L; Q
  131.                       end" Q8 \( o; O" I! \% G5 E' d# E
  132.                 3'd3:begin4 a" M" G& i2 Y5 v) W& H9 G
  133.                         MISO <= txd_data[4];
    9 z; J9 E6 A3 c- z7 W! {! Y8 G
  134.                         txd_state <= 3'd4;
    1 w# \/ Z3 ^2 w* h8 D- z9 I
  135.                       end
    2 k6 o1 j1 B- U0 I$ v0 l0 t  f
  136.                 3'd4:begin
    4 _( ]. l; Q9 D" K( A, @. _
  137.                         MISO <= txd_data[3];
    1 F: b/ f3 l- Q
  138.                         txd_state <= 3'd5;
    5 h9 w9 E' U' G% g9 D1 h
  139.                       end8 K; i* F/ l0 O8 o; `6 e- h
  140.                 3'd5:begin  t5 Z( z$ F$ C0 `& G: a
  141.                         MISO <= txd_data[2];! d& _7 @; g8 E# M6 V
  142.                         txd_state <= 3'd6;
    8 g3 ^1 i! Q0 I
  143.                       end
    ( T2 i) K/ T2 q2 M* _; _
  144.                 3'd6:begin
    ! Z1 W6 \/ Z( m# t) \1 \3 r' {
  145.                         MISO <= txd_data[1];. {# H4 c  `0 e0 O) a8 s
  146.                         txd_state <= 3'd7;) L. t  ?6 D; s) p$ R5 w, ?
  147.                       end! G. C3 Y# R- g& N, \+ s
  148.                 3'd7:begin
    " i# q# O6 e; U+ @( q. ~) c
  149.                         MISO <= txd_data[0];
    . P1 C: Q! e+ y/ V9 b; b
  150.                         txd_state <= 3'd0;
    & D# Q+ b3 E! }# A0 j
  151.                       end' j/ _" Z8 d( G6 I! p
  152.                 default: ;
    6 q$ t; H7 E; y5 F2 ]2 T
  153.             endcase! M$ u# q% ^2 `  e
  154.         end
    - K! B" O- e4 K& {! G- |  P' ~; C% F
  155. end4 |! K) T- R3 w1 _" q. a3 C
  156. ; _* \8 b& L0 \6 E
  157. endmodule
复制代码
+ `8 t! B# Y4 Y: ]% |0 V7 ^
0 ~9 y, G# S7 S8 ~/ c) ?
% G- a: b5 w3 Y8 {! z0 Y+ s, I9 e$ j+ d2 d
. o2 H. a) n# }+ V0 k
1 收藏 评论0 发布时间:2022-1-16 18:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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