spi 发送与接收 移位写法

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
相关推荐
ALINX技术博客16 小时前
AMD MoP 封装策略解读 | HBM 大热,为何 AMD Versal 系列反选 LPDDR5X?
fpga开发·fpga·amd·versal
zlinear数据采集卡18 小时前
从万用表的6步调零到硅片级微秒自校准:硬核拆解LHAMP188的宽压轨到轨与零漂移实战
arm开发·stm32·单片机·嵌入式硬件·fpga开发
Rambo.xia18 小时前
AXI-Stream反压与背靠背传输——TREADY反压丢帧、TDEST路由错误、反压死锁,流式数据一反压就出事
fpga开发
国科安芯20 小时前
ASC8T245S 8通道电平转换设计实战:从系统架构到QFN24 Layout再到量产测试
网络·单片机·物联网·安全·fpga开发·系统架构
传感器与混合集成电路2 天前
基于FPGA与ADC协同架构的高密度数据采集模块设计原理与应用场景分析
fpga开发·架构
Rambo.xia2 天前
10Gbps实时图像重采样:一个FPGA项目的完整交付复盘
fpga开发
zlinear数据采集卡2 天前
2mV纹波的代价:硬核拆解ZLinear模拟前端放大器与正负可调电源设计
arm开发·单片机·嵌入式硬件·fpga开发·架构·开源
小麦嵌入式2 天前
FPGA入门(八):一篇讲透跑马灯、闪烁灯、呼吸灯的原理与模拟波形分析
fpga开发
Rambo.xia2 天前
AXI4-Full突发传输掉数据——突发长度算错、WRAP边界、窄传输字节错位,调试一周才发现是协议理解错了
fpga开发
zlinear数据采集卡2 天前
硅片里的“自动纠错“:硬核拆解LHAMP188自动归零技术原理与三种封装的PCB布局实战
arm开发·单片机·嵌入式硬件·fpga开发·开源