Summary
Many digital sensors and digital control chips (DDS, serial ADC, serial DAC) communicate with the controller through IIC bus. However, IIC protocol is still a slow mode of communication. The standard IIC rate is 100 kbit/s and the fast mode rate is 400 kbit/s. This paper focuses on how to use counter control and frequency division clock control to complete the reading and writing operation of IIC.
IIC Protocol
_IIC protocol is a multi-computer communication, which consists of SDA data line and SCL clock line. All IIC devices can be mounted on the bus, but each device has a unique device read address and device write address. The device's read/write address can be seen in the chip datasheet using IIC as the digital interface, and the corresponding read/write timing and speed requirements can be found. The following is a general IIC protocol sequence:
_We can summarize the timing status of five IIC protocols:
In idle state, when both SDA and SCL signal lines are in high-level bus idle state.
_2. Start signal, SCL is the beginning of a data transmission marked by the descent edge on the SDA signal line during the high level period. The start signal should be initiated by the host.
Data transmission, under the control of SCL synchronization, SDA serial transmission of each bit, so the transmission of 8 bits data requires 8 SCL clocks. The state of SDA must be stable when SCL is at high level, while the state of SDA must be allowed to change only when SCL is at low level.
_4. Answer signal. Every 8-bit byte transmitted on IIC bus releases the bus during the 9th pulse. A response signal is sent by the receiver. Whether the feedback has been received successfully or not.
_5. Stop signal, release SDA signal line to high level during SCL keeping high level, mark the end of data transmission, IIC bus also returned to idle state.
Counter controls IIC reading and writing
_In "Basic Design of FPGA (3): UART Serial Communication", we have come into contact with the method of using counter to control timing, which is also practical in controlling IIC communication. A complete write operation is as follows:
case( i )
0: // iic Start
begin
isOut <= 1; //SDA port output
if( C1 == 0 ) rSCL <= 1'b1;
else if( C1 == 200 ) rSCL <= 1'b0; //SCL from high to low
if( C1 == 0 ) rSDA <= 1'b1;
else if( C1 == 100 ) rSDA <= 1'b0; //SDA changes from high to low
if( C1 == 250 -1) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
1: // Write Device Addr
begin rData <= {4'b1010, 3'b000, 1'b0}; i <= 5'd7; Go <= i + 1'b1; end
2: // Wirte Word Addr
begin rData <= Addr_Sig; i <= 5'd7; Go <= i + 1'b1; end
3: // Write Data
begin rData <= WrData; i <= 5'd7; Go <= i + 1'b1; end
4: //iic Stop
begin
isOut <= 1'b1;
if( C1 == 0 ) rSCL <= 1'b0;
else if( C1 == 50 ) rSCL <= 1'b1; //SCL first changes from low to high
if( C1 == 0 ) rSDA <= 1'b0;
else if( C1 == 150 ) rSDA <= 1'b1; //SDA from low to high
if( C1 == 250 -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
5:
begin isDone <= 1'b1; i <= i + 1'b1; end //Write I2C to End
6:
begin isDone <= 1'b0; i <= 5'd0; end
7,8,9,10,11,12,13,14: //Send Device Addr/Word Addr/Write Data
begin
isOut <= 1'b1;
rSDA <= rData[14-i]; //Send high-bit first
if( C1 == 0 ) rSCL <= 1'b0;
else if( C1 == 50 ) rSCL <= 1'b1;
else if( C1 == 150 ) rSCL <= 1'b0;
if( C1 == F250K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
15: // waiting for acknowledge
begin
isOut <= 1'b0; //Change SDA port to input
if( C1 == 100 ) isAck <= SDA;
if( C1 == 0 ) rSCL <= 1'b0;
else if( C1 == 50 ) rSCL <= 1'b1;
else if( C1 == 150 ) rSCL <= 1'b0;
if( C1 == F250K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
16:
if( isAck != 0 ) i <= 5'd0;
else i <= Go;
endcase
When writing data to IIC bus, three 8 bits bytes of data are needed to be written to the device write address, the device write address and the data to be written in turn. i represents different states on the bus, and controls the jump between states through the counter. When i is 0, the start signal is sent; when i is 7-14, the transmission of 8 bits data is controlled; when i is 1, 2 and 3, the device address, byte address and data are respectively called 7-14 to complete the data transmission; the rest are stop bit, reply bit, IIC communication completion position and so on.
_The method of reading data from devices is the same as this, but usually it is necessary to write device address and device address to IIC bus before reading data. The whole process of reading data is a little more troublesome than writing data, but as long as the process of jumping between States is well controlled.
Frequency Division Clock Control IIC Read and Write
_The method of controlling communication time sequence by counter is very flexible, almost all of the time sequence methods can be accomplished by this method; the disadvantage is that it is too troublesome to control the jump between states, and the more complicated the time sequence is, the more troublesome it is to use. In fact, in the "FPGA acquisition-transmission-display system (2): temperature acquisition based on FPGA and Ethernet transmission", when I am working on DS18B20. Sequence control is the method of counter control. DS18B20 requires a lot of timing, so the state jump in DS18B20 is quite complex.
In fact, when controlling IIC, a serial protocol with fixed clock rate, a low-frequency communication clock can be generated in external frequency or PLL to control the data transmission process. As follows:
always@(posedge clock_i2c)
begin
if(reset_n==1'b0) begin
tr_end<=0;
ack1<=1;
ack2<=1;
ack3<=1;
sclk<=1;
reg_sdat<=1;
end
else
case(cyc_count)
0:begin ack1<=1;ack2<=1;tr_end<=0;sclk<=1;reg_sdat<=1;end
1:reg_sdat<=0; //Begin transmission
2:sclk<=0;
3:reg_sdat<=i2c_data[23];
4:reg_sdat<=i2c_data[22];
5:reg_sdat<=i2c_data[21];
6:reg_sdat<=i2c_data[20];
7:reg_sdat<=i2c_data[19];
8:reg_sdat<=i2c_data[18];
9:reg_sdat<=i2c_data[17];
10:reg_sdat<=i2c_data[16];
11:reg_sdat<=1; //Response signal
12:begin reg_sdat<=i2c_data[15];ack1<=i2c_sdat;end
13:reg_sdat<=i2c_data[14];
14:reg_sdat<=i2c_data[13];
15:reg_sdat<=i2c_data[12];
16:reg_sdat<=i2c_data[11];
17:reg_sdat<=i2c_data[10];
18:reg_sdat<=i2c_data[9];
19:reg_sdat<=i2c_data[8];
20:reg_sdat<=1; //Response signal
21:begin reg_sdat<=i2c_data[7];ack2<=i2c_sdat;end
22:reg_sdat<=i2c_data[6];
23:reg_sdat<=i2c_data[5];
24:reg_sdat<=i2c_data[4];
25:reg_sdat<=i2c_data[3];
26:reg_sdat<=i2c_data[2];
27:reg_sdat<=i2c_data[1];
28:reg_sdat<=i2c_data[0];
29:reg_sdat<=1; //Response signal
30:begin ack3<=i2c_sdat;sclk<=0;reg_sdat<=0;end
31:sclk<=1;
32:begin reg_sdat<=1;tr_end<=1;end //IICEnd of transmission
endcase
__can see that the sensitive target of this always block is clock_i2c, the IIC clock signal after frequency division. The whole transmission process is clear at a glance. These two timing control methods are not only suitable for IIC protocol, but also for other serial protocols. This method will still be used in the next chapter of "Basic Design of FPGA (V): SPI Protocol".