spi _tx 发送模块 片选信号cs可以在top顶层控制模块产生
verilog
`timescale 1ns / 1ps
module spi_rom#(
parameter SIZE = 8
)(
input wire clk ,
input wire rst_n,
input wire [SIZE-1:0] data ,
input wire valid,
output reg sck ,
output wire busy ,
output reg mosi
);
parameter CUNT_MAX = 100 ;
parameter BUSY = 2'b10 ;
parameter IDEL = 2'b01 ;
reg fin ;
reg [1:0] state ;
reg [10:0] cunt ;
reg [10:0] cunt_b ;
reg [SIZE-1:0] data_r ;
assign busy=(state==BUSY)?1'b1:1'b0;
//状态
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
state<=IDEL;
else case (state)
IDEL:begin
if(valid==1)
state<=BUSY;
else
state<=state;
end
BUSY:begin
if(fin==1)
state<=IDEL;
else
state<=state;
end
default: ;
endcase
end
//计数器
always @(posedge clk) begin
if(state==IDEL)
cunt<=11'd0;
else begin
if(cunt==CUNT_MAX-1)
cunt<=11'd0;
else
cunt<=cunt+1'b1;
end
end
//cunt_b
always @(posedge clk ) begin
if(state==IDEL)
cunt_b<=11'd0;
else begin
if(cunt==CUNT_MAX-1)
cunt_b<=cunt_b+1;
else
cunt_b<=cunt_b;
end
end
//fin结束信号
always @(posedge clk ) begin
if((cunt_b==SIZE-1)&&(cunt==CUNT_MAX-1))
fin<=1'b1;
else
fin<=1'b0;
end
//数据的缓存
always @(posedge clk ) begin
if(state==IDEL&&valid==1)
data_r<=data;
else if(state==BUSY&&cunt==CUNT_MAX-2)
data_r<=(data_r<<1);
else
data_r<=data_r;
end
//sck的产生
always @(posedge clk ) begin
if(state==IDEL)
sck<=1'b0;
else begin
if(cunt_b==SIZE) //防止sck出现末尾的毛刺
sck<=1'b0;
else if(cunt<50)
sck<=1'b1;
else
sck<=1'b0;
end
end
//tx的输出
always @(posedge clk ) begin
if(state==IDEL)
mosi<=1'b0;
else begin
if(cunt==0)
mosi<=data_r[SIZE-1];
else
mosi<=mosi;
end
end
endmodule
spi_rx
verilog
`timescale 1ns / 1ps
module spi_rx#(
parameter SIZE = 8
)(
input clk ,
input rst_n ,
input miso ,
input sck ,
input cs ,
output reg [SIZE-1:0] data ,
output vlid
);
reg [8:0] cunt_b;
reg [1:0] rx_t ;
assign vlid=(cunt_b==SIZE)?1'b1:1'b0;
always @(posedge clk ) begin
if(!rst_n)
rx_t<=2'b00;
else
rx_t<={rx_t[0],sck};
end
//对下降沿计数
always @(posedge clk ) begin
if(!rst_n)
cunt_b<=0;
else if(cs==0)begin
if(vlid==1)
cunt_b<=0;
else if(rx_t==2'b10)
cunt_b<=cunt_b+1'b1;
else
cunt_b<=cunt_b;
end
else
cunt_b<=0;
end
//data
always @(posedge clk ) begin
if(cs==0&&rx_t==2'b10)
data[0]<=miso;
else if(cs==0&&rx_t==2'b01) //先移位再赋值相当于是
data<=(data<<1);
else
data<=data;
end
endmodule