1. 程式人生 > >spi master接口的fpga實現

spi master接口的fpga實現

工作 -1 form alt spa out idt logs 使用

前言

當你器件的引腳賊少的時候,需要主機和從機通信,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         : [email protected]     
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 [2:0] DIV_NUMBER = 4; //div number,you can change; 23 localparam CNT_MAX = (DIV_NUMBER >>1) - 1b1; //max cnt number,6/2 -1 ; 24 reg cnt; //sck cnt; 25 reg sck_en; //enable sck; 26 reg data_cnt_en; 27 reg sck_reg1; 28 reg sck_reg2; 29 wire sck_p; //posedge sck; 30 wire sck_n; //negedge sck; 31 wire send_over; 32 localparam IDEL = 2b00; 33 localparam SEND = 2b01; 34 localparam FINISH = 2b10; 35 reg [1:0] cstate; 36 reg [4:0] data_cnt; //cnt the send data; 37 reg [7:0] master_din_reg; 38 reg [7:0] master_dout_reg; 39 reg [2:0] mosi_cnt; 40 //produce sck; 41 always @(posedge clk or negedge rst_n) begin 42 if (~rst_n) begin 43 cnt <= 0; 44 sck <= 1b0; 45 end //if 46 else begin 47 if (sck_en == 1b1) begin 48 if (cnt == CNT_MAX) begin 49 cnt <= 0; 50 sck <= ~sck; 51 end 52 else begin 53 cnt <= cnt + 1b1; 54 sck <= sck; 55 end 56 end 57 else begin 58 cnt <= 0; 59 sck <= 1b0; 60 end 61 end //else 62 end //always 63 //produce sck_p and sck_n; 64 always @(posedge clk or negedge rst_n) begin 65 if (~rst_n) begin 66 sck_reg1 <= 1b0; 67 sck_reg2 <= 1b0; 68 end //if 69 else begin 70 sck_reg1 <= sck; 71 sck_reg2 <= sck_reg1; 72 end //else 73 end //always 74 assign sck_p = (sck_reg1 & (~sck_reg2)); //sck posedge; 75 assign sck_n = ((~sck_reg1) & sck_reg2); //sck negedge; 76 //fsm;hot code; 77 always @(posedge clk or negedge rst_n) begin 78 if (~rst_n) begin 79 cstate <= IDEL; 80 end 81 else begin 82 case (cstate) 83 IDEL: cstate <= (wr)? SEND : IDEL; 84 SEND: cstate <= (send_over) ? FINISH : SEND; 85 FINISH: cstate <= IDEL; 86 default: cstate <= IDEL; 87 endcase //case 88 end 89 end 90 always @(posedge clk or negedge rst_n) begin 91 if (~rst_n) begin 92 cs <= 1b1; 93 data_cnt_en <= 1b0; 94 sck_en <= 1b0; 95 master_din_reg <= 0; 96 master_dout <= 0; 97 end 98 else begin 99 case (cstate) 100 IDEL: begin 101 data_cnt_en <= 1b0; 102 master_din_reg <= (wr) ? master_din : master_din_reg; //load the data you want send to slaver; 103 end 104 SEND: begin 105 data_cnt_en <= 1b1; 106 cs <= 1b0; 107 sck_en <= 1b1; 108 master_dout <= (send_over) ? master_dout_reg : master_dout; //master receiverd data; 109 end 110 FINISH: begin //send and load ok; 111 sck_en <= 1b0; 112 cs <= 1b1; 113 data_cnt_en <= 1b0; 114 end 115 default: begin 116 cs <= 1b1; 117 sck_en <= 1b0; 118 data_cnt_en <= 1b0; 119 end 120 endcase //case 121 end 122 end 123 always @(posedge clk or negedge rst_n) begin 124 if (~rst_n) begin 125 data_cnt <= 0; 126 end 127 else begin 128 data_cnt <= (data_cnt_en) ? (data_cnt + 1b1) : 5d0; //4 div * 8bit = 32 cnt; 129 end 130 end 131 assign send_over = (data_cnt == 5d31) ? 1b1 : 1b0; 132 //rising edge miso; 133 always @(posedge clk or negedge rst_n) begin 134 if (~rst_n) begin 135 master_dout_reg <= 0; 136 end 137 else begin 138 master_dout_reg <= (sck_p) ? {master_dout_reg[6:0],miso} : master_dout_reg; 139 end 140 end 141 //miso; 142 always @(posedge clk or negedge rst_n) begin 143 if (~rst_n) begin 144 mosi_cnt <= 0; 145 end 146 else begin 147 if (sck_n) begin 148 if (mosi_cnt == 3d7) begin 149 mosi_cnt <= 0; 150 end 151 else begin 152 mosi_cnt <= mosi_cnt + 1b1; 153 end 154 end 155 else begin 156 mosi_cnt <= mosi_cnt; 157 end 158 end 159 end 160 always @(posedge clk or negedge rst_n) begin 161 if (~rst_n) begin 162 mosi <= 1b0; 163 end 164 else begin 165 mosi <= (sck_n) ? master_din_reg[3d7-mosi_cnt] : mosi; 166 end 167 end 168 endmodule

仿真:

技術分享

綜合資源使用:

技術分享

Fmax:

技術分享

以上。

spi master接口的fpga實現