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

FPGA SPI 驱动程序

1.引言

此驱动程序已经完成很久了,花了2个星期的时间,主要是提升程序运行的效率。最近整理文件的时候又看到了,记录一下。

2.程序框架分解

module adc7254_Ctrl(input               sys_clk,    //system clkc 50Minput               reset_n,    //reset flaginput               iData_a_in,      //ADC to fpga input               iData_b_in, output               sclk_out,   //to ADC output              cs_out,     //to ADC  output              sdin,    //to ADCoutput 		 [11:0]	oData_a, //get dataoutput		 [11:0]	oData_b	//get data
);
wire clk_200M;                   //PLL驱动
AD_PLL AD_PLL_inst(.inclk0(sys_clk),.c0(Clk_200M),.c1(sclk_out)
);
wire En_conv,En_send;            //定义ADC发送和接收程序的状态切换时间
adc_test adc_test_inst(.iRst_n(reset_n),.iDclk(sclk_out),.iSend_down(Send_down),.oAdc_rst_n(adc_rst_n),.oEn_conv(En_conv),.oEn_send(En_send)
);
wire Send_down;                   //ADC指令发送部分
adc_in_send adc_in_send_inst
(.iClk_200M(Clk_200M),.iRst_n(adc_rst_n),.iDcLK(sclk_out),.iEn_send(En_send),.oSDATA(sdin),.oSend_down(Send_down)
); 
wire Conv_down;
adc_out_conv adc_out_conv_inst				//ADC数据采样部分
(.iClk_200M		( Clk_200M  	    ),.iRst_n		   ( adc_rst_n 	 ),.iEn_conv		( En_conv 		),.iDcLK			( sclk_out 		),.iData_a_in		( iData_a_in 	),.iData_b_in		( iData_b_in 	),.oData_a		( oData_a	 	),	.oData_b		( oData_b 		),.oConv_down     ( Conv_down     )
);
assign cs_out = Conv_down & Send_down;       //状态完成
endmodule

3.子任务分解

(1)状态控制程序

其主要是以空状态,写状态,读状态三个状态顺序执行的。

module adc_test(input iRst_n,input iDclk,input iSend_down,output oAdc_rst_n,output reg oEn_send,output reg oEn_conv
);reg [1:0] state;
reg [5:0] sclk_cnt;
localparam state_IDLE  = 2'd0;
localparam state_Write = 2'd1;
localparam state_Read  = 2'd3;assign oAdc_rst_n = (iRst_n & state);
always @(posedge iDclk or negedge iRst_n) beginif(!iRst_n)beginsclk_cnt <= 6'd0;state <= state_IDLE;oEn_conv = 1'd0;oEn_send = 1'd0;  end else begin   case(state)state_IDLE:beginif (sclk_cnt > 6'd30 ) beginsclk_cnt <= 6'd0;state <= state_Write;oEn_conv = 1'd0;oEn_send = 1'd1;end else beginsclk_cnt <= sclk_cnt + 1'd1;state <= state_IDLE; oEn_conv = 1'd0;oEn_send = 1'd0;   end    endstate_Write:beginif (iSend_down == 1'd1 && sclk_cnt > 6'd30 ) beginsclk_cnt <= 0;state <= state_Read;oEn_conv = 1'd1;oEn_send = 1'd0;end else beginsclk_cnt <= sclk_cnt + 1'd1;state <= state_Write;oEn_conv = 1'd0;oEn_send = 1'd1;endendstate_Read:beginstate <= state_Read;sclk_cnt <= 1'd0;oEn_conv = 1'd1;oEn_send = 1'd0;endendcaseend
endendmodule

(2)写命令程序部分

module adc_in_send(input iClk_200M,     //200Minput iRst_n,input iDcLK,    //最小T>60ns input iEn_send,	 output  oSDATA,output oSend_down     );//==================使能接收标志位en==================////一旦启动不会突然停止除非复位信号到来reg en;reg [5:0] sclk_cnt;always @(posedge iDcLK or negedge iRst_n ) beginif (!iRst_n) beginen <= 1'd0;sclk_cnt <= 6'd0;end else if ( iEn_send == 1'd1 && sclk_cnt == 6'd0 ) beginen <= 1'd1;sclk_cnt <= 6'd32;end else if ( sclk_cnt > 6'd1 ) beginen <= en;sclk_cnt <= sclk_cnt - 1'd1;end else if (oSend_down == 1'd1 && sclk_cnt == 6'd1 ) beginen <= 1'd0;sclk_cnt <= sclk_cnt - 1'd1;end else beginen <= en;sclk_cnt <= sclk_cnt;endend
//==================使能接收标志位en==================//
//==================SDATA输出操作=========================//
reg [15:0]CFR_16bit_data = 16'h8840;	//需要写入寄存器中的数据
assign oSDATA = (en > 1'd0) ? ((sclk_cnt > 6'd17) ? CFR_16bit_data[sclk_cnt-6'd17] : 0 ): 0;
//==================SDATA操作=========================//
//==================oSend_down操作======================//
assign oSend_down = (sclk_cnt > 6'd1) ? 0 : 1;
//==================oSend_down操作======================//
endmodule

(3)读数据程序部分

module adc_out_conv(input iClk_200M,     //200Minput iRst_n,input iData_a_in,input iData_b_in,  input iDcLK,    //最小T=60ns input iEn_conv,output reg [11:0] oData_a,output reg [11:0] oData_b,output  oConv_down     //T>70ns);
//下降沿接收
//==================使能接收标志位en==================//
//一旦启动不会突然停止除非复位信号到来
reg en;//接收使能标志位
reg [5:0] sclk_cnt;
always @(posedge iDcLK or negedge iRst_n ) beginif (!iRst_n) beginen <= 1'd0;sclk_cnt <= 5'd0;end else if (iEn_conv == 1'd1   &&  sclk_cnt == 4'd0) beginen <= 1'd1;sclk_cnt <= 6'd17;end else if (sclk_cnt > 4'd1) beginen <= en;sclk_cnt  <= sclk_cnt - 1'd1;end else if (oConv_down == 1'd1 &&  sclk_cnt == 4'd1)beginen <= 1'd0;sclk_cnt <= sclk_cnt - 1'd1;end else beginen <= en;sclk_cnt <= sclk_cnt;end
end
//==================使能接收标志位en==================//
//==================dclk时钟采样==================//
reg	[6:0] dclk;
always@(posedge iClk_200M or negedge iRst_n) beginif(!iRst_n) begindclk <= 7'd0;end	else if(!en) begindclk <= 7'd0;end  else begindclk <= {dclk[5:0],iDcLK};endend
//==================dclk时钟采样==================//
//==================状态切换==================//reg [1:0] state;parameter state_IDLE = 2'd0;parameter state_Read = 2'd1;parameter state_Write = 2'd2;always@(posedge iClk_200M or negedge iRst_n)  beginif(!iRst_n ) beginstate <= state_IDLE;end else if(!en) beginstate <= state_IDLE;end else if(dclk[1] == 1 & dclk[2] == 0) beginstate <= state_Read;end else if (dclk[1] == 0 & dclk[2] == 1) beginstate <= state_Write;end else beginstate <=state;end            end
//==================状态切换==================//
//==================data串行转并行==================//
reg [2:0] Data_a_in_temp,Data_b_in_temp;//保证7次采样有4次为1
reg [11:0]  Data_a_temp,Data_b_temp;
always@(posedge iClk_200M or negedge iRst_n)
beginif(!iRst_n ) beginData_a_temp    <= 12'd0;Data_b_temp    <= 12'd0;Data_a_in_temp <= 3'd0;Data_b_in_temp <= 3'd0;end else if(sclk_cnt > 6'd16)beginData_a_in_temp <= 3'd0;Data_b_in_temp <= 3'd0;Data_a_temp    <= 12'd0;Data_b_temp    <= 12'd0;end else if(sclk_cnt > 6'd3 ) beginif(state == state_Read && dclk[6] == 0 ) beginData_a_in_temp <= Data_a_in_temp + iData_a_in;Data_b_in_temp <= Data_b_in_temp + iData_b_in;Data_a_temp    <= Data_a_temp;Data_b_temp    <= Data_b_temp;end else if(state == state_Write && dclk[0]!=dclk[1])beginData_a_in_temp <= 3'd0;Data_b_in_temp <= 3'd0;Data_a_temp    <= {Data_a_temp[10:0],Data_a_in_temp[2]};Data_b_temp    <= {Data_b_temp[10:0],Data_b_in_temp[2]};end else beginData_a_in_temp <= Data_a_in_temp;Data_b_in_temp <= Data_b_in_temp;Data_a_temp    <= Data_a_temp;Data_b_temp    <= Data_b_temp;endend else beginData_a_in_temp <= Data_a_in_temp;Data_b_in_temp <= Data_b_in_temp;Data_a_temp    <= Data_a_temp;Data_b_temp    <= Data_b_temp;end
end
//==================data串行转并行==================//
//==================oConv_down操作======================//
assign oConv_down = (sclk_cnt > 6'd1) ? 0 : 1;
//==================oConv_down操作======================//
//==================数据按帧输出==================//
always@(posedge iClk_200M or negedge iRst_n)
beginif(!iRst_n )beginoData_a <= 12'd0;oData_b <= 12'd0;endelse if( oConv_down == 1'd1)beginoData_a <= Data_a_temp;oData_b <= Data_b_temp;endelsebeginoData_a <= oData_a;oData_b <= oData_b;end
end
//==================数据按帧输出==================//
endmodule

相关文章:

FPGA SPI 驱动程序

1.引言 此驱动程序已经完成很久了&#xff0c;花了2个星期的时间&#xff0c;主要是提升程序运行的效率。最近整理文件的时候又看到了&#xff0c;记录一下。 2.程序框架分解 module adc7254_Ctrl(input sys_clk, //system clkc 50Minput re…...

【实战】十一、看板页面及任务组页面开发(五) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(二十七)

文章目录 一、项目起航&#xff1a;项目初始化与配置二、React 与 Hook 应用&#xff1a;实现项目列表三、TS 应用&#xff1a;JS神助攻 - 强类型四、JWT、用户认证与异步请求五、CSS 其实很简单 - 用 CSS-in-JS 添加样式六、用户体验优化 - 加载中和错误状态处理七、Hook&…...

mac m1 docker 安装kafka和zookeeper

获取本地ip地址 ifconfig en0 192.168.0.105. 下面的ip都会使用到 1、拉取镜像 docker pull wurstmeister/zookeeper docker pull wurstmeister/kafka 2、启动容器 启动 zookeeper docker run -d --name zookeeper -p 2181:2181 映射 3、 启动 kafka 注意&#xff…...

宏观经济和风电预测误差分析(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

GO学习之 搜索引擎(ElasticSearch)

GO系列 1、GO学习之Hello World 2、GO学习之入门语法 3、GO学习之切片操作 4、GO学习之 Map 操作 5、GO学习之 结构体 操作 6、GO学习之 通道(Channel) 7、GO学习之 多线程(goroutine) 8、GO学习之 函数(Function) 9、GO学习之 接口(Interface) 10、GO学习之 网络通信(Net/Htt…...

Sentinel —实时监控

Sentinel 提供对所有资源的实时监控。如果需要实时监控&#xff0c;客户端需引入以下依赖&#xff08;以 Maven 为例&#xff09;&#xff1a; <dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-transport-simple-http</artif…...

接口优化通用方案

目录 批量异步、回调缓存预取池化并行锁粒度索引大事务海量数据 批量 批量思想&#xff1a;批量操作数据库 优化前&#xff1a; //for循环单笔入库 for(TransDetail detail:transDetailList){ insert(detail); } 优化后&#xff1a; batchInsert(transDetailList); 异步、回…...

用Visual Studio 2022的.map文件来查看C++变量在内存中的布局情况

先看几个实例 代码1 #include <iostream> int data_arr[32768]; int main() {data_arr[1] 11;std::cout<<"data_arr[1]: " << data_arr[1] << std::endl;return data_arr[1]; } 上述代码在Win10 X64&#xff0c;MSVC Release模式下编译&…...

使用代理突破浏览器IP限制

一、实验目的: 主要时了解代理服务器的概念&#xff0c;同时如何突破浏览器IP限制 二、预备知识&#xff1a; 代理服务器英文全称是Proxy Server&#xff0c;其功能就是代理网络用户去取得网络信息。形象的说&#xff1a;它是网络信息的中转站&#xff0c;特别是它具有一个cac…...

HuggingFace中的 Files and versions 如何优雅下载到本地?(Python requests,tqdm)

前言 在使用huggingface把玩各种大模型时&#xff0c;如果选择从远程加载模型&#xff0c;这个过程可能因为网络问题而非常耗时甚至直接失败&#xff0c;所以把模型、分词器等相关文件下载到本地&#xff0c;再直接从本地加载就成了不可回避的流程。 在进入具体版本的模型后&…...

三、原型模式

一、什么是原型模式 原型&#xff08;Prototype&#xff09;模式的定义如下&#xff1a;用一个已经创建的实例作为原型&#xff0c;通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里&#xff0c;原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效&a…...

transformer实现词性标注

1、self-attention 1.1、self-attention结构图 上图是 Self-Attention 的结构&#xff0c;在计算的时候需要用到矩阵 Q(查询), K(键值), V(值)。在实际中&#xff0c;Self-Attention 接收的是输入(单词的表示向量 x组成的矩阵 X) 或者上一个 Encoder block 的输出。而 Q, K, V…...

Java中异或操作和OTP算法

最近在研究加密算法&#xff0c;发现异或操作在加密算法中用途特别广&#xff0c;也特别好用。下面以Java语言为例&#xff0c;简单记录一下异或操作&#xff0c;以及在算法中的使用&#xff0c;包括常用的OTP算法。 一&#xff0c;异或操作特征 1&#xff0c; 相同出0&#…...

K8S最新版本集群部署(v1.28) + 容器引擎Docker部署(下)

温故知新 &#x1f4da;第三章 Kubernetes各组件部署&#x1f4d7;安装kubectl&#xff08;可直接跳转到安装kubeadm章节&#xff0c;直接全部安装了&#xff09;&#x1f4d5;下载kubectl安装包&#x1f4d5;执行kubectl安装&#x1f4d5;验证kubectl &#x1f4d7;安装kubead…...

女子垒球运动的发展·垒球1号位

女子垒球运动的发展 1. 女子垒球运动的起源和发展概述 女子垒球运动&#xff0c;诞生于19世纪末的美国&#xff0c;作为棒球运动的衍生品&#xff0c;经过百年的积淀&#xff0c;已在全球范围内广泛传播&#xff0c;形成了丰富的赛事文化。她的起源&#xff0c;可以追溯到19世…...

Debian 30 周年,生日快乐!

导读近日是 Debian 日&#xff0c;也是由伊恩-默多克&#xff08;Ian Murdock&#xff09;创立的 Debian GNU/Linux 通用操作系统和社区支持的 Debian 项目 30 周年纪念日。 不管你信不信&#xff0c;从已故的伊恩-默多克于 1993 年 8 月 16 日宣布成立 Debian 项目&#xff0c…...

字符串匹配的Rabin–Karp算法

leetcode-28 实现strStr() 更熟悉的字符串匹配算法可能是KMP算法, 但在Golang中,使用的是Rabin–Karp算法 一般中文译作 拉宾-卡普算法,由迈克尔拉宾与理查德卡普于1987年提出 “ 要在一段文本中找出单个模式串的一个匹配&#xff0c;此算法具有线性时间的平均复杂度&#xff0…...

傅里叶变换(FFT)笔记存档

参考博客&#xff1a;https://www.luogu.com.cn/blog/command-block/fft-xue-xi-bi-ji 目录&#xff1a; FFT引入复数相关知识单位根及其相关性质DFT过程&#xff08;难点&#xff09;DFT结论&#xff08;重要&#xff09;IDFT结论&#xff08;重要&#xff09;IDFT结论证明&…...

ELK安装、部署、调试 (二) ES的安装部署

ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎&#xff0c;基于RESTful web接口操作ES&#xff0c;也可以利用Java API。Elasticsearch是用Java开发的&#xff0c;并作为Apache许可条款下的开放源码发布&#xff0c;是当前流行的企业…...

Android 13 - Media框架(8)- MediaExtractor

上一篇我们了解了 GenericSource 需要依赖 IMediaExtractor 完成 demux 工作&#xff0c;这一篇我们就来学习 android media 框架中的第二个服务 media.extractor&#xff0c;看看 IMediaExtractor 是如何创建与工作的。 1、MediaExtractorService media.extractor 和 media.p…...

router.push(‘/‘)跳转不触发重定向

我来帮你分析为什么 router.push(/) 没有按照预期跳转到 /fenlei 路径。 首先让我查看相关的代码文件&#xff1a; router/index.js{path: /,component: Layout,redirect: /fenlei},已查看文件 index.vue 225-240 已查看文件 index.js 65-85 现在让我查看更多上下文&#xff0c…...

长脉冲激光打孔技术及其与水平集算法的融合应用

长脉冲激光打孔&#xff0c;水平集算法工业级激光打孔就像用光做的"绣花针"&#xff0c;在金属表面精准戳出微米级孔洞。但当我们把激光脉冲时间拉长到毫秒量级时&#xff0c;事情就变得有趣起来——材料不再是瞬间汽化&#xff0c;而是经历缓慢的熔融、流动、再凝固…...

Linux内核核心机制与开发实践详解

1. Linux内核概述与预备知识Linux内核作为操作系统的核心组件&#xff0c;承担着管理硬件资源、提供系统服务的关键角色。要深入理解Linux内核&#xff0c;需要具备以下基础知识储备&#xff1a;C语言能力&#xff1a;内核代码90%以上由C语言编写&#xff0c;需掌握指针操作、内…...

华为HarmonyOS PC突破:一键运行Linux工具

文章目录前言从「望Linux兴叹」到「一键真香」这三个功能&#xff0c;打工人看了会流泪开发者&#xff1a;终于不用「双机党」了生态破局的关键一步普通用户也能受益&#xff1f;当然一点冷静的观察写在最后前言 昨儿个IT圈炸锅了。 华为鸿蒙PC端应用市场悄咪咪上线了个叫融合…...

农业AI实践:OpenClaw+Qwen2.5-VL-7B识别病虫害图片

农业AI实践&#xff1a;OpenClawQwen2.5-VL-7B识别病虫害图片 1. 为什么选择OpenClaw做农业病虫害识别&#xff1f; 去年夏天&#xff0c;我在自家后院种植的番茄突然出现叶片发黄、边缘卷曲的现象。作为非专业农户&#xff0c;我翻遍植物病理学资料仍无法确诊&#xff0c;直…...

告别手动配置:用快马AI生成openclaw自动化安装与环境管理脚本

作为一名经常需要配置各种开发环境的程序员&#xff0c;我深刻体会到手动安装工具的繁琐。最近在搭建一个爬虫项目时需要用到openclaw&#xff0c;发现传统安装方式存在几个明显的效率痛点&#xff1a; 版本查找耗时&#xff1a;需要反复在官网和文档间切换&#xff0c;确认最…...

高效图像压缩:MozJPEG从入门到精通

高效图像压缩&#xff1a;MozJPEG从入门到精通 【免费下载链接】mozjpeg Improved JPEG encoder. 项目地址: https://gitcode.com/gh_mirrors/mo/mozjpeg 在数字媒体传播中&#xff0c;图像体积与加载速度始终是开发者面临的核心矛盾。传统JPEG压缩算法受限于基础编码框…...

从‘古董’协议到云存储桥梁:聊聊FTP在现代开发中的那些‘真香’应用场景

从‘古董’协议到云存储桥梁&#xff1a;聊聊FTP在现代开发中的那些‘真香’应用场景 当谈到文件传输协议时&#xff0c;很多人第一反应可能是"这不是上个世纪的技术吗&#xff1f;"。确实&#xff0c;FTP(File Transfer Protocol)诞生于1971年&#xff0c;比大多数程…...

2026届必备的十大AI辅助写作助手实测分析

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 人工智能于学术写作领域的介入&#xff0c;先是在简单的语法校对、文献检索方面&#xff0c;…...

DeepSeek-OCR-2应用实战:快速提取发票信息,财务效率翻倍

DeepSeek-OCR-2应用实战&#xff1a;快速提取发票信息&#xff0c;财务效率翻倍 1. 财务人的痛点&#xff1a;发票处理的效率黑洞 每个月末&#xff0c;财务部门总要面对这样的场景&#xff1a; 堆积如山的纸质发票需要手工录入电子发票PDF需要逐个打开复制粘贴关键信息&…...