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

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

[复制链接]
STMCU小助手 发布时间:2022-1-16 18:00
一.SPI协议简要介绍
SPI,是英语Serial Peripheral Interface的缩写,顾名思义就是串行外围设备接口。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。
" ~/ F9 L+ G7 A' L  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拉低使能情况下。
& @, F( Y/ E6 I: f9 J" A
二.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发送数据与接收数据。
' Y8 b6 `$ j2 u" g/ T- a, T
  1. /***********************************************************************  a; V# g% c* |' F
  2.      ****************** name:SPI_Slaver_Driver **************1 l3 I8 g* }! S% V
  3.             ********** author:made by zzuxzt **********8 V- L0 A/ ~) t- h
  4.      ****************** time:2014.4.29 **********************
    7 v. l. A0 O. N9 D- `3 V  @
  5. ***********************************************************************/' U( m4 I6 ^0 s8 @; L$ @0 `
  6. //use SPI 3 mode,CHOL = 1,CHAL = 1
    3 T6 z* S' W; e+ a0 a( u; k& T7 Q' I
  7. module spi(input clk,
    / J5 `* y4 w; T8 x
  8.               input rst_n,
    ; l6 ^0 ]2 z1 E6 w5 ~( P! H
  9.               input CS_N,
    6 C3 {1 V$ `7 E8 ]( n, H
  10.               input SCK,
    " i* H+ F: f1 z& t% V8 P; x* H( B  x
  11.               input MOSI,' E( D2 g. @0 G5 m
  12.               input [7:0] txd_data,
    0 O4 x; q' {3 k$ m
  13.               output reg MISO,
    7 o- P# w( b' X- n+ g2 ~6 ~$ Z
  14.               output reg [7:0] rxd_data,0 c$ z& g7 P& A/ t. B
  15.               output rxd_flag);   //recieve done,please transmit data6 q4 ~* w. I$ l, W. @
  16. 9 x2 X0 i1 z' E# p" ]8 s/ x: `
  17. //-------------------------capture the sck-----------------------------
    6 \8 x# d% o+ F/ ^
  18. reg sck_r0,sck_r1;& z( u2 l" Z, @; k$ k
  19. wire sck_n,sck_p;
    6 z- V* M" ]- m6 q0 ?$ e) k
  20. always@(posedge clk or negedge rst_n)5 w. B( J8 \/ S9 E; I% x# g, C
  21. begin
      C  u1 ?8 k: X1 C% S% Z5 E. C% ^
  22.     if(!rst_n)8 I2 A5 t" R/ `+ v: A
  23.         begin
    3 T5 F* U3 c4 w  H- z' ~. g
  24.             sck_r0 <= 1'b1;   //sck of the idle state is high
    4 A" f' S3 p/ c$ P
  25.             sck_r1 <= 1'b1;
    4 H  f+ }5 M* v% r+ b
  26.         end! v6 A% r( d, @
  27.     else& D$ |. J6 [  `/ ^5 j2 U1 Y
  28.         begin
    : \5 V9 L7 m# q8 p1 V/ ~( g
  29.             sck_r0 <= SCK;
      |3 f* O* L! ?, V1 j
  30.             sck_r1 <= sck_r0;
    ( ?8 g7 W! U. y& x
  31.         end
    + u9 w& z/ H# c' Q" V
  32. end
    ) \, u! D' V" N$ e- M+ \" u

  33. % n5 _0 S- N7 y% o1 t6 U
  34. assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0;   //capture the sck negedge
    / _/ A6 |+ |2 d9 b# G3 O
  35. assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0;   //capture the sck posedge
    / C1 j0 ~+ r2 C: ?" d& [* P6 l( C

  36. 3 w4 p% ]- a8 L! e: a$ Y
  37. //-----------------------spi_slaver read data-------------------------------
    ( z) f2 A0 y5 H% \* H
  38. reg rxd_flag_r;  Q8 Q; Z. H0 j  \$ H. C* k2 C5 @
  39. reg [2:0] rxd_state;; H# G5 R8 g# S& d
  40. always@(posedge clk or negedge rst_n)
    0 N: ?0 r; R9 T0 C
  41. begin0 A# [2 ^( t/ B' Y; X% b
  42.     if(!rst_n)7 Q' r, B! V! L+ \, ]; ]
  43.         begin* b) }1 n/ ?& n' |* W+ \
  44.             rxd_data <= 1'b0;
    8 v$ V- \' A5 n; `: b
  45.             rxd_flag_r <= 1'b0;. Y) S& ^8 t0 L1 K2 F' ]! y& T5 G
  46.             rxd_state <= 1'b0;
    1 A% r$ y  U2 \; V% t
  47.         end
    8 r5 ]8 a  W# L' B/ Z( K1 f
  48.     else if(sck_p && !CS_N). s8 m/ J2 [5 g) \0 F, \% l
  49.         begin! y- w' Y3 x/ e7 w9 V
  50.             case(rxd_state)
    1 g1 B1 n5 M1 l) }7 b3 E
  51.                 3'd0:begin$ |8 s1 t  @7 q1 r* k5 f/ U
  52.                         rxd_data[7] <= MOSI;
    7 u1 |) c, q( Y
  53.                         rxd_flag_r <= 1'b0;   //reset rxd_flag/ t1 }$ \  w1 `4 a8 D
  54.                         rxd_state <= 3'd1;4 I  T7 J# b; ^( F3 H7 s0 q1 G
  55.                       end
    3 g* m9 `$ s# F3 f& ~$ @$ o
  56.                 3'd1:begin" _0 q5 j( r0 D0 e. ~9 J' e
  57.                         rxd_data[6] <= MOSI;# B, t! M, m6 M+ ~+ J) @. B
  58.                         rxd_state <= 3'd2;# s' g" y& @8 z8 ^- J3 Z
  59.                       end
    ; M9 P8 P0 v) |# f2 o* S) d
  60.                 3'd2:begin
    ) A  v& O& {. R# a/ T( d+ ~
  61.                         rxd_data[5] <= MOSI;
    + Q, v. x8 g) n6 s* Q( v1 Z
  62.                         rxd_state <= 3'd3;
    # t4 u1 t% H5 h5 }. i
  63.                       end
    + j4 Q( l9 e% a5 u8 D
  64.                 3'd3:begin
    7 A: P& I6 a! i/ d( G+ v. a
  65.                         rxd_data[4] <= MOSI;0 Z; x2 L# D  |. b9 e
  66.                         rxd_state <= 3'd4;
    2 p& D! s# D6 {$ w: h! x
  67.                       end
    + d& X- J/ U$ Z( ^
  68.                 3'd4:begin; j6 k& H4 L: G
  69.                         rxd_data[3] <= MOSI;
    ) D2 s- _+ A" j, ]
  70.                         rxd_state <= 3'd5;
    7 {# @5 F$ ?. w" [2 L
  71.                       end
    / o/ B) X5 P/ }; X
  72.                 3'd5:begin
    9 c; i: W: K3 a% U3 ~$ [
  73.                         rxd_data[2] <= MOSI;* h. {7 v1 ]& v& X8 J$ A" G
  74.                         rxd_state <= 3'd6;
    ; u. p5 ^$ Q+ _- \, ^% Z6 C7 m
  75.                       end
    ( S4 u  k" }  h: B: E" W+ E
  76.                 3'd6:begin7 i& X' k/ D  e& J1 T
  77.                         rxd_data[1] <= MOSI;  y$ q* w4 S4 q% l0 N# n: m+ G% s$ W
  78.                         rxd_state <= 3'd7;
    1 d# o1 v! L, C$ h# m
  79.                       end7 `4 ?8 {  o& p: [
  80.                 3'd7:begin5 J2 A; \3 b6 l5 E% p
  81.                         rxd_data[0] <= MOSI;
    3 L9 N7 J0 |. v8 @
  82.                         rxd_flag_r <= 1'b1;  //set rxd_flag
    0 G8 Z, K4 F2 A. n# I  q
  83.                         rxd_state <= 3'd0;! V5 k& A+ W! p% A# G) [) ^
  84.                       end$ z. \: U  Y* v# h1 ?" X. o
  85.                 default: ;# _. k& W% g( I7 Z  Y" e
  86.             endcase, _( j* t9 P, g0 J, I9 d$ y% {
  87.         end/ J) _; X" z  u. L4 T
  88. end; y' s0 X6 Q. \% U3 V& T0 r3 b8 y

  89. - \, z4 o7 Q$ w
  90. - G+ S  S/ U  V6 p
  91. //--------------------capture spi_flag posedge--------------------------------
    - K3 G3 B- R( Q9 k8 F
  92. reg rxd_flag_r0,rxd_flag_r1;
    : y5 c/ |& o9 ?9 F, l% s7 R" r
  93. always@(posedge clk or negedge rst_n)
    0 P0 H) e& h) h; }
  94. begin. a. R. N) ?. z$ B6 E' }
  95.     if(!rst_n)) F/ h. A; g; G& m! w0 D- q  [
  96.         begin# s$ K* m+ i/ G& ?( P5 \
  97.             rxd_flag_r0 <= 1'b0;" |* b5 D) Z2 x6 ~" ~1 c+ B5 b3 u6 A
  98.             rxd_flag_r1 <= 1'b0;7 i% \. h% ~2 U2 ^7 G4 x) G8 H( {
  99.         end9 `* V$ X* p& ?$ w
  100.     else1 y5 ^: [# }6 c& e4 N
  101.         begin: S3 _+ R1 p) q# s5 G$ k
  102.             rxd_flag_r0 <= rxd_flag_r;, L4 g& d$ g9 s5 N' U6 O/ y7 F0 f
  103.             rxd_flag_r1 <= rxd_flag_r0;
    9 D% V' Q* m! q3 D: D, \
  104.         end
    & R& _# n6 |3 P
  105. end
    2 t. |2 k/ G) {2 _) K8 w

  106. & s% h! K( c, W/ i( I% L, ~
  107. assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;% o3 r% ?; O. d0 r
  108. - n9 [6 c$ E+ K8 y* |8 @
  109. //---------------------spi_slaver send data---------------------------
    3 l0 h- ?9 L) y" c$ N- r
  110. reg [2:0] txd_state;
    0 Q1 f, ]" Y( m' j, U. O
  111. always@(posedge clk or negedge rst_n)+ a) c% X2 C" U! O& s0 G
  112. begin
    4 g- H5 |4 X/ F* o
  113.     if(!rst_n)/ N5 D# x$ d6 r* c$ t& G0 n
  114.         begin
    : W, L* `$ [2 R+ D1 r
  115.             txd_state <= 1'b0;# c6 g0 f6 i  T% q/ d4 T* v: B9 n
  116.         end
      E* q4 Q* ^$ C% Y8 G
  117.     else if(sck_n && !CS_N)) L" `  T9 \6 w) M; G# j; H
  118.         begin/ g+ P( G( C; r7 Q/ q' P% a9 `
  119.             case(txd_state)
    1 }* S  b3 ^5 W% P& k( o: ]
  120.                 3'd0:begin
    : ?, ~% L; [1 m* K* m; n
  121.                         MISO <= txd_data[7];
    - w+ ^/ E% [- d! {% i6 i
  122.                         txd_state <= 3'd1;& r2 {. D' |$ U4 p( S  g) R8 r2 M
  123.                       end
    % {4 I8 \" W  H$ v- }/ }) F
  124.                 3'd1:begin' _9 P* ]6 V% F7 @, L: d+ x8 w8 ?* i
  125.                         MISO <= txd_data[6];: u4 A) f: Z) P5 V* j9 o: V
  126.                         txd_state <= 3'd2;7 b9 o! l' U( J& _
  127.                       end
    4 ]% O, k3 H6 f; t% I; A* e
  128.                 3'd2:begin6 Q3 x/ X" Q$ y) D! {& K; X
  129.                         MISO <= txd_data[5];* R- \) P8 }: J
  130.                         txd_state <= 3'd3;
    2 O) g0 H5 X5 |' D" E
  131.                       end
    # ^9 o6 I* C0 H2 O# o* K: Z
  132.                 3'd3:begin, M* z* @* t& \  v/ N0 S5 A! N* {( I
  133.                         MISO <= txd_data[4];! U; d1 \: D) P# s9 v
  134.                         txd_state <= 3'd4;
    7 r! v6 s  R9 p3 C5 Y
  135.                       end$ S4 E% u/ A; r) v: p! j
  136.                 3'd4:begin8 p% u* e+ E1 i6 I
  137.                         MISO <= txd_data[3];0 q. }/ b* H/ k2 y; U9 @; y
  138.                         txd_state <= 3'd5;* @; g6 ]9 c& q, n2 H
  139.                       end
    - \8 }( W( \  T" f* b: g- _( _
  140.                 3'd5:begin
    % p$ S$ S6 a" d* J/ ^' b+ U" @
  141.                         MISO <= txd_data[2];+ S! N* B$ ?- n. z; o8 W% F
  142.                         txd_state <= 3'd6;
    3 M) s5 H' `. L0 b/ X/ v
  143.                       end9 V$ u& m$ r4 t3 b+ p$ p
  144.                 3'd6:begin1 m8 W; K# t9 c
  145.                         MISO <= txd_data[1];
    9 w  c" `2 T) {, _2 t
  146.                         txd_state <= 3'd7;
    1 g# O/ y3 Q# ?/ N
  147.                       end6 ~" X) o/ A, w; E4 U! J
  148.                 3'd7:begin- j" i: o- A8 `. a4 i. P/ s
  149.                         MISO <= txd_data[0];
    # u5 `( ?2 O" ?! _9 O! v
  150.                         txd_state <= 3'd0;6 U+ h! h% R  G; {0 K& K
  151.                       end
    0 R# Y, }. c$ d
  152.                 default: ;
    6 j1 t: T; y! h3 |1 U% K
  153.             endcase- D4 `, I% e5 N8 {3 D0 w  z
  154.         end6 T# k8 [6 m8 J: H6 m  _$ u
  155. end
    % y, j  ~6 X7 F: l( k8 ^
  156. - y4 e, E4 N8 h# I. w
  157. endmodule
复制代码
- Z- f1 u) u$ P! H5 Q
3 B' p! q& z: I1 j

& Z$ I3 l8 y+ g* b1 J
0 D( |$ N( a: E3 S
1 收藏 评论0 发布时间:2022-1-16 18:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版