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

合集下载

EEPROM_SPI

EEPROM_SPI
EEPROM&&SPI
EEPROM和SPI的使用
目标: 1、能熟练使用EEPROM数写数据 2、能熟练使用SPI接口实现数据的传输
EEPROM&&SPI
任务1:在EEPROM任意位置写入一个数据,再读取写入的数据 思考1:EEPROM是什么?PIC中的EEPROM有多大? 步骤:1、上网查阅资料 2、查阅数据手册 EEPROM (Electrically Erasable Programmable Read-Only Memory),电 可擦可编程只 读存储器--一 种掉电后数据 不丢失的存储 芯片。
• 4、WR=1 //启动写操作
EEPROM&&SPI
读数据
• void EEPROM_R() • { • EEADR=0X01; //地址 • RD=1; //使能读操作 • SHU=EEDATA;//读数据 • }
EEPROM&&SPI
任务2:连续写入200个数据,读取任意位置的数据
void EEPROM_R() { Unsigend char i; for(i=0;i<20;i++) { EEADR=0X01; RD=1; SHU[i]=EEDATA; } }
EEPROM&&SPI
时钟 数据输出
EEPROM&&SPI
• SPI初始化 • void spi_initatal() • {
SSPSTAT=0XC0; //时钟下降沿发送数据 SSPCON1=0X30;//SSPEEEPROM&&SPI
发送数据
• SSPBUF= data; //发送数据 • do { • ; • }while(SSPIF==0); //等待发送完毕 • SSPIF=0;

FPGA读写EEPROM

FPGA读写EEPROM

FPGA读写EEPROMFPGA读写EEPROMmodulei2c(clk,rst,data_in,scl,sda,wr_input,rd_input,lowbit,en,seg_data);input clk,rst;output scl;//I2C时钟线inout sda;//I2C数据线input[3:0] data_in;//拨码开关输入想写入EEPROM的数据input wr_input;//要求写的输入input rd_input;//要求读的输入output lowbit; //输出一个低电平给矩阵键盘的某一行output[1:0] en;//数码管使能output[7:0] seg_data;//数码管段数据reg[7:0] seg_data;reg scl;reg[1:0] en;reg[7:0] seg_data_buf;reg[11:0] cnt_scan;reg sda_buf;//sda输入输出数据缓存reg link; //sda输出标志reg phase0,phase1,phase2,phase3;//一个scl时钟周期的四个相位阶段,将一个scl周期分为4段//phase0对应scl的上升沿时刻,phase2对应scl的下降沿时刻,phase1对应从scl高电平的中间时刻,phase2对应从scl低电平的中间时刻,reg[7:0] clk_div;//分频计数器reg[1:0] main_state;reg[2:0] i2c_state;//对i2c操作的状态reg[3:0] inner_state;//i2c每一操作阶段内部状态reg[19:0] cnt_delay;//按键延时计数器reg start_delaycnt;//按键延时开始reg[7:0] writeData_reg,readData_reg;//要写的数据的寄存器和读回数据的寄存器reg[7:0] addr;//被操作的EEPROM字节的地址parameter div_parameter=100;// 分频系数,AT24C02最大支持400K时钟速率parameter start=4'b0000, //开始first=4'b0001, //第1位second=4'b0010,//第2位third=4'b0011, //第3位fourth=4'b0100, //第4位fifth=4'b0101, //第5位sixth=4'b0110, //第6位seventh=4'b0111, //第7位eighth=4'b1000, //第8位ack=4'b1001, //确认位stop=4'b1010; //结束位parameter ini=3'b000, //初始化EEPROM状态sendaddr=3'b001, //发送地址状态write_data=3'b010, //写数据状态?read_data=3'b011, //读数据状态read_ini=6'b100; //发送读信息状态assign lowbit=0;assign sda=(link)? sda_buf:1'bz;always@(posedge clk or negedge rst) beginif(!rst)cnt_delay<=0;else beginif(start_delaycnt) beginif(cnt_delay!=20'd800000)cnt_delay<=cnt_delay+1;elsecnt_delay<=0;endendendalways@(posedge clk or negedge rst) begin if(!rst) beginclk_div<=0;phase0<=0;phase1<=0;phase2<=0;phase3<=0;endelse beginif(clk_div!=div_parameter-1)clk_div<=clk_div+1;elseclk_div<=0;if(phase0)phase0<=0;else if(clk_div==99)phase0<=1;if(phase1)phase1<=0;else if(clk_div==24)phase1<=1;if(phase2)phase2<=0;else if(clk_div==49)phase2<=1;if(phase3)phase3<=0;else if(clk_div==74)phase3<=1;endend///////////////////////////EEPROM操作部分///////////// always@(posedge clk or negedge rst) beginif(!rst) beginstart_delaycnt<=0;main_state<=2'b00;i2c_state<=ini;inner_state<=start;scl<=1;sda_buf<=1;link<=0;writeData_reg<=5;readData_reg<=0;addr<=10;endelse begincase(main_state)2'b00: begin //等待读写要求writeData_reg<=data_in;scl<=1;sda_buf<=1;link<=0;inner_state<=start;i2c_state<=ini;if((cnt_delay==0)&&(!wr_input||!rd_input)) start_delaycnt<=1;else if(cnt_delay==20'd800000) beginstart_delaycnt<=0;if(!wr_input)main_state<=2'b01;else if(!rd_input)main_state<=2'b10;endend2'b01: begin //向EEPROM写入数据if(phase0) scl<=1;else if(phase2)scl<=0;case(i2c_state)ini: begin //初始化EEPROM case(inner_state)start: beginif(phase1) beginlink<=1;sda_buf<=0;endif(phase3&&link) begininner_state<=first;sda_buf<=1;link<=1;endendfirst:if(phase3) beginlink<=1;inner_state<=second; end second:if(phase3) beginsda_buf<=1;link<=1;inner_state<=third; end third:if(phase3) beginsda_buf<=0;link<=1;inner_state<=fourth; end fourth:if(phase3) beginsda_buf<=0;link<=1;inner_state<=fifth; end fifth:if(phase3) beginsda_buf<=0;link<=1;inner_state<=sixth; end sixth:if(phase3) beginsda_buf<=0;link<=1;inner_state<=seventh; end seventh:if(phase3) beginlink<=1;inner_state<=eighth; endeighth:if(phase3) beginlink<=0;inner_state<=ack;endack: beginif(phase0)sda_buf<=sda;if(phase1) beginif(sda_buf==1)main_state<=3'b000;endif(phase3) beginlink<=1;sda_buf<=addr[7];inner_state<=first;i2c_state<=sendaddr;endendendcaseendsendaddr: begin //送相应字节的地址case(inner_state) first:if(phase3) beginlink<=1;sda_buf<=addr[6]; inner_state<=second; end second:if(phase3) beginlink<=1;sda_buf<=addr[5]; inner_state<=third; end third:if(phase3) beginlink<=1;sda_buf<=addr[4]; inner_state<=fourth; end fourth:if(phase3) beginlink<=1;sda_buf<=addr[3];inner_state<=fifth; endfifth:if(phase3) beginlink<=1;sda_buf<=addr[2]; inner_state<=sixth; end sixth:if(phase3) beginlink<=1;sda_buf<=addr[1]; inner_state<=seventh; end seventh:if(phase3) beginlink<=1;sda_buf<=addr[0]; inner_state<=eighth; end eighth:if(phase3) beginlink<=0;inner_state<=ack;endack: beginif(phase0)sda_buf<=sda;if(phase1) beginif(sda_buf==1)main_state<=3'b000;endif(phase3) beginlink<=1;sda_buf<=writeData_reg[7]; inner_state<=first;i2c_state<=write_data;endendendcaseendwrite_data: begin //写入数据case(inner_state) first:if(phase3) beginlink<=1;sda_buf<=writeData_reg[6]; inner_state<=second; endsecond:if(phase3) beginlink<=1;sda_buf<=writeData_reg[5]; inner_state<=third; endthird:if(phase3) beginlink<=1;sda_buf<=writeData_reg[4]; inner_state<=fourth; endfourth:if(phase3) beginlink<=1;sda_buf<=writeData_reg[3]; inner_state<=fifth; endfifth:if(phase3) beginlink<=1;sda_buf<=writeData_reg[2]; inner_state<=sixth; endsixth:if(phase3) beginlink<=1;sda_buf<=writeData_reg[1]; inner_state<=seventh; endseventh:if(phase3) beginlink<=1;sda_buf<=writeData_reg[0]; inner_state<=eighth; endeighth:if(phase3) beginlink<=0;inner_state<=ack;endack: beginif(phase0)sda_buf<=sda;if(phase1) beginif(sda_buf==1)main_state<=2'b00; endelse if(phase3) begin link<=1;sda_buf<=0;inner_state<=stop; endendstop: beginif(phase1)sda_buf<=1;if(phase3)main_state<=2'b00; endendcasedefault:main_state<=2'b00; endcaseend2'b10: begin //读EEPROMif(phase0)scl<=1;else if(phase2)scl<=0;case(i2c_state)ini: begin //初始化EEPROM case(inner_state) start: beginif(phase1) beginlink<=1;sda_buf<=0;endif(phase3&&link) begin inner_state<=first; sda_buf<=1;link<=1;endfirst:if(phase3) beginsda_buf<=0;link<=1;inner_state<=second; end second:if(phase3) beginsda_buf<=1;link<=1;inner_state<=third; end third:if(phase3) beginsda_buf<=0;link<=1;inner_state<=fourth; end fourth:if(phase3) beginsda_buf<=0;link<=1;inner_state<=fifth; end fifth:if(phase3) beginsda_buf<=0;link<=1;inner_state<=sixth; end sixth:if(phase3) beginsda_buf<=0;link<=1;inner_state<=seventh; endseventh:if(phase3) beginsda_buf<=0;link<=1;inner_state<=eighth; end。

基于FPGA的SPI总线接口的实现

基于FPGA的SPI总线接口的实现

基于FPGA的SPI总线接口的实现0 引言串行接口已成为当前传输接口的发展趋势,原因在于串行的高速率传输性能和较简单的线路连接。

在已知的外围器件连接端口中,有USB,wishbone 和并行端口。

其中SPI 接口总线基于串行传输的思想,已经制定成为标准,成为常用的外围器件连接方式。

针对FLASH 这种常用的外围存储器件,有多种接口可供选择,然而具有SPI 接口的FLASH 芯片硬件连接方便,通过FPGA 编程可以便捷地实现FLASH 的存取功能。

因此基于FPGA 的具有SPI 总线接口的FLASH 功能实现为工程设计提供了一种原型,为进一步的工程开发奠定了基础。

1 SPI 总线介绍1.1 SPI 总线简介同步外设接口(serial peripheral,interface,SPI)是由摩托罗拉公司开发的全双工同步串行总线。

SPT 是一种串行同步通信协议,由1 个主设备和1 个或多个从设备组成,主设备启动一个与从设备的同步通信,从而完成数据的交换。

1.2 SPI 总线接口及时序SPI 接口由SDI(串行数据输入),SDO(串行数据输出),SCK(串行移位时钟),CS(从使能信号)四种信号构成,CS 决定了惟一的与主设备通信的从设备,如没有CS 信号,则只能存在一个从设备,主设备通过产生移位时钟来发起通信。

通信时,数据由SDO 输出,SDI 输入,数据在时钟的上升沿或下降沿从SDO 输出,在紧接着的下降沿或上升沿由SDI 读入,这样经过8/16 次时钟改变,完成8/16 位数据的传输。

在SPI 传输中,数据是同步进行发送和接收的。

数据传输的时钟基于来自主处理器的时钟脉冲,摩托罗拉没有定义任何通用SPI 时钟规范。

然而,最常用的时钟设置基于时钟极性(CPOL)和时钟相位(CPHA)两个参数;CPOL 定义SPI 串行时钟的活动状态,而CPHA 定义相对于数据位的时钟相位。

CPOL 和CPHA 的设置决定了数据取样的时钟沿。

使用Verilog来实现EEPROM的读写,进行一个简单的I2C实战应用

使用Verilog来实现EEPROM的读写,进行一个简单的I2C实战应用

使用Verilog来实现EEPROM的读写,进行一个简单的I2C实战应用 I2C在芯片的配置中应用还是很多的,比如摄像头、VGA转HDMI转换芯片,之前博主分享过一篇I2C协议的基础学习IIC协议学习笔记,这篇就使用Verilog来实现EEPROM的读写,进行一个简单的I2C实战应用。

 EEPROM 我使用的这个芯片是AT24C32,它手册上还有一种AT24C64,其实操作都是一样的,只是内存大小不同,AT24C32是32k(4096x8)AT24C64是64k(8192x8), SCL设置为频率200Khz SCL clk posedge data输入EEPROM SCL clk negedge data输出EEPROM SDA 双向Pin A2,A1,A0 Device Addr default all 0,只操作一片可悬空引脚。

 WP 接地正常读写,WP接Vcc写操作被禁止 字节寻址地址,是由12(AT24C32)或13bit(AT24C64)的地址组成,需要操作16位字地址高3或4位忽略即可。

 Device Address 8’hA0写器件地址,8’hA1读器件地址 写字节操作 随机读字节操作 我这个芯片是双字节数据地址,所以在写数据地址时要写两次,先是高字节后是低字节。

 开始结束标志 这个I2C总线的时序是一致的。

 EEPROM应答 输出应答sclk的第九个周期给出,低电平应答。

如果主机没有收到应答,需要重新配置。

 数据传输时序 sda数据线在scl时钟的下降沿中间变化,可以避免产生误触开始结束标志。

 I2C Design i2c_start为高电平有效,传输完成后会产生一个i2c_done结束标志,表示操作完成。

 I2C状态转移图 I2C写操作 (1)产生start位 (2)传送器件地址ID_Address,器件地址的最后一位为数据的传输方向位,R/W,低电平0表示主机往从机写数据(W),1表示主机从从机读数据(R)。

使用Verilog来实现EEPROM的读写,进行一个简单的I2C实战应用

使用Verilog来实现EEPROM的读写,进行一个简单的I2C实战应用

这个 I2C 总线的时序是一致的。 EEPROM 应答 输出应答 sclk 的第九个周期给出,低电平应答。如果主机没有收到应答, 需要重新配置。 数据传输时序 sda 数据线在 scl 时钟的下降沿中间变化,可以避免产生误触开始结束标 志。 I2C Design i2c_start 为高电平有效,传输完成后会产生一个 i2c_done 结束标志,表示 操作完成。 I2C 状态转移图 I2C 写操作
SDA 双向 Pin A2,A1,A0 Device Addr default all 0,只操作一片可悬空引脚。 WP 接地正常读写,WP 接 Vcc 写操作被禁止 字节寻址地址ห้องสมุดไป่ตู้是由 12(AT24C32)或 13bit(AT24C64)的地址组成, 需要操作 16 位字地址高 3 或 4 位忽略即可。 Device Address 8’hA0 写器件地址,8’hA1 读器件地址 写字节操作 随机读字节操作 我这个芯片是双字节数据地址,所以在写数据地址时要写两次,先是高字 节后是低字节。 开始结束标志
(1)产生 start 位 (2)传送器件地址 ID_Address,器件地址的最后一位为数据的传输方向 位,R/W,低电平 0 表示主机往从机写数据(W),1 表示主机从从机读数据 (R)。这里按照手册给出的操作图,应该是 W 即低电平。ACK 应答,应答 是从机发送给主机的应答,这里不用管。 (3)传送写入器件寄存器地址,即数据要写入的位置。同样 ACK 应答 不用管。 (4)传送要写入的数据。ACK 应答不用管。 (5)产生 stop 信号。 I2C 读操作 (1)产生 start 信号
其他部分没啥好说的根据时序图写就行了,需要注意的一点是我们应该在 sclk 的高电平的中间采样数据,在 sclk 低电平的中间改变数据,当 sclk 为高 电平的时候,sda 为出现下降沿为 start 位, sda 出现上升沿为 stop 位,所以 在 sclk 为高电平的时候 sda 应该保持稳定不能随意乱动。这就又回到了数据 传输有效的条件,只有在 sclk 为低电平期间,才允许数据变化,在高电平期 间,不允许数据变化,否则就会出现起始位或结束位。 EEPROM 有个仿真模型,在夏雨闻老师的书里面就有,这个模型默认是 200khz 的 sclk 驱动,仿真的时候可以将时间参数改小,我这里也分享出来。 仿真模型代码点击阅读原文可以查看。 根据仿真模型仿真的话基本不会有什幺问题,需要注意的是操作的完成标 志。从仿真上看到输入读写都没问题,但是 stop 标志没产生好,仿真看到读 写操作没问题,但实际还是不行的,需要严格按照 EEPROM 的手册操作时序 进行,差一点就不行。 我最后使用拨码开关作为读写使能,数码管显示读出来的输出,最后实现 了对指定存储地址读写数据。

[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串行总线接口的Verilog实现

SPI串行总线接口的Verilog实现

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根控制线。

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

盯着这张鬼时序图看了一天,唉,累 //=============================================================== module spi93c46 (rst, clk, sck, mo, mi, cs, led, write, read); input rst, clk, mi, write, read; output sck, cs, mo; output [7:0] led; reg [7:0] led; reg cs; reg mo; assign sck = clk;
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:
= Read16; = Read17; = Read18; = Read19; = Idle;
//第三个进程,同步时序 always 模块,格式化描述次态寄存器输出 always @ (negedge clk) case(next_state) Idle: cs <= 0; Ewen0: cs <= 0; Ewen1: begin cs <= 1; mo <= 1; end Ewen2: mo <= 0; Ewen3: mo <= 0; Ewen4: mo <= 1; Ewen5: mo <= 1;//以下四个为无用信号 Ewen6: mo <= 0; Ewen7: mo <= 0; Ewen8: mo <= 0; Ewen9: mo <= 0; Ewen10: cs <= 0;
从开始读数据手册,到研究时序,到编写 Verilog 程序,到仿真调试时序,整整 花了有 3-4 天时间。 最后时序已经完全正确, 却读不出任何数据,经过一个晚上的排查才发现是开发 板上的 DI DO SK CS 标号标错了,泪奔~~ 本来我想写一个完整的 SPI 接口出来,想了几天都没有头绪,最后还是写了一个 最简单的写数据读数据的小程序,如果做成接口也勉强可以用。 程序的功能很简单,往地址 0111111 的位置写了 00001111 的数据,地址都还没 有做成接口,固定在程序里面的。 具体用了一个状态机共 53 个状态,每一个状态都是一个 SCK 信号的处理,当然 有分为三个大状态,分别为 ENWR、WRITE、READ 93C46 要首先写 ENWR 信号才能写入数据,具体还得研究数据手册 通过这次 93C46 和上次写 18B20 的经历, 我感觉到数据手册的确是相当的重要的, 需要仔细推敲,分析每一个时序图!下次要做 I2C 接口的 24C02,1、2、3 线就 都学过拉。 当然作为初学者程序是写的那是超级的烂,欢迎拍砖
//状态机 parameter Idle = 32'd1, Ewen0=32'd10, Ewen1=32'd11, Ewen2=32'd12, Ewen3=32'd13, Ewen4=32'd14, Ewen5=32'd15, Ewen6=32'd16,Ewen7=32'd17, Ewen8=32'd18, Ewen9=32'd19, Ewen10=32'd110, Ewen11=32'd111, Write0=32'd20,Write1=32'd21,Write2=32'd22,Write3=32'd23,Write4 =32'd24, Write5=32'd25,Write6=32'd26,Write7=32'd27,Write8=32'd28,Write9 =32'd29, Write10=32'd120,Write11=32'd121,Write12=32'd122,Write13=32'd12 3,Write14=32'd124, Write15=32'd125,Write16=32'd126,Write17=32'd127,Write18=32'd12 8,Write19=32'd129,
Ewen11: cs <= 0; Write0: cs <= 0; Write1: begin cs <= 1; mo <= 1; end Write2: mo <= 0; Write3: mo <= 1;//101+add(7bit) Write4: mo <= 0; Write5: mo <= 1; Write6: mo <= 1; Write7: mo <= 1; Write8: mo <= 1; Write9: mo <= 1; Write10: mo <= 1; Write11: //data 8bit mo <= 0; Write12: mo <= 0; Write13: mo <= 0; Write14: mo <= 0; Write15: mo <= 1; Write16: mo <= 1; Write17: mo <= 1; Write18: mo <= 1;
led[4] <= Read16: led[3] <= Read17: led[2] <= Read18: led[1] <= Read19: begin led[0] <= cs <= 0; end endcase endmodule
mi; mi; mi; mi;
mi;
Read0: next_state Read1: next_state Read2: next_state Read3: next_state Read4: next_state Read5: next_state Read6: next_state Read7: next_state Read8: next_state Read9: next_state Read10: next_state Read11: next_state Read12: next_state Read13: next_state Read14: next_state Read15:
Read0=32'd30, Read1=32'd31, Read2=32'd32, Read3=32'd33, Read4=32'd34, Read5=32'd35, Read6=32'd36, Read7=32'd37, Read8=32'd38, Read9=32'd39, Read10=32'd130, Read11=32'd131, Read12=32'd132, Read13=32'd133, Read14=32'd134, Read15=32'd135, Read16=32'd136, Read17=32'd137, Read18=32'd138, Read19=32'd139; reg[31:0] current_state; reg[31:0] next_state; //第一个进程 always @(posedge clk ) if(rst) current_state <= Idle; else current_state <= next_state;//注意,使用的是非阻塞赋值
= Ewen6; = Ewen7; = Ewen8; = Ewen9; = Ewen10; = Ewen11; = Write0;
= Write1; = Write2; = Write3; = Write4; = Write5; = Write6; = Write7; = Write8; = Write9; = Write10; = Write11; = Write12; = Write13; = Write14;
= Ewen1; = Ewen2; = Ewen3; = Ewen4; = Ewen5;
Ewen5: next_state Ewen6: next_state Ewen7: next_state Ewen8: next_state Ewen9: next_state Ewen10: next_state Ewen11: next_state Write0: next_state Write1: next_state Write2: next_state Write3: next_state Write4: next_state Write5: next_state Write6: next_state Write7: next_state Write8: next_state Write9: next_state Write10: next_state Write11: next_state Write12: next_state Write13: next_state Write14:
next_state Write15: next_state Write16: next_state Write17: next_state Write18: next_state Write19: next_state
相关文档
最新文档