FPGA构造spi时序——AD7176为例(转)
reference:https://blog.csdn.net/fzhykx/article/details/79490330
項(xiàng)目中用到了一種常見(jiàn)的低速接口(spi),于是整理了一下關(guān)于spi相關(guān)的知識(shí),與AD采樣的芯片7176通信的協(xié)議為spi
一.對(duì)spi協(xié)議的理解
spi掃盲
????除了供電、接地兩個(gè)模擬連接以外,SPI總線定義四組數(shù)字信號(hào):
????-?接口時(shí)鐘SCLK(Serial Clock,也叫SCK、CLK),master輸出至slave的通訊時(shí)鐘。
????-?MOSI(?Master Output Slave Input,也叫SIMO、MTSR、DI、DIN、SI)自master輸出至slave的數(shù)據(jù)線。
????-?MISO?(Master Input Slave Output,也叫SOMI、MRST、DO、DOUT、SO)自slave輸出至master的數(shù)據(jù)線。
????-?SS(Slave select,也叫nSS、CS、CSB、CSN、EN、nSS、STE、SYNC)master對(duì)slave的片選信號(hào),自master輸出至slave,低有效。?
?SPI接口是一種典型的全雙工接口,通過(guò)同步時(shí)鐘SCLK的脈沖將數(shù)據(jù)一位位地傳送。所以在開(kāi)始通訊前,master首先要配置接口時(shí)鐘(確定其通訊頻率是SLAVE可以支持的,通常為數(shù)兆赫茲)。
?當(dāng)MASTER片選一個(gè)SLAVE時(shí),每向SLAVE發(fā)送一個(gè)周期的SCLK信號(hào),都會(huì)有1bit的數(shù)據(jù)從MOSI發(fā)送至slave,與此同時(shí),slave每收到一個(gè)周期的SCLK信號(hào),都會(huì)從MISO向master發(fā)送1bit的數(shù)據(jù)。這種全雙工通訊,是由硬件保證的(MASTER與HOST中各有一個(gè)移位寄存器作為收發(fā)數(shù)據(jù)的緩存)。
二.AD7176使用簡(jiǎn)單說(shuō)明
1>寫(xiě)入與讀入方法
????對(duì)于FPGA為master而言,要注意SCLK下降沿發(fā)數(shù)給AD7176,上升沿讀AD7176的數(shù)。在寫(xiě)入的時(shí)候,先用SPI時(shí)序,寫(xiě)入一個(gè)8bits的CMD,CMD就是通信寄存器,負(fù)責(zé)控制寫(xiě)入還是讀出和要通信的寄存器名稱,隨后寫(xiě)寫(xiě)入8bit/16bit/24bit的數(shù)據(jù)。
????在讀數(shù)據(jù)的時(shí)候也需要通過(guò)通信寄存器也就是CMD讀取,要規(guī)定好讀數(shù)據(jù)和讀哪個(gè)寄存器的值。
2>AD7176配置流程
具體寄存器還需要查看手冊(cè)具體配置。
三.程序源代碼講解
1>程序源碼
`timescale 1ns / 1ps // // Company: // Engineer: // // Create Date: 2017/03/10 11:08:45 // Design Name: // Module Name: spi_core // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // //module spi_core(input clk,//50Minput rst,input [7:0] din, //要輸出input s_valid, //要輸出input[1:0] readnum,//指示指令讀取數(shù)據(jù)的長(zhǎng)度 2’b00:0,2'b01:8,2'b10:256,2'b11:1664480(320*257*2)output spi_ready,output [23:0] dout,output m_valid,input cfg_finsih,input spi_miso,output spi_mosi,output spi_cs,output spi_clk,output empty); /* 本模塊只完成SPI協(xié)議所規(guī)定的時(shí)序,不涉及FLASH指令的編寫(xiě) */ parameter IDLE = 3'd0; parameter S1 = 3'd1; parameter S2 = 3'd2; parameter S3 = 3'd3; parameter S4 = 3'd4; parameter S5 = 3'd5; parameter S6 = 3'd6; parameter Smid =3'd7; reg [2:0] sta_spi; reg spi_ready_r; reg spi_clk_r; reg spi_cs_r; reg spi_mosi_r;wire wr_en; reg rd_en; wire dout_fifo; //wire empty; wire full; wire[14:0] rd_count;assign spi_clk = spi_clk_r; assign spi_cs = spi_cs_r; assign spi_mosi = dout_fifo;//spi_mosi_r; assign spi_ready = spi_ready_r; assign wr_en = s_valid; //fifo_generator_0 fifo_generator_0 ( //.rst(~rst), // input wire rst //.wr_clk(clk), // input wire wr_clk //.rd_clk(clk), // input wire rd_clk //.din(din), // input wire [7 : 0] din //.wr_en(wr_en), // input wire wr_en //.rd_en(rd_en), // input wire rd_en //.dout(dout_fifo), // output wire [0 : 0] dout //.full(full), // output wire full //.empty(empty), // output wire empty //.rd_data_count(rd_count) //); fifo_generator_0 fifo_generator_0 (.clk(clk), // input wire clk.srst(~rst), // input wire srst.din(din), // input wire [7 : 0] din.wr_en(wr_en), // input wire wr_en.rd_en(rd_en), // input wire rd_en.dout(dout_fifo), // output wire [0 : 0] dout.full(full), // output wire full.empty(empty) // output wire empty // .rd_data_count(rd_count) // output wire [15 : 0] rd_data_count ); reg recv_reg; reg recv_ok; reg [20:0] recv_num; reg [20:0] NUM; always @(posedge clk) beginif(~rst)beginsta_spi <= IDLE;spi_clk_r <= 1'b1;spi_cs_r <= 1'b1;spi_mosi_r <=1'b0;rd_en <= 1'b0;recv_reg <= 1'b0;recv_ok <= 1'b0;spi_ready_r <= 1'b0;recv_num <= 21'd0;endelse begincase(sta_spi)IDLE:begin recv_ok <= 1'b0;recv_num <= 21'd0;spi_clk_r <= 1'b1; if(~empty)beginrd_en <= 1'b1;sta_spi <= S1;spi_ready_r <= 1'b0;endelsespi_ready_r <= 1'b1;endS1:beginrd_en <= 1'b0;spi_clk_r <= 1'b0;spi_cs_r <= 1'b0;spi_mosi_r <= dout_fifo;sta_spi <= S2;endS2:beginspi_clk_r <= 1'b1; // sta_spi <= S3;if(~empty)beginrd_en <= 1'b1;sta_spi <= S1; end // else if(empty) // spi_cs_r<=1'b1; else if(readnum!=2'b00) //就是要讀數(shù)的意思sta_spi <= S4;elsesta_spi <= S3; endS3:beginsta_spi <= IDLE;spi_clk_r <= 1'b0;spi_cs_r <= 1'b1;endS4:beginspi_clk_r <= 1'b0;recv_ok <= 1'b0;sta_spi <= S5;endS5:beginspi_clk_r <= 1'b1;recv_num <= recv_num +1'b1;recv_reg <= spi_miso;recv_ok <= 1'b1; if(recv_num!=NUM)sta_spi <= S4;else beginsta_spi <= IDLE;spi_cs_r <= 1'b1;endendendcaseend endalways @(posedge clk) beginif(~rst)NUM <= 21'd0;else begincase(readnum)2'b00:NUM <= 21'd0;2'b01:NUM <= 21'd7;2'b11:NUM <= 21'd23;endcaseend end reg [23:0] dout_r; reg m_valid_r; reg [3:0] cnt_bit; always @(posedge clk) beginif(~rst)begindout_r <= 16'd0;m_valid_r <= 1'b0;cnt_bit <= 4'd0;endelse if(recv_ok)begin//m_valid_r <= 1'b0;dout_r <= {dout_r[22:0],recv_reg};cnt_bit <= cnt_bit + 1'b1;if(cnt_bit==4'd15)m_valid_r <= 1'b1;elsem_valid_r <= 1'b0;endelsem_valid_r <= 1'b0; end assign dout = dout_r; assign m_valid = m_valid_r;/*********************************/ endmodule?
2>軟件仿真時(shí)序
配置過(guò)程也就是FPGA用SPI輸出過(guò)程,每次片選信號(hào)CS拉低,下降沿發(fā)數(shù)
3>讀數(shù)階段軟件仿真
?
?
?
波形也和手冊(cè)的時(shí)序相對(duì)應(yīng)轉(zhuǎn)載于:https://www.cnblogs.com/limanjihe/p/9814697.html
總結(jié)
以上是生活随笔為你收集整理的FPGA构造spi时序——AD7176为例(转)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: JS函数addEventListener
- 下一篇: J2SE J2EE J2ME的区别