fpga spi回环

news2024/11/20 0:03:07

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.coloradmin.cn/o/2243695.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机网络-理论部分(二):应用层

网络应用体系结构 Client-Server客户-服务器体系结构&#xff1a;如Web&#xff0c;FTP&#xff0c;Telnet等Peer-Peer&#xff1a;点对点P2P结构&#xff0c;如BitTorrent 应用层协议定义了&#xff1a; 交换的报文类型&#xff0c;请求or响应报文类型的语法字段的含义如何…

路由器基本原理与配置

一 &#xff0c; 路由是什么&#xff1f; 从源主机到目标主机的转发过程&#xff1b; 二 &#xff0c; 路由器 &#xff08;1&#xff09;路由器的工作原理 路由器是一种三层设备&#xff0c;是使用IP地址寻址&#xff0c;实现从源IP到达目标IP地址的端到端的服务&#xff0c…

windows的WSL Ubuntu子系统重置root或其他用户的密码

思路&#xff1a;以管理员身份运行PowerShell&#xff0c;在命令行窗口重置密码 &#xff0c;不需要删除或重新安装Linux子系统。 1、以管理员身份运行PowerShell 2、用root用户启动Ubuntu&#xff0c;执行 wsl.exe --user root 3、重置密码&#xff0c;执行passwd username&…

autoDL微调训练qwen2vl大模型

autodl是一家GPU服务厂商&#xff0c;提供专业的GPU租用服务&#xff0c;秒级计费、稳定好用 先去autodl把官方的帮助文档看懂先 AutoDL帮助文档 autodl注册并登陆&#xff0c;充钱&#xff0c;根据自己的情况租用新实例 创建新实例后马上关机&#xff0c;因为有个省钱的办法…

9.2 使用haarcascade_frontalface_default.xml分类器检测视频中的人脸,并框出人脸位置。

1&#xff09;程序代码&#xff1a; # 2.使用haarcascade_frontalface_default.xml分类器检测视频中的人脸&#xff0c;并框出人脸位置 import cv2# 加载人脸检测的 Haar 级联分类器 face_cascade cv2.CascadeClassifier(./data/haarcascades/haarcascade_frontalface_defaul…

K8S containerd拉取harbor镜像

前言 接前面的环境 K8S 1.24以后开始启用docker作为CRI&#xff0c;这里用containerd拉取 参考文档 正文 vim /etc/containerd/config.toml #修改内容如下 #sandbox_image "registry.aliyuncs.com/google_containers/pause:3.10" systemd_cgroup true [plugins.…

ARM64环境部署EFK8.15.3收集K8S集群容器日志

环境规划 主机IP系统部署方式ES版本CPU架构用户名密码192.168.1.225Ubuntu 22.04.4 LTSdockerelasticsearch:8.15.3ARM64elasticllodyi4TMmZD ES集群部署 创建持久化目录(所有节点) mkdir -p /data/es/{data,certs,logs,plugins} mkdir -p /data/es/certs/{ca,es01}服务器…

前端小练习——星辰宇宙(JS没有上限!!!)

前言&#xff1a;在刚开始学习前端的时候&#xff0c;我们会学习到前端三件套中的JavaScript&#xff0c;可能那时候读者没有觉得JavaScript这个语言有多么的牛逼&#xff0c;本篇文章将会使用一个炫酷的案例来刷新你对JavaScript这个语言的认知与理解。 ✨✨✨这里是秋刀鱼不做…

图文教程 | 2024年IDEA安装使用教程,JDK简易下载方法

前言 &#x1f4e2;博客主页&#xff1a;程序源⠀-CSDN博客 &#x1f4e2;欢迎点赞&#x1f44d;收藏⭐留言&#x1f4dd;如有错误敬请指正&#xff01; 目录 一、IDEA安装 二、激活 三、JDK安装 四、JDK环境配置 五、验证 一、IDEA安装 进入官网下载&#xff1a; Other…

【阅读记录-章节2】Build a Large Language Model (From Scratch)

目录 2.Working with text data2.1 Understanding word embeddings2.2 Tokenizing text通过一个简单的实验来理解文本的词元化概念关键概念 2.3 Converting tokens into token IDs实现分词器类&#xff08;Tokenizer Class&#xff09;应用分词器测试文本的编码与解码通过分词器…

已有docker增加端口号,不用重新创建Docker

已有docker增加端口号&#xff0c;不用重新创建Docker 1. 整体描述2. 具体实现2.1 查看容器id2.2 停止docker服务2.3 修改docker配置文件2.4 重启docker服务 3. 总结 1. 整体描述 docker目前使用的非常多&#xff0c;但是每次更新都需要重新创建docker&#xff0c;也不太方便&…

网页作业9

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>服务中心</title><style>* {margin:…

HTML and CSS Support HTML 和 CSS 支持

GoTo DevExpress Data Grid 数据网格 HTML and CSS Support HTML 和 CSS 支持 HTML和CSS支持允许您创建完全自定义的UI元素&#xff0c;并消除使用基于属性的UI自定义和CustomDraw事件。您可以构建 HTML 格式的 UI&#xff0c;并使用 CSS 样式自定义 UI 元素的外观设置、大小、…

集群聊天服务器(7)数据模块

目录 Mysql数据库代码封装头文件与源文件 Mysql数据库代码封装 业务层代码不要直接写数据库&#xff0c;因为业务层和数据层的代码逻辑也想完全区分开。万一不想存储mysql&#xff0c;想存redis的话&#xff0c;就要改动大量业务代码。解耦合就是改起来很方便。 首先需要安装m…

如何确保Python爬虫程序的稳定性和安全性?

在当今数字化时代&#xff0c;Python爬虫被广泛应用于数据采集和信息抓取。然而&#xff0c;确保爬虫程序的稳定性和安全性是开发过程中的重要考虑因素。本文将探讨如何通过技术手段和最佳实践来提高Python爬虫的稳定性和安全性&#xff0c;并提供代码示例。 稳定性保障 1. 异…

【知识科普】统一身份认证CAS

什么是CAS 综合概述一、CAS概述二、CAS的组成与工作原理三、CAS的特性与支持四、CAS的应用场景 示例展示场景设定CAS认证过程 其他认证细节CAS认证过程的细节CAS认证过程的特性 参考文献 综合概述 统一身份认证CAS&#xff08;Central Authentication Service&#xff09;&…

golang通用后台管理系统09(系统操作日志记录)

1.日志工具类 package log/**** 日志记录 wangwei 2024-11-18 15:30*/ import ("log""os""path/filepath""time" )// 获取以当前日期命名的日志文件路径 func getLogFilePath() string {currentDate : time.Now().Format("2006-…

解决微信小程序自定义tabbar点击两次才能跳转

在每个页面的js文件下加上此代码&#xff0c;selected属性代表每一个页面的下标&#xff0c;在不同的js文件下&#xff0c;要对应不同的selected值 代码&#xff1a; onShow() { // 确保 TabBar 存在并且设置选中项 if (this.getTabBar && this.getTabBar()) { this.…

golang开源框架:go开源验证框架validator

validator 单个字段格式验证 先来一个单个字段格式的验证 目录结构 在main函数中 package mainimport "awesomeProject/validate"func main() {validate.SingleFieldValidate() }在validator.go中 package validateimport ("github.com/go-playground/val…

【Rust中的项目管理】

Rust中的项目管理 前言Package&#xff0c;Crate&#xff0c;Module &use &#xff0c;Path通过代码示例解释 Crate&#xff0c;Module &#xff0c;use&#xff0c;Path创建一个package&#xff1a;代码组织化skin.rs 中的代码struct & enum 相对路径和绝对路径引用同…