verlog简单的SPI收发接受器

verlog简单的SPI收发接受器

主程序代码如下

/***********************************
作者:robetwu
时间:2020.7.15
环境:Quartus 13.0
发送和接受缓存器可以使用memory
*******************/
module sample_spi(clk,rst_n,wr,rd,si,sclk,so,cs,data_out,data_receive_buff);

input clk;
input rst_n;
input wr;
input rd;
input si;//master线MISO
output reg sclk;//可以使用PLL或者定时器时钟以满足外设时钟要求
output reg cs;//片选
output reg so;//master线MOSI
reg [7:0]data_in;
reg [7:0]data_out_reg;//发送缓存寄电器
output  [7:0]data_out;

assign data_out=data_out_reg;//将发射的数据放入发射受寄电器中


//CPOL核CPHA的相关配置如下
//空闲状态sclk为低,CPOL=0;相位CPHA=0在sclk时钟的下降延发射接受数据
//空闲状态sclk为低,CPOL=0;相位CPHA=1在sclk时钟的上升延发射接受数据
//空闲状态sclk为高,CPOL=1;相位CPHA=0在sclk时钟的上升延发射接受数据
//空闲状态sclk为高,CPOL=1;相位CPHA=1在sclk时钟的下降延发射接受数据
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		begin
		sclk<=1;//配置为CPOL=1,CPHA=0;
		cs<=1;
		end
	else if(wr|rd)
		begin
			sclk=~sclk;
			cs<=0;
		end
	else
		begin
		sclk<=1;
		cs<=1;
		end
		
reg [4:0]send_stata;
reg [4:0]receive_stata;

//发生状态,发生从高向低发生
parameter bit7=4'd0,bit6=4'd1,bit5=4'd2,bit4=4'd3,
bit3=4'd4,bit2=4'd5,bit1=4'd6,bit0=4'd7,bit_end=4'd8;

//发送指令

always@(posedge sclk)
if(wr)
begin
send_stata<=bit7;
send_task;
end

task	send_task;
begin
case(send_stata)
bit7:
	begin
	so<=data_out_reg[7];//发送接受
	send_stata<=bit6;
	end
bit6:
	begin
	so<=data_out_reg[6];//发送
	send_stata<=bit5;
	end
bit5:
	begin
	so<=data_out_reg[5];//发送
	send_stata<=bit4;
	end
bit4:
	begin
	so<=data_out_reg[4];//发送
	send_stata<=bit3;
	end
bit3:
	begin
	so<=data_out_reg[3];//发送
	send_stata<=bit2;
	end
bit2:
	begin
	so<=data_out_reg[2];//发送
	send_stata<=bit1;
	end
bit1:
	begin
	so<=data_out_reg[1];//发送
	send_stata<=bit0;
	end
bit0:
	begin
	so<=data_out_reg[0];//发送
	send_stata<=bit_end;
	end
bit_end:
	begin
	so<='bz;//发送
	send_stata<=bit7;
	end	

endcase
end
endtask

//接受指令
//接受状态 ,接收从高向低接受
parameter bit70=4'd0,bit60=4'd1,bit50=4'd2,bit40=4'd3,
bit30=4'd4,bit20=4'd5,bit10=4'd6,bit00=4'd7,bit_end0=4'd8;
output reg[7:0]data_receive_buff;//接受缓存寄电器
reg js_byte;

always@(*)
if(js_byte==1)
	data_out_reg<=data_receive_buff;
else
	data_out_reg<=8'hzz;
//assign data_out_reg=(js_byte==1)?data_receive_buff:8'hzz;

always@(posedge sclk)
	if(rd)
	begin
	js_byte<=0;
	receive_stata<=bit70;
	receive_task;
	end


task receive_task;
case(receive_stata)
bit70:
	begin
	data_receive_buff[7]<=si;//接受
	receive_stata<=bit60;
	end
bit60:
	begin
	data_receive_buff[6]<=si;
	receive_stata<=bit50;
	end
bit50:
	begin
	data_receive_buff[5]<=si;
	receive_stata<=bit40;
	end
bit40:
	begin
	data_receive_buff[4]<=si;
	receive_stata<=bit30;
	end
bit30:
	begin
	data_receive_buff[3]<=si;
	receive_stata<=bit20;
	end
bit20:
	begin
	data_receive_buff[2]<=si;
	receive_stata<=bit10;
	end
bit10:
	begin
	data_receive_buff[1]<=si;
	receive_stata<=bit00;
	end
bit00:
	begin
	data_receive_buff[0]<=si;
	receive_stata<=bit_end0;
	js_byte<=1;
	end
bit_end0:
	begin
	data_receive_buff<=8'hzz;
	receive_stata<=bit70;
	end
endcase
endtask
	

endmodule

测试文件如下


`timescale 1ns/1ns
module sample_spi_tb;
reg clk;
reg rst_n;
reg wr;
reg rd;
reg  si;//master线MISo
wire sclk;
wire cs;
wire so;//master线MOSI
wire [7:0]data_receive_buff;

wire [7:0]data_out;


sample_spi sample_spi_inst(
			.clk(clk),.rst_n(rst_n),.wr(wr),.rd(rd),
			.si(si),.so(so),.sclk(sclk),.cs(cs),
			.data_out(data_out),.data_receive_buff(data_receive_buff));
			

initial
begin
	wr=0;rd=1;rst_n=0;clk=0;
	#10 rst_n=1;
	repeat(20)
	begin
	#20 si=1;
	#20 si=0;
	#20 si=1;
	#20 si=0;
	#20 si=0;
	#20 si=1;
	#20 si=0;
	#20 si=1;
	end
	wr=1;rd=0;
	repeat(20)
	begin
	#20 si=1;
	#20 si=0;
	#20 si=1;
	#20 si=0;
	#20 si=0;
	#20 si=1;
	#20 si=0;
	#20 si=1;
	end
	#10000;
end	

always #10 clk=~clk;

endmodule

测试方式为先读取数据,然后将读取的数据发送出去;

测试结果如下

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值