FPGA和eeprom通信

本文有参考【精品博文】IIC 通信协议的Verilog实现作者的一些思想,并尝试补充eeprom一端的代码,并不完美,主要是

一eeprom完全按照scl上升沿或下降沿采取动作(写数据或读数据),很难在scl低电平中间点使sda线发生变化(似乎不太符合iic协议要求),

二另外在FPGA放弃sda线控制权和eeprom取得sda线控制权之间会有一小段高阻态(衔接并不连续),以下代码

`timescale 1 ns / 100ps
module exx( clk,rst_n,keywr,keyrd,sda,scl); //fpga端代码
input clk; 
input rst_n; 
input keywr;
input keyrd;
output reg scl;
inout sda; 

reg[3:0] cnt; 
reg[3:0] count;

reg wr;
reg rd;
reg link;
reg sdabuf;
reg[8:1] buffer;
reg[3:0] state;

parameter
idl=0,
st1=1,
wdv=2,
ac1=3,
wwd=4,
ac2=5,
wdt=6,
ac3=7,
st2=8,
rdv=9,
ac4=10,
rdt=11,
nac=12,
stp=13;

assign sda=link?sdabuf:1'bz; //fpga控制或放弃sda线

always @(negedge clk or negedge rst_n)
if(!rst_n) scl<=1;
else if(state>st1)scl<=~scl;

always @(posedge clk or negedge rst_n)
if(!rst_n) begin 
state<=idl;
wr<=0;
rd<=0;
count<=8;
link<=1;
sdabuf<=1;
buffer<=0;
end
else 
case(state)
idl: //空闲状态
if(!keyrd||!keywr) 
begin 
  if(!keywr)wr<=1; 
  if(!keyrd)rd<=1; 
  sdabuf<=0; 
  state<=st1; 
  buffer<=8'b10100000; 
end

st1: state<=wdv; //发送启动信号
        
wdv:if(!scl&&count>0) //发送器件地址8'b10100000;  
      begin 
      sdabuf<=buffer[count]; 
      count<=count-1; 
      end
     else if(!scl&&count==0) 
        begin 
        count<=8; 
        link<=0;   //放弃sda线控制权,等待检测应答信号
        state<=ac1; 
        end
 
ac1:   //接收第一次应答
    begin   
      if(scl)
        begin
          if(!sda) 
            begin 
              buffer<=8'b1000_0001; //准备写字地址8'b1000_0001=d'129;
              sdabuf<=0; 
              link<=1;  //接收到应答信号后重新获取sda线控制权,准备写字地址
              state<=wwd; 
            end
        end
    end

wwd:if(!scl&&count>0) //发送字地址 
      begin 
      sdabuf<=buffer[count]; 
      count<=count-1; 
      end
     else if(!scl&&count==0) 
        begin 
        count<=8; 
        link<=0; 
        state<=ac2; 
    &

你可能感兴趣的:(fpga开发)