D2--FPGA SPI接口通信2022-08-03( 二 )


下面代码在硬件板卡上完成测试 。该代码使用MODE0,即CPOL=CPHA=0的模式 。程序分为以下四步,第一步产生sck同步时钟,第二步依据en指示信号写数据,第三步依据en指示信号并发读数据,第四步产生ui交互信号 。
【D2--FPGA SPI接口通信2022-08-03】module spi_wr(inputclk_i,//user interface// inputspi_en,//其他模块的spi使能信号// input[7:0]data,outputspi_busy,//指示spi的状态,表示SPI过程outputspi_done,//指示spi结束一次动作outputled,// outputspi_cs,//SPI从机的片选信号,低电平有效 。outputspi_clk,//主从机之间的数据同步时钟 。outputspi_mosi,//数据引脚,主机输出,从机输入 。inputspi_miso//数据引脚,主机输入,从机输出 。);// assign spi_cs = 0;//1.同步时钟产生模块 用50MHz分频为50KHzassign spi_clk = m_clk;parameter [9:0] SPI_DIV= 10'd499;//分频定为50KHz,50Mhz/50K/2- 1'b1=499reg [9:0] clk_cnt = 10'd0;//分频计数器always@(posedge clk_i)beginif(clk_cnt < SPI_DIV&&spi_busy)clk_cnt <= clk_cnt + 1'b1;else clk_cnt <= 10'd0;endreg m_clk = 1'b0;always@(posedge clk_i)beginif(spi_en)m_clk <= 1'b0;else if(clk_cnt==SPI_DIV) m_clk <= ~m_clk;end//2.接收en信号和数据,执行spi mosi操作(写数据)//计数发送个数reg [3:0]tx_cnt = 0;always@(posedge clk_i)beginif(spi_en)begintx_cnt <= 0; end else if((clk_cnt == SPI_DIV)&&(tx_cnt==4'd8))begintx_cnt <= 0;end else if((clk_cnt == SPI_DIV)&&spi_clk==0)tx_cnt<=tx_cnt+1;end//移位寄存器发送wire [7:0]data;reg[7:0]data_reg=8'b0;//数据源always@(posedge clk_i)beginif(spi_en)data_reg <= data;else if(spi_done)data_reg <=8'b0;else if(clk_cnt == SPI_DIV&&spi_clk==1)data_reg[7:0] <= {data_reg[6:0],data_reg[7]};endassign spi_mosi = data_reg[7];//3.接收en信号和数据,执行spi miso操作(读数据)reg[7:0]data_fifo=8'b0;always@(posedge clk_i)beginif((clk_cnt == SPI_DIV)&&spi_clk==0)begincase (tx_cnt)0 : data_fifo[7] <= spi_miso;1 : data_fifo[6] <= spi_miso;2 : data_fifo[5] <= spi_miso;3 : data_fifo[4] <= spi_miso;4 : data_fifo[3] <= spi_miso;5 : data_fifo[2] <= spi_miso;6 : data_fifo[1] <= spi_miso;7 : data_fifo[0] <= spi_miso;default: ;endcaseend else data_fifo <= data_fifo;end//4.发出user interface相关指示信号wire spi_en;reg spi_busy =0;assign spi_done = ((clk_cnt == SPI_DIV)&&(tx_cnt==4'd8)) ? 1'b1 : 1'b0;assign led = (data_fifo==8'b11010111) ? 1'b1 : 1'b0;//产生busy信号,指示spi进程always@(posedge clk_i)beginif(spi_en)spi_busy<=1'b1;else if(spi_done)spi_busy<=1'b0;elsespi_busy<=spi_busy;endvio_0 use_vio (.clk(clk_i),// input wire clk.probe_out0(spi_en),// output wire [0 : 0] probe_out0.probe_out1(data)// output wire [7 : 0] probe_out1);ila_0 your_instance_name (.clk(clk_i), // input wire clk.probe0({data_reg,data_fifo}), // input wire [15:0]probe0.probe1(tx_cnt), // input wire [3:0]probe1 .probe2({spi_en,spi_mosi,spi_miso,spi_busy}) // input wire [3:0]probe2);