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

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

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

0 x* X! o9 W& j2 V6 g
二.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发送数据与接收数据。

1 u+ v+ c. r1 w, R0 u
  1. /***********************************************************************
    7 h7 E9 ]/ S9 _+ F' ^) p9 X$ |
  2.      ****************** name:SPI_Slaver_Driver **************1 x9 x8 ^& O- G1 w
  3.             ********** author:made by zzuxzt **********
    . b6 c+ K$ x* |8 E  V8 o5 b, E. i
  4.      ****************** time:2014.4.29 **********************3 X# R- g# z/ L+ e- u4 _8 G* b/ z
  5. ***********************************************************************/
    & B  v, C9 E9 V
  6. //use SPI 3 mode,CHOL = 1,CHAL = 18 t6 ~+ U/ G$ |# B& V# D+ B
  7. module spi(input clk,
    8 v! p; g, S; ?  h
  8.               input rst_n,. e' ?5 B" q+ S6 Y4 i% f( V
  9.               input CS_N,, I, O3 m% F6 v4 Y" ^
  10.               input SCK,7 ?3 Z+ E! \& F: Q; a
  11.               input MOSI,
    1 U) w/ ]5 N' E9 H
  12.               input [7:0] txd_data,1 T2 b7 n+ E7 Y  v& h, }
  13.               output reg MISO,
      @0 W" i6 V; u
  14.               output reg [7:0] rxd_data,
    : l' u* o5 ?$ I1 r3 ~. g2 s
  15.               output rxd_flag);   //recieve done,please transmit data
    7 ]& \5 S7 m& j7 g) }  U1 U9 d

  16. ( }. h! I) b- T) X: t% j; v
  17. //-------------------------capture the sck-----------------------------
    4 G  r% h+ N. R6 Y3 B- U
  18. reg sck_r0,sck_r1;
    , n6 C' {/ E; ^! B  a& h" R
  19. wire sck_n,sck_p;1 e" @- ]' i: W( k
  20. always@(posedge clk or negedge rst_n)
    $ ?$ d0 @; I* M: c( ]- y" V
  21. begin
    ) W; S1 {# D/ e0 m+ E! D* g" g
  22.     if(!rst_n)$ A- ]6 [9 t4 V  j4 ]! y
  23.         begin
    + L& B) R' s( h  n+ C
  24.             sck_r0 <= 1'b1;   //sck of the idle state is high. q: H: y1 p* b# h1 N( l
  25.             sck_r1 <= 1'b1;
    # l( z2 x: @- o; O1 Y4 l2 w" Z
  26.         end
    7 B% _( c, U& p( O6 k, N1 H
  27.     else
      }/ @' B' y* a- \) D* j8 X) s
  28.         begin
    2 `% j* V2 Q7 @3 j5 w
  29.             sck_r0 <= SCK;& U2 H" s- v8 }# q9 s' r+ U! m( O9 j
  30.             sck_r1 <= sck_r0;
    $ S, S5 A9 N6 k% C
  31.         end1 o3 p3 V3 q* b
  32. end
    # w$ W4 x3 s2 Q, M! k& e

  33. ' V5 B# N1 N$ n- R, q8 f+ C! @" Z
  34. assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0;   //capture the sck negedge
    % x. |8 }" q; Z$ ~" S5 A/ T
  35. assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0;   //capture the sck posedge% q. ?: h7 }& h1 H8 ]

  36. , A# E( b7 I% }
  37. //-----------------------spi_slaver read data-------------------------------" _0 s" H! M  R6 L' @7 D3 I
  38. reg rxd_flag_r;; I+ m$ o% T3 Q7 q1 }# v# y! ]# c
  39. reg [2:0] rxd_state;
    2 I# T3 V% y5 U/ h$ Q
  40. always@(posedge clk or negedge rst_n)
    . k7 `" n/ j. d; K5 A0 O9 {( i
  41. begin
    % Q  q$ D; `* j+ i. }6 `  P1 V
  42.     if(!rst_n)
    - p/ F* I2 n, W8 b( P
  43.         begin" g5 F+ V/ N) E% Y" z( l
  44.             rxd_data <= 1'b0;
    5 W& n. c* t: B+ {* I! Y( o% j
  45.             rxd_flag_r <= 1'b0;! {$ r1 _8 c1 Y9 B
  46.             rxd_state <= 1'b0;' N/ L* r, i6 d5 v# J4 d
  47.         end
    1 e1 s" N! v8 }  v
  48.     else if(sck_p && !CS_N)
    # T% ~; e" J( l4 a/ U
  49.         begin
    / Y0 ]0 X; D, j! g! Z4 A6 K) x
  50.             case(rxd_state)2 h9 J9 L+ j+ W6 e
  51.                 3'd0:begin1 {3 g7 S6 \2 \+ S% r
  52.                         rxd_data[7] <= MOSI;5 _0 S0 z" g2 h" N8 h4 j, n1 T6 G
  53.                         rxd_flag_r <= 1'b0;   //reset rxd_flag# C7 X5 q7 g+ z- Y. U* k# _
  54.                         rxd_state <= 3'd1;; {; b% v6 S+ H' U
  55.                       end
    ( J" \* u. R) ^$ C( I3 ]- e
  56.                 3'd1:begin2 N. _! L: b: F( X- a/ R) D3 b
  57.                         rxd_data[6] <= MOSI;$ E+ T& V$ l* o
  58.                         rxd_state <= 3'd2;0 x) d) r5 T3 o# @4 n8 A; m
  59.                       end, h9 Q  P9 Y& P; ?9 j
  60.                 3'd2:begin
    1 M! }7 q5 [! k
  61.                         rxd_data[5] <= MOSI;1 Y9 u+ u' Y3 N7 b2 s9 Z  Z  T
  62.                         rxd_state <= 3'd3;1 q( j% q# D+ L' ~' w7 p% U) C
  63.                       end
    8 i/ i7 D* u$ @9 a
  64.                 3'd3:begin' J- L# o( ~6 T6 k0 H5 t$ g
  65.                         rxd_data[4] <= MOSI;
    ! J% l$ V3 Q- k6 B! g5 F
  66.                         rxd_state <= 3'd4;
    & h/ i( V! P6 f3 _# {/ ^+ V  [
  67.                       end. o" X$ W- e' O; }1 P7 |
  68.                 3'd4:begin
    0 Y' h% x6 R9 n( I) f
  69.                         rxd_data[3] <= MOSI;; \) r  {. V; D) R0 _0 h6 Q
  70.                         rxd_state <= 3'd5;  D! p+ g. ~8 {
  71.                       end7 F8 u" ~2 d  c9 L
  72.                 3'd5:begin
    - m+ O" h& p" _4 n6 T9 r
  73.                         rxd_data[2] <= MOSI;
    ' k8 U5 K) x( Z: T
  74.                         rxd_state <= 3'd6;
    8 ^# y' A  s0 d
  75.                       end$ i3 L6 i8 |: o( B  S
  76.                 3'd6:begin
    , G' f# D$ w( Y/ \% c
  77.                         rxd_data[1] <= MOSI;
    ' o, g/ q; e1 a7 k* H2 v+ `" F
  78.                         rxd_state <= 3'd7;
    # l6 D2 T5 ~) l
  79.                       end
    ; Y* D: ]" L4 C
  80.                 3'd7:begin
    6 K% e" s1 ]! l6 s$ j
  81.                         rxd_data[0] <= MOSI;; {0 Z/ w8 Q' z9 t  s  Z
  82.                         rxd_flag_r <= 1'b1;  //set rxd_flag. _- H$ D  O2 M7 _$ M/ [
  83.                         rxd_state <= 3'd0;
    7 \5 a, M. y* _7 d# R. k4 W
  84.                       end
    $ z" V! V% f3 z+ M2 A
  85.                 default: ;
    4 g- w. I: R0 H. Z$ ^) l9 r
  86.             endcase6 D$ M, c' R( T/ ?" n
  87.         end
    7 S5 `: c0 _2 b  y) @% n
  88. end# _; U! ^1 Y. h0 C  b
  89. / E8 k6 }& [; k
  90. ) J: F" l) F5 q* g$ B
  91. //--------------------capture spi_flag posedge--------------------------------% C$ ^8 K4 L# P' ^/ n
  92. reg rxd_flag_r0,rxd_flag_r1;
    * x. F8 V0 i. d2 V3 e4 E
  93. always@(posedge clk or negedge rst_n)/ o" H* o6 ~. ~$ ?4 r9 e5 q. g
  94. begin
    ; ^2 R; d  l# C, h, i) O. O
  95.     if(!rst_n)& i. e+ m5 Q" z; _% u6 I
  96.         begin
    1 w- C* y0 Z! w' r' ~. T! ]# E
  97.             rxd_flag_r0 <= 1'b0;. c3 ^$ j8 G& f, C7 n1 ?4 T# _
  98.             rxd_flag_r1 <= 1'b0;
    $ ]) U' T( z& e, z
  99.         end& K7 N1 D4 H. d: M7 d* y8 Y
  100.     else
    : a/ _& J$ L% ^5 S; Q' r
  101.         begin9 Y( E) v- h% H3 n
  102.             rxd_flag_r0 <= rxd_flag_r;
    ; j) M" M- g" \; V, _
  103.             rxd_flag_r1 <= rxd_flag_r0;
    4 Q$ Z3 k' @( d. _/ E# t/ U, P
  104.         end
    ' |( @% L1 ?4 _6 Z! a
  105. end7 N$ O$ U! R! W1 d! E  F( x9 N

  106. $ d* S# ?  y' Y7 y
  107. assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;" @$ b9 z- k& b$ j

  108. 9 h6 M7 L) ]. m( w
  109. //---------------------spi_slaver send data---------------------------
    ) ~6 W$ z9 P5 A% I9 [
  110. reg [2:0] txd_state;
      u( }- ?, `* v8 `4 ?
  111. always@(posedge clk or negedge rst_n)
    , D$ x# n1 M( c: [. M
  112. begin$ _: {: ^- D, H7 D1 c
  113.     if(!rst_n)
    " @  V8 v/ j/ }& J
  114.         begin) D* ]" g& R3 V- D1 \! \
  115.             txd_state <= 1'b0;
    - s' D9 g6 Z  C2 D, m7 W
  116.         end
    , @- {% e3 E- k2 c9 b% g
  117.     else if(sck_n && !CS_N)/ t4 J4 c! e) p( k. t0 Y
  118.         begin
    8 k4 X! w% F7 m: E4 V/ ~
  119.             case(txd_state)
    - I) o/ @3 @" i
  120.                 3'd0:begin
    2 A8 a' F; T% x& a/ c
  121.                         MISO <= txd_data[7];9 R. H/ w2 X$ v6 H* J2 Y+ n% V
  122.                         txd_state <= 3'd1;- b3 _0 s7 z+ }4 I/ F  z1 W
  123.                       end
    ! S7 ?$ m/ i9 L6 v0 \  M
  124.                 3'd1:begin
    6 z* k8 n! n6 [' D. T& l1 B3 L
  125.                         MISO <= txd_data[6];2 o9 [  g1 U" L2 P5 J0 W- [
  126.                         txd_state <= 3'd2;& B" k- {2 }9 X' }/ `
  127.                       end
    ) L+ B' D" A9 }
  128.                 3'd2:begin
    6 A# W5 l! d0 s6 _- h) T
  129.                         MISO <= txd_data[5];! O4 Z0 c5 Y& a. T9 b
  130.                         txd_state <= 3'd3;
    8 P3 F9 N. @$ {: n9 U0 E5 ^  ?
  131.                       end3 j6 D8 \, f+ M7 J4 Y. N) p
  132.                 3'd3:begin
    : d+ O9 l% x3 h5 F
  133.                         MISO <= txd_data[4];8 s) ?$ [. J+ c9 r3 Y6 Y
  134.                         txd_state <= 3'd4;
    1 _- O* Q( Q6 q8 a
  135.                       end
    " M2 M- c# l$ W
  136.                 3'd4:begin1 q) k1 m9 _. O9 _: P) T* [& F
  137.                         MISO <= txd_data[3];: w' ~( Z5 i% }* l
  138.                         txd_state <= 3'd5;. u# Q: I+ u2 z. A" I
  139.                       end& o; }- d' J+ {2 ]% c7 `
  140.                 3'd5:begin
    + h- N; V. Z+ w  Z
  141.                         MISO <= txd_data[2];
    1 N- H# @2 t$ L: k
  142.                         txd_state <= 3'd6;) P- e0 t; O9 g* O& ~- T
  143.                       end6 Z% x$ |9 M2 i1 T5 \& [
  144.                 3'd6:begin
    7 x2 ^, _! s. c' t
  145.                         MISO <= txd_data[1];
    ( w$ I$ ^% l) |' K4 \
  146.                         txd_state <= 3'd7;( Q' y  X) `! ?6 E' n% X0 q6 E9 a
  147.                       end
    $ O0 x9 e9 \3 D, W7 S0 F8 F  e
  148.                 3'd7:begin. L4 K3 M$ N- m2 t
  149.                         MISO <= txd_data[0];' @8 \: \% `# c! T. v# H0 A4 f
  150.                         txd_state <= 3'd0;; h9 V% M* P% I9 D4 O
  151.                       end
    ! W. }* X7 N2 o9 }3 t
  152.                 default: ;
    % W# A! T& A9 p) N) y1 J( Z* }5 M" x
  153.             endcase. A: m' _, Q5 G* \# b
  154.         end
    ' F  d$ W* y) s9 B) ?
  155. end1 N3 e. }- u  d) b0 ]! u! e
  156. 4 k* H, Q  K/ X( |5 e' q
  157. endmodule
复制代码

' Z9 C  \. s) R* |: {8 d; Z4 ~9 S# E
/ P% o# h. ]1 Y8 T" z+ u) W' o" w) s1 y% ]. @6 @* R3 H/ c7 t% u5 a" `( n

* A9 M3 @( ]' P4 O& {
1 收藏 评论0 发布时间:2022-1-16 18:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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