Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
17 years ago

I2C code help

Hello. Im in the stages of designing an I2C interface to the audio codec on my fpga. Its very simple, as im new to verilog and still in debugging stages. One snag is when Im attempting to read certain bits of a parallel input. My code, in state s2, seems alright but it goes unstable in simulation when leaving s2. Can you think of what is wrong, or an alternative way of coding my problem?


module i2c(SCL_io, SDA_io, clk, rst, write);
input write, clk, rst;
output SCL_io;
inout SDA_io;
reg stopcount 			= 0;
reg bitcount			= 0;
reg msbcount			= 0;
reg indata				= 8'b01001010; 
reg SCL,SDA;
reg pres, next;
parameter s0=4'b0000,s1=4'b0001,s2=4'b0010,s3=4'b0011,s4=4'b0100,s5=4'b0101,s6=4'b0110,s7=4'b0111,s8=4'b1000; 
always@(posedge clk)
begin
	if(rst) 	pres=s0;
	else 		pres=next;
end
always @ (pres or write or stopcount or msbcount or indata or bitcount)
begin
	case (pres)
	s0: begin
		SDA = 1'b1;
		SCL = 1'b1;
		if(write) next=s1;
		else next=s0;
		end
		
	s1:	begin
		SDA = 1'b0;
		SCL = 1'b1;
		next=s2;
		end
		
	s2: begin
		SDA = 1'b0;
		SCL = 1'b0;
		stopcount <= stopcount + 1;
		if(stopcount == 4) next=s8; 
		else
					begin
					case (msbcount)
					1: begin
					if( indata == 1'b1) 
						next=s5; 
						else next=s3;
						end
					
					2: begin
					if( indata == 1'b1) 
						next=s5; 
						else next=s3;
						end
					
					3: begin
					if( indata == 1'b1) 
						next=s5; 
						else next=s3;
						end
					
					4: begin
					if( indata == 1'b1) 
						next=s5; 
						else next=s3;
						end
					
					5: begin
					if( indata == 1'b1) 
						next=s5; 
						else next=s3;
						end
					
					6: begin
					if( indata == 1'b1) 
						next=s5; 
						else next=s3;
						end
					
					7: begin
					if( indata == 1'b1) 
						next=s5; 
						else next=s3;
						end
					
					8: begin
					if( indata == 1'b1) 
						next=s5; 
						else next=s3;
						end
					endcase
					end
				
					
					
		end				
		
	s3:	begin
		SDA = 1'b0;
		SCL = 1'b1;
		next=s4;
		end
		
	s4:	begin
		SDA = 1'b0;
		SCL = 1'b0;
		bitcount <= bitcount+1;
		msbcount <= msbcount+1;
		if(bitcount == 8) next=s7;
		else
					begin
					case (msbcount)
					1: begin
					if( indata== 1'b1) 
						next=s5; 
						else next=s3;
						end
					
					2: begin
					if( indata== 1'b1) 
						next=s5; 
						else next=s3;
						end
					
					3: begin
					if( indata== 1'b1) 
						next=s5; 
						else next=s3;
						end
					
					4: begin
					if( indata== 1'b1) 
						next=s5; 
						else next=s3;
						end
					
					5: begin
					if( indata== 1'b1) 
						next=s5; 
						else next=s3;
						end
					
					6: begin
					if( indata== 1'b1) 
						next=s5; 
						else next=s3;
						end
					
					7: begin
					if( indata== 1'b1) 
						next=s5; 
						else next=s3;
						end
					
					8: begin
					if( indata== 1'b1) 
						next=s5; 
						else next=s3;
						end
					endcase
					end
				
					
					
		end				
		
		
			
	s5:	begin
		SDA = 1'b1;
		SCL = 1'b1;
		next=s6;
		end
		
	s6:	begin
		SDA = 1'b1;
		SCL = 1'b0;
		bitcount <= bitcount+1;
		msbcount <= msbcount+1;
		if(bitcount == 8) next=s7;
		else
					begin
					case (msbcount)
					1: begin
					if( indata== 1'b1) 
						next=s5; 
						else next=s3;
						end
					
					2: begin
					if( indata== 1'b1) 
						next=s5; 
						else next=s3;
						end
					
					3: begin
					if( indata== 1'b1) 
						next=s5; 
						else next=s3;
						end
					
					4: begin
					if( indata== 1'b1) 
						next=s5; 
						else next=s3;
						end
					
					5: begin
					if( indata== 1'b1) 
						next=s5; 
						else next=s3;
						end
					
					6: begin
					if( indata== 1'b1) 
						next=s5; 
						else next=s3;
						end
					
					7: begin
					if( indata== 1'b1) 
						next=s5; 
						else next=s3;
						end
					
					8: begin
					if( indata== 1'b1) 
						next=s5; 
						else next=s3;
						end
					endcase
					end
				
					
					
		end				
			
	s7: begin
		SDA = 1'b1;
		SCL = 1'b1;
		if(~SDA) next=s2;
		else next=s7;
		next=s2;
		end
		
	s8: begin
		SDA = 1'b1;
		SCL = 1'b0;
		next=s0;
		end
	endcase
end
assign SDA_io = SDA;
assign SCL_io = SCL;
endmodule

7 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    It seems you don't initialize "stopcount" and go out of the s2 state.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    stopcount is initalised at the top. does it need to be defined as zero again? Also, i think it has something to do with msbcount. what do u think?

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    i have been playing with my code, however the counts are just so unstable. Any better method you could suggest to get this working efficeintly?

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    The counters need to be in a clocked process otherwise they'll increment every time a signal in the sensitivity list changes and also you'll find it won't act the same way in hardware.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Do you think putting the counters in their own clk sensitive case statement would help? I hava feeling it wont work. Any strategies you can suggest?

    As a side note, i have a master i2c core working on a pic. but im having trouble getting the fpga to send back and ack. Is this the right way to set up linking the pic to the fpga?

    [input from pic SDA]--------------------[bi-directional to/from audio codec]

    [input from pic SCL]--------------------[output to audio codec]
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hello,

    Although I didn't test it, I attach the code modified. In the verilog reg defines registers and wires, you should make it clear which are real register and which are just wire. I hope it will help.

    Thanks,
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Gee, you are a genious! Thanks for your help, it works well now!

    I changed my code a bit though, instead of msbcount and all those case satements I just used a right shift operator and tested bit 7.

    Only problem now is simulating when SDA is forced low for the acknowledgement. I have tried forcing SDA low at the right point in the waveform, but it doesnt seem to work...anything special i need to do to simulate bi-directional pins?