FPGA的SPI从机模块实现
一. SPI总线协议


二. FPGA的SPI从机实现
1. 首先确定模块的输出输入管脚
module myspi(nrst, clk, ncs, mosi, miso, sck);
input clk, nrst;
input ncs, mosi, sck;
output miso;
2. SCK跳变沿检测
reg[2:0] sck_edge;
always @ (posedge clk or negedge nrst)
begin
if(~nrst)
begin
sck_edge <= 3'b000;
end
else
begin
sck_edge <= {sck_edge[1:0], sck};
end
end
wire sck_riseedge, sck_falledge;
assign sck_riseedge = (sck_edge[2:1] == 2'b01); //检测到SCK由0变成1,则认为发现上跳沿
assign sck_falledge = (sck_edge[2:1] == 2'b10); //检测到SCK由1变成0,则认为发现下跳沿
3. SPI接收部分
SPI接收部分使用有限状态机:
reg[7:0] byte_received;
reg[3:0] bit_received_cnt;
reg rec_flag;
reg[1:0] rec_status; //SPI接收部分状态机
reg[7:0] rec_data;
reg[2:0] rec_flag_width; //SPI接收完成标志位脉冲宽度寄存器
always @ (posedge clk or negedge nrst) //每次sck都会接收数据,spi的顶端模块状态机决定是否取用
begin
if(~nrst)
begin
byte_received <= 8'h00;
bit_received_cnt <= 4'h0;
rec_flag <= 1'b0;
rec_status <= 2'b00;
rec_flag_width <= 3'b000;
end
else
begin
if(~ncs)
begin
case (rec_status)
2'b00: begin
if(sck_riseedge)
begin
byte_received <= {byte_received[6:0], mosi};
if(bit_received_cnt == 4'h7)
begin
bit_received_cnt <= 4'b0000;
rec_status <= 2'b01;
end
else
begin
bit_received_cnt <= bit_received_cnt+1;
end
end
end
2'b01: begin
rec_data <= byte_received;
rec_flag <= 1'b1;
if(rec_flag_width==3'b100) begin
rec_flag_width <= 3'b000;
rec_status <= 2'b11;
end
else begin
rec_flag_width <= rec_flag_width+1;
end
end
2'b11: begin
rec_flag <= 1'b0;
rec_status <= 2'b00;
end
endcase
end
end
end
这里,使用rec_flag的原因是通知另一个模块处理接收数据(后面将会提到),rec_data若在下一次数据传输完成前不做处理则会丢失。
4. SPI发送部分
reg miso;
reg sending_flag; //正在发送标志位
reg[7:0] byte_sended; //发送移位寄存器
reg[3:0] bit_sended_cnt; //SPI发送位计数器
reg[1:0] send_status; //SPI发送部分状态机
always @ (posedge clk or negedge nrst)
begin
if(~nrst)
begin
byte_sended <= 8'h00;
bit_sended_cnt <= 4'b0000;
send_status <= 2'b00;
sending_flag <= 1'b0;
end
else
begin
if(~ncs)
begin
case (send_status)
2'b00: begin
if(send_flag)
begin //锁存发送数据
send_status <= 2'b01; //2'b01;
byte_sended <= send_data;
sending_flag <= 1'b1;
miso <= send_data[7];
end
end
2'b01: begin //发送数据移入移位寄存器
if(sck_riseedge) begin
//miso <= byte_sended[7];
//byte_sended <= {byte_sended[6:0], 1'b0};
send_status <= 2'b11;
end
end
2'b11: begin //根据sck下降沿改变数据
miso <= byte_sended[7];
if(sck_falledge) ///---------------------------------------这里多移了一位
begin
//miso <= byte_sended[7];
byte_sended <= {byte_sended[6:0], 1'b0};
if(bit_sended_cnt == 4'b0111)
begin
send_status <= 2'b10;
bit_sended_cnt <= 4'b0000;
sending_flag <= 1'b0;
end
else
begin
bit_sended_cnt <= bit_sended_cnt+1;
end
end
end
2'b10: begin //数据发送完毕
send_status <= 2'b00;
//sending_flag <= 1'b0;
miso <= 1'b0;
end
endcase
end
end
end
经过实测,SCK频率低于clk频率8倍以上,通信可靠稳定,测试芯片为XC3S50-TQ144,平台为ISE,clk为25MHz。
FPGA的SPI从机模块实现的更多相关文章
- 如何让FPGA中的SPI与其他模块互动起来
在上一篇文章<FPGA的SPI从机模块实现>中,已经实现了SPI的从机模块,如何通过SPI总线与FPGA内部其他模块进行通信,是本文的主要讨论内容. 一. 新建FPGA内部DAC控制模块 ...
- FPGA构造spi时序——AD7176为例(转)
reference:https://blog.csdn.net/fzhykx/article/details/79490330 项目中用到了一种常见的低速接口(spi),于是整理了一下关于spi相关的 ...
- IIS7注册本机模块
问题描述:打开mp4文件要映射给mod_h264_streaming.dll(http://h264.code-shop.com/trac/wiki/Mod-H264-Streaming-Intern ...
- python开发学习-day09(队列、多路IO阻塞、堡垒机模块、mysql操作模块)
s12-20160312-day09 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: ...
- 基于FPGA的SPI FLASH控制器设计
1.SPI FLASH的基本特征 本文实现用FPGA来设计SPI FLASH,FLASH型号为W25Q128BV.支持3种通信方式,SPI.Dual SPI和Quad SPI.FLASH的存储单元无法 ...
- ARM与FPGA通过spi通信设计2.spi master的实现
这里主要放两个代码第一个是正常的不使用状态机的SPI主机代码:第二个是状态机SPI代码 1.不使用状态机:特权同学<深入浅出玩转FPGA>中DIY数码相框部分代码: /////////// ...
- ARM与FPGA通过spi通信设计1.spi基础知识
SPI(Serial Peripheral Interface--串行外设接口)总线系统是一种同步串行外设接口,它可以使MCU与各种外围设备以串行方式进行通信以交换信息.SPI总线可直接与各个厂家生产 ...
- 嵌入式驱动开发之dsp fpga通信接口---spi串行外围接口、emif sram接口
-----------------------------------------author:pkf ------------------------------------------------ ...
- FPGA之SPI SD卡读操作
这几天在FPGA调试与SD通信,读SD卡里的图片,之前接触32时没有去研究过SD卡,不太熟悉操作流程,在网上找了很多资料,也看了几个32开发板的资料,但大多数都讲得不是特别清楚,只能瞎操作了一番,在别 ...
随机推荐
- 《编程珠玑》第二章 aha算法
A题:给定一个最多包含40亿个随机排列的32位整数的顺序文件,找出一个不在文件中的32位整数. 1.在文件中至少存在这样一个数? 2.如果有足够的内存,如何处理? 3.如果内存不足,仅可以用文件来进行 ...
- 【转】6.4.6 将驱动编译进Linux内核进行测试
原文网址:http://www.apkbus.com/android-98520-1-1.html 前面几节都是将Linux驱动编译成模块,然后动态装载进行测试.动态装载驱动模块不会随着Android ...
- ubuntu 硬件系统信息
查看ubuntu硬件信息 1, 主板信息 .查看主板的序列号 -------------------------------------------------- #使用命令 dmidecode | ...
- Gradle+Jetty实现静态资源的热部署
本文转自http://www.cnblogs.com/huang0925/p/3302487.html --------------------------------------- 通过Gradle ...
- 安装MySQLdb-python时无法找到-lprobes_mysql处理一则
安装MySQLdb时,我已经做好了如下两点:1)配置好mysql_config 有两种方式可以做: ① 做个软连接,把mysql_config链接到/usr/local/bin下 ② ...
- Android,使用Json发送数据中,使用的Java转义字符 KanKan原创
kankan原创 与php后台发送数据的时候.要求用到这样的格式. private void sendJson(){ //初始化自己定义的handler CashHandler handler = n ...
- Android应用程序组件Content Provider应用实例
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6950440 文简要介绍了Android应用程序 ...
- SPOJ 130 - Rent your airplane and make money(dp+优化)
题意:有n列预定航班,从st时刻开始出发,飞行时间为d,花费为p,且同一时刻不能有两个航班,求最大的花费 对航班的开始时间(或结束时间)按升序排序,从后往前找到对应结束时间所在的航班位置(如按结束时间 ...
- Oracle SQL函数之转换函数
chartorowid(c1) [功能]转换varchar2类型为rowid值 [参数]c1,字符串,长度为18的字符串,字符串必须符合rowid格式 [返回]返回rowid值 [示例] SQL> ...
- ubuntu WiFi: operation not possible due to RF-kill《转载》
Some people have been experiencing WiFi problems with Ubuntu 10.10 since an update that happend just ...