当前位置:   article > 正文

xilinxFPGA-SPI协议详解(基于verilog)_xilinx spi 文档

xilinx spi 文档

FPGA】——(基于verilog)SPI四种模式详解

原理分析

对于 spi 通讯协议,相比较于 IIC ,可以说 spi 快很多,而且 spi 是可以全双工的,具有单独的发送线路和接收线路,我们从它的时序来进行分析吧。
在这里插入图片描述
从图中我们可以看到有一个是使能信号 SS ,空闲是高电平,当使能时为低电平,只有拉低时数据才能进行发送和接收。
还有 CLK 时钟信号, spi 就是通过时钟信号的跳变来进行读取数据,时钟信号有两种模式,在 0 模式下,时钟信号空闲为低电平,在 1 模式下,时钟信号空闲为高电平。
因为 spi 是全双工的,所以有两个数据线,分别是 MOSIMISOIO 分别代表 inputoutput ,这样就很好记哪个是数据发送,呢个是数据接收了。数据线也有两个模式,在 0 模式下在第一个时钟跳变沿读取数据,第二个时钟跳变沿改变数据,而在 1 模式下是第一个时钟条边沿改变数据,第二个时钟跳变沿读取数据。
通过时钟两种模式和数据发送接收的两种模式就可以组成四种模式,又因为 FPGA 可以作为主机或者从机,所以一共有八种模式,接下来我会详细讲解这四种模式对于 FPGA 的实现。

主机模式

0 0模式

发送

module spi_tx(	//定义spi发送模块。
	input Clk,	//定义系统时钟信号。
	input Reset_n,	//定义复位信号。
	input [7:0]spi_Data,	//定义需要发送数据,由上层模块输入数据。
	input spi_En,	//定义发送使能信号。
	output reg spi_Clk,	//定义spi时钟信号。
	output reg spi_TXD,	//定义spi数据发送信号。
	output reg spi_done	//定义发送完成使能信号。
);
	reg [7:0]cnt_Clk;	//定义一个八位计数器,用来对系统时钟分频来控制spi时钟频率。
	parameter MAX_CLK = 8'd1;	//定义分频大小。
	wire clk_done;	//定义spi时钟半个周期使能信号。
	reg [4:0]cnt_state;	//定义一个5位寄存器来记录发送数据状态。
	parameter MAX_STATE = 5'd16;	//定义最大状态。
	
	always @(posedge Clk or negedge Reset_n)	begin	//定义系统时钟分频计数器。
		if (!Reset_n)	//复位清零。
			cnt_Clk <= 8'd0;
		else if (!spi_En)	begin	//使能有效时,spi时钟才工作,取反是因为低电平有效。
			if (MAX_CLK <= cnt_Clk)	//计满清零。
				cnt_Clk <= 8'd0;
			else	//否则加一。
				cnt_Clk <= cnt_Clk + 1'b1;
		end
		else	//使能无效清零。
			cnt_Clk <= 8'd0;
	end
	assign clk_done = (cnt_Clk == MAX_CLK);	//每计满一次使能一次。
	always @(posedge Clk or negedge Reset_n)	begin	//定义状态变换信号。
		if (!Reset_n)	//复位清零。
			cnt_state <= 5'd0;
		else if (!spi_En)	begin	//使能有效状态才可以增加。
			if (MAX_STATE <= cnt_state)	//计满清零。
				cnt_state <= 5'd0;
			else if (clk_done)	//系统时钟分频计数器计满加一。
				cnt_state <= cnt_state + 1'b1;
			else	//否则不变。。
				cnt_state <= cnt_state;
		end
		else	//使能无效清零。
			cnt_state <= 5'd0;
	end
	
	always @(posedge Clk or negedge Reset_n)	begin	//定义数据发送模块。
		if (!Reset_n)	begin	//复位清零,数据位在空闲时为高阻态。
			spi_Clk <= 1'b0;
			spi_TXD <= 1'bz;
		end
		else if (!spi_En)	begin	//使能有效。
			case (cnt_state)	//更据状态来赋值。
				0: begin spi_Clk <= 1'b0; spi_TXD <= spi_Data[0]; end	//初始状态令时钟低电平,将数据最低位0位发送到数据信号上。
				1: spi_Clk <= 1'b1;	//时钟上升沿读取数据,下同。
				2: begin spi_Clk <= 1'b0; spi_TXD <= spi_Data[1]; end	//时钟下降沿将改变数据,下同。
				3: spi_Clk <= 1'b1;
				4: begin spi_Clk <= 1'b0; spi_TXD <= spi_Data[2]; end
				5: spi_Clk <= 1'b1;
				6: begin spi_Clk <= 1'b0; spi_TXD <= spi_Data[3]; end
				7: spi_Clk <= 1'b1;
				8: begin spi_Clk <= 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号