当前位置: 首页 > article >正文

fpga spi回环

SPI设备间的数据传输之所以又被称为数据交换,是因为 SPI协议规定一个 SPI设备
不能在数据通信过程中仅仅只充当一个"发送者(Transmitter)“或者"接收者
(Receiver)”.在每个 Clock 周期内,SPI 设备都会发送并接收一个 bit 大小的数据(不管主
设备好还是从设备),相当于该设备有一个 bit 大小的数据被交换了.一个 Slave 设备要想能够
接收到 Master 发过来的控制信号,必须在此之前能够被 Master 设备进行访问。 所以,
Master 设备必须首先通过 SS/CS pin 对 Slave 设备进行片选,把想要访问的 Slave 设备选上.
在数据传输的过程中,每次接收到的数据必须在下一次数据传输之前被采样,如果之前接收到的数据没有被读取,那么这些已经接收完成的数据将有可能会被丢弃,导致 SPI物理模块最终失效.因此,在程序中一般都会在 SPI传输完数据后,去读取 SPI设备里的数据,即使这
些数据在我们的程序里是无用的(虽然发送后紧接着的读取是无意义的,但仍然需要从寄存器中读出来)。

`timescale 1ns / 1ps
// 主机master
//两个从机  8'd01  8'd02
module top#(parameter SIZE=16)(
    input                clk   ,
    input                rst_n ,
    input         [7:0]  addr  ,
    input                valid ,
    input     [SIZE-1:0] data  ,
    input                miso  ,//实际中是从机返回主机的数据线    //仿真里面可以用mosi简化代替 
    output  reg[SIZE-1:0]data_c,//对返回的数据线进行数据读取        
    output  wire        valid_c,//读取完结束信号
    output  reg         mosi   ,
    output  wire   [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 [SIZE-1:0]        data_t;
reg [9:0]             cunt  ;
reg [4:0]             cunt_b;


assign valid_c=fin;
always @(posedge clk ) begin
    if(state==BUSY&&cunt==49)
    data_c<=data_c<<1;
    else if(state==BUSY&&cunt==50)
    data_c[0]<=mosi;
    else
    data_c<=data_c;    
end



//数据的存储
always @(posedge clk ) begin
    if(state==IDEL&&valid==1)
    data_t<=data;
    else if(state==BUSY&&cunt==49)  //取计数中间信号最稳定 
    data_t<=data_t<<1;
    else 
    data_t<=data_t;
end
//状态的转移
always @(posedge clk ) begin
    if(!rst_n)
    state<=IDEL;
    else if(state==IDEL&&valid==1) //因为直接有地址了所以不需要再延长这个valid信号
    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的产生
assign cs[0]=(addr==8'd01)?1:0;  //从机1
assign cs[1]=(addr==8'd02)?1:0;  //从机2
//对mosi的输出
always @(posedge clk ) begin
    if(state==IDEL)
    mosi<=0;
    else begin    
    if(cunt==1) //或者条件写成cunt==0   表示第一个最高位bit的值 mosi应该拉高还是置低的 
    mosi<=data_t[SIZE-1];
    else
    mosi<=mosi;
    end
end

endmodule

仿真激励文件

`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'b1011_0000_0000_1111;
    #20
    valid<=0;
end

always #10  clk=~clk ;
top #(                       . SIZE  (16     ) 
)u_top(
    /*input                */.clk    (clk    ),
    /*input                */.rst_n  (rst_n  ),
    /*input         [7:0]  */.addr   (addr   ),
    /*input                */.valid  (valid  ),
    /*input     [SIZE-1:0] */.data   (data   ),
    /*input                */.miso   ( mosi  ),//从机返回主机的数据线
    /*output  reg[SIZE-1:0]*/.data_c (       ),//对返回的数据线进行数据读取
    /*output  wire         */.valid_c(       ),//读取完结束信号
    /*output  reg          */.mosi   (mosi   ),
    /*output  wire   [1:0] */.cs     (cs     ), //相当于是有2个从机 引脚约束的话是有2个
    /*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

在这里插入图片描述


http://www.kler.cn/a/400966.html

相关文章:

  • go-zero(二) api语法和goctl应用
  • 基本数据类型:Kotlin、Dart (Flutter)、Java 和 C++ 的比较
  • 游戏引擎学习第16天
  • 父组件提交时让各自的子组件验证表格是否填写完整
  • 解决微信小程序自定义tabbar点击两次才能跳转
  • Redis知识分享(三)
  • 【每日题解】3239. 最少翻转次数使二进制矩阵回文 I
  • Dolby TrueHD和Dolby Digital Plus (E-AC-3)编码介绍
  • MaaS模型即服务的优势与发展前景
  • 百度世界大会2024,展现科技改变生活的力量
  • Vue 生成二维码
  • 革命性AI搜索引擎!ChatGPT最新功能发布,无广告更智能!
  • Leetcode 回文数
  • 游戏引擎学习第17天
  • 使用合适的Prompt充分利用ChatGPT的能力
  • 如何用WordPress和Shopify提升SEO表现?
  • labview中连接sql server数据库查询语句
  • 一次需升级系统的wxpython安装(macOS M1)
  • Macmini中普通鼠标与TrackPad联动问题解决
  • openGauss 6.0.0单机部署(企业版)
  • 单机顶集群的大数据技术来了
  • ks 小程序sig3
  • vue3绘制画图工具
  • EUV光刻胶行业全面且深入的分析
  • 集群聊天服务器(7)数据模块
  • sql server index FORCESEEK