⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c_slave.v

📁 完整的I2C slave model以及spec詳附在內,適合想利用verilog開發此類傳輸的人參考
💻 V
字号:
`timescale 1us/10ps
`define true        1'b1
`define false       1'b0
`define clk_period  60

module i2c_slave( //input
                scl,sda_i,                
                sda_oe,
               //output
                sda_o);
                
 
input scl,sda_i;
input sda_oe;

output sda_o;

reg start,stop,rd,wr;
integer i;
reg sda;
wire sda_o=~sda_oe? sda: 0;

reg [6:0] addr;
reg [7:0] mem[0:1023];  
reg [7:0] temp;
reg tmp;
reg wp;
reg continue,burst;

reg [3:0] index;

initial begin
  start=0;sda=0;burst=0;
  stop=0;wp=0; tmp=0;
  rd=0;wr=0;temp=0;
  index=0; //for debugging
  continue=`true;
end
//----- start condition -----
always @(negedge sda_i or posedge stop)
begin
 if (scl==1)
 begin
    @(negedge scl) ;
    start=1;
    wr=0;  //---- clear original write command
    rd=0;
    stop=#1 0;
    $display(" i2c_slave; start condition detected at %t us", $time);  
 end   
end    
//------ stop condition ------      
always @(posedge sda_i)
begin
 if ((scl==1)) 
 begin   
  stop=#1 1;
  start=0;
  addr=0;
  $display(" i2c_slave; stop condition detected at %t us", $time);  
 end
end  
//------addr  decode -------
always @(posedge start)
begin 
 //if (start==1)
 begin  
   i=0;
   for (i=0;i<=6;i=i+1)   
   begin   
     //index=6-i;       
     @(posedge scl); 
     addr[6-i]=sda_i;  //--- first address decode
   end  
     //--- read or write decode -----           
     @(posedge scl);           
     rd=sda_i;  
     wr=~sda_i;

     //--- gen slave's ack ----
     wait (~sda_oe);
     sda=0;     
     start=0;
 end
end   

always @(posedge wr) $display(" i2c_slave; wr command at %t us", $time);
always @(posedge rd) $display(" i2c_slave; rd command at %t us", $time);
 

always @(posedge wr)
begin
  repeat(2)      // one wait for rd wr command, 
  @(negedge scl);// one wait for ack  
  wp=0;          // gen a write pulse to write to MEM

 while (continue) // for burst write
 begin            
     if (burst==0)
     begin
         for (i=0;i<=7;i=i+1)
         begin  
            //index=7-i;   
            @(posedge scl)
            temp[7-i]<=sda_i;  
         end
            wp=1;
         #5 wp=0;  
     end else if (burst==1)
     begin
         temp[7]<=tmp;
         for (i=1;i<=7;i=i+1)
         begin  
            @(posedge scl)
            temp[7-i]<=sda_i;  
         end
            wp=1;
         #5 wp=0;  
     end    
               
      @(negedge scl);
      @(negedge scl);
      @(posedge scl);
      tmp<=sda_i;
      #(`clk_period);     // the delay time/100000 should be modified 
                          // delay time/100000 see line 194 document
      if (stop==1) begin  // depend on the scl clk period, judge if burst mode
         continue=`false;
         burst=1'b0;
      end else begin
         continue=`true;
         burst=1'b1;
      end             
 end// end while
 continue=`true;       // return to it's initial state
 burst=1'b0;  
end

always @(negedge wp)
addr<=#1 addr+1;

always @(negedge wp)
begin
 mem[addr]<=temp;
end 
 
wire [7:0] test1,test2,test3,test4,test5; 
assign test1=mem[45];
assign test2=mem[46];
assign test3=mem[47];

assign test4=mem[12];
assign test5=mem[13];

always @(posedge rd)
begin
 temp=mem[addr];
 @(negedge scl);           //wait rd scl pulse end 
    while(continue)
    begin
      temp=mem[addr];    
      if (burst==0)
      begin
       for (i=0;i<=7;i=i+1)
       begin
          @(negedge scl);  //while i=0 , @(negedge is for ack)
          #(`clk_period/4);
          sda=temp[7-i];
          #(`clk_period/4);
       end 
      end else if (burst==1)        
        for (i=1;i<=7;i=i+1)         
        begin 
           //index=7-i;       // debugging usage                    
           @(negedge scl);          
           #(`clk_period/4);                      
           sda=temp[7-i]; 
                      
           #(`clk_period/4); 
        end    
    
        @(negedge scl);     // wait for last transfer bit
        #(`clk_period/4);  
        addr<=addr+1;
        sda<=0;             // eliminate the glitch
        @(negedge scl);     // wait for master ack                 
        
        temp=mem[addr];    
        sda=temp[7];  
        @(posedge scl);
                            // sda_i ___________/-----
                            // scl   _____/----------
                            //            |<-t->|
                            // delay #(clk_period) must > t to meet stop condition
                            // must not accross the scl clk period
                            // the delay time/100000 should be modified                   
        #(`clk_period); 
        if (stop==1) begin  // ¦b¦¹¦۰ʧP©w¬O§_¬° burst mode   
              continue=`false;                                                        
              burst=1'b0;                                                             
        end else begin                                                                             
              continue=`true;                                                         
              burst=1'b1;                                                                
        end                                                                        
   end// end while                                                                  
   continue=`true;       // return to it's initial state                        
   burst=1'b0;                                                                  
          
end
 
endmodule

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -