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
测试方式为先读取数据,然后将读取的数据发送出去;
测试结果如下