UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Visitor techno-rogue
Visitor
6,660 Views
Registered: ‎12-24-2016

I2C Master Code Verification

Jump to solution

Hello! 

I am using multiple cascadable register to implement I2C master code on a Spartan-3E board.The I2C is part of the configuration process for an ADV7171 Video Encoder.I was wondering if there was any way to verify successful I2C communication by checking whether or not the SDA pin has been pulled low by the master on the 9th clock cycle.My I2C frequency is around 50Khz.
As part of my attempt to verify the I2C ack bit, I tried the following, which did NOT work :

wire ACK;	
assign ACK = IO? (STARTCLK? SDA? 0 : 1 : 0) : 0; //IO = 9th clock cycle , STARTCLK is used to check if I2C has been initiated or not.

If ACK goes high, then an LED should light up, which doesn't.
Is this method generally realizable? If so, then there must be a problem with the code.Otherwise, How else can I verify successful I2C communication?
I am also sharing the entire I2C module code and images of the START and STOP conditions.

`timescale 1ns / 1ps
module i2c    (                          input STATUSin,             //CLKin bit of DCM
					 input config_rst,          //POWER UP DCM RESET
					 input clk_i2c,
					 input RESET,
					 inout SDA,            
					 output SCL,
					 output reg LED,
					 output reg DONE
					 );
        wire [3 : 0] i2c_reset;    // to ensure on state reset
	wire SDA_W;                // srl output
	reg [2 : 0] Bit_Counter;
	reg [4 : 0] Byte_Counter;
	reg IO;                   //buffer control, 1 = impedance state on inout pin SDA
	reg STARTCLK;             //Clock Start for SCL
	reg Clk_Enable;           //input clock_i2c divided by 32 using reg [4 : 0] counter
	wire STARTI2C;            
	reg [4 : 0] counter;      
        reg SCLreg;               //I2C clock register    

	FDS flop_reg000 (.D(1'b0),  .C(clk_i2c), .Q(i2c_reset[0]), .S(1'b0));	
	FD  flop_reg001 (.D(i2c_reset[0]),  .C(clk_i2c), .Q(i2c_reset[1]));
	FD  flop_reg010 (.D(i2c_reset[1]),  .C(clk_i2c), .Q(i2c_reset[2]));
	FD  flop_reg011 (.D(i2c_reset[2]),  .C(clk_i2c), .Q(i2c_reset[3]));
 --------------------------------------SRL DECLARATIONS-------------------------------------------
  SRL16E #(                        /////START REGISTER
      .INIT(16'hFFFF) // Initial Value of Shift Register
   ) SRL16E_inst9 (
      .Q(SDA_W),        // SRL data output
      .A0(1'b1),    	   // Select[0] input
      .A1(1'b1),     	// Select[1] input
      .A2(1'b1),     	// Select[2] input
      .A3(1'b1),     	// Select[3] input
      .CE(Clk_Enable && !(Bit_Counter == 7)),     	// Clock enable input
      .CLK(clk_i2c),   	// Clock input
      .D(Q15_8)         // SRL data input
   ); 
SRLC16E #(
      .INIT(16'h5600) // Initial Value of Shift Register
   ) SRLC16E_inst8 (
      .Q(),       	// SRL data output
      .Q15(Q15_8),   // Carry output (connect to next SRL)
      .A0(1'b1),     // Select[0] input
      .A1(1'b1),     // Select[1] input
      .A2(1'b1),     // Select[2] input
      .A3(1'b1),     // Select[3] input
      .CE(Clk_Enable && !(Bit_Counter == 7)),     // Clock enable input
      .CLK(clk_i2c), // Clock input
      .D(Q15_7)      // SRL data input
   );
SRLC16E #(
      .INIT(16'h0538) // Initial Value of Shift Register
   ) SRLC16E_inst7 (
      .Q(),       // SRL data output
      .Q15(Q15_7),   // Carry output (connect to next SRL)
      .A0(1'b1),     // Select[0] input
      .A1(1'b1),     // Select[1] input
      .A2(1'b1),     // Select[2] input
      .A3(1'b1),     // Select[3] input
      .CE(Clk_Enable && !(Bit_Counter == 7)),     // Clock enable input
      .CLK(clk_i2c),   // Clock input
      .D(Q15_6)        // SRL data input
   );
SRLC16E #(
      .INIT(16'h0000) // Initial Value of Shift Register   //Test Data
   ) SRLC16E_inst6 (
      .Q(),       // SRL data output
      .Q15(Q15_6),   // Carry output (connect to next SRL)
      .A0(1'b1),     // Select[0] input
      .A1(1'b1),     // Select[1] input
      .A2(1'b1),     // Select[2] input
      .A3(1'b1),     // Select[3] input
      .CE(Clk_Enable && !(Bit_Counter == 7)),     // Clock enable input
      .CLK(clk_i2c),   // Clock input
      .D(Q15_5)        // SRL data input
   );
SRLC16E #(
      .INIT(16'h0000) // Initial Value of Shift Register
   ) SRLC16E_inst5 (
      .Q(),       // SRL data output
      .Q15(Q15_5),   // Carry output (connect to next SRL)
      .A0(1'b1),     // Select[0] input
      .A1(1'b1),     // Select[1] input
      .A2(1'b1),     // Select[2] input
      .A3(1'b1),     // Select[3] input
      .CE(Clk_Enable &&!(Bit_Counter == 7)),     // Clock enable input
      .CLK(clk_i2c),   // Clock input
      .D(Q15_4)        // SRL data input
   );
SRLC16E #(
      .INIT(16'h0000) // Initial Value of Shift Register
   ) SRLC16E_inst4 (
      .Q(),       // SRL data output
      .Q15(Q15_4),   // Carry output (connect to next SRL)
      .A0(1'b1),     // Select[0] input
      .A1(1'b1),     // Select[1] input
      .A2(1'b1),     // Select[2] input
      .A3(1'b1),     // Select[3] input
      .CE(Clk_Enable && !(Bit_Counter == 7)),     // Clock enable input
      .CLK(clk_i2c),   // Clock input
      .D(Q15_3)        // SRL data input
   );
SRLC16E #(                                                      /////STOP REGISTER
      .INIT(16'h00CB) // Initial Value of Shift Register
   ) SRLC16E_inst3 (
      .Q(),       // SRL data output
      .Q15(Q15_3),   // Carry output (connect to next SRL)
      .A0(1'b1),     // Select[0] input
      .A1(1'b1),     // Select[1] input
      .A2(1'b1),     // Select[2] input
      .A3(1'b1),     // Select[3] input
      .CE(Clk_Enable && !(Bit_Counter == 7)),     // Clock enable input  //2MORE SRLS
      .CLK(clk_i2c),   // Clock input 
      .D(Q15_2)        // SRL data input
   );
		
SRLC16E #(		      .INIT(16'h8A09) // Initial Value of Shift Register
   ) SRLC16E_inst2 (
      .Q(),       // SRL data output
      .Q15(Q15_2),   // Carry output (connect to next SRL)
      .A0(1'b1),     // Select[0] input
      .A1(1'b1),     // Select[1] input
      .A2(1'b1),     // Select[2] input
      .A3(1'b1),     // Select[3] input
      .CE(Clk_Enable && !(Bit_Counter == 7)),     // Clock enable input  //2MORE SRLS
      .CLK(clk_i2c),   // Clock input 
      .D(Q15_1)        // SRL data input
   );
SRLC16E #(	      .INIT(16'h2A00) // Initial Value of Shift Register
   ) SRLC16E_inst1 (
      .Q(),       
      .Q15(Q15_1),   
      .A0(1'b1),     
      .A1(1'b1),     
      .A2(1'b1),   
      .A3(1'b1),   
      .CE(Clk_Enable && !(Bit_Counter == 7)),     
      .CLK(clk_i2c),    
      .D(1'b0)      
   );
-----------------------------------------------SRL DECLARATIONS--------------------------------------
	always @ (posedge clk_i2c)
begin
	if(RESET || (|i2c_reset) || STATUSin || config_rst)
	begin counter <= 0; SCLreg <= 0;  Clk_Enable <= 0;  end
	
	else if (DONE)               //All bytes transferred
	begin
	counter <= 0;
	SCLreg <= 0;
	Clk_Enable <= 0;
	end
	
	else
	begin
	counter <= counter + 1;
	SCLreg  <= counter[4];      //Output MSB of 5 bit counter to SCL
	if(counter == 31)           //Dividing clock by 32
	Clk_Enable <= 1;
	else
	Clk_Enable <= 0;
	end	
end
	always @ (posedge clk_i2c)
begin
	if(RESET || (|i2c_reset) || STATUSin || config_rst)
	begin IO <= 0; Bit_Counter <= 0; Byte_Counter <=0; STARTCLK <=0; DONE <= 0; LED <=1; end
	else if(Clk_Enable)
 begin
	if(IO==0)                                   //Normal 0 to 7 bits
	begin
	Bit_Counter <= Bit_Counter + 1;         
	if(Byte_Counter == 17)               
	begin
	STARTCLK <= 0;
	DONE <= 1;
	end
	if(Bit_Counter == 7)               
	begin
	IO <= 1;
	Byte_Counter <= Byte_Counter + 1;
	end	
	end
	
	else                                   //IO==1, 9th bit
	begin
	IO <= 0;
	if (Byte_Counter == 2)
	STARTCLK <= 1;
	end
end end assign STARTI2C = (Byte_Counter == 2); assign SDA = IO? (STARTI2C? 1'b0 : 1'bz) : STARTCLK? (SDA_W) : 1'b1 ; //SDA_W = Shift Register Output. assign SCL = STARTCLK? SCLreg : 1'b1; endmodule

Thank you!

Tags (3)
upload.jpg
0 Kudos
1 Solution

Accepted Solutions
Teacher muzaffer
Teacher
10,767 Views
Registered: ‎03-31-2012

Re: I2C Master Code Verification

Jump to solution

@techno-rogue >> Is that(verifying the ACK bit within the FPGA) possible?

 

Certainly. The trick is to know when to look for the said ACK. During ACK cycle, the master gives the bus back to the slave, ie float SDA on the negedge. Then you can sample SDA on the next posedge. If it is high it means pull-up is the only drive and the slave didn't drive it to zero. If it's low, then the slave has driven a zero ie ACK'ed. Again, this is only possible if the master only drives a hard-zero and let's the bus float for a 1; it allows the slave to drive the bus to zero without conflict.

 

 

- Please mark the Answer as "Accept as solution" if information provided is helpful.
Give Kudos to a post which you think is helpful and reply oriented.
14 Replies
Visitor techno-rogue
Visitor
6,653 Views
Registered: ‎12-24-2016

Re: I2C Master Code Verification

Jump to solution
EDIT : .I was wondering if there was any way to verify successful I2C communication by checking whether or not the SDA pin has been pulled low by the SLAVE on the 9th clock cycle.
0 Kudos
Teacher muzaffer
Teacher
6,643 Views
Registered: ‎03-31-2012

Re: I2C Master Code Verification

Jump to solution

@techno-rogue in I2C you should never drive the SDA IO to high. There are only two valid output states for your IO: tri-state or drive to zero. The pull-ups on the wire should take care of the high-state. 

- Please mark the Answer as "Accept as solution" if information provided is helpful.
Give Kudos to a post which you think is helpful and reply oriented.
Visitor techno-rogue
Visitor
6,590 Views
Registered: ‎12-24-2016

Re: I2C Master Code Verification

Jump to solution
assign SDA = IO? (STARTI2C? 1'b0 :  1'bz) : STARTCLK? (SDA_W) : 1'bz;

Thank you! That makes sense.I am declaring the inout SDA and SCL pins PULLUPs in the UCF file.However, it doesn't solve my problem of being able to acknowledge/receive the "ACK" bit of the slave after 1 byte is transferred.Is that(verifying the ACK bit within the FPGA) possible?

 

 

wire ACK;	
assign ACK = IO? (STARTCLK? SDA? 0 : 1 : 0) : 0;   //IO = 9th clock cycle , STARTCLK is used to check if I2C has been initiated or not.
0 Kudos
Teacher muzaffer
Teacher
10,768 Views
Registered: ‎03-31-2012

Re: I2C Master Code Verification

Jump to solution

@techno-rogue >> Is that(verifying the ACK bit within the FPGA) possible?

 

Certainly. The trick is to know when to look for the said ACK. During ACK cycle, the master gives the bus back to the slave, ie float SDA on the negedge. Then you can sample SDA on the next posedge. If it is high it means pull-up is the only drive and the slave didn't drive it to zero. If it's low, then the slave has driven a zero ie ACK'ed. Again, this is only possible if the master only drives a hard-zero and let's the bus float for a 1; it allows the slave to drive the bus to zero without conflict.

 

 

- Please mark the Answer as "Accept as solution" if information provided is helpful.
Give Kudos to a post which you think is helpful and reply oriented.
Visitor techno-rogue
Visitor
6,573 Views
Registered: ‎12-24-2016

Re: I2C Master Code Verification

Jump to solution

Thank you for the timely response! All changes on the SDA line are already taking place on the negedge so it'll be floated on the negedge too.
However, when you say that "the master only drives a hard-zero and let's the bus float for a 1" , Does this also hold for the Shift Register outputs? Let's say that I am transferring 10101010 (AA'H) , surely the ones here need not be floated? I'll try this and get back to you ASAP.

0 Kudos
Visitor techno-rogue
Visitor
6,563 Views
Registered: ‎12-24-2016

Re: I2C Master Code Verification

Jump to solution

I did as you asked and sampled the SDA pin on the 1st posedge after the negedge at which SDA becomes floating.
I have not been able to verify the I2C ack bit.

	begin
        counter  <= counter + 1;
	SCLreg   <= counter[4];
	if(counter == 31)               //for SCL 
	Clk_Enable <= 1;
	else
	Clk_Enable <= 0;
	if (counter == 16)               //posedge SCL
	begin
	if(IO && STARTCLK)               //IO=1, High Impedance 1'bz on SDA line
	begin
	if(SDA == 0 )                    // (SDA == 1)
	LED <= 0;
	end
	end
	end	

Now, even if I change to if SDA == 0 to if SDA == 1,  the  LED does not go from its reset value of 1 to 0.
In the simulation, when I use pullup(SDA) or pulldown(SDA) ,I do get the expected LED toggling from 1 to 0.
My declaration of SDA in .UCF is :

Net "SDA"  LOC = "C5"  | DRIVE = 8 | PULLUP = TRUE;
Net "SDA"  IOSTANDARD = LVCMOS33;
0 Kudos
Visitor techno-rogue
Visitor
6,554 Views
Registered: ‎12-24-2016

Re: I2C Master Code Verification

Jump to solution
	if(counter == 31)           
	Clk_Enable <= 1;
	else if(counter == 16)                 //posedge SCL
	Clk_Enable_Ack <= 1;
	else
	begin
	Clk_Enable <= 0;
	Clk_Enable_Ack <= 0;
	end



       assign LED = Clk_Enable_Ack? (IO && STARTCLK)? SDA : 1'bz : 1'bz;

This does not work either.Perhaps this isn't the right way to read an inout pin.I am completely stumped.The simulation results attached seem to be according to the I2C standard, but the hardware doesn't work,

0 Kudos
Teacher muzaffer
Teacher
6,528 Views
Registered: ‎03-31-2012

Re: I2C Master Code Verification

Jump to solution

@techno-rogue 

two things: when you say hardware doesn't work, how long a pulse of led do you expect to see? if your clock frequency is 50 KHz, the ack will be high for one cycle and the LED will not blink visibly.

 

What I would suggest is to take a look at some working code to see how the IO is managed. There is claim of one core here:  http://opencores.org/project,i2c_master_slave_core

I haven't looked at it myself but give it a try and see how it manages the bus. 

- Please mark the Answer as "Accept as solution" if information provided is helpful.
Give Kudos to a post which you think is helpful and reply oriented.
0 Kudos
Visitor techno-rogue
Visitor
6,476 Views
Registered: ‎12-24-2016

Re: I2C Master Code Verification

Jump to solution

I have gone through the code over and over again, but to no avail, I think there's something wrong with the ADV7171.So, is there any way I could verify the I2C code without using any peripherals/external devices with the Spartan-3E?
Thank you!

UCF DECLARATIONS :


///UCF

Net "SDA" LOC = "C5" | DRIVE = 8 | IOSTANDARD = LVCMOS33 | PULLUP = TRUE;
Net "SCL" LOC = "A4" | DRIVE = 8 | IOSTANDARD = LVCMOS33;

 

 

Also, I am attaching the code and have thoroughly commented it, would be extremely grateful if anyone could have a look.

`timescale 1ns / 1ps
module i2c    ( 			 input STATUSin,             //CLKin bit of DCM
					 input config_rst,           //POWER UP DCM RESET
					 input clk_i2c,
					 input RESET,
					 inout SDA,            
					 output SCL,
					 output reg DONE,
					 output reg LED
					 );

        wire [3 : 0] i2c_reset;   			// to ensure on state reset
	wire SDA_W; 					// srl output
	wire IN;					// ACK bit 
	reg [2 : 0] Bit_Counter;
	reg [4 : 0] Byte_Counter;
	reg [4 : 0] counter;				//Divide incoming clock
	reg IO;                   			//buffer control, 1 = impedance state on inout pin SDA
	reg STARTCLK;             			//Clock Start for SCL
	reg Clk_Enable;           			//input clock_i2c divided by 32 using reg [4 : 0] counter  
        reg SCLreg;               			//I2C clock register 
	reg Clk_Enable_Ack;                             
	

	FDS flop_reg000 (.D(1'b0),  .C(clk_i2c), .Q(i2c_reset[0]), .S(1'b0));	
	FD  flop_reg001 (.D(i2c_reset[0]),  .C(clk_i2c), .Q(i2c_reset[1]));          //Initial RESET
	FD  flop_reg010 (.D(i2c_reset[1]),  .C(clk_i2c), .Q(i2c_reset[2]));
	FD  flop_reg011 (.D(i2c_reset[2]),  .C(clk_i2c), .Q(i2c_reset[3]));

/////SRL----------------------------------------------------------------------------------------------------------------------

  SRL16E #(                        /////START REGISTER
      .INIT(16'hFFFE) // Initial Value of Shift Register
   ) SRL16E_inst9 (
      .Q(SDA_W),        // SRL data output
      .A0(1'b1),    	   // Select[0] input
      .A1(1'b1),     	// Select[1] input
      .A2(1'b1),     	// Select[2] input
      .A3(1'b1),     	// Select[3] input
      .CE(Clk_Enable && !(IO)),     	// Clock enable input
      .CLK(clk_i2c),   	// Clock input
      .D(Q15_8)         // SRL data input
   );
	SRLC16E #(
      .INIT(16'h5600) // Initial Value of Shift Register
   ) SRLC16E_inst8 (
      .Q(),       	// SRL data output
      .Q15(Q15_8),   // Carry output (connect to next SRL)
      .A0(1'b1),     // Select[0] input
      .A1(1'b1),     // Select[1] input
      .A2(1'b1),     // Select[2] input
      .A3(1'b1),     // Select[3] input
      .CE(Clk_Enable && !(IO)),     // Clock enable input
      .CLK(clk_i2c), // Clock input
      .D(Q15_7)      // SRL data input
   );
SRLC16E #(
      .INIT(16'h0538) // Initial Value of Shift Register
   ) SRLC16E_inst7 (
      .Q(),       // SRL data output
      .Q15(Q15_7),   // Carry output (connect to next SRL)
      .A0(1'b1),     // Select[0] input
      .A1(1'b1),     // Select[1] input
      .A2(1'b1),     // Select[2] input
      .A3(1'b1),     // Select[3] input
      .CE(Clk_Enable && !(IO)),     // Clock enable input
      .CLK(clk_i2c),   // Clock input
      .D(Q15_6)        // SRL data input
   );
SRLC16E #(
      .INIT(16'h0000) // Initial Value of Shift Register   //Test Data
   ) SRLC16E_inst6 (
      .Q(),       // SRL data output
      .Q15(Q15_6),   // Carry output (connect to next SRL)
      .A0(1'b1),     // Select[0] input
      .A1(1'b1),     // Select[1] input
      .A2(1'b1),     // Select[2] input
      .A3(1'b1),     // Select[3] input
      .CE(Clk_Enable && !(IO)),     // Clock enable input
      .CLK(clk_i2c),   // Clock input
      .D(Q15_5)        // SRL data input
   );
SRLC16E #(
      .INIT(16'h0000) // Initial Value of Shift Register
   ) SRLC16E_inst5 (
      .Q(),       // SRL data output
      .Q15(Q15_5),   // Carry output (connect to next SRL)
      .A0(1'b1),     // Select[0] input
      .A1(1'b1),     // Select[1] input
      .A2(1'b1),     // Select[2] input
      .A3(1'b1),     // Select[3] input
      .CE(Clk_Enable &&!(IO)),     // Clock enable input
      .CLK(clk_i2c),   // Clock input
      .D(Q15_4)        // SRL data input
   );
SRLC16E #(
      .INIT(16'h0000) // Initial Value of Shift Register
   ) SRLC16E_inst4 (
      .Q(),       // SRL data output
      .Q15(Q15_4),   // Carry output (connect to next SRL)
      .A0(1'b1),     // Select[0] input
      .A1(1'b1),     // Select[1] input
      .A2(1'b1),     // Select[2] input
      .A3(1'b1),     // Select[3] input
      .CE(Clk_Enable && !(IO)),     // Clock enable input
      .CLK(clk_i2c),   // Clock input
      .D(Q15_3)        // SRL data input
   );
SRLC16E #(                                                      /////STOP REGISTER
      .INIT(16'h00CB) // Initial Value of Shift Register
   ) SRLC16E_inst3 (
      .Q(),       // SRL data output
      .Q15(Q15_3),   // Carry output (connect to next SRL)
      .A0(1'b1),     // Select[0] input
      .A1(1'b1),     // Select[1] input
      .A2(1'b1),     // Select[2] input
      .A3(1'b1),     // Select[3] input
      .CE(Clk_Enable && !(IO)),     // Clock enable input  //2MORE SRLS
      .CLK(clk_i2c),   // Clock input 
      .D(Q15_2)        // SRL data input
   );
		
SRLC16E #(		      .INIT(16'h8A09) // Initial Value of Shift Register
   ) SRLC16E_inst2 (
      .Q(),       // SRL data output
      .Q15(Q15_2),   // Carry output (connect to next SRL)
      .A0(1'b1),     // Select[0] input
      .A1(1'b1),     // Select[1] input
      .A2(1'b1),     // Select[2] input
      .A3(1'b1),     // Select[3] input
      .CE(Clk_Enable && !(IO)),     // Clock enable input  //2MORE SRLS
      .CLK(clk_i2c),   // Clock input 
      .D(Q15_1)        // SRL data input
   );
SRLC16E #(	      .INIT(16'h2A00) // Initial Value of Shift Register
   ) SRLC16E_inst1 (
      .Q(),       
      .Q15(Q15_1),   
      .A0(1'b1),     
      .A1(1'b1),     
      .A2(1'b1),   
      .A3(1'b1),   
      .CE(Clk_Enable && !(IO)),     
      .CLK(clk_i2c),    
      .D(1'b0)      
   );

/////SRL----------------------------------------------------------------------------------------------------------
	
	always @ (posedge clk_i2c)
begin
	if(RESET || (|i2c_reset) || STATUSin || config_rst)
	begin counter <= 0; SCLreg <= 0;  Clk_Enable <= 0; LED <= 1; Clk_Enable_Ack <= 0; end
	
	else if (DONE)               //All bytes transferred
	begin
	counter <= 0;
	SCLreg <= 0;
	Clk_Enable <= 0;
	end
	
	else
 begin
	counter <= counter + 1;
	SCLreg  <= counter[4]; 
	
	if(counter == 31)
	begin
	Clk_Enable <= 1;
	Clk_Enable_Ack <= 0;
	end
	
	else
	begin
	Clk_Enable <= 0;
	if(counter == 15 && IO)       Clk_Enable_Ack <= 1;   //For Receiving ACK
	if(Clk_Enable_Ack && !IN)     LED <= 0;
	end
 end
end
	always @ (posedge clk_i2c)
begin
	if(RESET || (|i2c_reset) || STATUSin || config_rst)
	begin IO <= 0; Bit_Counter <= 0; Byte_Counter <=0; STARTCLK <=0; DONE <= 0;  end
	

	else if(Clk_Enable)
 begin
	if(IO==0)                                   //Normal 0 to 7 bits
	begin

	Bit_Counter <= Bit_Counter + 1;         
	
	if(Byte_Counter == 17)               
	begin
	STARTCLK <= 0;
	DONE <= 1;
	end
	

	
	if(Bit_Counter == 7)               
	begin
	if(Byte_Counter > 1) IO <= 1;
	if(Byte_Counter == 1) STARTCLK <= 1;
	Byte_Counter <= Byte_Counter + 1;
	end
	
	end
	
	else                                  
	IO <= 0;
 end
 	
end
	assign SDA =  IO? 1'bz : SDA_W? 1'bz : SDA_W;
	assign SCL = STARTCLK? SCLreg : 1'b1;
	assign IN = SDA;
endmodule
StartingI2C.JPG
EndingI2C.JPG
RandomByteTransferbetween2acks.JPG
0 Kudos
Teacher muzaffer
Teacher
4,730 Views
Registered: ‎03-31-2012

Re: I2C Master Code Verification

Jump to solution

@techno-rogue let me ask one more time what you expect to see: are you really trying to observe a single 50 KHz pulse on an LED? 

 

Also are you simulating with an i2c slave device which properly sends the ack during the turn-around? You need to make sure your master stops driving a low and let the slave device drive the bus or let it float as necessary. 

- Please mark the Answer as "Accept as solution" if information provided is helpful.
Give Kudos to a post which you think is helpful and reply oriented.
0 Kudos
Visitor techno-rogue
Visitor
4,710 Views
Registered: ‎12-24-2016

Re: I2C Master Code Verification

Jump to solution

I apologize if I've been vague about this before.

During initial reset, I reset the LED register to a value of 1.(LED = always lit).If ANY ACK signal is received, LED will go from 1 to 0 and then remain at zero.Now, this doesn't happen.
As for the other part, I do not ever drive the SDA pin high, as you suggested.I have also checked in simulation that after each set of 8 SCL cycles, the SDA pin is always put in a high impedance state.


assign SDA = IO|SDA? 1'bz : 1'b0;

An image of a byte (0x00) being transferred.

sample8bit0transition.JPG
0 Kudos
Teacher muzaffer
Teacher
4,669 Views
Registered: ‎03-31-2012

Re: I2C Master Code Verification

Jump to solution

@techno-rogue 

>> I have also checked in simulation that after each set of 8 SCL cycles, the SDA pin is always put in a high impedance state.

 

do you have an appropriate slave in your simulation model which can drive the SDA bus for ACK ?

- Please mark the Answer as "Accept as solution" if information provided is helpful.
Give Kudos to a post which you think is helpful and reply oriented.
0 Kudos
Visitor techno-rogue
Visitor
3,935 Views
Registered: ‎12-24-2016

Re: I2C Master Code Verification

Jump to solution

I got my hands on new hardware yesterday and the code works out wonderfully well.I was able to verify the exact number of Acks. I apologize for consuming so much time and resources.However, I have a new question, and am not sure whether to post it here or start another thread? The question pertains to a similar issue regarding the I2C bus.Specifically, instead of using the SRL primitive, I created my own module of an 8 bit shift register with synchronous parallel load enable.This modification was necessary to selectively program a few registers and not rely on the Auto Increment feature.The simulation patterns (START,STOP, Byte Transfer) remain the same, but I don't receive even one ACK from the slave.

	always @ (*)
begin
	case (Byte_Counter) 
	0 : LUT <= 8'h56;                        			//Device Addres  
	1 : LUT <= i2c_address;                         //Register Address
	2 : LUT <= i2c_val;                        		//Data
	5 : LUT <= 8'h7E;                        			//STOP & START
	default : LUT <= 8'hFF;
	endcase
end

	always @ (*)
begin
	case (Reg_Counter)
	1 :begin i2c_address <= 8'h00; i2c_val <= 8'h02;	end           
	2 :begin i2c_address <= 8'h03; i2c_val <= 8'h00;   end   
	3 :begin i2c_address <= 8'h05; i2c_val <= 8'h09;   end   
	4 :begin i2c_address <= 8'h07; i2c_val <= 8'h07;   end
	5 :begin i2c_address <= 8'h09; i2c_val <= 8'h00;	end
	default : begin i2c_address <=8'h00; i2c_val <= 8'h00;   end
	endcase
end

Variable LUT is loaded into the 8 bit Shift Register on the 9th(when SDA=high impedance) clock cycle.

Since this wasn't working, I registered the output of the muxes inferred above and forced it into the 8 bit SRL :

always @ (posedge clk_i2c) temp <= LUT;

However, that hasn't worked either, but I do get one interesting warning :

INFO:Xst:2260 - The FF/Latch <i2c_ADV7171/temp_6> in Unit <Verilog> is equivalent to the following FF/Latch : <i2c_ADV7171/temp_4>

As far as I can tell, this shouldn't happen because temp[6] and temp[4] aren't throughout equal.
 


0 Kudos
Visitor techno-rogue
Visitor
3,893 Views
Registered: ‎12-24-2016

Re: I2C Master Code Verification

Jump to solution

I was just experimenting and realized that when I replace my custom Shift Register (provided above) with the SRL16 E primitive, the design works.This is very surprising.I tried to make small changes to the logic by using a simple register with a Load Enable and a multiplexer to single out the bits.However, that doesn't work either.


Why is it that the SRL16E primitive design works but not the others? I have provided code for my shift register (serial in,serial out, parallel synchronous load) module above.The simulation results are the same for all three designs.

Can anyone offer an explanation for this apparently bizarre behavior? 

0 Kudos