Drop Down MenusCSS Drop Down MenuPure CSS Dropdown Menu

Saturday, April 15, 2017

Verilog Code for I2C Protocol


I2C PROTOCOL

Hola Amigos
I2C devices have been around us from a long time. If you have done any arduino projects with any peripherals such as Bluetooh (HC-05) or Gyroscope (MPU6050) or Barometer etc you might be surprised you have already used I2C devices. Yes

An I2C basically consists of a master micro controller and a slave device which responds to the requests of the master. A slave cannot operate on its own. It can't even communicate with other slave without having nay permission from the master.

      You may have come across multi master schematic but it become much more complex to handle such situation because of data leakage and also it requires more than 1 micro controllers. So if you are using an I2C you cannot use any other non-I2C device on the same bus as bothe SDA and SCL lines are in conjunction with the I2C module. If you find this facility somewhere you are being fooled seriously !!!
 I2C works on 2 signals as SCL and SDA
                                           SCL - Serial Clock
                                           SDA- Serial Data
When SDA is having negedge and SCL is positive level triggered then we have start signal and with every SCL clock a bit is transferred. Combining up to eight bit the slave receives an address. Then come the R/W signal means whether the slave has to read or write from/to address. AT the very moment after R/W bit the last bit known as acknowledgement bit is sent. Then the slave sends bit by bit data and finalizing by the acknowledge bit and the process comes to a STOP.

Do remember that when SDA changes the SCL lines must remain stable hence SDA doesn't change at posedge or nedge of SCL and only on the level of SCL i.e. either 1 or 0.

Here is a demonstration


Pic Credit- Google
 You can easily see the working as I have explained in comparison to the diagrams.
 Ok Coming down to the code

Starting with Master module and with its inputs



clk = Normal clock
sda = serial data
scl = serial clock
data_wr = data that has to be written if rw = 0;
address = address of slave
register = address of register which has to be read
rw = read or write pin

Next we move to declaration of internal variables


temp = to copy address incoming
register2 = to copy register value
scl2x = clock with which sda works to change sda while scl is 0
i = internal counter
n = single counter for start and stop conditions

One must note that initially we have sda and scl = 1 
After 5ns we turn sda to 0 to introduce start bit condition


From Line 28 to 30 :- we use n as a flag to start scl and scl2x to start bit transmitting
At Line 33 :- Temp stores the concated value of address of slave then rw bit and                                                acknowledge bit
At Line 34:- Incoming register address is stored in register2 internal variable because                                     further we will be using shift operators which doesn't work on wires and always                       does on reg data type.
At Line 36 :- If n==1 means start condition and if rw=1 means we have to read register thus                        scl will run upto 50 times
                       Similarly for rw=1 means we have to write scl will run 64 times.
                       The value 50 and 64 can be obtained by self coding 




This piece of code is for stop bit condition.

At Line 55 :- Till value of i reaches 9 we will grab bit by bit from temp
                       Here temp is having 6 bit slave address and 2 bits of rw and ack. Thus each bit                          is being read by shifting temp one by one and reading its MSB
                       Same is happening after Line 60 to get address of register
At Line 65 :- if rw ==0 we will recieve data which has to be written hence same process is                              followed too.

Here is the full code -:

Master Code-:
module master(data,address,clk,rw,sda,scl,register,data_wr);
output reg sda;
input [7:0] data;
input [7:0] data_wr;
reg [7:0]data_wr_dup;
input clk;
input rw;
output reg scl;
input [6:0] address;
input [7:0] register;
reg [8:0] temp;
reg [7:0] register2;
reg pstate;
reg scl2x;
reg ack;
reg a;
integer i;
integer n;
initial begin
i = 0;
n = 0;
scl2x = 0;
ack = 1'b1;
sda = 1;
scl = 1;
#5 sda = 0;  //START BIT condition starts here
end
                                                always @(negedge sda)
                                                if(scl==1)
                                                n=1;
always @(posedge clk)begin
ack = 0;
temp = {address,rw,ack};
register2 = register;
data_wr_dup = data_wr;
if(n==1 && rw==1)
repeat(50)begin
#2 scl <= !scl;n=0;
#1 scl2x <= !scl2x;n=0;
end
else if(n==1 && rw==0)
repeat(64) begin
#2 scl = !scl;
#1 scl2x = !scl2x;n=0;
end
end
always @(posedge clk)begin
if(i==25 && rw==1)
repeat(2)
#1 scl2x = !scl2x;
else if(i==32 && rw==0)
repeat(2)
#1 scl2x = !scl2x;end
always @(posedge scl2x)begin
if(i<=9)begin
sda = temp[8];
temp = temp<<1;
end
else if(i==12 || i==13)
sda = 1'b0;
else if(i>=14)begin
sda = register2[7];
register2 = register2<<1;
end
if(rw==0 && i>=23)begin
sda = data_wr_dup[7];
data_wr_dup = data_wr_dup<<1;
end
i = i + 1;
if(i>32 && rw ==0)
sda= 1;
else if(i>25 && rw==1)
sda = 1;
end
slave slv(data,sda,scl);
endmodule


And here is the code for Slave-:

module slave(out,sda,scl);
input sda;
input scl;
output reg [7:0]out;
integer j = 0;
reg [6:0]temp;
reg [7:0]add;
reg rw;
reg [7:0]register_address;
reg bitin;
reg [7:0]storage[0:38];
initial
storage[37]=16;
parameter address = 7'b1101001;
always @(posedge scl)begin
//if({sda,scl}==2'b01)begin
bitin = sda;
if(j<8)
temp = {temp,bitin};
if(j==8)
            if(bitin==0)
                        rw = 0;
            else
                        rw = 1;
j = j +1 ;
if(temp==address && (j>15 && j<24) && rw==1)begin
            add = {add,bitin};
end
if(temp==address && rw == 0 && j>15 && j!=24 && j<33)begin
            add = {add,bitin};
end
else if(j==24)
            register_address = add;
if(j==33 && rw==0)
storage[register_address]=add;
out = storage[add];
end
endmodule

And here is the testbench _-:

module tbmast;

            // Inputs
            reg [6:0] address;
            reg [7:0] register;
            reg [7:0] data;
            reg [7:0] data_wr;
            reg clk;
            reg rw;

            // Outputs
            wire sda;
            wire scl;

            // Instantiate the Unit Under Test (UUT)
            master uut (
                        .address(address),
                        .register(register),
                        .clk(clk),
                        .rw(rw), 
                        .sda(sda),
                        .scl(scl),
                        .data(data),
                        .data_wr(data_wr)
            );

            initial begin
                        // Initialize Inputs
                        address = 105;
                        register = 7'b0100101;
                        clk = 0;
                        rw = 0;
                        data_wr = 20;

                        // Wait 100 ns for global reset to finish
                        #100;
       
                        // Add stimulus here

            end
      always
                        #1 clk = !clk;
endmodule

Here is the waveform for rw==0 means write a data to register
Better ZOOM it




Master Model
 Slave Model

So Long

Saturday, April 8, 2017

Verilog Code for Sequence Detector




SEQUENCE DETECTOR

Hola Amigos
Beginning with the simple theory about Sequence Detector. A sequence detector an algorithm which detects a sequence within a given set of bits. Of course the length of total bits must be greater than sequence that has to be detected.
Sequence detector basically is of two types –

a.      Overlapping
b.     Non Overlapping
In overlapping some of the last bits can also be used for the start of detection of next sequence within the given bits.



For Example Let the sequence be 11011 and given bits 1101101101101101
Now lets work on overlapping concept.
We have 5 bits here in 11011 hence we will have 5 states. Let em be A/B/C/D and E.
Initially pstate will be A.
Now

1.     Incoming bit is 1 (from 1101101101101101) and it matches with first bit of sequence hence jump to next B. Requirement(1011)
2.     Incoming bit is 1 (from 1101101101101101)and it matches with  first bit of requirement hence jump to state C. Requirement (011)
3.     Incoming bit is 0 (from 1101101101101101) and it matches with first bit of requirement hence jump to state D. Requirement (11)
4.     Incoming bit is 1 (from 1101101101101101) and it matches with first bit of requirement hence jump to state E. Requirement (1)
5.     Incoming bit is 0 (from 1101101101101101) and it matches with first bit of requirement hence jump to state A. Requirement (). Output is 1 as we have found a sequence


To be more clear here is a table-


Notice that state C has 11 and requires 011. Now if it receives 1 instead of zero then instead of resetting and going back to A it will remain at C because C has 11 which can be used for starting of 11011 . This is called Overlapping. Similarly after state E we have restart to detect sequence then instead of starting again from A we will jump to C since it already has some bits which can serve as starting point. Remember always jump to that state which can provide maximum starting bits of sequence . Here B has 1 which can also serve but it isn’t maximum.


          Ok again for better understanding we have 11011 then
11011  can serve as starting bit i.e state B
11011 can serve as starting bits i.e state C
11011 cannot serve as starting bits since sequence doesn’t start with 011
11011 cannot serve as starting bits since sequence doesn’t start with 1011



Here is the state diagram for this sequence. I am pretty sure you must have understood Overlapping till now. If No! you can contact or this state diagram should suffice.






Let's go step by step
(A) Idle state is A waiting for 1 which if it gets will jump to B else will remain to A

(B) If receives 1 will jump to C else will jup back to idle A 

(C) If receives 1 will remain at itself as it has 11 to start with however if it receives         0 then it will jump to state D


(D) If receives 0 will jump to state A else will jump to state E

(E) If receives 0 will jump to A else will jump to Cand output will be 1 which                   means that a sequence has been detected.



Now how many FFs do we require to make this machine. We have 5bits here so
by using this equation we can find
                                           2x-1<5<2x
Thus we get X = 3 hence 3 FFs

To design in verilog here is the code for both Overlap and NonOverlap-

//***************************************************************************//
module sequence_detector(sequence,overlap,detect,clk,q);
input [15:0]sequence;
reg [15:0]temp;
reg bitin;
input overlap;
input [4:0]detect;
input clk;
output reg q;
integer i=0;
reg [2:0]pstate;
parameter A = 3'b000, B = 3'b001, C = 3'b011, D = 3'b100, E = 3'b101;
initial begin
pstate <=A;
$monitor("Pstate=%d bit=%b q=%b",pstate,bitin,q);
end
always @(posedge clk)begin
if(i==0)
temp = sequence;
i = i + 1;
end
always @(posedge clk)begin
bitin = temp[15];
temp=temp<<1;
if(overlap==1'b1)begin
case(pstate)
A:
if(bitin==1'b1)begin
pstate = B;
q = 0;
end
else begin
pstate = A;
q = 0;
end
B:
if(bitin==1'b1)begin
pstate = C;
q = 0;
end
else begin
pstate = A;
q = 0;
end
C:
if(bitin==1'b0)begin
pstate = D;
q = 0;
end
else begin
pstate = C;
q = 0;
end
D:
if(bitin==1'b1)begin
pstate = E;
q = 0;
end
else begin
pstate = A;
q = 0;
end
E:
if(bitin==1'b1)begin
pstate = C;
q = 1;
end
else begin
pstate = A;
q = 0;
end
endcase
end
else if(overlap==1'b0) begin
case(pstate)
A:
if(bitin==1'b1)begin
pstate = B;
q = 0;
end
else begin
pstate = A;
q = 0;
end
B:
if(bitin==1'b1)begin
pstate = C;
q = 0;
end
else begin
pstate = A;
q = 0;
end
C:
if(bitin==1'b0)begin
pstate = D;
q = 0;
end
else begin
pstate = A;
q = 0;
end
D:
if(bitin==1'b1)begin
pstate = E;
q = 0;
end
else begin
pstate = A;
q = 0;
end
E:
if(bitin==1'b1)begin
pstate = A;
q = 1;
end
else begin
pstate = A;
q = 0;
end
endcase
end
end
endmodule

and here is the Test Bench
//*************************************************************************//
module sequence();
reg clk,overlap;
reg [4:0]detect;
reg [15:0]sequence;
wire q;

initial begin
clk = 0;
overlap = 1; //1 for overlap 0 for non overlap
sequence = 16'b1101101101101101;
detect = 5'b11011;
end
always #2 clk=!clk;
sequence_detector yeah(sequence,overlap,detect,clk,q);
endmodule
//**************************************************************************//

Here is the simulator output (Overlapping)

Here is the Console Output for Overlapping

Here is the simulator output (Non-Overlapping)

Here is the Console Output for NonOverlapping

Here is the State Table for this question

For the truth table here it is


D2 = X’*Y1 + X*Y2*Y0
D1 = X *Y0

D0 = X

Here is the data flow diagram

So Long 


      



Latest Post

Self Balancing Bot with PID

In my previous project, I dealt with self-balancing robot without PID controller in this version of embedded the PID control on the sa...