2. 从模块(SPI_slave):
module spi_slave(
input rst_n,
input cs_n,
input sclk,
input mosi,
output miso,
output [7:0] reg0_out,
output [7:0] reg1_out,
output [7:0] reg2_out,
output [7:0] reg3_out
);
reg miso_r;
reg [7:0] reg1_out_r;
reg [7:0] reg2_out_r;
reg [7:0] reg3_out_r;
reg [7:0] reg0_out_r;
reg start;
reg wr_rd;
reg [3:0] bit_cnt;
reg [6:0] reg_addr;
reg [7:0] reg_data;
parameter reg0_address = 7'b0000000; //address of reg0
parameter reg1_address = 7'b0000001; //address of reg1
parameter reg2_address = 7'b0000010; //address of reg2
parameter reg3_address = 7'b0000011; //address of reg3
//start
always @ (posedge sclk or negedge rst_n)
begin
if(~rst_n)
start <= 1'b0;
else
start <= 1'b1;
end
//bit_cnt
always @ (posedge sclk or negedge rst_n)
begin
if(~rst_n)
bit_cnt <= 4'b0;
else if(start)
bit_cnt <= bit_cnt + 1'b1;
end
//wr_rd
always @ (posedge sclk or negedge rst_n)
begin
if(~rst_n)
wr_rd <= 1'b0;
else if(bit_cnt == 4'b0 && mosi == 1'b0)
wr_rd <= 1'b0;
else if(bit_cnt == 4'b0 && mosi == 1'b1)
wr_rd <= 1'b1;
end
//reg_addr
always @ (negedge sclk or negedge rst_n)
begin
if(~rst_n)
reg_addr <= 7'b0;
else if(bit_cnt >= 4'd1 && bit_cnt <= 4'd7)
reg_addr <= {reg_addr[5:0],mosi};
end
//reg_data
always @ (posedge sclk or negedge rst_n)
begin
if(~rst_n)
reg_data <= 8'b0;
else if(!wr_rd && bit_cnt >= 4'd7)
reg_data <= {reg_data[6:0],mosi};
else if(wr_rd && bit_cnt == 4'd6)
reg_data <= reg2_out_r;
else if(wr_rd && bit_cnt >= 4'd7)
reg_data <= {reg_data[6:0],reg_data[7]};
end
//reg_out
assign reg0_out = reg0_out_r;
assign reg1_out = reg1_out_r;
assign reg2_out = reg2_out_r;
assign reg3_out = reg3_out_r;
always @ (negedge sclk or negedge rst_n)
begin
if(~rst_n)
begin
reg0_out_r <= 8'b0;
reg1_out_r <= 8'b0;
reg2_out_r <= 8'b0;
reg3_out_r <= 8'b0;
end
else if(!wr_rd && bit_cnt == 4'd0)
case(reg_addr)
reg0_address: reg0_out_r <= reg_data;
reg1_address: reg1_out_r <= reg_data;
reg2_address: reg2_out_r <= reg_data;
reg3_address: reg3_out_r <= reg_data;
endcase
end
//miso
assign miso = miso_r;
always @ (negedge sclk or posedge rst_n)
begin
if(~rst_n)
miso_r <= 1'b0;
else if(wr_rd && bit_cnt >= 4'd7)
miso_r <= reg_data[7];
end
endmodule
3. Testbench(tb):
`timescale 1us/1us
module tb();
regclk_40k;
regrst_n;
reg [7:0] data_in;
regsend_start;
wiresclk;
wirecs_n;
wiremosi;
wiremiso;
wire [7:0] data_out;
wire data_out_vld;
wire [7:0] reg0_out;
wire [7:0] reg1_out;
wire [7:0] reg2_out;
wire [7:0] reg3_out;
spi_master i_spi_master(
.clk_40k (clk_40k),
.rst_n (rst_n),
.data_in (data_in),
.send_start (send_start),
.sclk (sclk),
.cs_n (cs_n),
.mosi (mosi),
.miso (miso),
.data_out (data_out),
.data_out_vld (data_out_vld)
);
spi_slave i_spi_slave(
.rst_n (rst_n),
.cs_n (cs_n),
.sclk (sclk),
.mosi (mosi),
.miso (miso),
.reg0_out (reg0_out),
.reg1_out (reg1_out),
.reg2_out (reg2_out),
.reg3_out (reg3_out)
);
initial
begin
rst_n = 1'b0;
#10rst_n = 1'b1;
end
initial
begin
clk_40k = 1'b0;
forever
#1clk_40k = ~clk_40k;
end
initial
begin
send_start = 1'b0;
data_in = 8'd0;
forever
begin
#200;
data_in = $random()%256;
send_start = 1'b1;
#2
send_start = 1'b0;
#8000;
end
end
endmodule
4. 仿真结果:
按照testbench对SPI主从设备进行仿真,仿真结果如图:
- 系统时钟和SPI时钟不一致,clk_40k为高频系统时钟,利用计数器分频实现1k波特率SPI时钟;
- 复位信号rst_n低电平有效,正常传输时始终处于高电平;
- 开始传输时send_start信号拉高,传输结束时data_out_vld信号拉高;
- SPI主设备将输入数据data_in并行转mosi串行输出,SPI从设备将接收到的串行存入数据,将移位后的数据data_out并行转miso串行输出。
05
SPI的优缺点
5.1 SPI协议优点
5.1 SPI协议缺点
- 需要4个引脚接口;
- 支持传输距离较短;
- 硬件层面没有定义校错协议和从机应答信号。
-
mcu
+关注
关注
146文章
16840浏览量
349734 -
SPI
+关注
关注
17文章
1686浏览量
91135 -
串行端口
+关注
关注
0文章
31浏览量
11637
发布评论请先 登录
相关推荐
评论