spi master接口的fpga实现

前言

当你器件的引脚贼少的时候,需要主机和从机通信,spi就派上了用场,它可以一对多,但只是片选到的从机能和主机通信,其他的挂机。

spi:serial peripheral interface 串行外围接口

大致了解:

spi是个同步协议,数据在master和slaver间交换通过时钟sck,由于它是同步协议,时钟速率就可以各种变换。

sck:主机提供,从机不能操控,从器件由主机产生的时钟控制。数据只有在sck来了的上升沿或者下降沿才传输。

高级一点的spi芯片有配置寄存器,高级一点的工作有四种模式,采样相位和sck空闲电平可配置。

当然在这里我们主要实现简单的spi协议:sck是系统时钟的四分频,wr请求信号有效时,主机开始工作,数据位8bit,sck空闲时低电平,工作时第一个沿数据传输。只有一个从机,cs低电平片选。

看下结构:

接口定义:

编码实现:(版权所有,请勿用于商业用途,仅供学习使用)

  1 //************************************************
  2 //  Filename      : spi_ms_test1.v                             
  3 //  Author        : Kingstacker                  
  4 //  Company       : School                       
  5 //  Email         : kingstacker_work@163.com     
  6 //  Device        : Altera cyclone4 ep4ce6f17c8  
  7 //  Description   : spi master module;data 8bit;sck is 4 div of the clk;                              
  8 //************************************************
  9 module  spi_ms #(parameter WIDTH = 8)(
 10     //input;
 11     input    wire    clk, 
 12     input    wire    rst_n,
 13     input    wire    wr, //send request;
 14     input    wire    [WIDTH-1:0]    master_din, //the data you want send;
 15     input    wire    miso, //the data form slave;
 16     //output;
 17     output   reg     cs, //slave select;
 18     output   reg     sck, //data exchange clock;
 19     output   reg     mosi,    //master out;
 20     output   reg     [WIDTH-1:0]    master_dout //the data you received;
 21 );
 22 localparam CLK_HZ = 50_000_000;  //clk frequency;  
 23 localparam SCK_HZ = 12_500_000;  //sck frequency;
 24 localparam DIV_NUMBER = CLK_HZ / SCK_HZ;
 25 localparam CNT_MAX = (DIV_NUMBER >>1) - 1'b1;
 26 localparam DATA_CNT_MAX = 5'd31;
 27 localparam MOSI_CNT_MAX = 3'd7;
 28 localparam IDEL = 2'b00;
 29 localparam SEND = 2'b01;
 30 localparam FINISH = 2'b10; 
 31 reg cnt; //sck cnt;
 32 reg sck_en; //enable sck;
 33 reg data_cnt_en;
 34 reg sck_reg1;
 35 reg sck_reg2;
 36 wire sck_p; //posedge sck;
 37 wire sck_n; //negedge sck;
 38 wire send_over;
 39 reg [1:0] cstate;
 40 reg [4:0] data_cnt; //cnt the send data;
 41 reg [2:0] mosi_cnt;
 42 reg [WIDTH-1:0] master_din_reg; 
 43 reg [WIDTH-1:0] master_dout_reg;
 44 //produce sck;
 45 always @(posedge clk or negedge rst_n) begin
 46     if (~rst_n) begin
 47         cnt <= 0;
 48         sck <= 1'b0;
 49     end //if
 50     else begin
 51         if (sck_en == 1'b1) begin
 52             if (cnt == CNT_MAX) begin
 53                 cnt <= 0;
 54                 sck <= ~sck;
 55             end
 56             else begin
 57                 cnt <= cnt + 1'b1;
 58                 sck <= sck;
 59             end
 60         end
 61         else begin
 62             cnt <= 0;
 63             sck <= 1'b0;
 64         end
 65     end //else
 66 end //always
 67 //produce sck_p and sck_n;
 68 always @(posedge clk or negedge rst_n) begin
 69     if (~rst_n) begin
 70         sck_reg1 <= 1'b0;
 71         sck_reg2 <= 1'b0;
 72     end //if
 73     else begin
 74         sck_reg1 <= sck;
 75         sck_reg2 <= sck_reg1;    
 76     end //else
 77 end //always
 78 assign sck_p = (sck_reg1 & (~sck_reg2)); //sck posedge;
 79 assign sck_n = ((~sck_reg1) & sck_reg2); //sck negedge;
 80 //fsm;hot code;
 81 always @(posedge clk or negedge rst_n) begin
 82     if (~rst_n) begin
 83         cstate <= IDEL;
 84     end
 85     else begin
 86         case (cstate)
 87             IDEL:    cstate <= (wr)? SEND : IDEL; 
 88             SEND:    cstate <= (send_over) ? FINISH : SEND; 
 89             FINISH:  cstate <= IDEL;
 90             default: cstate <= IDEL;
 91         endcase //case
 92     end
 93 end
 94 always @(posedge clk or negedge rst_n) begin
 95     if (~rst_n) begin
 96         cs <= 1'b1;
 97         data_cnt_en <= 1'b0;
 98         sck_en <= 1'b0;
 99         master_din_reg <= 0;
100         master_dout <= 0;
101     end
102     else begin
103         case (cstate)
104             IDEL: begin
105             data_cnt_en <= 1'b0;
106             master_din_reg <= (wr) ? master_din : master_din_reg; //load the data you want send to slaver;
107             end 
108             SEND: begin
109                 data_cnt_en <= 1'b1;
110                 cs <= 1'b0; 
111                 sck_en <= 1'b1;
112                 master_dout <= (send_over) ? master_dout_reg : master_dout; //master receiverd data;
113             end
114             FINISH: begin                  //send and load ok;
115                 sck_en <= 1'b0;
116                 cs <= 1'b1;
117                 data_cnt_en <= 1'b0;
118             end
119             default: begin
120                 cs <= 1'b1;
121                 sck_en <= 1'b0;
122                 data_cnt_en <= 1'b0;
123             end
124         endcase //case
125     end
126 end
127 always @(posedge clk or negedge rst_n) begin
128     if (~rst_n) begin
129         data_cnt <= 0;
130     end
131     else begin
132         data_cnt <= (data_cnt_en) ? (data_cnt + 1'b1) : 5'd0; //4 div * 8bit = 32 cnt;
133     end
134 end
135 assign send_over = (data_cnt == DATA_CNT_MAX) ? 1'b1 : 1'b0;
136 //rising edge miso;
137 always @(posedge clk or negedge rst_n) begin
138     if (~rst_n) begin
139         master_dout_reg <= 0;
140     end
141     else begin
142         master_dout_reg <= (sck_p) ? {master_dout_reg[6:0],miso} : master_dout_reg;
143     end
144 end
145 //mosi;
146 always @(posedge clk or negedge rst_n) begin
147     if (~rst_n) begin
148         mosi_cnt <= 0;
149     end
150     else begin
151         if (sck_n) begin
152             if (mosi_cnt == MOSI_CNT_MAX) begin
153                 mosi_cnt <= 0;
154             end
155             else begin
156                 mosi_cnt <= mosi_cnt + 1'b1;
157             end
158         end
159         else begin
160             mosi_cnt <= mosi_cnt;
161         end
162     end
163 end
164 always @(posedge clk or negedge rst_n) begin
165     if (~rst_n) begin
166         mosi <= 1'b0;
167     end
168     else begin
169         mosi <= (sck_n) ? master_din_reg[MOSI_CNT_MAX-mosi_cnt] : mosi;
170     end
171 end
172 endmodule

仿真:

综合资源使用:

Fmax:

 

以上。

posted @ 2017-09-07 15:31  小翁同学  阅读(4748)  评论(7编辑  收藏  举报