|  | @@ -5,17 +5,24 @@
 | 
	
		
			
				|  |  |  // 0 - write data/command
 | 
	
		
			
				|  |  |  //     [15:8] - data bits (must be 1 for read)
 | 
	
		
			
				|  |  |  //     [7]    - ACK bit (must be 1 for write)
 | 
	
		
			
				|  |  | -//     [2]    - follow with P condition
 | 
	
		
			
				|  |  | -//     [1]    - follow with Sr condition
 | 
	
		
			
				|  |  | +//     [2:1]  - 00 = normal byte (S if needed, no following Sr/P)
 | 
	
		
			
				|  |  | +//              01 = follow with Sr (S if needed)
 | 
	
		
			
				|  |  | +//              10 = follow with P (S if needed)
 | 
	
		
			
				|  |  | +//              11 = dummy clocks (no S, for synchronization)
 | 
	
		
			
				|  |  |  //
 | 
	
		
			
				|  |  |  // 1 - read data/status
 | 
	
		
			
				|  |  |  //     [15:8] - data bits
 | 
	
		
			
				|  |  |  //     [7]    - ack bit
 | 
	
		
			
				|  |  | -//     [1]    - bus idle (after P condition)
 | 
	
		
			
				|  |  | +//     [6]    - SDA
 | 
	
		
			
				|  |  | +//     [5]    - SCL
 | 
	
		
			
				|  |  | +//     [4]    - "started" (no S will be issued before next byte)
 | 
	
		
			
				|  |  | +//     [2:1]  - bits [2:1] from last command
 | 
	
		
			
				|  |  |  //     [0]    - busy
 | 
	
		
			
				|  |  |  //
 | 
	
		
			
				|  |  |  // 2 - baud rate divisor (f = clk/(4*(divisor+1)))
 | 
	
		
			
				|  |  |  //
 | 
	
		
			
				|  |  | +// 3 - bit [0] - send dummy clocks on SCL when idle
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  |  // This unit handles S(r) and P conditions by considering two classes of
 | 
	
		
			
				|  |  |  // symbols: "normal", when SCL is asserted at the end of the
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -46,7 +53,6 @@ module i2c (
 | 
	
		
			
				|  |  |     reg			  busy;		// Data received, running
 | 
	
		
			
				|  |  |     reg			  end_s, end_p; // Trailing S(r) or P
 | 
	
		
			
				|  |  |     reg			  started;	// S sent, but not P
 | 
	
		
			
				|  |  | -   reg			  is_sr;	// Sending an S(r)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     reg [1:0]		  outsymb; // Output symbol [abnormal, data]
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -68,6 +74,8 @@ module i2c (
 | 
	
		
			
				|  |  |  	  sda_out <= 1'b1;
 | 
	
		
			
				|  |  |  	  phase   <= 2'b00;
 | 
	
		
			
				|  |  |  	  do_read <= 1'b0;
 | 
	
		
			
				|  |  | +	  end_s   <= 1'bx;
 | 
	
		
			
				|  |  | +	  end_p   <= 1'bx;
 | 
	
		
			
				|  |  |  	  started <= 1'b0;
 | 
	
		
			
				|  |  |         end
 | 
	
		
			
				|  |  |       else
 | 
	
	
		
			
				|  | @@ -128,9 +136,9 @@ module i2c (
 | 
	
		
			
				|  |  |  				do_read <= 1'b1;
 | 
	
		
			
				|  |  |  				if (bitctr[3])
 | 
	
		
			
				|  |  |  				  begin
 | 
	
		
			
				|  |  | -				     bitctr  <= end_p ? 4'd12 :
 | 
	
		
			
				|  |  | -						end_s ? 4'd14 : 4'd0;
 | 
	
		
			
				|  |  | -				     busy    <= end_p;
 | 
	
		
			
				|  |  | +				     bitctr  <= end_s ? 4'd14 :
 | 
	
		
			
				|  |  | +						end_p ? 4'd12 : 4'b0;
 | 
	
		
			
				|  |  | +				     busy    <= end_p & ~end_s;
 | 
	
		
			
				|  |  |  				     // If we are to be followed by
 | 
	
		
			
				|  |  |  				     // an S(r) condition, we are not
 | 
	
		
			
				|  |  |  				     // really "started".
 | 
	
	
		
			
				|  | @@ -152,13 +160,13 @@ module i2c (
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  			   // Start condition
 | 
	
		
			
				|  |  |  			   4'd14: begin
 | 
	
		
			
				|  |  | -			      started <= 1'b1;
 | 
	
		
			
				|  |  | +			      started <= ~(end_s & end_p);
 | 
	
		
			
				|  |  |  			      outsymb <= 2'b11; // A1
 | 
	
		
			
				|  |  |  			   end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  			   4'd15: begin
 | 
	
		
			
				|  |  | -			      started <= 1'b1;
 | 
	
		
			
				|  |  | -			      outsymb <= 2'b00; // N0
 | 
	
		
			
				|  |  | +			      // N0, unless dummy in which case N1
 | 
	
		
			
				|  |  | +			      outsymb <= { 1'b0, ~started };
 | 
	
		
			
				|  |  |  			   end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  			   default: begin
 | 
	
	
		
			
				|  | @@ -202,14 +210,16 @@ module i2c (
 | 
	
		
			
				|  |  |     //
 | 
	
		
			
				|  |  |     always_comb
 | 
	
		
			
				|  |  |       case (addr)
 | 
	
		
			
				|  |  | -       2'b00: rdata = { 16'b0, wreg, 4'b0, end_p, end_s, busy | do_read };
 | 
	
		
			
				|  |  | -       2'b01: rdata = { 16'b0, rreg, 4'b0, end_p, end_s, busy | do_read };
 | 
	
		
			
				|  |  | +       2'b00: rdata = { 16'b0, wreg, i2c_sda, i2c_scl, started, 1'b0,
 | 
	
		
			
				|  |  | +			end_p, end_s, busy | do_read };
 | 
	
		
			
				|  |  | +       2'b01: rdata = { 16'b0, rreg, i2c_sda, i2c_scl, started, 1'b0,
 | 
	
		
			
				|  |  | +			end_p, end_s, busy | do_read };
 | 
	
		
			
				|  |  |         2'b10: rdata = { 24'b0, divisor };
 | 
	
		
			
				|  |  | -       default: rdata = 32'b0;
 | 
	
		
			
				|  |  | +       default: rdata = 32'bx;
 | 
	
		
			
				|  |  |       endcase // casez (addr)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     //
 | 
	
		
			
				|  |  | -   // IRQ (edge) when unit idle
 | 
	
		
			
				|  |  | +   // IRQ (level) when unit idle
 | 
	
		
			
				|  |  |     //
 | 
	
		
			
				|  |  |     assign irq = ~(busy | do_read);
 | 
	
		
			
				|  |  |  
 |