FPGA sample - Lattice I2C IP (EFB) #2

 Lattice Diamond Setting

  • Click "IPexpress button" and select "EFB" IPX
  • Select "Project Path" (source code files), "File Name" and "Module Output" is Verilog
  • Click "Customize"

  • Select Primary I2C
    • EFB have 2 I2C controller, suggestion use primary I2C
  • "EFB Enable" tab  "EFB Function Enable" Field  Click "Primary User"

  

  • Configuration Primary I2C
    • Speed is 400KHz
    • Slave Address is "0001001"
  • "I2C" tab "Primary I2C " Field → "I2C Bus Preformance" is 400KHz → "Slave Address" is 7'b0001001
  • Click "Generate" to generate hardware I2C code
  • Founad hardware I2C IPX in your project files

 範例程式碼

  •  宣告 EFB-IP

 /***********************************************************************
 *                                                                      *
 * EFB Module Instanitiation                                            *
 *                                                                      *
 ***********************************************************************/	   
wire rst_p = ~RST_N ;
efbi2c UUT  ( .wb_clk_i (CLK      ),
              .wb_rst_i (rst_p    ),
              .wb_cyc_i (wb_cyc_i ),
              .wb_stb_i (wb_stb_i ),
              .wb_we_i  (wb_we_i  ),
              .wb_adr_i (wb_adr_i ),
              .wb_dat_i (wb_dat_i ),
              .wb_dat_o (wb_dat_o ), 
              .wb_ack_o (wb_ack_o ),      
              .i2c1_scl (SCL      ),
              .i2c1_sda (SDA      ),
              .i2c1_irqo(i2c1_irq_o) );

  • EFB-IP 的 address / data / control pin 訊號順序
 /////////////////////////////////////////////
//                                          //
//    State Machines Sequential Block       //
//                                          //
//////////////////////////////////////////////   
always @ (posedge CLK or negedge RST_N)
begin 
	if(!RST_N)
	begin 
		wb_dat_i 	<= 8'h00;
		wb_stb_i 	<= 1'b0 ;
		wb_adr_i 	<= 8'h00;
		wb_we_i  	<= 1'b0;   
	end   
	else 
	begin 
		wb_dat_i 	<=  n_wb_dat_i;
		wb_stb_i 	<=  n_wb_stb_i;
		wb_adr_i 	<=  n_wb_adr_i;
		wb_we_i  	<=  n_wb_we_i ;
	end 
end 

always @ (posedge CLK or negedge RST_N)
begin 
	if(!RST_N) 
	begin 
		c_state  	<= 10'h000;
		efb_flag 	<= 1'b0 ;
		dat_count	<= 8'd0;
	end  
	else 
	begin  
		c_state  	<= n_state   ;
		efb_flag 	<= n_efb_flag;
		dat_count 	<= n_dat_count ;
	end  
end
  • EFB-IP state machine 加入 oem 程序碼
//////////////////////////////////////////////
//                                          //
//    State Machines Combinational Block    //
//                                          //
//////////////////////////////////////////////   
always @ ( * )
begin 
		n_efb_flag    	= 1'b0 ; 
		n_state       	= c_state ; 
		n_dat_count   	= dat_count ;
		n_wb_dat_i    	= 8'h00;
		n_wb_stb_i    	= 1'b0 ;
		n_wb_adr_i    	= 8'h00;
		n_wb_we_i     	= 1'b0;
		n_temp0       	= temp0;
		i2c_cmd_d     	= i2c_cmd_q;
		i2c_check_d   	= i2c_check_q;
		i2c_data_d    	= i2c_data_q;  
		cmdVRMEn_d	  	= cmdVRMEn_q;	
  
    case(c_state)
    `state0 : // I2C in idle 
    begin 
		n_wb_dat_i 		= 8'h00;
        n_wb_stb_i 		= 1'b0;
        n_wb_adr_i 		= 8'h00;
        n_wb_we_i  		= 1'b0;           
        n_wb_stb_i 		= 1'b0;    
        n_state 		= `state1 ;              
    end   
    
	`state1 : // Enable I2C Interface 
	begin 
		if (wb_ack_o && efb_flag) 
		begin
			n_wb_dat_i 	= `ALL_ZERO ;
			n_wb_adr_i 	= `ALL_ZERO ;
			n_wb_we_i 	= `LOW ;
			n_wb_stb_i 	= `LOW ;
			n_efb_flag 	= `LOW ;
			n_state 	= `state2;
		end
		else if(!wb_ack_o)
		begin
			n_efb_flag 	= `HIGH ;
			n_wb_adr_i 	= `MICO_EFB_I2C_CR;
			n_wb_dat_i 	= 8'h88;
			n_wb_we_i 	= `WRITE;
			n_wb_stb_i 	= `HIGH ; 
			n_state 	= c_state; 
		end
	end

	`state2 : // Clock Disable 
	begin 		
		if (wb_ack_o && efb_flag) 
		begin
			n_wb_dat_i 	= `ALL_ZERO ;
			n_wb_adr_i 	= `ALL_ZERO ;
			n_wb_we_i 	= `LOW ;
			n_wb_stb_i 	= `LOW ;
			n_efb_flag 	= `LOW ;
			n_state 	= `state3;
		end
		else if(!wb_ack_o)
		begin
			n_efb_flag 	= `HIGH ;
			n_wb_adr_i 	= `MICO_EFB_I2C_CMDR;
			n_wb_dat_i 	= 8'h04;
			n_wb_we_i 	= `WRITE;
			n_wb_stb_i 	= `HIGH ; 
			n_state 	= c_state; 
		end
	end
  
	`state3 : // Wait for not BUSY  
	begin 
		if (wb_ack_o && efb_flag) 
		begin
			n_wb_dat_i 	= `ALL_ZERO ;
			n_wb_adr_i 	= `ALL_ZERO ;
			n_wb_we_i 	= `LOW ;
			n_wb_stb_i 	= `LOW ;
			n_efb_flag 	= `LOW ;
			if(wb_dat_o & ( `MICO_EFB_I2C_SR_BUSY) )
				n_state = c_state;
			else
				n_state = `state4;
		end
		else if(!wb_ack_o) 
		begin
			n_efb_flag 	= `HIGH ;
			n_wb_we_i 	= `READ_STATUS;
			n_wb_adr_i 	= `MICO_EFB_I2C_SR;
			n_wb_dat_i 	= 0 ;
			n_wb_stb_i 	= `HIGH ; 
			n_state 	= c_state; 
		end
	end
  
	`state4 : // Discard data 1 
	begin 
		if (wb_ack_o && efb_flag) 
		begin
			n_wb_dat_i 	= `ALL_ZERO ;
			n_wb_adr_i 	= `ALL_ZERO ;
			n_wb_we_i 	= `LOW ;
			n_wb_stb_i 	= `LOW ;
			n_efb_flag 	= `LOW ;
			n_temp0 	= wb_dat_o; 
			n_state 	= `state5;
		end
		else if(!wb_ack_o) 
		begin
			n_efb_flag 	= `HIGH ;
			n_wb_we_i 	= `READ_DATA;
			n_wb_adr_i 	= `MICO_EFB_I2C_RXDR;
			n_wb_dat_i 	= 0 ;
			n_wb_stb_i 	= `HIGH ; 
			n_state 	= c_state; 
		end
	end
 
 
	`state5 : // Discard data 2 
	begin 
		if (wb_ack_o && efb_flag) 
		begin
			n_wb_dat_i = `ALL_ZERO ;
			n_wb_adr_i = `ALL_ZERO ;
			n_wb_we_i =  `LOW ;
			n_wb_stb_i = `LOW ;
			n_efb_flag = `LOW ;
			n_temp0 = wb_dat_o; 
			n_state = `state7;   // keep clock stretching disabled per PCN#10A-13
		end
		else if(!wb_ack_o) 
		begin
			n_efb_flag = `HIGH ;
			n_wb_we_i =  `READ_DATA;
			n_wb_adr_i = `MICO_EFB_I2C_RXDR;
			n_wb_dat_i =  0 ;
			n_wb_stb_i = `HIGH ; 
			n_state = c_state; 
		end
	end
 
	`state7: // wait for data to come
	begin 	
		if (wb_ack_o && efb_flag) 
		begin
			n_wb_dat_i = `ALL_ZERO ;
			n_wb_adr_i = `ALL_ZERO ;
			n_wb_we_i =  `LOW ;
			n_wb_stb_i = `LOW ;
			n_efb_flag = `LOW ;
			if(wb_dat_o & (`MICO_EFB_I2C_SR_TRRDY)) 
				n_state = `state8;		   
			else
				n_state = c_state;
		end
		else if(!wb_ack_o)
		begin
			n_efb_flag = `HIGH ;
			n_wb_we_i =  `READ_STATUS;
			n_wb_adr_i = `MICO_EFB_I2C_SR;
			n_wb_dat_i =  0 ;
			n_wb_stb_i = `HIGH ; 
			n_state = c_state; 
		end
	end

	`state8: // Store i2C Command Information 
	begin 
		if (wb_ack_o && efb_flag) begin
			n_wb_dat_i 	= `ALL_ZERO ;
			n_wb_adr_i 	= `ALL_ZERO ;
			n_wb_we_i 	=  `LOW ;
			n_wb_stb_i 	= `LOW ;
			n_efb_flag 	= `LOW ;
			i2c_cmd_d 	= wb_dat_o; 
			n_state 	= `state9;
       end
       else if(!wb_ack_o)
	   begin
			n_efb_flag = `HIGH ;
			n_wb_we_i =  `READ_DATA;
			n_wb_adr_i = `MICO_EFB_I2C_RXDR;
			n_wb_dat_i =  0 ;
			n_wb_stb_i = `HIGH ; 
			n_state = c_state; 
		end
	end
  
	`state9 : // Send ACK or NACK Based upon Command Receive & Wait for Stop `state 17 
	begin 
		if (wb_ack_o && efb_flag) 
		begin
			n_wb_dat_i 	= `ALL_ZERO ;
			n_wb_adr_i 	= `ALL_ZERO ;
			n_wb_we_i 	= `LOW ;
			n_wb_stb_i 	= `LOW ;
			n_efb_flag 	= `LOW ;
			
			// oem command
		end      
		else 
		begin if(!wb_ack_o)
			n_efb_flag 	= `HIGH ;
			n_wb_adr_i 	= `MICO_EFB_I2C_CMDR;
			n_wb_dat_i 	= {4'h0,~cmd_data,3'b100};    
			n_wb_we_i 	= `WRITE;
			n_wb_stb_i 	= `HIGH ; 
			n_state 	= c_state; 
		end
	end
 
 
	`state10 : // Command Valid 
	begin         
		if (wb_ack_o && efb_flag) 
		begin
			n_wb_dat_i 	= `ALL_ZERO ;
			n_wb_adr_i 	= `ALL_ZERO ;
			n_wb_we_i 	= `LOW ;
			n_wb_stb_i 	= `LOW ;
			n_efb_flag 	= `LOW ;
			if(wb_dat_o & ( `MICO_EFB_I2C_SR_TRRDY) )
				n_state = `state11;
			else if (~wb_dat_o[6])		// if stop bit
				n_state = `state2;
			else
				n_state = c_state;
		end
		else if(!wb_ack_o)
		begin
			n_efb_flag 	= `HIGH ;
			n_wb_we_i 	= `READ_STATUS;
			n_wb_adr_i 	= `MICO_EFB_I2C_SR;
			n_wb_dat_i 	= 0 ;
			n_wb_stb_i 	= `HIGH ; 
			n_state 	= c_state; 
		end
	end
 
 
	`state11: // Store checksum byte Information
	begin 	
		if (wb_ack_o && efb_flag) 
		begin
			n_wb_dat_i 	= `ALL_ZERO ;
			n_wb_adr_i 	= `ALL_ZERO ;
			n_wb_we_i 	= `LOW ;
			n_wb_stb_i 	= `LOW ;
			n_efb_flag 	= `LOW ;
			i2c_check_d = wb_dat_o;
			if(command_data == ~i2c_check_d) 
			begin			
				// oem command
			end 
			else
				n_state = `state17;
		end
		else if(!wb_ack_o)
		begin
			n_efb_flag 	= `HIGH ;
			n_wb_we_i 	= `READ_DATA;
			n_wb_adr_i 	= `MICO_EFB_I2C_RXDR;
			n_wb_dat_i 	= 0 ;
			n_wb_stb_i 	= `HIGH ; 
			n_state 	= c_state; 
		end
	end
 
 
	`state12: // Wait for TRRDY Bit 
	begin 
		if (wb_ack_o && efb_flag) 
		begin
			n_wb_dat_i 	= `ALL_ZERO ;
			n_wb_adr_i 	= `ALL_ZERO ;
			n_wb_we_i 	= `LOW ;
			n_wb_stb_i 	= `LOW ;
			n_efb_flag 	= `LOW ;
			if(wb_dat_o & ( `MICO_EFB_I2C_SR_TRRDY))
			begin
				// Read command
			end 
			else if (~wb_dat_o[6])
				n_state = `state2;		
			else
				n_state = c_state;
		end    
		else if(!wb_ack_o)
		begin
			n_efb_flag 	= `HIGH ;
			n_wb_we_i 	= `READ_STATUS;
			n_wb_adr_i 	= `MICO_EFB_I2C_SR;
			n_wb_dat_i 	= 0 ;
			n_wb_stb_i 	= `HIGH ; 
			n_state 	= c_state; 
		end
    end
 
	`state13: // Check for read or write operation Go to State15
	begin 	
		if (wb_ack_o && efb_flag) 
		begin
			n_wb_dat_i 	= `ALL_ZERO ;
			n_wb_adr_i 	= `ALL_ZERO ;
			n_wb_we_i 	= `LOW ;
			n_wb_stb_i 	= `LOW ;
			n_efb_flag 	= `LOW ;
			if(wb_dat_o & ( `MICO_EFB_I2C_SR_SRW))
				n_state = `state15;
			else
				n_state = c_state;
		end
		else if(!wb_ack_o)
		begin
			n_efb_flag 	= `HIGH ;
			n_wb_we_i 	= `READ_STATUS;
			n_wb_adr_i 	= `MICO_EFB_I2C_SR;
			n_wb_dat_i 	= 0 ;
			n_wb_stb_i 	= `HIGH ; 
			n_state 	= c_state; 
		end
	end
 
 
	`state14: 
	begin // Read Data
		if (wb_ack_o && efb_flag) 
		begin
			n_wb_dat_i 	= `ALL_ZERO ;
			n_wb_adr_i 	= `ALL_ZERO ;
			n_wb_we_i 	= `LOW ;
			n_wb_stb_i 	= `LOW ;
			n_efb_flag 	= `LOW ;
			n_dat_count = dat_count - 1;
			i2c_wr_data[n_dat_count] <= wb_dat_o;		  
			n_state 	= `state19;			 
		end
		else if(!wb_ack_o)
		begin
			n_efb_flag 	= `HIGH ;
			n_wb_we_i 	= `READ_DATA;
			n_wb_adr_i 	= `MICO_EFB_I2C_RXDR;
			n_wb_dat_i 	= 0 ;
			n_wb_stb_i 	= `HIGH ; 
			n_state 	= c_state; 
		end
     end
	 
	`state15: // Send Data to Master
	begin 
		if (wb_ack_o && efb_flag) 
		begin
			n_wb_dat_i 	= `ALL_ZERO ;
			n_wb_adr_i 	= `ALL_ZERO ;
			n_wb_we_i 	= `LOW ;
			n_wb_stb_i 	= `LOW ;
			n_efb_flag 	= `LOW ;
			n_state 	= `state18;
		    n_dat_count = dat_count - 1 ;
		end
		else if(!wb_ack_o)
		begin
			n_efb_flag 	= `HIGH ;
			n_wb_adr_i 	= `MICO_EFB_I2C_TXDR;
			if(n_dat_count != 1)
				n_wb_dat_i = i2c_cmd_q;
			else
				n_wb_dat_i = i2c_data_q;
			n_wb_we_i 	= `WRITE;
			n_wb_stb_i 	= `HIGH ; 
			n_state 	= c_state; 
		end
  end
 
 
 
	`state16: // Send NACK Based upon Command Receive
	begin 	
		if (wb_ack_o && efb_flag) 
		begin
			n_wb_dat_i 	= `ALL_ZERO ;
			n_wb_adr_i	= `ALL_ZERO ;
			n_wb_we_i 	= `LOW ;
			n_wb_stb_i 	= `LOW ;
			n_efb_flag 	= `LOW ;
        //  n_count_en 	= `LOW ;
			n_state 	= `state17;
		end
		else if(!wb_ack_o)
		begin
			n_efb_flag 	= `HIGH ;
			n_wb_adr_i 	= `MICO_EFB_I2C_CMDR;
			n_wb_dat_i 	= 8'h0C; 
			n_wb_we_i 	= `WRITE;
			n_wb_stb_i 	= `HIGH ; 
			n_state 	= c_state; 
		end
     end
 
 
	`state17: // Wait till Stop is Send 
	begin 
		if (wb_ack_o && efb_flag) 
		begin
			n_wb_dat_i 	= `ALL_ZERO ;
			n_wb_adr_i 	= `ALL_ZERO ;
			n_wb_we_i 	= `LOW ;
			n_wb_stb_i 	= `LOW ;
			n_efb_flag 	= `LOW ;
			if(~wb_dat_o[6])
				n_state = `state2;
			else
				n_state = c_state;
		end
		else if(!wb_ack_o)
		begin
			n_efb_flag 	= `HIGH ;
			n_wb_we_i 	= `READ_STATUS;
			n_wb_adr_i 	= `MICO_EFB_I2C_SR;
			n_wb_dat_i 	= 0 ;
			n_wb_stb_i 	= `HIGH ; 
			n_state 	= c_state; 
		end
	end
 
	`state18: // Wait for TxRDY flag and send data again if required 
	begin 	
		if (wb_ack_o && efb_flag) 
		begin
			n_wb_dat_i 	= `ALL_ZERO ;
			n_wb_adr_i 	= `ALL_ZERO ;
			n_wb_we_i 	= `LOW ;
			n_wb_stb_i 	= `LOW ;
			n_efb_flag 	= `LOW ;
			if ( dat_count == 8'h00) 	   
				n_state = `state16;	// Send Nack for Any More Read Request 
			else if(wb_dat_o & (`MICO_EFB_I2C_SR_TRRDY ))
     		    n_state = `state15;                   // Send Data  
			else
				n_state = c_state;
		end
		else if(!wb_ack_o)
		begin
			n_efb_flag 	= `HIGH ;
			n_wb_we_i 	= `READ_STATUS;
			n_wb_adr_i 	= `MICO_EFB_I2C_SR;
			n_wb_dat_i 	= 0 ;
			n_wb_stb_i 	= `HIGH ; 
			n_state 	= c_state; 
		end
     end

 
   `state19: // Wait for TRRDY bit 
	begin  
		if (wb_ack_o && efb_flag) 
		begin
			n_wb_dat_i 	= `ALL_ZERO ;
			n_wb_adr_i 	= `ALL_ZERO ;
			n_wb_we_i 	= `LOW ;
			n_wb_stb_i 	= `LOW ;
			n_efb_flag 	= `LOW ;
	        if ( dat_count == 8'h00)
				n_state = `state16;		   
			else if(wb_dat_o & ( `MICO_EFB_I2C_SR_TRRDY) )
				n_state = `state14;
			else if (~wb_dat_o[6])
				n_state = `state2;
			else
				n_state = c_state;
		end 
		else if(!wb_ack_o)
		begin
			n_efb_flag 	= `HIGH ;
			n_wb_we_i 	= `READ_STATUS;
			n_wb_adr_i 	= `MICO_EFB_I2C_SR;
			n_wb_dat_i 	= 0 ;
			n_wb_stb_i 	= `HIGH ; 
			n_state 	= c_state; 
		end
	end
	endcase
end

 

 參考資料



 






留言

張貼留言

這個網誌中的熱門文章

EC 所需知識 - SMBUS

EC 所需知識 - KBC

EC 所需知識 - LPC