SPI基础代码模版
user输入: valid信号 , 要输出的值
输出 :一个周期读valid , 读到的值

module spi_drive#(
parameter P_DATA_WIDTH = 8 ,
P_READ_DATA_WIDTH = 8 ,
P_CPOL = 0 ,
P_CPHL = 0
)(
input i_clk ,
input i_rst ,
output o_spi_clk ,
output o_spi_cs ,
output o_spi_mosi ,
input i_spi_miso ,
input [P_DATA_WIDTH - 1 :0] i_user_data ,
input i_user_valid ,
output o_user_ready ,
output [P_READ_DATA_WIDTH - 1:0] o_user_read_data ,
output o_user_read_valid
);
reg ro_spi_clk ;
reg ro_spi_cs ;
reg ro_spi_mosi ;
reg ro_user_ready ;
reg [P_DATA_WIDTH - 1:0] r_user_data ;
reg r_run ;
reg [15:0] r_cnt ;
reg r_spi_cnt ;
reg [P_READ_DATA_WIDTH - 1:0] ro_user_read_data ;
reg ro_user_read_valid ;
reg r_run_1d ;
/***************wire******************/
wire w_user_active ;
wire w_run_negedge ;
/***************assign****************/
assign o_spi_clk = ro_spi_clk ;
assign o_spi_cs = ro_spi_cs ;
assign o_spi_mosi = ro_spi_mosi ;
assign o_user_ready = ro_user_ready ;
assign o_user_read_data = ro_user_read_data ;
assign o_user_read_valid = ro_user_read_valid ;
assign w_run_negedge = !r_run & r_run_1d ;
/***************always****************/
assign w_user_active = i_user_valid & o_user_ready;
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_user_ready <='d1;
else if(w_user_active)
ro_user_ready <= 'd0;
else if(w_run_negedge)
ro_user_ready <= 'd1;
else
ro_user_ready <= ro_user_ready;
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_user_data <= 'd0;
else if(w_user_active)
r_user_data <= i_user_data;
else if(r_spi_cnt)
r_user_data <= r_user_data << 1;
else
r_user_data <= r_user_data;
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_run <= 'd0;
else if(r_spi_cnt && r_cnt == 7)
r_run <= 'd0;
else if(w_user_active)
r_run <= 'd1;
else
r_run <= r_run;
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_run_1d <= 'd0;
else
r_run_1d <= r_run;
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_cnt <= 'd0;
else if(r_spi_cnt && r_cnt == 7)
r_cnt <= 'd0;
else if(r_spi_cnt)
r_cnt <= r_cnt + 1;
else
r_cnt <= r_cnt;
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_spi_cnt <= 'd0;
else if(r_run)
r_spi_cnt <= r_spi_cnt + 1;
else
r_spi_cnt <= 'd0;
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_spi_clk <= P_CPOL;
else if(r_run)
ro_spi_clk <= ~ro_spi_clk;
else
ro_spi_clk <= P_CPOL;
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_spi_cs <= 'd1;
else if(w_user_active)
ro_spi_cs <= 'd0;
else if(!r_run)
ro_spi_cs <= 'd1;
else
ro_spi_cs <= ro_spi_cs;
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_spi_mosi <= 'd0;
else if(w_user_active)
ro_spi_mosi <= i_user_data[P_DATA_WIDTH - 1];
else if(r_spi_cnt)
ro_spi_mosi <= r_user_data[P_DATA_WIDTH - 2];
else
ro_spi_mosi <= ro_spi_mosi;
end
always@(posedge ro_spi_clk,posedge i_rst)
begin
if(i_rst)
ro_user_read_data <= 'd0;
else
ro_user_read_data <= {
ro_user_read_data[P_DATA_WIDTH - 2 : 0],i_spi_miso};
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_user_read_valid <= 'd0;
else if(r_spi_cnt && r_cnt == 7)
ro_user_read_valid <= 'd1;
else
ro_user_read_valid <= 'd0;
end
endmodule
1. SPI协议与芯片交互接口
实际上就是加入了(芯片命令cmd + 寄存器地址) 的数据。读写操作的位数可以由spi控制器来控制,用于完成各种spi协议芯片的读写任务。
读数据

写数据

module spi_drive#(
parameter P_DATA_WIDTH = 8 ,
P_OP_LEN = 32,
P_READ_DATA_WIDTH = 8 ,
P_CPOL = 0 ,
P_CPHL = 0
)(
input i_clk ,//系统时钟
input i_rst ,//复位
//spi驱动
output o_spi_clk ,//spi的clk
output o_spi_cs ,//spi的片选
output o_spi_mosi ,//spi的主机输出
input i_spi_miso ,//spi的从机输入
//操作通道
input [P_OP_LEN - 1 :0] i_user_op_data ,//操作数据(命令8bit+地址24bit)
input [1 :0] i_user_op_type ,//操作类型(读、写、指令)
input

博客围绕SPI基础代码模版展开,介绍了其输入输出情况。还阐述了SPI协议与芯片交互接口,即加入芯片命令和寄存器地址的数据,读写位数由控制器控制;以及SPI协议的控制器(状态机),可连续读出FIFO中的数据。
9万+

被折叠的 条评论
为什么被折叠?



