SPI接口的Verilog HDL实现

串口外设接口SPI(Serial Peripheral Interface)是一种由Motorola公司推出的一种同步串行接口,得到了广泛应用。

SPI通信协议

SPI,顾名思义就是串行外围通信接口,只需四条线就可以完成主、从与各种外围器件全双工同步通信。4根接口线分别是:串行时钟线(SCK)、主机输入/从机输出数据线(MISO)、主机输出/从机输入(MOSI),低电平有效从机选择线(CS)。
SPI系统可分为主机设备和从机设备两类设备,其中主机提供SPI时钟信号和片选信号,从机设备是接受SPI信号的任何集成电路。当SPI工作时,在移位寄存器中的数据逐位从输出引脚(MOSI)输出,同时从输入引脚(MISO)逐位接受数据。发送和接收操作都受控于SPI主机设备的时钟信号(SCK),从而保证同步,因此只能有一个主设备,但从设备可以有多个,通过不同的片选信号可以同时选择一个或多个从设备。
下面是用Verilog HDL实现的SPI主模式,其中读写操作都是低字节在前,高字节在后,每次传输一个字节
module spi_master(
			addr,
			in_data,
			out_data,
			wr,
			rd,
			cs,
			clk,
			miso,
			mosi,
			sclk
    );
input[1:0]addr;
input [7:0]in_data;
output [7:0]out_data;
reg [7:0]out_data;
input clk;
input wr;
input rd;
input cs;
inout miso;
inout mosi;
inout sclk;

reg sclk_buffer = 0;
reg mosi_buffer = 0;
reg busy = 0;

reg [7:0]in_buffer = 0;
reg [7:0]out_buffer = 0;
reg [7:0]clkcount = 0;
reg [7:0]clkdiv = 0;
reg [4:0]count = 0;

always@(cs or rd or addr or out_buffer or busy or clkdiv) begin
	out_data = 8'bx;
	if(cs&&rd) begin
		case(addr)
			2'b00 : out_data = out_buffer;
			2'b01 : out_data = {7'b0,busy};
			2'b10 : out_data = clkdiv;
			default: out_data = out_data;
		endcase
	end
end

always@(posedge clk) begin
	if(!busy) begin
		if(cs&&wr) begin
			case(addr)
				2'b00 : begin
					in_buffer <= in_data;
					busy <= 1'b1;
					end
				2'b10 : in_buffer <= clkdiv;
				default : in_buffer <= in_buffer;
			endcase
		end// end if(cs&&wr);
	end
	else begin
		clkcount <= clkcount+1;
		if(clkcount >= clkdiv) begin
			clkcount <=0;
			
			if(count%2 == 0) begin
				mosi_buffer <= in_buffer[7];
				in_buffer <= in_buffer<<1;
			end
			
			if(count>0 && count<17) begin
				sclk_buffer <= ~sclk_buffer;
			end
			
			count <= count+1;
			
			if(count > 17) begin
				busy <= 0;
				count <= 0;
			end
		end
	end
end

	always@(posedge sclk_buffer) begin
		out_buffer = out_buffer<<1;
		out_buffer[0] = miso;
	end
	
	assign sclk=sclk_buffer;
	assign mosi=mosi_buffer;
	
endmodule

写功能的仿真结果
SPI接口的Verilog HDL实现_第1张图片


你可能感兴趣的:(FPGA)