前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >基于fpga的spi通信设计_协议的概念

基于fpga的spi通信设计_协议的概念

作者头像
全栈程序员站长
发布于 2022-11-19 05:43:12
发布于 2022-11-19 05:43:12
82200
代码可运行
举报
运行总次数:0
代码可运行

大家好,又见面了,我是你们的朋友全栈君。

一、SPI协议

1、SPI协议概括

SPI(Serial Peripheral Interface)——串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应用在EEPROM、FLASH、实时时钟,AD转换器以及数字信号处理器和数字信号解码器之间。SPI是一种高速,全双工,同步的通信总线,在芯片上只占用四根线(CS、MOSI、MISO、SCK),极大的节约了芯片的引脚。

2、SPI物理层

SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或者多个从设备。图1是一个主设备一个从设备的物理连接示意图。图中SCK是由主设备发送给从的时钟,该时钟决定了主设备发送数据的速率;MOSI是主设备发送给从设备的数据;MISO是从设备发送给主设备的数据;CS是片选信号,即只有片选信号为预先规定的使能信号时(高电平或者低电平)对此芯片的操作才有效。

图1 点对点通信

图2 一主多从通信

3、SPI协议层

SPI通信是四线串行通信,也就是说数据是一位一位传输的。这也即是SCK存在的意义,SCK提供通信所需的时钟脉冲,MOSI和MISO则基于此时钟进行数据传输。数据输出通过MOSI线,数据在时钟的上升沿或下降沿时改变,在紧接着的下降沿或者上升沿被读取。完成一位数据传输,输入也使用同样原理。这样,至少在8次时钟信号的改变(上升沿和下降沿为一次),就可以实现8位数据的传输。

需要注意的是,SCK信号线只由主设备控制,从设备不能控制信号线。同样,在一个基于SPI的设备中,至少要有一个主控设备。这样传输的特点:此传输方式有一个优点,与普通串行通信不同,普通的串行通信一次连续传送至少8位数据,而SPI允许数据一位一位的传送,甚至允许暂停,因为SCK时钟线由主控设备控制,当没有时钟跳变时,从设备不采集或传送数据。也就是说,主设备通过对SCK时钟线的控制可以完成对通信的控制。SPI协议还可以实现数据的交换:因为SPI的数据输入和输出线独立所以允许同时完成数据的输入和输出。不同的SPI设备的实现方式不尽相同,主要时改变和采集数据的时间不同,在时钟信号上升沿或下降沿采集有不同的定义。

SPI总线有四种工作方式(SPI0、SPI1、SPI2、SPI3),其中使用的最为广泛的是SPI0和SPI3方式。

SPI模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性和相位可以进行配置,时钟极性(CPOL)对传输协议没有重大的影响。如果CPOL=0,串行同步时钟的空闲状态为低电平;如果CPOL=1,串行同步时钟的空闲状态为高电平。时钟相位(CPHA)能够配置用于选择两种不同的传输协议之一进行数据传输。如果CPHA=0,在串行同步时钟的第一个跳变沿(上升沿或下降沿)数据被采集;如果CPHA=1,在串行同步时钟的第二个跳变沿(上升沿或下降沿)数据被采集。SPI主模块和与之通信的外设时钟相位和极性应该一致。

SPI时序图详解:SPI接口有四种不同的数据传输时序,取决于CPOL和CPHA的组合。图3中给出了这四种时序,时序与CPOL和CPHA的关系也可以从图中看出。

图3 SPI四种时序

图3中可以看出,CPOL是用来决定SCK时钟信号空闲时的电平。CPOL=0,SCK空闲时为低电平;CPOL=1,SCK空闲时为高电平。CPHA是用来决定采样输入数据MISO时刻,CPHA = 0,在第一个SCK时钟沿进行数据采样;CPHA=1,在第二个SCK时钟沿进行数据采集。(工作模式的确定:由SLAVE的工作模式确定MASTER的工作模式)。

二、SPI协议使用举例

这里通过使用SPI3来实现主机发送数据。

图4 SPI3 工作模式的主机发送数据

在SPI3模式下,CPOL = 1,CPHA = 1。SCK在空闲时为高电平,在SCK的第二个时钟沿从机进行数据的采集(只考虑主机发送情况),在SCK的第一个时钟沿发送数据MOSI。

三、使用verilog实现SPI3工作模式的时序

1、SPI3模式下工作过程如下图所示,

图5 SPI发送数据过程

接下来分析图5所示SPI发送数据的过程,首先在复位信号到来时,进入s0状态,在s0状态计数器和分频器模块加载初始值,如果发送数据开始信号spi_start有效进入s1状态,s1状态加载待发送的数据,同时计数器计数计数,分频器开始工作,如果i=1,进入s2状态,s2状态主要用来发送数据,如果i为偶数,进入s3状态,该状态是用来采集数据,由于只考虑发送,因此此模块不进行数据采集工作,如果i=15,进入s4状态,否则如果i为奇数,则进入s2状态。;在s4状态,发送最后一位数据,如果i=16,进入s5状态,此时整个SPI时序模拟完成。

2、数据路径

由图5可知,构成SPI发送时序的基本电路块包括计数器,移位寄存器和触发器模块。

图6 数据路径

图6中,左移寄存器将8位的待发送的数据spi_data转换为串行的数据mosi一位一位的发送出去,计数器用来计数发送数据的个数,触发器用来产生分频后的sck时钟信号。

3、控制信号

图7 控制信号

图7中给出了各个状态哪些控制信号应该有效,参照图5图6图7可以理清spi整个发送数据的过程。

四、 verilog描述

接下来使用verilog来描述图6所示的电路,控制信号可根据图7进行描述。

spi发送模块(该模块主要描述控制信号):

代码语言:javascript
代码运行次数:0
运行
复制
module SPI_SEND(input clk_50m,
input rst_n,
input spi_start,
input[7:0] spi_data,
output reg spi_done,
output sck,
output reg cs,
output mosi
);
reg load_c;
reg en_c;
reg load_a;
reg en_a;
reg load_b;
reg en_b;
wire [4:0]i;
parameter [4:0] s0 = 'b000001;
parameter [4:0] s1 = 'b000010;
parameter [4:0] s2 = 'b000100;
parameter [4:0] s3 = 'b001000;
parameter [4:0] s4 = 'b010000;
parameter [4:0] s5 = 'b100000;
reg [5:0]current_state = 'd0;
reg [5:0]next_state = 'd0;
always @(posedge clk_50m or negedge rst_n)
if(!rst_n)
current_state <= s0;
else
current_state <= next_state;
always @(*)
case(current_state)
s0:	begin
if(spi_start)
next_state = s1;
else
next_state = s0;
end
s1:	begin/该状态加载待发送的数据
if(i == 'd1)
next_state = s2;
else
next_state = s1;
end
s2:	begin1,3,5,7,9,11,13,15
if(i[0] == 1'b0)//
next_state = s3;
else
next_state = s2;
end
s3:	begin2,4,6,8,10,12,14,16
if(i == 'd15)
next_state = s4;
else if(i[0] == 'd1)
next_state = s2;
else
next_state = s3;
end
s4:	begin
if(i == 'd16)
next_state = s5;
else
next_state = s4;
end
s5:	begin
if(i == 'd0)
next_state = s0;
else
next_state = s5;
end
default:	next_state = s0;
endcase
always @(*)
case(current_state)
s0:	begin///空闲状态
load_c = 'd1;
en_c = 'd0;
load_a = 'd0;
en_a = 'd0;
load_b = 'd1;
en_b = 'd0;
spi_done = 'd0;
cs = 'd1;
end
s1:	begin加载待发送数据状态
load_c = 'd0;
en_c = 'd1;
load_a = 'd1;
en_a = 'd0;
load_b = 'd0;
en_b = 'd1;
spi_done = 'd0;
cs = 'd0;			
end
s2:	begin	第一个时钟沿发送数据
load_c = 'd0;
en_c = 'd1;
load_a = 'd0;
en_a = 'd1;
load_b = 'd0;
en_b = 'd1;
spi_done = 'd0;
cs = 'd0;	
end
s3:	begin第二个时钟沿采样数据
load_c = 'd0;
en_c = 'd1;
load_a = 'd0;
en_a = 'd0;
load_b = 'd0;
en_b = 'd1;
spi_done = 'd0;
cs = 'd0;
end
s4:	begin数据发送完毕
load_c = 'd0;
en_c = 'd1;
load_a = 'd0;
en_a = 'd0;
load_b = 'd0;
en_b = 'd0;
spi_done = 'd0;
cs = 'd0;			
end
s5:	begin
load_c = 'd0;
en_c = 'd0;
load_a = 'd0;
en_a = 'd0;
load_b = 'd0;
en_b = 'd0;
spi_done = 'd1;
cs = 'd1;	
end
default:	begin
load_c = 'd1;
en_c = 'd0;
load_a = 'd0;
en_a = 'd0;
load_b = 'd1;
en_b = 'd0;
spi_done = 'd0;
cs = 'd1;			
end
endcase
// Instantiate the module
count_num count_num (
.clk_50m(clk_50m), 
.load_c(load_c), 
.en_c(en_c), 
.count(i)
);
// Instantiate the module
left_shifter left_shifter (
.clk_50m(clk_50m), 
.load_a(load_a), 
.en_a(en_a), 
.spi_data_in(spi_data), 
.mosi(mosi)
);
// Instantiate the module
sck_generate sck_generate (
.clk_50m(clk_50m), 
.load_b(load_b), 
.en_b(en_b), 
.sck(sck)
);
endmodule

计数器电路描述:

代码语言:javascript
代码运行次数:0
运行
复制
module count_num(input clk_50m,
input load_c,
input en_c,
output reg[4:0]count
);
always @(posedge clk_50m)	 
if(load_c)
count <= 'd0; 
else if(en_c)	begin
if(count == 'd16)
count <= 'd0;
else
count <= count + 'd1;
end
else
count <= count;
endmodule

移位寄存器电路描述:

代码语言:javascript
代码运行次数:0
运行
复制
module left_shifter(input clk_50m,
input load_a,
input en_a,
input [7:0]spi_data_in,
output mosi
);
reg [7:0]data_reg;
always @(posedge clk_50m)
if(load_a)
data_reg <= spi_data_in;
else if(en_a)
data_reg <= {data_reg[6:0],1'b0};
else
data_reg <= data_reg;
assign mosi = data_reg[7];
endmodule

触发器电路描述:

代码语言:javascript
代码运行次数:0
运行
复制
//SPI3模式下工作,SCK空闲时为高电平
//
module sck_generate(input clk_50m,
input load_b,
input en_b,
output reg sck
);
always @(posedge clk_50m)
if(load_b)
sck <= 'd1;
else if(en_b)
sck <= ~sck;
else
sck <= 'd1;
endmodule

仿真激励文件:

代码语言:javascript
代码运行次数:0
运行
复制
module test;
// Inputs
reg clk_50m;
reg rst_n;
reg spi_start;
reg [7:0]spi_data;
// Outputs
wire spi_done;
wire sck;
wire cs;
wire mosi;
// Instantiate the Unit Under Test (UUT)
SPI_SEND uut (
.clk_50m(clk_50m), 
.rst_n(rst_n), 
.spi_start(spi_start), 
.spi_done(spi_done), 
.sck(sck), 
.cs(cs), 
.spi_data(spi_data),
.mosi(mosi)
);
initial begin
// Initialize Inputs
clk_50m = 0;
rst_n = 0;
spi_start = 0;
spi_data = 'd0;
// Wait 100 ns for global reset to finish
#100;
// Add stimulus here
end
always #5 clk_50m = ~clk_50m;
reg [4:0] count = 'd0;
always @(posedge clk_50m)	
if(count == 'd20)
count <= 'd20;
else
count <= count + 'd1;
always @(posedge clk_50m)
if(count <= 'd10)
rst_n <= 'd0;
else
rst_n <= 'd1;
reg [9:0]cnt = 'd0; 
always @(posedge clk_50m)
if(spi_done)	
cnt <= 'd0;
else if(cnt == 'd500)
cnt <= 'd500;
else
cnt <= cnt + 'd1;
always @(posedge clk_50m)
if(cnt=='d499)	begin
spi_start <= 'd1;
spi_data <= 'b10101010;
end
else	begin
spi_start <= 'd0;
spi_data <= spi_data;
end
endmodule

使用ISIM仿真结果:

图8 仿真结果

图8中待发送的数据spi_data[7:0]=10101010,由于使用的是SPI3模式(CPOL=1,CPHA=1),此模式下SCK空闲时为1,在SCK第一个时钟沿进行数据发送(即图中SCK下降沿进行数据发送),从图中波形可以看出 ,在cs为低时,mosi被一位一位的送出(高位先输出)。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/181785.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年10月15日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
超实用!Dify调用Java的3种实现方式!
在一些复杂的业务中,我们可能需要使用 Dify 调用外部程序(如 Java 程序),因为这样才能满足业务的特殊需求。
磊哥
2025/06/11
2170
超实用!Dify调用Java的3种实现方式!
实战:Dify智能体+Java=自动化运营工具!
我们在运营某个圈子的时候,可能每天都要将这个圈子的“热门新闻”发送到朋友圈或聊天群里,但依靠传统的实现手段非常耗时耗力,我们通常要先收集热门新闻,再组装要新闻内容,再根据内容设计海报等。
磊哥
2025/05/23
1430
实战:Dify智能体+Java=自动化运营工具!
探索Dify:开启大语言模型应用开发新时代
在当今科技飞速发展的时代,AI 技术的迅猛发展令人瞩目。从最初简单的图像识别,到如今复杂的自然语言处理,AI 正以前所未有的速度融入我们的生活和工作。大语言模型作为 AI 领域的重要突破,更是成为了众多开发者关注的焦点。它能够理解和生成自然语言,为智能客服、内容创作、智能问答等应用场景提供了强大的支持。
正在走向自律
2025/05/24
2670
探索Dify:开启大语言模型应用开发新时代
用Dify零代码给你的网站做AI客服!
Dify的一个“应用”指基于LLM构建的实际场景应用。通过创建应用,可将智能 AI 技术应用于特定的需求。它既包含了开发 AI 应用的工程范式,也包含了具体的交付物。
JavaEdge
2025/06/01
2030
手把手教你:Windows与Linux下Dify+DeepSeek实现ragflow构建企业知识库
在当今人工智能飞速发展的时代,大语言模型(LLMs)已经成为众多领域的核心技术驱动力。无论是在智能客服、智能写作,还是在数据分析、决策支持等方面,大语言模型都展现出了强大的能力和潜力。然而,随着数据安全和隐私保护意识的不断提高,越来越多的企业和开发者开始寻求本地化部署大语言模型的解决方案,以确保数据的安全性和可控性。
范赟鹏
2025/05/30
7910
手把手教你:Windows与Linux下Dify+DeepSeek实现ragflow构建企业知识库
使用Dify快速搭建AI Agent智能助手应用
智能助手(Agent Assistant),利用LLM的推理能力,自主对复杂的人类任务进行目标规划、任务拆解、工具调用、过程迭代,在无人类干预的情况下完成任务。
JavaEdge
2025/06/01
2760
使用Dify快速搭建AI Agent智能助手应用
RAG+AI工作流+Agent:LLM框架该如何选择,全面对比MaxKB、Dify、FastGPT、RagFlow、Anything-LLM,以及更多推荐
MaxKB = Max Knowledge Base,是一款基于 LLM 大语言模型的开源知识库问答系统,旨在成为企业的最强大脑。它能够帮助企业高效地管理知识,并提供智能问答功能。想象一下,你有一个虚拟助手,可以回答各种关于公司内部知识的问题,无论是政策、流程,还是技术文档,MaxKB 都能快速准确地给出答案:比如公司内网如何访问、如何提交视觉设计需求等等
汀丶人工智能
2024/08/05
12.4K0
RAG+AI工作流+Agent:LLM框架该如何选择,全面对比MaxKB、Dify、FastGPT、RagFlow、Anything-LLM,以及更多推荐
Spring AI 1.0 正式发布!核心内容和智能体详解
在经历了八个里程碑式的版本之后(M1~M8),Spring AI 1.0 正式版本,终于在 2025 年 5 月 20 日正式发布了,这是另一个新高度的里程碑式的版本,标志着 Spring 生态系统正式全面拥抱人工智能技术,并且意味着 Spring AI 将会给企业带来稳定 API 支持。
磊哥
2025/05/22
1.7K0
Spring AI 1.0 正式发布!核心内容和智能体详解
大型语言模型智能应用Coze、Dify、FastGPT、MaxKB 对比,选择合适自己的LLM工具
Coze、Dify、FastGPT 和 MaxKB 都是旨在帮助用户构建基于大型语言模型 (LLM) 的智能应用的平台。它们各自拥有独特的功能和侧重点,以下是对它们的简要对比:
星哥玩云
2025/04/08
9430
大型语言模型智能应用Coze、Dify、FastGPT、MaxKB 对比,选择合适自己的LLM工具
Dify学习笔记01:什么是Dify
最近接触了不少构建智能体的平台,所以就考虑是否有开源的平台可以让我深入学习一下智能体,所以就了解到了Dify。
叫我阿柒啊
2025/03/23
9410
Dify学习笔记01:什么是Dify
手把手教你用DeepSeek和Dify打造企业级AI助手
检索增强生成 (RAG) 是一种先进的技术,它通过检索相关知识来增强 AI 响应。通过为模型提供必要的上下文信息,它可以提高响应的准确性和相关性。当您上传内部文档或特定领域的材料时,AI 可以根据这些知识生成更明智的答案。
wayn
2025/03/06
7450
手把手教你用DeepSeek和Dify打造企业级AI助手
行业落地案例分享:Dify在顺丰内部实施AI智能助手
Dify是一个开源的大语言模型(LLM)应用开发平台,结合了后端即服务(BaaS)和LLMOps的概念,旨在为开发者提供便捷的工具,以快速构建和部署生成式AI应用。
福大大架构师每日一题
2025/03/17
9800
行业落地案例分享:Dify在顺丰内部实施AI智能助手
做一个免费的可视化 MCP 插件:mcp-server-chart
当前 AI 模型因数据孤岛限制而无法充分发挥潜力,MCP 方案的出现,使得 AI 应用能够安全地访问和操作本地及远程数据,为 AI 应用提供了连接万物的接口,解决了数据获取的问题。
用户1413276
2025/05/16
1.2K2
Dify 与 FastGPT 流程编排能力对比分析
在人工智能快速发展的今天,大语言模型(LLM)应用平台正在重塑各行各业的工作流程。其中,Dify 和 FastGPT 作为两款具有重要影响力的工具,凭借各自独特的流程编排能力,为开发者和使用者提供了强大的支持。流程编排的优劣直接影响着应用的效率、灵活性和可扩展性,因此深入理解这两个平台的特点对于选择合适的工具至关重要。
井九
2024/10/12
2.7K0
Dify 与 FastGPT 流程编排能力对比分析
DeepSeek 全场景集成工具指南
DeepSeek 的爆火催生了丰富的生态工具矩阵。本指南精选 22+ 个实用工具,覆盖 6 大核心场景,通过模块化选型建议帮助开发者快速构建 AI 工作流。文末附部署路线图!特点:覆盖开发/办公/科研场景、支持主流技术栈、强化行业解决方案。
徐建国
2025/02/12
1.3K0
DeepSeek 全场景集成工具指南
89.4K star!这个开源LLM应用开发平台,让你轻松构建AI工作流!
嗨,大家好,我是小华同学,关注我们获得“最新、最全、最优质”开源项目和高效工作学习方法
小华同学ai
2025/04/06
2810
89.4K star!这个开源LLM应用开发平台,让你轻松构建AI工作流!
从0到1玩转MCP:AI的「万能插头」,代码手把手教你!
在人工智能飞速发展的今天,LLM 的能力令人叹为观止,但其局限性也日益凸显 —— 它们往往被困于训练数据的「孤岛」,无法直接触及实时信息或外部工具。
机器之心
2025/04/07
4350
从0到1玩转MCP:AI的「万能插头」,代码手把手教你!
基于 RAG 和 Dify 的生产级电话销售话术生成工具
数据经济已成为当下企业主流,大多企业虽有数据中心掌管海量数据,却只能利用其中很小一部分创造实际价值。”数据富有但洞察贫乏”的状态主要源于数据访问和分析的技术门槛。
JavaEdge
2025/04/02
2780
全面解析 Model Context Protocol(MCP)及其在 LangChain 中的实践:打造真正可用的本地AI助手
随着大语言模型(LLM)的广泛应用,AI 系统在处理复杂任务时,常常需要与外部数据源和工具进行交互。然而,传统的集成方式存在接口碎片化、上下文封闭、安全隐患和复用性差等问题。​
Lethehong
2025/05/07
1.2K0
全面解析 Model Context Protocol(MCP)及其在 LangChain 中的实践:打造真正可用的本地AI助手
MCP详解及手把手实战
Model Context Protocol(MCP)是一个开放协议,旨在标准化大型语言模型(LLM)与外部数据源和工具之间的集成方式。它为 AI 应用程序提供了一种统一的接口,使得不同的系统和服务能够高效、安全地协同工作。
知识浅谈
2025/04/20
2K0
MCP详解及手把手实战
推荐阅读
相关推荐
超实用!Dify调用Java的3种实现方式!
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档