veriolg实现spi总线

合集下载

SPI_I2S

SPI_I2S

应用笔记487利用MAX II CPLD 实现SPI 至I 2S 的接口引言本应用笔记介绍怎样使用Altera ®MAX ®II CPLD 来实现协议转换,通过串行外设接口(SPI)控制inter-IC 声音(I 2S)总线上的音频设备数据流。

I 2S 和SPI 接口I 2S 是3线半双工串行接口,常用于通过被称为I 2S 总线的3线总线来连接系统中的音频设备。

I 2S 设备和总线使用3条线:串行数据(SDA ),承载了对应于每一个音频通道的两路时分复用音频数据;串行时钟(SCK )和字选择(WS ),控制数字音频数据在I 2S 总线上不同设备之间的传输。

I 2S 系统能够处理和串行时钟分开的串行音频数据,以消除抖动。

SPI 是4线全双工串行接口,常用于连接系统内部和外部的系统处理器(主机)和外设(从机)。

SPI 利用单独的数据输出信号线(主机输出从机输入,即MOSI )和数据输入信号线(主机输入从机输出,即MISO ) 以及时钟(SCLK )和从机选择或者片选信号(CS )来进行通信。

本设计支持SPI 接口主机对其他设备的数据流控制,包括A/D 转换器、数字信号处理器、数字滤波器、音频处理器、PC 多媒体音频转换器等 I 2S 总线设备。

有的嵌入式系统并没有为音频数据通信提供I 2S 接口,但是有SPI 接口。

您可以在和这些接口相似的环境中有效地使用本设计。

利用MAX IICPLD 实现SPI 至I 2S 的接口SPI 主机的桥接接口是SPI 从机,它有四条信号线(CS , SCLK , MISO 和MOSI )。

I 2S 总线一侧接口是I 2S 主机,它有三条信号线(I2S_ SCK , I2S_SDA 和I2S_WS )。

CLK 是主机时钟,位于I 2S 主机外部。

图1所示为采用 MAX II CPLD 来实现SPI 至I 2S 接口。

2007年12月,1.0版图1.利用MAX II CPLD实现SPI至I2S接口本设计提供协议转换功能,通过SPI 接口(更常用的4线串行接口,用于连接串行外设接口和微处理器或者主机)来控制I2S 总线(带宽相对较窄的协议,用于连接系统中的数字音频设备)上音频设备的数据流。

[FPGA][Verilog][SPI]简单的读写SPI接口EEPROM-93C46程序

[FPGA][Verilog][SPI]简单的读写SPI接口EEPROM-93C46程序

Write19: begin mo <= 0; cs <= 0; end
Read0: cs <= 0; Read1://110+add(7bit) begin cs <= 1; mo <= 1; end Read2: mo <= 1; Read3: mo <= 0;//110 Read4: mo <= 0; Read5: mo <= 1; Read6: mo <= 1; Read7: mo <= 1; Read8: mo <= 1; Read9: mo <= 1; Read10: mo <= 1; Read11: begin mo <= 0; led[7] <= mi; end Read12: led[7] <= mi; Read13: led[6] <= mi; Read14: led[5] <= mi; Read15:
从开始读数据手册,到研究时序,到编写 Verilog 程序,到仿真调试时序,整整 花了有 3-4 天时间。 最后时序已经完全正确, 却读不出任何数据,经过一个晚上的排查才发现是开发 板上的 DI DO SK CS 标号标错了,泪奔~~ 本来我想写一个完整的 SPI 接口出来,想了几天都没有头绪,最后还是写了一个 最简单的写数据读数据的小程序,如果做成接口也勉强可以用。 程序的功能很简单,往地址 0111111 的位置写了 00001111 的数据,地址都还没 有做成接口,固定在程序里面的。 具体用了一个状态机共 53 个状态,每一个状态都是一个 SCK 信号的处理,当然 有分为三个大状态,分别为 ENWR、WRITE、READ 93C46 要首先写 ENWR 信号才能写入数据,具体还得研究数据手册 通过这次 93C46 和上次写 18B20 的经历, 我感觉到数据手册的确是相当的重要的, 需要仔细推敲,分析每一个时序图!下次要做 I2C 接口的 24C02,1、2、3 线就 都学过拉。 当然作为初学者程序是写的那是超级的烂,欢迎拍砖

SPI总线的原理与Verilog设计实现

SPI总线的原理与Verilog设计实现

SPI总线的原理与Verilog设计实现一、软件平台与(硬件)平台软件平台:1、(操作系统):Windows-8.12、开发套件:ISE14.73、(仿真)工具:Model(Sim)-10.4-SE硬件平台:1、(FPGA)型号:Xilinx公司的XC6SLX45-2CSG3242、Flash型号:WinBond公司的W25Q128BV Qual SPI Flash存储器二、原理介绍SPI(Serial Peripheral Interface,串行外围设备(接口)),是Motorola公司提出的一种同步串行(接口技术),是一种高速、全双工、同步(通信)总线,在(芯片)中只占用四根管脚用来控制及数据传输,广泛用于EEP(ROM)、Flash、RTC((实时时钟))、(ADC)((数模转换器))、(DSP)((数字信号)(处理器))以及数字信号解码器上。

SPI通信的速度很容易达到好几兆bps,所以可以用SPI总线传输一些未压缩的(音频)以及压缩的(视频)。

下图是只有2个chip利用SPI总线进行通信的结构图时序图如下所示:从上面的时序图可以很清楚的看出,当ROM的地址加1以后,ROM的数据是滞后了一个时钟才输出的,而ROM数据输出的时刻(这个时候ROM的输出数据并没有稳定)刚好是spi_module模块发送下个数据最高位的时刻,那么这就有可能导致数据发送错误,从以上时序图就可以看出8’h33和8’h24两个数据正确发送了,但是8’h98这个数据就发送错误了。

为了解决这个问题,其实只需要把spi_module模块的发送状态机在加一个冗余状态就行了,spi_module模块的发送状态机一共有0~15总共16个状态,那么我在加一个冗余状态,这个状态执行的操作和最后那个状态执行的操作完全相同,这样就预留了一个时钟的时间用来预先设置好要发送的数据,这样的效果是发送数据的最后一个bit实际上占用了3个时钟周期,其中第一个时钟周期把O_tx_done 拉高,后两个时钟周期把O_tx_done拉低。

一种通用SPI总线接口的FPGA设计与实现

一种通用SPI总线接口的FPGA设计与实现
GA.EDN,v 48,n 27,Dec 11,2003,p 14
【21朱海君,敬岚,陆军.基于MSCl2lO单片机的串口通讯设计. 微计算机信息,2004(4) [3】左东广,魏瑞轩.SPl接口技术与应用.工业控制计算机200l狮4) 作者简介:华卓立(1980一),男(汉族),华南理工大学微电子专业 2005级研究生,研究方向为专用集成电路设计与系统集成。 Biogmphy:HuA Zhuo—li(1980一),Gentleman(Han),YuDu Jian球i
3设计原构。
1.典型应用 sPI接口的典型应用如图1所示。微处理器与从设备通过 发送指令的方式实现双向数据传输。

图1 2.模块设计
根据sPI总线的原理,可分为以下功能模块:通信模块,控制模 块月F0模块(缓冲存储器),配置漠块崩[据收发模块,如图2所示。
2 SPI总线原理
sPI总线由四根线组成:串行时钟线(scK),主机输出从机输 入线(M0sI),主机输入从机输出线(MIsO),还有一根是从机选择 线(Ss),它们在与总线相连的各个设备之问传送信息。
sPI总线中所有的数据传输由串行时钟scK来进行同步, 每个时钟脉冲传送l比特数据。scK由主机产生,是从机的一个 输入。时钟的相位(cPHA)与极性(cPOL)可以用来控制数据的传 输。cPOL=“0”表示scK的静止状态为低电平,cPoL=“1”则表 示scK静止状态为高电平。时钟相位(cPHA)可以用来选择两 种不同的数据传输模式。如果cPHA=“0”,数据在信号ss声明 华卓立:研究生
3.期刊论文 阮航 浅谈FPGA的SPI接口控制音频芯片 -仪器仪表用户2008,15(3)
本篇论文主要完成的任务是通过FPGA的SPI接口控制音频codec芯片.然后,基于Cyclone EP1C6Q240C8实验箱进行了软件下载和调试,实验结果表明了 系统设计方案的正确性和可行性.

FPGA实现SPI

FPGA实现SPI

FPGA实现SPIFPGA(Field Programmable Gate Array)是一种可编程逻辑器件,可以实现不同的数字电路功能。

SPI(Serial Peripheral Interface)是一种同步串行通信协议,常用于连接外围设备和主控制器。

在本文中,将介绍如何使用FPGA实现SPI。

1.确定硬件资源:首先,需要确定FPGA中可用的IO资源。

SPI需要至少4个IO口,分别是主设备的时钟引脚(SCK),主设备输出的数据引脚(MOSI),主设备输入的数据引脚(MISO)和片选引脚(SS)。

根据所用的FPGA型号,可以查找对应的引脚定义。

2.确定SPI时序:SPI的时序是非常重要的,不同设备可能有不同的时序规范。

一般情况下,SPI的时序包括时钟下降沿数据采样、时钟上升沿数据输出等。

SPI的时序图可以在设备的数据手册中找到。

3. 编写SPI控制器:SPI控制器可以用硬件描述语言如VHDL或Verilog编写。

控制器的功能包括生成时钟、控制数据的发送和接收、以及处理片选信号。

a.时钟生成:SPI通信需要一个时钟信号来驱动数据的传输。

可以通过计数器模块来生成控制器的时钟信号。

计数器的频率一般是SPI时钟频率的若干倍。

b. 数据发送:对于主设备(Master),要发送数据给外设,可以使用移位寄存器(Shift Register)来存储要发送的数据。

可以使用计数器生成移位寄存器的时钟信号,通过串行输入数据,并在时钟的上升沿时将数据发送到MOSI引脚。

c.数据接收:对于主设备,要接收外设发送的数据,可以使用另一个移位寄存器来接收MISO引脚传输的数据。

可以使用计数器生成移位寄存器的时钟信号,通过MISO引脚接收数据,并在时钟的下降沿时将数据存储到接收寄存器。

d.片选控制:SPI通信需要一个片选信号来选择要与主设备通信的外设。

可以通过一个时序控制器实现片选信号的生成。

在与一些外设通信时,使能片选信号,否则禁用片选信号。

SPI协议的Verilog 实现

SPI协议的Verilog 实现

// //接收数据存入 out_data
6
begin case(addr) 1'b0: begin in_buffer = in_data; busy = 1'b1; end 转入工作状态 1'b1: begin busy = 1'b0;end endcase end end else begin if(cs) begin clkcount = clkcount + 1'b1; if(clkcount >= 8'b10) // 控制 SCK 周期 begin clkcount = 0; if((count % 2) == 0) //待发数据存入缓存区,
DataPort[5]-DataPort[0] : busy、sdo 、addr、cs、wr、rd DataPort[21]-DataPort[14] :待发送 8bit 数据 DataPort[13]-DataPort[6] : 接收的 8bit 数据
3
� 总结
完成时间:12.4--12.12 前期:该阶段主要是熟悉 SPI 工作原理,进一步掌握和认识 SPI 通信协议。Chipscore 的使 用之前未曾接触, 在这一阶段, 我先通过简单编程结合开发板抓取数据进行分析达到 对其的基本掌握。 中期:在熟悉 SPI 的工作原理之后,开始尝试编写代码。写了两三次代码,效果均不理想, 很多问题在编写代码的时候没有考虑清楚,导致到了仿真阶段结果与预期有所差距, 且代码冗长复杂。参考了一些资料,效果也不是很好,特别是数据传输暂停部分, 很 多都省略了。不过借鉴别人写的代码也让我收获了不少编写的经验,有些情况下, 运 用不同的逻辑思维可以让代码更简洁、 更具有健壮性。 当然期间也遇到了一些自己无 法解决的问题,非常感谢福星学长耐心的指导,让我学到了不少知识和经验。 后期:该阶段主要是对代码进行再修改、波形仿真以及抓数据调试。 问题及分析: 小问题遇到不少,不过大多都通过 error 的提示,或者上网搜索,找到了问题的原因, 并予以解决。也有软件上的原因,比如:第一次装 ISE 的时候可能没有安装好,上板调试的 时候,cable 不能识别。经过测试分析发现 ISE 里的 drive 没有装上。考虑到这样一个问题的 出现可能还会附带有一些软件上的漏洞,重装了一遍 ISE,问题解决。 使用 chipscope 的时候,芯片配置不对连接失败,查阅该电路板的资料,重新配置,问 题解决。在 chipscope 里面有些触发信号找不到,经分析是被优化了,通过简单修改代码避 免它被优化后,问题解决。运行 chipscope 后发现 waveform 始终没反应,经过一番分析, 认 为时钟线的引脚配置有问题,重换一个时钟信号线 I/O 引脚,问题解决。解决后发现抓取的 波形没有明显的高低跳变,经分析可能是参考时钟选取不对,重选后问题解决。

I2C verilog (非常详细的i2c学习心得)

I2C verilog (非常详细的i2c学习心得)

图 5. AT24C02/4/8/16 读指定地址存储单元的数据帧格式
首先是一堆输入输出、寄存器的定义,我们读程序的时候大可先不看这些,等到后面有 需要的时候再回过头来看这些定义, 这里需要注意的是 SDA 与 DATA 的类型, 都是 inout 型, SDA 我们很容易理解,因为主机和从机都会给 SDA 线上发信号,比如字节写入格式时,主机 先给 SDA 发了 1 个 8 位数据,然后作为应答位,从机要把 SDA 拉低,表示我已经接受到你 的信号了,在应答位时主机是不能操作 SDA 线的。然而 DATA 设定为 inout 型,我们可以看 到图 2,其实在字节写入格式时,DATA 是 signal 模块传输给 EEPROM_WR 模块,作为要写入 的数据。 而在字节读取格式时, EEPROM_WR 通过 SDA 从 EEPROM 中读取数据, 其实跟 DATA 是没有关系的,这里可以只将 DATA 设定为 input 型,设定为 inout 型是因为后续的程序会将 EEPROM_WR 读取到的数据发给 signal,与 signal 当初发送的数据进行比较,检验通信是否 正确。如果将比较数据这程序操作放在 EEPROM_WR 模块中,就可以将 DATA 设为 input。 提到 inout 类型,还得再多补充两句,inout,顾名思义,双向口既能作为输入又能作为 输出,可以节省管脚,在具体实现上一般是用三态门来实现,图 6 就是用三态门实现的 sda 总线的示意图。
单,使用发送数据线 TXD 和接收数据线 RXD 来传送数据,接收和发送可以单独进行也可以 同时进行。它传送数据的格式有严格的规定,每个数据以相同的位串形式传送,每个串行数 据由起始位,数据位,奇偶校验位和停止位组成。从起始位到停止位为一个字符的完整通信 格式。SPI 情况就相对多一些,根据时钟极性(CPOL)和时钟相位(CPHA)两个参数的不同有四 种基本情况,传送数据的格式与 UART 差不多。而 I2C 总线的协议要比 UART 和 SPI 复杂,能 掌握 I2C,也就能掌握 UART 和 SPI。言归正传,回到我们的 I2C 设计实例。 第一步首先了解,这个 I2C 实例的功能。 这个实例实现了通过 I2C 总线对 EEPROM 写入数据, 再将写入 EEPROM 中的数据读取出 来的一个过程。实例的重点在于对 I2C 总线协议时序的掌握,即用 I2C 总线要求的格式将数 据写入到 EEPROM 中,再读取出来。 什么是 EEPROM?EEPROM (Electrically Erasable Programmable Read‐Only Memory),电可 擦可编程只读存储器, 一种掉电后数据不丢失的存储芯片。 EEPROM 可以在电脑上或专用设 备上擦除已有信息,重新编程。所以,EEPROM 是可以写入数据也可以读取数据的,并且 EEPROM 掉电数据并不会丢失,在后面将程序烧写到开发板的过程中可以验证这一点。 第二步,简单地了解一下这个实例的各个模块。

基于UVM的SPI接口IP核的设计与验证

基于UVM的SPI接口IP核的设计与验证

基于UVM的SPI接口IP核的设计与验证SPI(Serial Peripheral Interface)是一种常用的串行外设接口,广泛应用于数字系统中。

为了实现SPI接口的功能,需要设计和验证相应的IP核。

本文将介绍基于UVM(Universal Verification Methodology)的SPI接口IP核的设计与验证。

首先,我们需要了解SPI接口的基本原理。

SPI接口由一个主设备和一个或多个从设备组成。

主设备通过时钟信号控制数据的传输,同时使用片选信号选择从设备。

主设备通过一个数据线发送数据,并通过另一个数据线接收从设备返回的数据。

SPI接口的主要特点是数据传输速度快、灵活性高,适用于多种外设连接。

在设计SPI接口的IP核时,我们需要考虑以下几个方面。

首先,IP核需要支持不同的SPI模式,包括不同的时钟极性和相位设置。

其次,IP核需要能够处理不同的数据位宽,并支持全双工和半双工传输模式。

此外,IP核还需要支持多个从设备的片选信号,并能够处理中断请求。

为了验证SPI接口的IP核,我们采用了UVM方法。

UVM 是一种基于SystemVerilog的验证方法学,提供了一套丰富的验证库和方法。

我们可以利用UVM提供的功能,建立一个完整的验证环境,并编写验证测试用例。

在验证SPI接口的IP核时,我们需要分别验证其主设备和从设备的功能。

对于主设备,我们可以编写测试用例来验证其发送数据的正确性、时序和时钟控制的准确性。

对于从设备,我们可以编写测试用例来验证其接收数据的正确性和片选信号的选择准确性。

通过使用UVM方法,我们可以模拟SPI接口的IP核,并在仿真平台上验证其功能和性能。

通过编写一系列的测试用例,我们可以确保IP核在不同的工作场景下都能正常工作。

综上所述,本文介绍了基于UVM的SPI接口IP核的设计与验证。

通过设计一个支持多种模式、不同数据位宽和多个从设备的IP核,并利用UVM方法进行验证,我们可以确保IP核在实际应用中的正确性和可靠性。

【CPLD+Verilog】CPLD实现SPI接口

【CPLD+Verilog】CPLD实现SPI接口

CPLD 实现SPI 接口1 实现原理CPLD 实现SPI 接口模块,通过对寄存器的操作,实现SPI 接口功能,对外部SPI 设备进行访问。

CPLD 内部SPI 模块逻辑框图如下所示。

CLK_DIVRX_SHIFT_REGSTATUS LOGICspi_clkspi_cs spi_dospi_tx_data_we_pulsereset_n spi_tx_data spi_rx_data spi_clk_div spi_rx_data_rd_pulsespi_dispi_tx_data_we_busy spi_rx_data_rd_ready spi_data_tx_we_overflow spi_data_rx_rd_nop spi_data_rx_rd_overtime cpld_clkCONTROL LOGICCOUNT LOGIC通过对主时钟分频,得到的SPI 接口时钟,其分频值可通过spi_clk_div 值设定,最小为6分频,当设置分频值低于6分频时,默认6分频。

SPI 接口的片选信号spi_cs 在写数据传输寄存器spi_tx_data 时,通过自动产生写脉冲spi_tx_data_we_pulse ,逻辑综合生成。

spi_rx_data_rd_pulse 在读取接收数据spi_rx_data 的数据时自动产生。

spi_di 和spi_do 分别由数据移位寄存器通过数据移位产生和接收。

spi_clk 由内部分频时钟和传输状态逻辑综合输出,在有数据时输出,无数据时保持高电平。

状态逻辑spi_tx_data_we_busy 信号分别表示数据正在传输,无法写入spi_tx_data 寄存器; spi_rx_data_rd_ready 信号表示数据接收完成,可读取spi_rx_data 寄存器的值。

错误状态逻辑spi_data_tx_we_overflow 信号表示在spi_tx_data 寄存器中写入了待传输值后,还未传输就又写入新的传输数据,表示写数据溢出。

基于APB总线的SPI接口设计与实现

基于APB总线的SPI接口设计与实现

基于APB总线的SPI接口设计与实现刘梦影;王芬芬【摘要】基于高性能外设总线(APB,Advance Peripheral Bus)接口,设计了一个支持多样化工作模式和通信格式的SPI接口.为实现高速通信,该SPI采用一个复用移位寄存器.用硬件描述语言Verilog HDL设计并实现了SPI模块.仿真结果表明,该SPI接口能够支持多种工作模式和通信方式,同时确保数据传输有效.【期刊名称】《电子与封装》【年(卷),期】2018(018)005【总页数】5页(P28-32)【关键词】SPI;APB总线;多样化;复用【作者】刘梦影;王芬芬【作者单位】中国电子科技集团公司第五十八研究所,江苏无锡214072;中国电子科技集团公司第五十八研究所,江苏无锡214072【正文语种】中文【中图分类】TN4021 引言现如今,数字技术高速发展,许多芯片或作为核心器件用于数据交换,具有承上启下的数据交换枢纽作用,或用于集成电路之间进行数据存储和显示等[1]。

为适应通信环境和高速的通信速率要求,通常使用多个微处理器完成信号的收发处理,因此需要一种高效的数据总线快速有效地完成它们之间大量的数据交换。

因此,设计一个高效快速的通信接口是至关重要的[2]。

串行外围设备接口SPI总线技术是Motorola公司推出的一种微处理器、微控制器以及外设间的串行数据接口标准[3],主要用于扩展外设和进行数据交换[4]。

SPI接口连线简单,配置灵活,传输效率高[5],因此应用广泛,很多器件如E2PROM、FLASH、实时时钟、A/D转换器等都用到了SPI接口[6]。

郭艾华[7]设计了一种可灵活配置为主/从设备,设置传输速率,支持DMA功能并适用于多种时钟模式的SPI协议IP核,但从机片选信号只可由主机输出,存在一定的局限性。

李琦、贺明等[8]以微处理器S3C2440和嵌入式Linux操作系统组成的嵌入式系统作为开发平台,设计了一款基于ARM嵌入式系统的SPI驱动程序,该设计存在两组8位移位寄存器,支持传输8位数据,但未有效地运用硬件资源。

SPI总线接口的verilog的实现

SPI总线接口的verilog的实现

十二SPI总线接口的verilog的实现1.实验目的项目中使用的许多器件需要SPI接口进行配置,比如PLL:ADF4350,AD:AD9627,VGA:AD8372等,本实验根据SPI协议,编写了一个简单的SPI读写程序,可以进行32位数据的读写,可以设置SPI SCLK相对于主时钟的分频比。

2.实验原理SPI总线系统是一种同步串行外设接口,它可以使MCU与各种外围设备以串行方式进行通信以交换信息。

外围设置FLASHRAM、网络控制器、LCD显示驱动器、A/D转换器和MCU等。

SPI总线系统可直接与各个厂家生产的多种标准外围器件直接接口,该接口一般使用4条线:串行时钟线(SCK)、主机输入/从机输出数据线MISO、主机输出/从机输入数据线MOST和低电平有效的从机选择线SS(有的SPI接口芯片带有中断信号线INT、有的SPI接口芯片没有主机输出/从机输入数据线MOSI)。

SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。

也是所有基于SPI的设备共有的,它们是SDI(数据输入),SDO(数据输出),SCK(时钟),CS(片选)。

(1)MOSI –主设备数据输出,从设备数据输入(2)MISO –主设备数据输入,从设备数据输出(3)SCLK –时钟信号,由主设备产生(4)CS –从设备使能信号,由主设备控制其中CS是控制芯片是否被选中的,也就是说只有片选信号为预先规定的使能信号时(高电位或低电位),对此芯片的操作才有效。

这就允许在同一总线上连接多个SPI设备成为可能。

接下来就是负责通讯的3根线了。

通讯是通过数据交换完成的,这里先要知道SPI是串行通讯协议,也就是说数据是一位一位的传输的。

这就是SCK时钟线存在的原因,由SCK 提供时钟脉冲,SDI,SDO则基于此脉冲完成数据传输。

数据输出通过 SDO线,数据在时钟上升沿或下降沿时改变,在紧接着的下降沿或上升沿被读取。

Verilog的spi总线

Verilog的spi总线

SPI串行总线接口的Verilog实现摘要:集成电路设计越来越向系统级的方向发展,并且越来越强调模块化的设计。

SPI(Serial Peripheral Bus)总线是Motorola公司提出的一个同步串行外设接口,容许CPU 与各种外围接口器件以串行方式进行通信、交换信息。

本文简述了SPI总线的特点,介绍了其4条信号线,SPI串行总线接口的典型应用。

重点描述了SPI串行总线接口在一款802.11b芯片中的位置,及该接口作为基带和射频的通讯接口所完成的功能,并给出了用硬件描述语言Verilog HDL 实现该接口的部分程序。

该实现已经在Modelsim 中完成了仿真, 并经过了FPGA 验证, 最后给出了仿真和验证的结果。

在SOC设计中,利用EDA 工具设计芯片实现系统功能已经成为支撑电子设计的通用平台.并逐步向支持系统级的设计方向发展。

而且,在设计过程中,越来越强调模块化设计。

SPI总线是Motorola公司提出的一个同步串行外设接口,具有接口线少、通讯效率高等特点。

本文给出的是利用Verilog HDL实现的SPI总线模块,该模块是802.11b无线局域网芯片中一个子模块,该模块完成了芯片中基带(base band)与RF的通讯工作.1 SPI总线接口概述SPI(Serial Parallel Bus)总线是Motorola公司提出的一个同步串行外设接口,允许CPU 与各种外围接口器件(包括模/数转换器、数/模转换器、液晶显示驱动器等)以串行方式进行通信、交换信息。

他使用4条线:串行时钟线(SCK)、主机输入/从机输出线(MISO)、主机输出/从机输入线(MOSI)、低电平有效的使能信号线(CS)。

这样,仅需3~4根数据线和控制线即可扩展具有SPI接口的各种I/O 器件其典型结构如图1所示。

SPI总线具有以下特点:(1)连线较少,简化电路设计。

并行总线扩展方法通常需要8根数据线、8~16根地址线、2~3根控制线。

一种可复用的SPI接口设计与实现

一种可复用的SPI接口设计与实现

一种可复用的SPI接口设计与实现朱道山【摘要】Based on the investigation of SPI interface standard,a new design scheme of reusable SPI interface is proposed,and with the new design of SPI interface the disadvantage is solved that the communication couldn't be triggered by the slave module and the transmission takes no feedback when using general SPI protocol.And with the adoption of Johnson counter for clock frequency dividing,the validity of data transmission in NAK mechanism is guaranteed.This proposed scheme,implemented on FPGA,is verified in Qusetasim simulation environment.Experimental results indicate that this proposed scheme could meet the requirement of high-rate data transmission,and for its reliability in performance,could also serve as a new IP core for data communication of between MPUs.%基于SPI接口标准的研究,提出一种新型的可复用SPI接口设计方案.通过重新设计SPI接口,解决了SPI无法由从设备发起通信以及传输无反馈的不足.时钟分频采用约翰逊计数器实现,保证了SPI在没有应答机制的情况下数据传输的正确性.该设计基于FPGA实现,并在Qusetasim仿真环境下验证通过.设计满足sPI接口串行数据高速传输的要求,性能可靠,可作为独立的IP核应用于微处理器之间的数据传输.【期刊名称】《通信技术》【年(卷),期】2017(050)002【总页数】4页(P389-392)【关键词】SPI接口;FPGA;复用;IP核;约翰逊计数器【作者】朱道山【作者单位】中国西南电子技术研究所,四川成都610036【正文语种】中文【中图分类】TN911.7近年来,随着通信系统的发展,为了适应任务复杂性的要求,往往使用多个微处理器完成对接收信号的处理,这就需要一种高效的数据总线来完成它们之间的大量数据传输。

Verilog--SPI协议

Verilog--SPI协议

Verilog--SPI协议Verilog -- SPI协议简介SPI是⼀种全双⼯通信,并且是⼀种同步传输⽅式(slave的接收clk需要master给出)SPI总线是⼀种4线总线,因其硬件功能很强,所以与SPI有关的软件就相当简单,使中央处理器(Central Processing Unit,CPU)有更多的时间处理其他事务。

正是因为这种简单易⽤的特性,越来越多的芯⽚集成了这种通信协议,⽐如AT91RM9200。

SPI是⼀种⾼速、⾼效率的串⾏接⼝技术。

通常由⼀个主模块和⼀个或多个从模块组成,主模块选择⼀个从模块进⾏同步通信,从⽽完成数据的交换。

SPI是⼀个环形结构,通信时需要⾄少4根线(事实上在单向传输时3根线也可以)。

SPI的通信原理很简单,它以主从⽅式⼯作,这种模式通常有⼀个主设备和⼀个或多个从设备,需要⾄少4根线,事实上3根也可以(单向传输时)。

也是所有基于SPI的设备共有的,它们是MISO(主设备数据输⼊)、MOSI(主设备数据输出)、SCLK(时钟)、CS(⽚选)。

(1)MISO– Master Input Slave Output,主设备数据输⼊,从设备数据输出;(2)MOSI– Master Output Slave Input,主设备数据输出,从设备数据输⼊;(3)SCLK – Serial Clock,时钟信号,由主设备产⽣;(4)CS – Chip Select,从设备使能信号,由主设备控制。

其中,CS是从芯⽚是否被主芯⽚选中的控制信号,也就是说只有⽚选信号为预先规定的使能信号时(⾼电位或低电位),主芯⽚对此从芯⽚的操作才有效。

这就使在同⼀条总线上连接多个SPI设备成为可能。

(以上来⾃百度百科)SPI最⼤传输速率SPI是⼀种事实标准,由Motorola开发,并没有⼀个官⽅标准。

已知的有的器件SPI已达到50Mbps。

具体到产品中SPI的速率主要看主从器件SPI控制器的性能限制。

板级通信总线之SPI及其Verilog实现

板级通信总线之SPI及其Verilog实现

板级通信总线之SPI及其Verilog实现打算写⼏篇专题,系统总结下常⽤的⽚上总线、现场总线,就先从最常⽤的SPI开始吧。

1. SPI是⼲什么的?除了SPI还有那些其它电路板及的通讯总线?有何差别?相信接触过MCU的同学对SPI都不陌⽣,详细定义就不罗嗦了。

SPI常⽤的场合包括ADC读写、存储芯⽚读写、MCU间通讯等等。

可以⼀主多从(通过⽚选来选择Slave),也可以做成菊花链等等形式的拓扑。

与SPI类似的总线还有IIC、UART等,甚⾄还有很多单根线的总线,原理都是基于简单的串⾏通信,区别在于收发时序和连接拓扑。

要熟练使⽤这些总线,关键在于理解其时序图,在此基础上创造各种变种的总线形式也不是难事(当然为了设计的通⽤性不建议这么做)。

以下维基百科的SPI词条介绍⾮常全⾯,推荐阅读。

2. SPI是什么样的?在此借⽤⼀张维基百科上的图,SPI通常有4根线,SS⽤于选定当前通信的slave,SCLK为通信的基准时钟,采样/发送都在时钟边沿执⾏,MOSI、MISO为串⾏的数据线。

以下是⼀个典型的SPI时序图,Master和Slave均在时钟上升沿采样,下降沿发送数据。

数据从最⾼位(MSB)开始发送。

需要注意图中所有的时序关系都要被满⾜,包括CS下降沿到第1个时钟上升沿间隔(t sclk_su)、数据的建⽴时间(t SU)、保持时间(t HD)等等。

通常这些参数由具体的器件决定,如果不满⾜则有通信失败的风险。

3. 如何使⽤SPI?SPI有哪⼏种配置模式(相位、极性)?根据SPI时钟信号的空闲状态、是上升沿采样还是下降沿采样,SPI有四种模式。

CPOL=0表⽰时钟空闲时为低电平,反之为⾼电平;CPHA=0表⽰时钟信号第⼀个边沿是采样边沿,反之表⽰第2个边沿是采样边沿。

对于带SPI接⼝的MCU⽽⾔,通常可由软件配置CPOL(Clock Polarity)、CPHA(Clock Phase),以适应和不同类型器件的通信。

FPGA实现SPI

FPGA实现SPI

FPGA实现SPIFPGA(Field-Programmable Gate Array)是一种可编程的逻辑芯片,可以通过编程实现不同的功能。

SPI(Serial Peripheral Interface)是一种通信协议,可以在芯片之间进行数据传输。

要在FPGA上实现SPI,首先需要了解SPI的基本原理和通信方式。

SPI使用主从模式,由一个主设备控制多个从设备。

主设备通过时钟信号(SCLK)控制数据的传输,同时使用一个片选信号(SS)来选择目标从设备。

主设备通过MOSI(Master Out Serial In)线将数据发送给从设备,从设备则通过MISO(Master In Serial Out)线将数据回传给主设备。

为了实现SPI通信,需要在FPGA内部设计SPI控制器。

SPI控制器的主要功能包括时钟生成、数据发送和接收、片选信号控制等。

在FPGA中,可以使用可编程逻辑单元(PL)和可编程输入/输出单元(IOB)来实现SPI控制器。

首先,需要使用PL来生成时钟信号。

可以使用计数器和状态机来实现时钟分频和时序控制。

通过控制计数器以及时钟信号的边沿来生成SPI所需的SCLK信号。

接下来,需要使用IOB来进行数据的发送和接收。

可以将MOSI线和MISO线分别连接到适当的IOB引脚。

对于数据的发送,可以通过内部存储器或寄存器来存储要发送的数据,并通过控制逻辑将数据发送到MOSI线上。

对于数据的接收,从MISO线上获取到的数据需要经过逻辑电平转换,并存储或传递给其他组件。

最后,需要使用逻辑电平转换器来生成SPI的片选信号。

可以使用门电路或者专门的逻辑转换芯片来控制片选信号的逻辑电平。

通常情况下,只有在特定的片选信号处于逻辑低电平时,相关的从设备才能接收和响应数据。

在设计完成后,可以使用硬件描述语言(HDL)如Verilog或VHDL来描述SPI控制器,并使用FPGA开发工具进行综合、布局和编程。

在开发工具中,可以了解到FPGA的资源占用情况,时序约束和时钟分频等设置,以及进行仿真和调试。

Verilog实现FPGA作为从机与STM32进行SPI协议通信

Verilog实现FPGA作为从机与STM32进行SPI协议通信

FPGA作为从机与STM32进行SPI协议通信Verilog实现一.SPI协议简要介绍SPI,是英语Serial Peripheral Interface的缩写,顾名思义就是串行外围设备接口。

SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。

SPI总线是Motorola公司推出的三线同步接口,同步串行3线方式进行通信:一条时钟线SCK,一条数据输入线MOSI,一条数据输出线MISO;用于 CPU 与各种外围器件进行全双工、同步串行通讯。

SPI主要特点有:可以同时发出和接收串行数据;可以当作主机或从机工作;提供频率可编程时钟;发送结束中断标志;写冲突保护;总线竞争保护等。

SPI总线有四种工作方式(SP0, SP1, SP2, SP3),其中使用的最为广泛的是SPI0和SPI3方式。

SPI模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性和相位可以进行配置,时钟极性(CPOL)对传输协议没有重大的影响。

如果CPOL=0,串行同步时钟的空闲状态为低电平;如果CPOL=1,串行同步时钟的空闲状态为高电平。

时钟相位(CPHA)能够配置用于选择两种不同的传输协议之一进行数据传输。

如果 CPHA=0,在串行同步时钟的第一个跳变沿(上升或下降)数据被采样;如果CPHA=1,在串行同步时钟的第二个跳变沿(上升或下降)数据被采样。

SPI主模块和与之通信的外设时钟相位和极性应该一致。

以下是SPI时序图:主要讲解一下广泛使用的两种方式设置:SPI0方式:CPOL=0,CPHA=0;SCK空闲状态为低电平,第一个跳变沿(上升沿)采样数据,无论对Master还是Slaver都是如此。

SPI3方式:CPOL=1,CPHA=1;SCK空闲状态为高电平,第二个跳变沿(上升沿采样数据,无论对Master还是Slaver都是如此。

基于SPI 总线FLASH 时序控制的FPGA 实现

基于SPI 总线FLASH 时序控制的FPGA 实现

基于SPI 总线FLASH 时序控制的FPGA 实现薛宏亮 合肥工业大学仪器科学与光电工程学院 安徽合肥 2300090 引言FLASH 存储器作为一类新型存储器,因具有功耗低、速度快、容量大、成本低和非易失性等优点在各种嵌入式系统中得到越来越广泛地应用。

随着技术的发展和需求的提高,数据的处理日益向着高速化的趋势发展,此时,通过普通的处理器来读取FLASH 中的数据已经达不到要求。

而利用FPGA 控制FLASH 存储器的读取可以达到较高的处理速度,所以在高速数据处理领域,利用FPGA 实现FLASH 存储系统控制的工程应用相当广泛。

本文以winbond 公司的SPI 接口FLAH 芯片W25Q128BV 和Altera 公司的Cyclone 系列FPGA 芯片EP4CE6F17C8为例,用Verilog 硬件描述语言实现了以SPI 总线协议为基础的FLASH 读取控制时序,实现了FPGA 和FLASH 存储器的接口操作。

1 SPI 总线协议和W25Q128BV 芯片介绍1.1 SPI 总线协议SPI(Serial Peripheral Interface)是一种高速的、全双工、同步的通信总线。

由于其在芯片管脚上只占用4根线,节约了管脚资源的同时也为PCB 布局节省了空间,因而越来越多的芯片集成了这种通信协议。

SPI 的通信原理简单,它以主从模式工作,通常需要一个主设备和一个或者多个从设备,需要至少4根线,分别是SDI(数据输入)、SDO(数据输出)、SCLK(时钟)、CS(片选)。

其中SDI 用于主设备数据输入,从设备数据输出;SDO 用于主设备数据输出,从设备数据输入;SCLK 为时钟信号,必须由主设备提供;CS 为从设备使能信号,由主设备控制。

SPI 是串行通信协议,SDI 和SDO 与SCLK 同步,是基于SCLK 提供的时钟脉冲完成数据的逐位传输。

1.2 W25Q128BV 芯片介绍W25Q128BV 是winbond 公司开发的128Mbit SPI 接口的串行FLASH 存储芯片,由于它所需引脚少,功耗低,所以通常作为空间、引脚和功耗有限的系统的存储设备。

v2lvs命令将verilog网表转为spice网表

v2lvs命令将verilog网表转为spice网表

v2lvs命令将verilog网表转为spice网表使用举例在《calibre自带v2lvs命令使用指南》介绍了calibre v2lvs命令的参数及其作用,这篇主要对其如何将verilog网表转为spice网表进行举例说明。

1verilog网表转为spice网表,最基本的v2lvs -v verilog.v -o spice.spi2verilog网表转为spice网表,并将需要附加的.verilog库转换到输出的spice.spi网表中v2lvs -v verilog.v -l other_lib.v -o spice.spi3verilog网表转为spice网表,并将需要附加的.spice库 include 到生成的spice.spi网表中v2lvs -v verilog.v -s other_lib.spi -o spice.spi4verilog网表转为spice网表,并将verilog中的地 s0、s1 分别改名为 GND和VDDv2lvs -v verilog_file -s0 GND -s1 VDD -o spice_file5verilog网表转为spice网表,大综合v2lvs -v verilog.v -l other_lib.v -s other_lib.spi -s0 GND -s1 VDD -o spice.spi 或者有更多的.verilog和.spice库需要以spice.spi中输出,可以使用多个-l和-s参数以上只是个人使用中的一些小结,如有不正确和不全面之处希望大家留言补充。

做为现今流行的深亚微米集成电路物理验证工具,calibre 有其强大的功能,其 v2lvs命令能够方便的把verilog格式网表转为spice格式网表,对于IC后端的工程师来说是非常有用,且有必要掌握的。

命令:v2lvs可用参数:[-l verilog_lib_file] [-lsp spice_library_file] [-lsr spice_library_file] [-s spice_library_file] [-s0 groundnet] [-s1 powernet] [-sk] [-p prefix] [-w warning_level] [-a array_delimiters] [-c char1[char2]] [-u unnamed_pin_prefix] [-t svdb_dir] [-addpin pin_name] [-b] [-n] [-i] [-e] [-h] [-cb][-ictrace]参数介绍:··-v verilog_design_fileSpecifies the filename of the input Verilog structural netlist.· -o output_spice_fileSpecifies where to place the output LVS SPICE netlist. Default is standard out.· -l verilog_lib_fileSpecifies the location of the Verilog primitive library file. It is not translated.· -lsp spice_library_fileSpecifies SPICE library file name using pin mode. The SPICE file is parsed for interface configurations. Pins with pin select ([ ]) annotation are kept as individual pins using escaped identifiers.· -lsr spice_library_fileSpecifies SPICE library file name using range mode. The SPICE file is parsed for interface configurations. Pins with pin select ([ ]) annotation are assembled into Verilog ranges. · -s spice_library_fileSpecifies that the -o output file have a .INCLUDE statement placed at the beginning that points to the SPICE library file.· -s0 groundnetSpecifies the default net name for mapping to pin connections with a value of zero (0). Outputs the specified names in place of Verilog supply0 nets and generates .GLOBAL declarations in the output netlist.· -s1 powernetSpecifies the default net name for mapping to pin connections with a value of one (1). Outputs the specified names in place of Verilog supply1 nets and generates .GLOBAL declarations in the output netlist.· -skSpecifies that Verilog supply0 and supply1 nets are not connected to the globalpower and ground nets.· -p prefixAdds prefix to Verilog gate level primitive cells.· -w warning_levelControls the amount of warning message output. Possible level choices are:0 Selects to output no warning messages.1 Selects to output warning messages for skipped blocks and modules only.2 Selects to output level 1 and calls to undeclared modules and pin arrayswith widths wider than ports. This is the default.3 Selects to output level 2 and called port array mismatches andunsupported compiler directives.4 Selects output level 3 plus all ignored constructs.· -a array_delimitersChanges the array delimiter characters. The default is [ ].· -c char1[char2]Sets the substitution characters for escaped identifier characters illegal inSPICE. char1 replaces $, comma, (, ), and =. char2 replaces /. No space isneeded between the two user-supplied arguments.· -u unnamed_pin_prefixSpecifies a prefix to add to unnamed pin connections in module instantiations.· -t svdb_dirAdds source netlist pin direction information to the SVDB. This is used inCalibre xRC.· -addpin pin_name。

SPI接口的verilog实现

SPI接口的verilog实现

/****************************************************************************** ****************** SPI MASTER* January 2007******************************************************************************* *****************/`timescale 10ns/1nsmodule SPI_Master ( miso, mosi, sclk, ss, data_bus, CS, addr, pro_clk, WR, RD);inout [7:0] data_bus; // 8 bit bidirectional data businput pro_clk; // Host Processor clockinput miso; // Master in slave outinput [1:0] addr; // A1 and A0, lower bits of address businput CS; // Chip Selectinput WR, RD; // Write and read enablesoutput mosi; // Master out slave inoutput sclk; // SPI clockoutput [7:0] ss; // 8 slave select linesreg [7:0] shift_register; // Shift registerreg [7:0] txdata; // Transmit bufferreg [7:0] rxdata; // Receive bufferreg [7:0] data_out; // Data output registerreg [7:0] data_out_en; // Data output enablereg [7:0] control, status; // Control Register COntrols things like ss, CPOL, CPHA, clock divider// Status Register is a dummy register never used.reg [7:0] clk_divide; // Clock divide counterreg [3:0] count; // SPI word length counterreg sclk;reg slave_cs; // Slave cs flagreg mosi; // Master out slave inreg spi_word_send; // Will send a new spi word.wire [7:0] data_bus;wire [7:0] data_in = data_bus;wire spi_clk_gen;wire [2:0] divide_factor = control[2:0];wire CPOL = control[3];wire CPHA = control[4];wire [7:0]ss;/* Slave Select lines */assign ss[7] = ~( control[7] & control[6] & control[5] & (~slave_cs)); assign ss[6] = ~( control[7] & control[6] & ~control[5] & (~slave_cs)); assign ss[5] = ~( control[7] & ~control[6] & control[5] & (~slave_cs)); assign ss[4] = ~( control[7] & ~control[6] & ~control[5] & (~slave_cs)); assign ss[3] = ~(~control[7] & control[6] & control[5] & (~slave_cs)); assign ss[2] = ~(~control[7] & control[6] & ~control[5] & (~slave_cs)); assign ss[1] = ~(~control[7] & ~control[6] & control[5] & (~slave_cs)); assign ss[0] = ~(~control[7] & ~control[6] & ~control[5] & (~slave_cs));/* clock divide */assign spi_clk_gen = clk_divide[divide_factor];/* Clock Divider */always @ (negedge pro_clk) beginclk_divide = clk_divide + 1;end/* Reading the miso line and shifting */always @ (posedge (sclk ^ (CPHA ^ CPOL)) or posedge spi_word_send) begin if (spi_word_send) beginshift_register[7:0] = txdata;end else beginshift_register = shift_register << 1;shift_register[0] <= miso;endend/* Writing the mosi */always @ (negedge (sclk ^ (CPHA ^ CPOL)) or posedge spi_word_send) begin if (spi_word_send) beginmosi = txdata[7];end else beginmosi = shift_register[7];endend/* Contolling the interrupt bit in the status bit */always @ (posedge slave_cs or posedge spi_word_send) begin if (spi_word_send) beginstatus[0] = 0;end else beginstatus = 8'h01;rxdata = shift_register; // updating read buffer endend/* New SPI wrod starts when the transmit buffer is updated */ always @ (posedge pro_clk) beginif (spi_word_send) beginslave_cs <= 0;end else if ((count == 8) & ~(sclk ^ CPOL)) beginslave_cs <= 1;endend/* New Spi word is intiated when transmit buffer is updated */ always @ (posedge pro_clk) beginif (CS & WR & addr[1] & ~addr[0]) beginspi_word_send <=1;end else beginspi_word_send <=0;endend/* Generating the SPI clock */always @ (posedge spi_clk_gen) beginif (~slave_cs) beginsclk = ~sclk;end else if (~CPOL) beginsclk = 0;end else beginsclk = 1;endend/* Counting SPI word length */always @ (posedge sclk or posedge slave_cs) beginif (slave_cs) begincount = 0;end else begincount = count + 1;endend/* Reading, writing SPI registers */always @ (posedge pro_clk) beginif (CS) begincase (addr)2'b00 : if (WR) control <= data_in;2'b01 : if (RD) data_out <= status; // Void2'b10 : if (WR) txdata <= data_in;2'b11 : if (RD) data_out <= rxdata;endcaseendend/* Controlling the data out enable */always @ (RD or data_out) beginif (RD)data_out_en = data_out;elsedata_out_en = 8'bz;endassign data_bus = data_out_en;initialbeginmosi = 0;//sclk = 0;control = 0;count = 0;slave_cs = 1;txdata = 0;rxdata = 0;clk_divide = 0;data_out = 0;endendmodule/********************************************** END ******************************************************************/。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

从机模块slave_spi.v连接有ram,模拟CA T25010芯片存储数据,用rden,wren,data,address 进行通信,CAT25010芯片具体通信协议可参考起使用说明。

module slave_spi(clk,rst,cs,sck,si,so,rden,wren,data,address,data_send);input clk,rst,cs,sck;input si;input [7:0] data_send; //读取外部ram的数据,用于发送output rden,wren;output [7:0] data; //写入外部ram的数据output [7:0] address; //写入外部ram的数据的地址output so;reg rden,wren;reg [7:0] data;reg [7:0] address;reg [7:0] data_in;reg [7:0] addr_in;reg [7:0] data_send_buff;reg so_buff,link_so;reg [4:0] s_state;reg [3:0] read_state;reg [7:0] opecode;reg [3:0] readin_bit;wire so;assign so = link_so? so_buff:1'bz;parameter read_code=8'b0000_0011,write_code=8'b0000_0010;parameter idle=5'b00001,s_opecode=5'b00010,s_address=5'b00100,s_write=5'b01000,s_read=5'b10000;parameter bit7=4'b0010,bit6=4'b0011,bit5=4'b0100,bit4=4'b0101,bit3=4'b0110,bit2=4'b0111,bit1=4'b1000,bit0=4'b1001,bit_end=4'b1010;//提取上升沿的寄存器wire neg_cs,pos_cs;wire neg_sck,pos_sck;reg sck_temp1,sck_temp2;reg cs_temp1,cs_temp2;//提取CS和ack的上升沿河下降沿always @(posedge clk or negedge rst) beginif(!rst)beginsck_temp1<=0;sck_temp2<=0;//sck_temp3<=0;cs_temp1<=1;cs_temp2<=1;//cs_temp3<=1;endelsebeginsck_temp1<=sck;sck_temp2<=sck_temp1;//sck_temp3<=sck_temp2;cs_temp1<=cs;cs_temp2<=cs_temp1;//cs_temp3<=cs_temp2;endendassign neg_cs = ~cs_temp1&cs_temp2; assign pos_cs = cs_temp1&~cs_temp2; assign neg_sck = ~sck_temp1&sck_temp2; assign pos_sck = sck_temp1&~sck_temp2;always @(posedge clk or negedge rst) beginif(!rst)beginso_buff<=0;link_so<=0;rden<=0;wren<=0;data<=0;address<=0;data_in<=0;addr_in<=0;s_state<=idle;read_state<=bit7;opecode<=0;readin_bit<=0;endelsebeginif(pos_cs)beginso_buff<=0;link_so<=0;rden<=0;wren<=0;data<=0;address<=0;data_in<=0;addr_in<=0;s_state<=idle;read_state<=bit7;opecode<=0;readin_bit<=0;endelsebegincase(s_state)idle:beginif(neg_cs)s_state<=s_opecode;elsebegins_state<=idle;endends_opecode:beginif(pos_sck)beginopecode<={opecode[6:0],si};readin_bit<=readin_bit+1'b1;endelsebeginif(readin_bit==8)beginreadin_bit<=0;if(opecode==read_code||opecode==write_code)begins_state<=s_address;endelses_state<=idle;endendends_address:beginif(pos_sck)beginreadin_bit<=readin_bit+1'b1;addr_in<={addr_in[6:0],si};endelsebeginif(readin_bit==8)beginreadin_bit<=0;if(opecode==write_code)begins_state<=s_write;address<=addr_in;endelsebegins_state<=s_read;address<=addr_in;rden<=1;///////endendendends_write:beginif(pos_sck)beginreadin_bit<=readin_bit+1'b1;data_in<={data_in[6:0],si};endelsebeginif(readin_bit==8)begindata<=data_in;//??????wren<=1;if(neg_sck)begin//??????wren<=0;//??????readin_bit<=0;endendendends_read: read8bit;default: s_state<=idle;endcaseendendendtask read8bit;begincase(read_state)bit7:beginif(neg_sck)beginrden<=0;link_so<=1;so_buff<=data_send_buff[7];data_send_buff<={data_send_buff[6:0],data_send_buff[7]};read_state<=bit6;endelsebegindata_send_buff<=data_send;read_state<=bit7;endendbit6:beginif(neg_sck)beginso_buff<=data_send_buff[7];data_send_buff<={data_send_buff[6:0],data_send_buff[7]};read_state<=bit5;endelseread_state<=bit6;endbit5:beginif(neg_sck)beginso_buff<=data_send_buff[7];data_send_buff<={data_send_buff[6:0],data_send_buff[7]};read_state<=bit4;endelseread_state<=bit5;endbit4:beginif(neg_sck)beginso_buff<=data_send_buff[7];data_send_buff<={data_send_buff[6:0],data_send_buff[7]};read_state<=bit3;endelseread_state<=bit4;bit3:beginif(neg_sck)beginso_buff<=data_send_buff[7];data_send_buff<={data_send_buff[6:0],data_send_buff[7]};read_state<=bit2;endelseread_state<=bit3;endbit2:beginif(neg_sck)beginso_buff<=data_send_buff[7];data_send_buff<={data_send_buff[6:0],data_send_buff[7]};read_state<=bit1;endelseread_state<=bit2;endbit1:beginif(neg_sck)beginso_buff<=data_send_buff[7];data_send_buff<={data_send_buff[6:0],data_send_buff[7]};read_state<=bit0;endelseread_state<=bit1;endbit0:beginif(neg_sck)beginso_buff<=data_send_buff[7];data_send_buff<={data_send_buff[6:0],data_send_buff[7]};read_state<=bit_end;endelseread_state<=bit0;bit_end:beginif(neg_sck)beginlink_so<=0;endelseread_state<=bit_end;enddefault: read_state<=bit7;endcaseendendtaskendmodule测试仿真文件`timescale 1ms/1ms`define halfperiod 10module top;reg cs,rst,clk;reg si,sck;reg [7:0] cnt;reg [7:0] data_send;reg [7:0] rd_code;reg [7:0] wr_code;reg [7:0] addr;reg [7:0] mdata;//reg [7:0]wire [7:0] data;wire [7:0] address;always #(`halfperiod) clk=~clk;initialbegincs=1;cnt=0;rst=1;clk=1;rd_code=8'b0000_0011;wr_code=8'b0000_0010;addr=100;mdata=200;data_send=50;#15 rst=0;#30 rst=1;//#1000 cs=1;//#4000 $stop;repeat(10)begin#500 cs=0;si=wr_code[7];@(negedge sck) si=wr_code[6]; @(negedge sck) si=wr_code[5]; @(negedge sck) si=wr_code[4]; @(negedge sck) si=wr_code[3]; @(negedge sck) si=wr_code[2]; @(negedge sck) si=wr_code[1]; @(negedge sck) si=wr_code[0];@(negedge sck) si=addr[7];@(negedge sck) si=addr[6];@(negedge sck) si=addr[5];@(negedge sck) si=addr[4];@(negedge sck) si=addr[3];@(negedge sck) si=addr[2];@(negedge sck) si=addr[1];@(negedge sck) si=addr[0]; addr=addr+1;@(negedge sck) si=mdata[7]; @(negedge sck) si=mdata[6]; @(negedge sck) si=mdata[5]; @(negedge sck) si=mdata[4]; @(negedge sck) si=mdata[3]; @(negedge sck) si=mdata[2]; @(negedge sck) si=mdata[1]; @(negedge sck) si=mdata[0]; mdata=mdata+1;@(negedge sck) si=1'bz;#800 cs=1;endrepeat(10)begin#1000 cs=0;si=rd_code[7];@(negedge sck) si=rd_code[6];@(negedge sck) si=rd_code[5];@(negedge sck) si=rd_code[4];@(negedge sck) si=rd_code[3];@(negedge sck) si=rd_code[2];@(negedge sck) si=rd_code[1];@(negedge sck) si=rd_code[0];@(negedge sck) si=addr[7];@(negedge sck) si=addr[6];@(negedge sck) si=addr[5];@(negedge sck) si=addr[4];@(negedge sck) si=addr[3];@(negedge sck) si=addr[2];@(negedge sck) si=addr[1];@(negedge sck) si=addr[0];addr=addr+1;@(negedge sck) si=1'bz;@(negedge sck) ;@(negedge sck) ;@(negedge sck) ;@(negedge sck) ;@(negedge sck) ;@(negedge sck) ;@(negedge sck) ;data_send=data_send+1;@(negedge sck) si=1'bz;#800 cs=1;end#1000 $stop;endalways @(posedge clk)beginif(cs==0)beginif(cnt==8'b0011_0010) //50beginsck=~sck;cnt=0;endelsecnt=cnt+1;endelsecnt=0;endslave_spi ss(clk,rst,cs,sck,si,so,rden,wren,data,address,data_send); endmodule。

相关文档
最新文档