I2C Verilog Code Explanation II









In my previous post, I explained working of I2C Verilog code. Same is continued here.

else if(left_bits == 10)begin
  if(sda == 0)begin
   left_bits <= 1;
   direction <= 1;
   temp <= temp_reserved;
  end
  else begin
   direction <= 1;
   alpha <= 0;
   left_bits <= left_bits + 1;
  end
end


When the ACK/NACK is received at 9 then at 10 it is compared with 1 and 0. If the acknowledgment received is 0 then left_bits is reset to its initial value that is 1. The direction is again set to 1 to make the Master ready to send data to Slave. The register TEMP which is now XXXXXXX gets renewed or say reset with a copy that we stored earlier i.e. in TEMP_RESERVED. If the received acknowledgment is 1 then direction will be changed to 1 because now the Master will have to send the address of register which stores data in the Slave. Setting ALPHA = 0 is not necessary here though. LEFT_BITS is again incremented.

else if(left_bits >=11 && left_bits <=17)begin
  alpha <= register[6];
  register <= register<<1;
  left_bits <= left_bits + 1;
end


From 11 to 17 i.e. 7 counts the Master will send the address of the register of the Slave from where data has to be retrieved. The process is same as I explained earlier to send Slave address hence I am not gonna repeat the same.

else if (left_bits >= 18 && left_bits <= 28)begin
  direction <=0;
  left_bits <= left_bits + 1;
end


From 18 to 28 the slave will send an ACK bit to tell the master that if the register address is matched or not. This happens on 19th cycle. However, there is a clock cycle delay here in Slave at this position. The SDA line is continuous from Master to Slave. Since we cannot do any operation on wires, therefore, we have to store data from wire to a register in the Slave in order to use it. However, storing this data results in an extra clock cycle, since values get updated after the clock cycle and not along with clock cycle for a non-blocking assignment (<=). For blocking assignment (=) the task is done first having the blocking assignment and the rest of the tasks are completed. 

Example
initial begin
a = 0;
c = 0;
end
always @(posedge clk)begin
  a <= a + 1;
  a <= a + 2;
  c <= c + 1;
  a <= a + 3;
  c <= c + 2;
end

After executing the above command if you are thinking that the result will be a = 6 and c = 3, then you are wrong !!.
The right answer is a = 3 and c = 2;

However, if you code like this snippet below using blocking assignments
always @(posedge clk)begin
  a = a + 1;
  a = a + 2;
  c = c + 1;
  a = a + 3;
  c = c + 2;
end
 The output will be a = 6 and c = 2;

Whenever we use non-blocking assignments each line of code does not depend on the previous line. They will occur simultaneously with the past data. Data is changed after the clock cycle ends and not immediately. In case of blocking assignment, the first line will be given first priority. After it's execution, the second line is executed. Data is changed immediately. 
Thus 
a <= a + 1; mean a = 0 + 1 = 1
a <= a + 2 means a = 0 + 2 = 2 . It won't depend on the previous calculation. 
a <= a + 3 means a = 0 + 3 = 3   It won't depend on the previous calculation
At the end of clock cycle a = 3

However,
a = a + 1 means a = 0 + 1 = 1. This will be executed immediately.
a = a + 2 means a = 1 + 2 = 3 This will be executed after the previous execution
a = a + 3 means a = 3 + 3 = 6.

Non-blocking assignments are used only when sequential conditions are present i.e. flip-flops. Blocking assignments are used for combinational blocks. I hope it is clear the difference between blocking and non-blocking assignments. 

To manage this bit delay in slave I had to use a blocking assignment. The Slave sends the 8-bit data stored in its register to Master by setting direction = 0 on the SDA line. 

else if(left_bits == 29)begin
  direction <= 1;
  alpha <= 1;
  left_bits <= left_bits + 1;
end


For the 29th count, the Master will set the direction 1 and the Slave will set the direction as 0 as it is the turn of Master to send the acknowledgment bit now informing the Slave that it has received the 8-bit data. The acknowledgment is sent by assigning ALPHA = 1 i.e. SDA is pulled high. 

else if(left_bits == 30)begin
  alpha <= 0;
  left_bits <= left_bits + 1;
end
else if(left_bits == 31)begin
  #2 alpha <= 1;
  left_bits <= left_bits + 1;
end
else if(left_bits == 32)
  a <= 0;
end

At the count 30 ALPHA is set to 0 as ACK is only of 1 bit. For the count 31 ALPHA is set to 1 i.e SDA is pulled high. No negative edge is present afterward here. For the count 32 "a" is set to 0 thus switching SCL line to 1. Since there is not negedge of SDA there SCL won't start clocking again which I have already explained earlier. #2 is the time delay to 2 ns to introduce the STOP condition. 

Fig - STOP Condition

Although #1 should be present there as in the above image I mistakenly added an extra clock cycle. You are free to experiment.

I'll explain the SLAVE code later.

So Long

I2C Verilog Code Explanation I


In this post, I am going to explain my previous post regarding I2C. You can visit the post by clicking here.



INOUT  SDA: The SDA line is the inout port because Master will send data, address along this line as well as the Slave will send ACK/ NACK along the same SDA line hence it has to be inout type.

OUTPUT REG SCL: The SCL line will be the output from Master to other Slaves. SCL is controlled by Master here by the register "a" in the code.

REG DIRECTION: This register will decide whether the direction of flow of data on the SDA line. The line assign sda = direction?alpha:1'bz. using the direction keyword.

Its equivalent code will be
 if(direction==1)
   sda = alpha;
 else if(direction==0)
  sda = 1'bz;

If Master sets the direction as 1 then sda = alpha. At the same moment, Slave must also have the direction set to 0 in order to allow data from Master. When the Slave wants to send the data then the Slave will set the direction as 1 and Master will set it as 0.

REG ALPHA: This register holds the bit that has to be sent on the SDA line. Since SDA is a wire, therefore it is not possible to use it inside always@ block.

REG [6:0] ADDRESS: This 7-bit register holds the 7bit register holds the address of the slave.

REG[7:0] TEMP: This 8-bit register holds the address of the slave along with RW bit that has to be sent on the SDA line.

REG[7:0] TEMP_RESERVED: This 8-bit register just holds a copy of TEMP register for future use.

TEMP = {ADDRESS,RW}: This concatenates the 7-bit address and 1 bit RW into an 8-bit register and stores the final data back in TEMP.
always @(posedge clk)begin
  if(a==0)
    scl <= 1;
  else if(a==1)
    scl <= !scl;
end

Here "a" is a switch. When "ON" it will clock the SCL line. When OFF it will pull up the SCL line HIGH. It is just a manual control for Master to control SCL.

always @(negedge sda)
  a <= 1;
As soon as the SDA line is pulled down, "a" is triggered to start SCL clock. This is the START condition. Although SDA has many negative edges it won't affect SCL because of above code. When we want a STOP condition then SDA is pulled HIGH first. Thus no negative edge occurs after that point and then "a" is triggered low which pulls SCL HIGH and STOP condition is achieved.
always @(negedge scl)begin
  #1 forever #2 scl2 <= !scl2;
SCL2 is an internal clock which starts as soon as SCL is triggered. This is done because we cannot use SCL for our operation. SDA only changes when SCL is LOW (See the LAST image in my post) and not on positive edge or negative edge. #1 is the delay of 1ns. SCL2 starts ticking after 1ns start of SCL. Using the posedge of SCL2 we achieve our required condition to change SDA when SCL is LOW.


Look at this image above. SDA changes when SCL is low (in middle). It neither changes at positive edge nor at the negative edge.

SDA changes at positive edge / negative edge of SCL2 which itself changes at LOW SCL.
Thus SCL and SCL2 are 1ns apart.
integer left_bits = 1;
LEFT_BITS is just a counter for proper operation that I used. It would create a havoc working without it.
always @(negedge scl2)begin
All the SDA operations are operated on a clocked edge of SCL2 not SCL to maintain I2C standard.
if(left_bits <= 8) begin
  alpha <= temp[7];
  temp <= temp<<1;
  left_bits <= left_bits + 1;
end

The above code above is pretty simple. It loops for 8 times in order to send 8 bits which include 7-bit Slave address and 1-bit RW. temp[7] is the MSB which has to be sent first on SDA. (bit by bit).
However, after sending the MSB we have to send the next bit i.e temp[6] therefore, I left shifted the temp bit which shifts 1 bit towards left.

Example:
If temp[7:0] = 10101010;
temp = temp<<1;  Here temp will be 0101010X

if I had used temp = temp<<<1; then temp would be 01010100.

If I had used temp = temp<<2; then temp would be 101010XX

I hope I have cleared the difference between << and <<<. Similarly, we can use >> and >>> although it is of no use here.

NOTE: Initially, the direction is set to 1 in Master and 0 in slave i.e. Master is sending data on SDA line which SLAVE has to accept.
else if(left_bits == 9)begin
direction <= 0;
ack <= sda;
left_bits <= left_bits + 1;
end

After sending 8 bits direction is changed to 0 in Master and 1 in Slave. It is the turn of Master to accept from Slave. At this moment Slave, if the address is matched it will send 0 NACK or 1 if the address is not matched. ACK is opposite of NACK.

.....................
To be continued in next post.



ESP8266 WebSockets

I worked on web sockets on a Wemos D1 mini using an ESP8266 chip and it worked fabulously. I have designed an "HTML" file which can initiate a connection with my D1 mini to control the onboard LED.

Any board with ESP will work here. In my application, I can switch on and switch off the onboard LED of the board. A continuous connection was also made to see the real-time calculation going on the ESP board with my browser.

However, I faced some problems like socket timeout which I haven't solved yet. The problem is that when the ESP is connected to the browser, it shows the real-time data for some minutes after which the connection is stopped. I still have to figure out the reason to solve this issue.

WebSockets have helped me to a great extent. I can use the serial monitor over wifi now. I can even update the values over wifi and get back the current readings.

I began with the web socket library by "Ipnica" at GitHub. Click here to download the library. After installing ESP board on Arduino IDE and the above-downloaded library I was good to go.

The code for a simple WebSocket connection is here

I am assuming readers know most of the commands here.

WebSocketsServer webSocket = WebSocketsServer(81);

This will create an instance of WebSocket server at port 81. Your address will be like ws://192.168.5.2:81/
Do remember that "ws" here represents WebSockets. Its the representation of a web socket url. Similarly "wss" is for WebSocket Secure just like HTTPS.

void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length)

This void method is very important. The payload will contain the data that has to be sent or is being received. The length is the length of the payload. "type" indicates the type of data i.e TEXT of Binary. Num contains the data about the IP address of the connected client.

case WStype_DISCONNECTED:
  • When the socket is disconnected this condition is fired up.

case WStype_CONNECTED:
  • When the socket is connected successfully this condition is fired up.

case WStype_TEXT:
  • When the data received is of type TEXT
case WStype_BIN:
  • When the data received is of type Binary !!

webSocket.sendTXT(num, x, strlen(x));
  • When the user wants to send a data to the browser of type TEXT. The first argument is the details about the ip address of the connected client. The second argument is a const char * type data. The third argument is the length of const char *x.
It can also be used like this.
webSocket.sendTXT(num, "Yay It works!!", strlen("Yay It works!!));


Incase when we want to send normal string then the command should be

String s = String(a);
char const *x = s.c_str();
char const *x = s.c_str();

Here s can be "Hello" or any integer converted into a String.

String _payload = String((char *) &payload[0]);
  • This will store the incoming character array inform of string into the payload.
The HTML file 
con = new WebSocket('ws://192.168.1.5:81/',['arduino']);
  • A new websocket connection is initiated with the mentioned ws address and the following protocol. The first argument can be variable too. My Wemos has the wsIP ws://192.168.1.5:81/
con.onopen = function(event){ console.log("Opened"); };
Whenever a new Web Socket connection has opened this property "onopen" is initiated. You can put any conditions in the curly braces. If you are using Chrome then press Ctrl + Shift + I and then click console tab above to see the message that will be logged in console, once a connection has been opened.

con.onmessage = function (evt) {
var received_msg = evt.data;
document.getElementById("message").innerHTML = evt.data;};

Whenever a new message arrives on the browser this property is fired up. An event is raised that contains the data received. 

con.onclose = function(){
console.log("Masakaaaa!!!");};


Whenever a WS connection is closed the above function is fired up which may or may not log events depending upon the user choice. I have logged a string on the console here.

function SwitchON() {
var toSend = "ON";
con.send(toSend); };

This is a function named SwitchON. Whenever this function is called, a string is sent to the server.

<input type="button" onclick="SwitchON()"> Turn LED Off

This will create a button which when clicked will call the SwitchON function which in turn will send data.

Here is the working of the WebSocket.



So Long