spi 回环

verilog 复制代码
///tx  极性0  (sclk信号线空闲时为低电平)
///     相位0 (在sclk信号线第一个跳变沿进行采样)
`timescale 1ns / 1ps

//两个从机  8'd01  8'd02
module top(
    input               clk  ,
    input               rst_n,
    input         [7:0] addr ,
    input               valid,
    input         [15:0]data ,
    output  reg         mosi ,
    output  reg    [1:0]cs   , //相当于是有2个从机 引脚约束的话是有2个
    output  reg         sclk 
    );
parameter CLK_DIV=100;
parameter IDEL = 2'b01;
parameter BUSY = 2'b10;
parameter cong1= 2'b01;
parameter cong2= 2'b10;
reg [1:0] state;
reg       fin  ;
reg       d    ;
reg [10:0]cunt1;
reg [9:0] cunt ;
reg [4:0] cunt_b;
//将valid信号延长
always @(posedge clk or negedge rst_n) begin
     if(state==IDEL)begin
         if(valid==1)
         d<=1;
         else
         d<=d;
     end
    else
    d<=0;        
end
always @(posedge clk or negedge rst_n) begin
    if(state==IDEL)begin
        if(d==1)
        cunt1<=cunt1+1;
        else
        cunt1<=cunt1;
    end
    else
    cunt1<=0;
end
//状态的转移
always @(posedge clk ) begin
    if(!rst_n)
    state<=IDEL;
    else if(state==IDEL&&cunt1==200)
    state<=BUSY;
    else if(state==BUSY&&fin==1)
    state<=IDEL;
    else
    state<=state;
end
//产生一个计数器对时钟周期计数
always @(posedge clk ) begin
    if(state==IDEL)
    cunt<=0;
    else begin
        if(cunt==CLK_DIV-1)
        cunt<=0;
        else
        cunt<=cunt+1;
        end
end
//对sclk计数
always @(posedge clk ) begin
    if(state==IDEL)
    cunt_b<=0;
    else begin
        if(cunt==CLK_DIV-1)
        cunt_b<=cunt_b+1;
        else
        cunt_b<=cunt_b;
    end
end
//sclk的产生
always @(posedge clk ) begin
    if(state==IDEL)
    sclk<=0;
    else if(fin==1)
    sclk<=0;
    else begin
    if(cunt<CLK_DIV/2)
    sclk<=1;
    else
    sclk<=0;
    end
end

//fin产生
always @(posedge clk) begin
    if(cunt==CLK_DIV-1&&cunt_b==15)
    fin<=1;
    else
    fin<=0;
end
//cs的产生
always @(posedge clk ) begin
    if(addr==8'd01)
    cs<=2'b01;
    else if(addr==8'd02)  //(state==BUSY||d==1)这个条件也可以不要 相当于只要选中一直拉高
    cs<=2'b10;
    else
    cs<=0;
end
//对mosi的输出
always @(posedge clk ) begin
    if(state==IDEL)
    mosi<=0;
    else case (cunt_b)
        0:mosi <=data[0]  ;
        1:mosi <=data[1]  ;
        2:mosi <=data[2]  ; 
        3:mosi <=data[3]  ;
        4:mosi <=data[4]  ;
        5:mosi <=data[5]  ;
        6:mosi <=data[6]  ;
        7:mosi <=data[7]  ;
        8:mosi <=data[8]  ;
        9:mosi <=data[9]  ;
        10:mosi<=data[10] ; 
        11:mosi<=data[11] ;
        12:mosi<=data[12] ;
        13:mosi<=data[13] ;
        14:mosi<=data[14] ;
        15:mosi<=data[15] ;
        default:mosi<=0; 
    endcase
end
endmodule

///rx
`timescale 1ns / 1ps
module rx_spi(
    input            clk  ,
    input            rst_n,
    input            mosi ,
    input            sclk ,
    input            cs   , //一位宽 例化的时候比如这个是从机连线就是cs[1]
    output reg [15:0]data ,
    output           valid        
    );
reg  [1:0]  sclk_t;
reg  [7:0]  cunt_b;
       
//对sclk_t缓存
always @(posedge clk or negedge rst_n) begin
    if(cs==1)
    sclk_t<={sclk_t[0],sclk};
    else
    sclk_t<=2'b00;
end
//对2'b10 这个下降沿计数
always @(posedge clk ) begin
    if(!rst_n)
    cunt_b<=0;
    else if(cs==1&&sclk_t==2'b10)
    cunt_b<=cunt_b+1;
    else
    cunt_b<=cunt_b;
end
//valid的产生
assign valid=(cs==1&&cunt_b==15);
//data的补充
always @(posedge clk ) begin
    if(cs==1) begin
        if(sclk_t==2'b10)
        case (cunt_b)
            0:data[0]<=mosi; 
            1:data[1]<=mosi;
            2:data[2]<=mosi;
            3:data[3]<=mosi;
            4:data[4]<=mosi;
            5:data[5]<=mosi;
            6:data[6]<=mosi;
            7:data[7]<=mosi;
            8:data[8]<=mosi;
            9:data[9]<=mosi;
            10:data[10]<=mosi;
            11:data[11]<=mosi;
            12:data[12]<=mosi;
            13:data[13]<=mosi;
            14:data[14]<=mosi;
            15:data[15]<=mosi;
            default: data=data;
        endcase
        else 
        data<=data;
    end
    else
    data<=0;
end
endmodule
//tb仿真激励文件
`timescale 1ns / 1ps
module tb(
    );
reg         clk  ;///
reg         rst_n;///
reg  [7:0]  addr ;///
reg         valid;///
reg  [15:0] data ;///
wire        mosi ;
wire [1:0]  cs   ;
wire        sclk ;  
initial begin
    clk=1    ;
    rst_n<=0 ;
    #100
    rst_n<=1 ;
    #100
    addr<=8'd02;
    valid<=1;
    data<=16'h1234;
    #20
    valid<=0;
end

always #10  clk=~clk ;
top u_top(
    /*input           */.clk  (clk  ),
    /*input           */.rst_n(rst_n),
    /*input     [7:0] */.addr (addr ),
    /*input           */.valid(valid),
    /*input     [15:0]*/.data (data ),
    /*output reg      */.mosi (mosi ),
    /*output reg [1:0]*/.cs   (cs   ),
    /*output reg      */.sclk (sclk )
    );
rx_spi u_rx1(
    /*input       */.clk  (clk  ),
    /*input       */.rst_n(rst_n),
    /*input       */.mosi (mosi ),
    /*input       */.sclk (sclk ),
    /*input       */.cs   (cs[1]), //一位宽 例化的时候比如这个是从机连线就是cs[1]
    /*output [7:0]*/.data ( ),
    /*output      */.valid( )        
    );
endmodule
 

仿真波形图

采样跳变沿笔记

相关推荐
XINVRY-FPGA34 分钟前
XC7A100T-2FGG484I Xilinx Artix-7 FPGA
arm开发·嵌入式硬件·fpga开发·硬件工程·信息与通信·信号处理·fpga
cmc10281 小时前
129.FPGA绑定管脚时差分管脚只绑_p是不行的,tx与rx只绑一个也不行
fpga开发
望获linux1 小时前
【实时Linux实战系列】FPGA 与实时 Linux 的协同设计
大数据·linux·服务器·网络·数据库·fpga开发·操作系统
cycf1 小时前
系统同步输出延迟分析(七)
fpga开发
国科安芯1 小时前
高辐射环境下AS32S601ZIT2型MCU的抗辐照性能与应用潜力分析
网络·人工智能·单片机·嵌入式硬件·fpga开发
爱吃汽的小橘10 小时前
用串口控制DAC
fpga开发
FPGA_ADDA15 小时前
RFSOC27DR+VU13P 6U VPX板卡
fpga开发·信号处理·adda射频采集·rfsoc27dr·vu13p
ARM+FPGA+AI工业主板定制专家15 小时前
【JETSON+FPGA+GMSL】实测分享 | 如何实现激光雷达与摄像头高精度时间同步?
人工智能·数码相机·机器学习·fpga开发·机器人·自动驾驶
白码王子小张15 小时前
FPGA实现CIC抽取滤波器
fpga开发·vivado·xilinx·cic滤波器
沉默_是金16 小时前
2024年江苏省大学生电子设计竞赛 || 无线传输信号模拟系统
fpga开发