OpenCores
URL https://opencores.org/ocsvn/i2c_master_slave_core/i2c_master_slave_core/trunk

Subversion Repositories i2c_master_slave_core

[/] [i2c_master_slave_core/] [trunk/] [i2c_master_slave_core/] [verilog/] [rtl/] [ms_core.v] - Diff between revs 2 and 6

Only display areas with differences | Details | Blame | View Log

Rev 2 Rev 6
///////////////////////////////////////ms_core.v////////////////////////////////////////////////////////////////////////
///////////////////////////////////////ms_core.v////////////////////////////////////////////////////////////////////////
//                                                                                                                    //                        
//                                                                                                                    //                        
//Design engineer:      Ravi Gupta                                                                                    //                
//Design engineer:      Ravi Gupta                                                                                    //                
//Company Name   :      Toomuch Semiconductor   
//Company Name   :      Toomuch Semiconductor   
//Email          :      ravi1.gupta@toomuchsemi.com                                                                   //        
//Email          :      ravi1.gupta@toomuchsemi.com                                                                   //        
//                                                                                                                    //        
//                                                                                                                    //        
//Purpose        :      This is the core which will be used to interface I2C bus.                                     //        
//Purpose        :      This is the core which will be used to interface I2C bus.                                     //        
//Created        :      23-11-07                                                                                      //
//Created        :      23-11-07                                                                                      //
                                                                                                                      //                
                                                                                                                      //                
//Modification : Changes made in data_reg_ld                                                                          //        
//Modification : Changes made in data_reg_ld                                                                          //        
                                                                                                                      //        
                                                                                                                      //        
//Modification : Change byte_trans generation bit                                                                     //        
//Modification : Change byte_trans generation bit                                                                     //        
                                                                                                                      //                
                                                                                                                      //                
//Modification : Implemented a halt bit that will be generated at the completion of 9th scl pulse in master_mode only //
//Modification : Implemented a halt bit that will be generated at the completion of 9th scl pulse in master_mode only //
                                                                                                                      //                                        
                                                                                                                      //                                        
//Modification : After core reset(time out feature) core will go in idle escaping stop generation so need to clear    //
//Modification : After core reset(time out feature) core will go in idle escaping stop generation so need to clear    //
//all                                                                                                                 //
//all                                                                                                                 //
//of status register.                                                                                                 //                
//of status register.                                                                                                 //                
                                                                                                                      //
                                                                                                                      //
//Modification : Remove the sm_state clause,so that even if there is no acknowledegement it will not stop the         //
//Modification : Remove the sm_state clause,so that even if there is no acknowledegement it will not stop the         //
//generation of SCL and SDA                                                                                           //                                
//generation of SCL and SDA                                                                                           //                                
//untill it gets command to generate stop from processor.                                                             //        
//untill it gets command to generate stop from processor.                                                             //        
                                                                                                                      //                
                                                                                                                      //                
//Modification : Now also checking for detect_start in acknowledgement state for repeted start condition.             //        
//Modification : Now also checking for detect_start in acknowledgement state for repeted start condition.             //        
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
 
 
 
 
 
module core(clk,rst,sda_oe,sda_in,sda_o,scl_oe,scl_in,scl_o,ack,mode,rep_start,master_rw,data_in,slave_add,bus_busy,byte_trans,slave_addressed,arb_lost,slave_rw,time_out,inter,ack_rec,i2c_up,time_out_reg,prescale_reg,inter_rst,inter_en,halt_rst,data_en,time_rst,h_rst);
module core(clk,rst,sda_oe,sda_in,sda_o,scl_oe,scl_in,scl_o,ack,mode,rep_start,master_rw,data_in,slave_add,bus_busy,byte_trans,slave_addressed,arb_lost,slave_rw,time_out,inter,ack_rec,i2c_up,time_out_reg,prescale_reg,inter_rst,inter_en,halt_rst,data_en,time_rst,h_rst);
 
 
////////////////////////////////////////////////signal defination////////////////////////////////////////////////////////////////
////////////////////////////////////////////////signal defination////////////////////////////////////////////////////////////////
 
 
input   clk;                    //System Clock
input   clk;                    //System Clock
input   rst;                    //Main Reset
input   rst;                    //Main Reset
output  sda_oe;                 //I2C serial data line output to be connected to control line of bidirectional buffer on physical SDA line
output  sda_oe;                 //I2C serial data line output to be connected to control line of bidirectional buffer on physical SDA line
input   sda_in;                 //I2C serial data line input
input   sda_in;                 //I2C serial data line input
output  sda_o;                  //I2C sda line always asssign to zero this is to be connected to input of bidirectional buffer on physical SDA line
output  sda_o;                  //I2C sda line always asssign to zero this is to be connected to input of bidirectional buffer on physical SDA line
output  scl_oe;                 //I2C serial clock line output to be connected to control line of bidirectiional buffer on physical scl line
output  scl_oe;                 //I2C serial clock line output to be connected to control line of bidirectiional buffer on physical scl line
input   scl_in;                 //I2C serial clock line input
input   scl_in;                 //I2C serial clock line input
output  scl_o;                  //SCL output line to be connected to input of bidirectional line
output  scl_o;                  //SCL output line to be connected to input of bidirectional line
input   ack;                    //Acknowledgement signal from control register
input   ack;                    //Acknowledgement signal from control register
input   mode;                   //master/slave mode select
input   mode;                   //master/slave mode select
input   rep_start;              //repeated start
input   rep_start;              //repeated start
input   master_rw;              //command to core in master mode
input   master_rw;              //command to core in master mode
input   [7:0]data_in;            //data from processor to be outputed on I2C
input   [7:0]data_in;            //data from processor to be outputed on I2C
input   [7:0]slave_add;          //I2C slave address
input   [7:0]slave_add;          //I2C slave address
input data_en;
input data_en;
output time_rst;
output time_rst;
input h_rst;
input h_rst;
 
 
//status signal:
//status signal:
 
 
output  bus_busy;               //bus busy
output  bus_busy;               //bus busy
inout   byte_trans;             //transfer of byte is in progress_reg_en
inout   byte_trans;             //transfer of byte is in progress_reg_en
 
 
inout   slave_addressed;        //addressed as slave
inout   slave_addressed;        //addressed as slave
inout   arb_lost;               //arbitration has lost
inout   arb_lost;               //arbitration has lost
inout   slave_rw;               //indicates the operation by slave
inout   slave_rw;               //indicates the operation by slave
inout   time_out;               //indicates that SCL LOW time has been exceeded
inout   time_out;               //indicates that SCL LOW time has been exceeded
output  inter;                  //interrupt pending,will be used for interrupting processor
output  inter;                  //interrupt pending,will be used for interrupting processor
input   inter_rst;              //use to clear the interrupt
input   inter_rst;              //use to clear the interrupt
input   inter_en;               //processor wants to take interrupt or not
input   inter_en;               //processor wants to take interrupt or not
 
 
//signal for processor
//signal for processor
input halt_rst;
input halt_rst;
output  ack_rec;                //indicates that ack has been recieved,will be used to inform if master reciever wants to terminate the transfer
output  ack_rec;                //indicates that ack has been recieved,will be used to inform if master reciever wants to terminate the transfer
output  [7:0]i2c_up;             //I2C data for micro processor
output  [7:0]i2c_up;             //I2C data for micro processor
//timing control registers
//timing control registers
input [7:0]time_out_reg;         //max SCL low period.
input [7:0]time_out_reg;         //max SCL low period.
input [7:0]prescale_reg;         //clock divider for generating SCL frequency.
input [7:0]prescale_reg;         //clock divider for generating SCL frequency.
 
 
/////////////////////////////////////////End of port defination//////////////////////////////////////////////////////////////////
/////////////////////////////////////////End of port defination//////////////////////////////////////////////////////////////////
 
 
wire master_slave,arbitration_lost,bb,gen_start,rep_start,byte_trans_delay,byte_trans_fall;
wire master_slave,arbitration_lost,bb,gen_start,rep_start,byte_trans_delay,byte_trans_fall;
 
 
//wire scl_out,sda_out,clk_cnt_enable,clk_cnt_rst,bit_cnt_enable,bit_cnt_rst,timer_cnt_enable,timer_cnt_rst,scl_in,sda_in,sda_out_reg,stop_scl_reg,master_sda,  gen_stop;
//wire scl_out,sda_out,clk_cnt_enable,clk_cnt_rst,bit_cnt_enable,bit_cnt_rst,timer_cnt_enable,timer_cnt_rst,scl_in,sda_in,sda_out_reg,stop_scl_reg,master_sda,  gen_stop;
wire master_sda,scl_in,gen_stop,sm_stop,detect_stop,detect_start,addr_match,core_rst,stop_scl,scl_out,neg_scl_sig,sda_sig;
wire master_sda,scl_in,gen_stop,sm_stop,detect_stop,detect_start,addr_match,core_rst,stop_scl,scl_out,neg_scl_sig,sda_sig;
//reg [7:0]clk1_cnt,bit1_cnt,timer1_cnt;
//reg [7:0]clk1_cnt,bit1_cnt,timer1_cnt;
reg posedge_mode,negedge_mode;
reg posedge_mode,negedge_mode;
reg [2:0]scl_state;
reg [2:0]scl_state;
reg [1:0]state;
reg [1:0]state;
reg [2:0]scl_main_state;
reg [2:0]scl_main_state;
wire [7:0] add_reg,shift_reg;
wire [7:0] add_reg,shift_reg;
wire [7:0]clk_cnt,bit_cnt;
wire [7:0]clk_cnt,bit_cnt;
reg  [7:0]time_cnt;
reg  [7:0]time_cnt;
reg  [7:0]i2c_up;
reg  [7:0]i2c_up;
wire bit_cnt_enable,bit_cnt_rst,clk_cnt_enable,clk_cnt_rst,data_reg_ld,data_reg_en,sda_in,serial_out,i2c_serial_out,add_reg_ld,add_reg_en,posedge_mode_sig,negedge_mode_sig,interrupt;
wire bit_cnt_enable,bit_cnt_rst,clk_cnt_enable,clk_cnt_rst,data_reg_ld,data_reg_en,sda_in,serial_out,i2c_serial_out,add_reg_ld,add_reg_en,posedge_mode_sig,negedge_mode_sig,interrupt;
wire [7:0]zero;
wire [7:0]zero;
wire [7:0]reg_clr;
wire [7:0]reg_clr;
 
 
wire slave_sda,sda_out,halt,arb_rst,interrupt_rst,d_detect_stop;
wire slave_sda,sda_out,halt,arb_rst,interrupt_rst,d_detect_stop;
 
 
shift shift_data(neg_scl,rst,data_reg_ld,data_reg_en,sda_in,data_in,serial_out,shift_reg);      //shift register for transferring the data
shift shift_data(neg_scl,rst,data_reg_ld,data_reg_en,sda_in,data_in,serial_out,shift_reg);      //shift register for transferring the data
shift shift_add(neg_scl,rst,add_reg_ld,add_reg_en,sda_in,reg_clr,i2c_serial_out,add_reg);       //shift register for transferring address
shift shift_add(neg_scl,rst,add_reg_ld,add_reg_en,sda_in,reg_clr,i2c_serial_out,add_reg);       //shift register for transferring address
counter clock_counter(clk,rst,clk_cnt_enable,clk_cnt_rst,zero,clk_cnt);                         //This will count number of clock pulses for prescale
counter clock_counter(clk,rst,clk_cnt_enable,clk_cnt_rst,zero,clk_cnt);                         //This will count number of clock pulses for prescale
counter bit_counter(neg_scl,rst,bit_cnt_enable,bit_cnt_rst,zero,bit_cnt);                       //Implementation of bit counter
counter bit_counter(neg_scl,rst,bit_cnt_enable,bit_cnt_rst,zero,bit_cnt);                       //Implementation of bit counter
 
 
 
 
 
 
 
 
 
 
 
 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
reg clk_cnt_enable_sig;
reg clk_cnt_enable_sig;
assign clk_cnt_enable = clk_cnt_enable_sig;
assign clk_cnt_enable = clk_cnt_enable_sig;
 
 
reg clk_cnt_rst_sig;
reg clk_cnt_rst_sig;
assign clk_cnt_rst = clk_cnt_rst_sig;
assign clk_cnt_rst = clk_cnt_rst_sig;
 
 
 
 
//reg sda_in_sig;
//reg sda_in_sig;
//assign sda_in = sda_in_sig;
//assign sda_in = sda_in_sig;
 
 
reg sm_stop_sig;
reg sm_stop_sig;
assign sm_stop = sm_stop_sig;
assign sm_stop = sm_stop_sig;
 
 
//reg scl_in_sig;
//reg scl_in_sig;
//assign scl_in = scl_in_sig;
//assign scl_in = scl_in_sig;
 
 
reg gen_start_sig;
reg gen_start_sig;
assign gen_start = gen_start_sig;
assign gen_start = gen_start_sig;
 
 
reg gen_stop_sig;
reg gen_stop_sig;
assign gen_stop = gen_stop_sig;
assign gen_stop = gen_stop_sig;
 
 
reg master_slave_sig;
reg master_slave_sig;
assign master_slave = master_slave_sig;
assign master_slave = master_slave_sig;
 
 
reg detect_start_sig;
reg detect_start_sig;
assign detect_start=detect_start_sig;
assign detect_start=detect_start_sig;
 
 
reg detect_stop_sig;
reg detect_stop_sig;
assign detect_stop=detect_stop_sig;
assign detect_stop=detect_stop_sig;
 
 
reg byte_trans_sig;
reg byte_trans_sig;
assign byte_trans= byte_trans_sig;
assign byte_trans= byte_trans_sig;
 
 
reg bb_sig;
reg bb_sig;
assign bb=bb_sig;
assign bb=bb_sig;
 
 
reg slave_addressed_sig;
reg slave_addressed_sig;
assign slave_addressed=slave_addressed_sig;
assign slave_addressed=slave_addressed_sig;
 
 
reg slave_rw_sig;
reg slave_rw_sig;
assign slave_rw=slave_rw_sig;
assign slave_rw=slave_rw_sig;
 
 
reg inter_sig;
reg inter_sig;
assign inter=inter_sig;
assign inter=inter_sig;
assign interrupt=inter_sig;
assign interrupt=inter_sig;
 
 
reg time_out_sig;
reg time_out_sig;
assign time_out=time_out_sig;
assign time_out=time_out_sig;
 
 
reg ack_rec_sig;
reg ack_rec_sig;
assign ack_rec=ack_rec_sig;
assign ack_rec=ack_rec_sig;
 
 
reg add_reg_enable_sig;
reg add_reg_enable_sig;
assign add_reg_en=add_reg_enable_sig;
assign add_reg_en=add_reg_enable_sig;
 
 
reg data_reg_en_sig;
reg data_reg_en_sig;
assign data_reg_en=data_reg_en_sig;
assign data_reg_en=data_reg_en_sig;
 
 
reg data_reg_ld_sig;
reg data_reg_ld_sig;
assign data_reg_ld=data_reg_ld_sig;
assign data_reg_ld=data_reg_ld_sig;
 
 
reg stop_scl_sig;
reg stop_scl_sig;
assign stop_scl=stop_scl_sig;
assign stop_scl=stop_scl_sig;
 
 
reg core_rst_sig;
reg core_rst_sig;
assign core_rst=core_rst_sig;
assign core_rst=core_rst_sig;
 
 
reg sda_out_sig;
reg sda_out_sig;
assign sda_out=sda_out_sig;
assign sda_out=sda_out_sig;
 
 
reg scl_out_sig;
reg scl_out_sig;
assign scl_out=scl_out_sig;
assign scl_out=scl_out_sig;
 
 
reg master_sda_sig;
reg master_sda_sig;
assign master_sda=master_sda_sig;
assign master_sda=master_sda_sig;
 
 
reg slave_sda_sig;
reg slave_sda_sig;
assign slave_sda=slave_sda_sig;
assign slave_sda=slave_sda_sig;
 
 
reg arbitration_lost_sig;
reg arbitration_lost_sig;
assign arbitration_lost=arbitration_lost_sig;
assign arbitration_lost=arbitration_lost_sig;
 
 
reg arb_lost_sig;
reg arb_lost_sig;
assign arb_lost=arb_lost_sig;
assign arb_lost=arb_lost_sig;
 
 
reg byte_trans_delay_sig;
reg byte_trans_delay_sig;
assign byte_trans_delay=byte_trans_delay_sig;
assign byte_trans_delay=byte_trans_delay_sig;
 
 
reg byte_trans_fall_sig;
reg byte_trans_fall_sig;
assign byte_trans_fall=byte_trans_fall_sig;
assign byte_trans_fall=byte_trans_fall_sig;
 
 
reg halt_sig;
reg halt_sig;
assign halt = halt_sig;
assign halt = halt_sig;
 
 
reg arb_rst_sig;
reg arb_rst_sig;
assign arb_rst=arb_rst_sig;
assign arb_rst=arb_rst_sig;
 
 
reg interrupt_rst_sig;
reg interrupt_rst_sig;
assign interrupt_rst=interrupt_rst_sig;
assign interrupt_rst=interrupt_rst_sig;
 
 
reg rep_start_sig;
reg rep_start_sig;
assign time_rst = core_rst;
assign time_rst = core_rst;
 
 
reg d_detect_stop_sig;
reg d_detect_stop_sig;
assign d_detect_stop = d_detect_stop_sig;
assign d_detect_stop = d_detect_stop_sig;
 
 
reg d1_detect_stop_sig;
reg d1_detect_stop_sig;
 
 
 
 
assign bus_busy = bb;
assign bus_busy = bb;
assign reg_clr=8'b00000000;
assign reg_clr=8'b00000000;
assign neg_scl_sig=(~scl_in);
assign neg_scl_sig=(~scl_in);
assign neg_scl=neg_scl_sig;
assign neg_scl=neg_scl_sig;
assign zero=8'b00000000;
assign zero=8'b00000000;
assign posedge_mode_sig=posedge_mode;
assign posedge_mode_sig=posedge_mode;
assign negedge_mode_sig=negedge_mode;
assign negedge_mode_sig=negedge_mode;
assign sda_o = 1'b0;    //assign this to 0 always
assign sda_o = 1'b0;    //assign this to 0 always
assign scl_o = 1'b0;
assign scl_o = 1'b0;
 
 
 
 
 
 
parameter       scl_idle=3'b000,scl_start=3'b001,scl_low_edge=3'b010,scl_low=3'b011,scl_high_edge=3'b100,scl_high=3'b101;
parameter       scl_idle=3'b000,scl_start=3'b001,scl_low_edge=3'b010,scl_low=3'b011,scl_high_edge=3'b100,scl_high=3'b101;
parameter       scl_address_shift=3'b001,scl_ack_address=3'b010,scl_rx_data=3'b011,scl_tx_data=3'b100,scl_send_ack=3'b101,scl_wait_ack=3'b110,scl_main_idle=                    3'b000;
parameter       scl_address_shift=3'b001,scl_ack_address=3'b010,scl_rx_data=3'b011,scl_tx_data=3'b100,scl_send_ack=3'b101,scl_wait_ack=3'b110,scl_main_idle=                    3'b000;
 
 
parameter       a=2'b00,b=2'b01,c=2'b10;
parameter       a=2'b00,b=2'b01,c=2'b10;
 
 
////////////////////SCL Generator///////////////////////////////
////////////////////SCL Generator///////////////////////////////
//This machine will generate SCL and SDA when in master mode.It will
//This machine will generate SCL and SDA when in master mode.It will
//also generate START and STOP condition.
//also generate START and STOP condition.
 
 
//always@(scl_state or arbitration_lost or sm_stop or gen_stop or rep_start
//always@(scl_state or arbitration_lost or sm_stop or gen_stop or rep_start
//              or bb or gen_start or master_slave or clk_cnt or bit_cnt or
//              or bb or gen_start or master_slave or clk_cnt or bit_cnt or
//              scl_in  or sda_out or master_sda or core_rst)
//              scl_in  or sda_out or master_sda or core_rst)
always@(posedge clk or posedge rst or posedge core_rst or posedge h_rst)
always@(posedge clk or posedge rst or posedge core_rst or posedge h_rst)
begin
begin
 
 
//State machine initial conditions
//State machine initial conditions
 
 
if(rst || h_rst)
if(rst || h_rst)
begin
begin
        scl_state<=scl_idle;
        scl_state<=scl_idle;
        scl_out_sig<=1'b1;
        scl_out_sig<=1'b1;
        sda_out_sig<=1'b1;
        sda_out_sig<=1'b1;
        stop_scl_sig<=1'b0;
        stop_scl_sig<=1'b0;
        clk_cnt_enable_sig<=1'b0;
        clk_cnt_enable_sig<=1'b0;
        clk_cnt_rst_sig<=1'b1;
        clk_cnt_rst_sig<=1'b1;
        //bit_cnt_rst_sig<=1'b0;
        //bit_cnt_rst_sig<=1'b0;
        //bit_cnt_enable_sig<=1'b0;
        //bit_cnt_enable_sig<=1'b0;
end
end
 
 
else if(core_rst)
else if(core_rst)
begin
begin
 
 
        scl_state<=scl_idle;
        scl_state<=scl_idle;
        scl_main_state <= scl_main_idle;
        scl_main_state <= scl_main_idle;
        scl_out_sig<=1'b1;
        scl_out_sig<=1'b1;
        sda_out_sig<=1'b1;
        sda_out_sig<=1'b1;
        stop_scl_sig<=1'b0;
        stop_scl_sig<=1'b0;
        clk_cnt_enable_sig<=1'b0;
        clk_cnt_enable_sig<=1'b0;
        clk_cnt_rst_sig<=1'b1;
        clk_cnt_rst_sig<=1'b1;
        slave_addressed_sig<=1'b0;
        slave_addressed_sig<=1'b0;
end
end
 
 
 
 
else
else
begin
begin
 
 
                case (scl_state)
                case (scl_state)
 
 
                        scl_idle:
                        scl_idle:
                        begin
                        begin
                                arb_rst_sig <= 1'b1;
                                arb_rst_sig <= 1'b1;
                                interrupt_rst_sig<=1'b1;
                                interrupt_rst_sig<=1'b1;
                                sda_out_sig<=1'b1;
                                sda_out_sig<=1'b1;
                                stop_scl_sig<=1'b0;
                                stop_scl_sig<=1'b0;
 
 
                                        if(master_slave && !bb && gen_start)
                                        if(master_slave && !bb && gen_start)
                                        begin
                                        begin
                                                scl_state<=scl_start;
                                                scl_state<=scl_start;
 
 
                                        end
                                        end
                        end
                        end
 
 
 
 
                        scl_start:
                        scl_start:
                        begin
                        begin
                                arb_rst_sig <= 1'b0;
                                arb_rst_sig <= 1'b0;
                                interrupt_rst_sig<=1'b0;
                                interrupt_rst_sig<=1'b0;
                                clk_cnt_enable_sig<=1'b1;                               //enable the counter as soon as machine enters in this state.
                                clk_cnt_enable_sig<=1'b1;                               //enable the counter as soon as machine enters in this state.
                                clk_cnt_rst_sig<=1'b0;
                                clk_cnt_rst_sig<=1'b0;
                                //sda_out_sig<=1'b0;                                    //generating start condition
                                //sda_out_sig<=1'b0;                                    //generating start condition
                                stop_scl_sig<=1'b0;
                                stop_scl_sig<=1'b0;
                        if(clk_cnt == prescale_reg / 3)
                        if(clk_cnt == prescale_reg / 3)
                                sda_out_sig<= 1'b0;
                                sda_out_sig<= 1'b0;
 
 
                                        if(clk_cnt == prescale_reg)             //wait for prescale value to over
                                        if(clk_cnt == prescale_reg)             //wait for prescale value to over
                                                scl_state<=scl_low_edge;
                                                scl_state<=scl_low_edge;
                                        else
                                        else
                                                scl_state<=scl_start;
                                                scl_state<=scl_start;
                        end
                        end
 
 
                        scl_low_edge:
                        scl_low_edge:
                        begin
                        begin
                                clk_cnt_rst_sig<=1'b1;                  //This state will generate only SCL negative edge,and reset all the counters
                                clk_cnt_rst_sig<=1'b1;                  //This state will generate only SCL negative edge,and reset all the counters
                                //timer_cnt_enable_sig<=1'b1;                   //except timer counter which will be enabled at this state.
                                //timer_cnt_enable_sig<=1'b1;                   //except timer counter which will be enabled at this state.
                                //timer_cnt_rst_sig<=1'b0;                      //also reseting the timer counter in this state.
                                //timer_cnt_rst_sig<=1'b0;                      //also reseting the timer counter in this state.
                                scl_out_sig<=1'b0;
                                scl_out_sig<=1'b0;
                                scl_state<=scl_low;
                                scl_state<=scl_low;
                                stop_scl_sig<=1'b0;
                                stop_scl_sig<=1'b0;
                        end
                        end
 
 
                        scl_low:
                        scl_low:
                        begin
                        begin
                                clk_cnt_enable_sig<=1'b1;                       //enable the clock counter
                                clk_cnt_enable_sig<=1'b1;                       //enable the clock counter
                                clk_cnt_rst_sig<=1'b0;
                                clk_cnt_rst_sig<=1'b0;
                                scl_out_sig<=1'b0;
                                scl_out_sig<=1'b0;
 
 
                                                        if(arbitration_lost)
                                                        if(arbitration_lost)
                                                                stop_scl_sig<=1'b0;
                                                                stop_scl_sig<=1'b0;
                                                else if(rep_start_sig)
                                                else if(rep_start_sig)
                                                        begin
                                                        begin
                                                                sda_out_sig<=1'b1;
                                                                sda_out_sig<=1'b1;
                                                                stop_scl_sig<=1'b0;
                                                                stop_scl_sig<=1'b0;
                                                        end
                                                        end
 
 
 
 
                                                 else if((gen_stop) && ((scl_main_state != scl_ack_address) && (scl_main_state != scl_send_ack)
                                                 else if((gen_stop) && ((scl_main_state != scl_ack_address) && (scl_main_state != scl_send_ack)
                                                                        && (scl_main_state != scl_wait_ack)))           //Ravi remove sm_stop from oring with gen_stop
                                                                        && (scl_main_state != scl_wait_ack)))           //Ravi remove sm_stop from oring with gen_stop
                                                        begin
                                                        begin
                                                                sda_out_sig<=1'b0;
                                                                sda_out_sig<=1'b0;
                                                                stop_scl_sig<=1'b1;
                                                                stop_scl_sig<=1'b1;
 
 
                                                        end
                                                        end
 
 
                                                        /*else if(rep_start)
                                                        /*else if(rep_start)
                                                        begin
                                                        begin
                                                                sda_out_sig<=1'b1;
                                                                sda_out_sig<=1'b1;
                                                                stop_scl_sig<=1'b0;
                                                                stop_scl_sig<=1'b0;
                                                        end*/
                                                        end*/
                                                        else if(clk_cnt == prescale_reg / 3)
                                                        else if(clk_cnt == prescale_reg / 3)
                                                        begin
                                                        begin
                                                                                sda_out_sig<=master_sda;
                                                                                sda_out_sig<=master_sda;
                                                                                stop_scl_sig<=1'b0;
                                                                                stop_scl_sig<=1'b0;
 
 
                                                        end
                                                        end
 
 
                                                        else
                                                        else
                                                                stop_scl_sig<=1'b0;
                                                                stop_scl_sig<=1'b0;
 
 
 
 
                                                                                        //determine next state. 
                                                                                        //determine next state. 
 
 
                                        if(clk_cnt == prescale_reg)
                                        if(clk_cnt == prescale_reg)
                                        begin
                                        begin
                                                if(bit_cnt == 8'b0000_0111 && arbitration_lost )
                                                if(bit_cnt == 8'b0000_0111 && arbitration_lost )
                                                        scl_state<=scl_idle;
                                                        scl_state<=scl_idle;
                                                else if(interrupt && inter_en)                                                                  //uncomenting out for cheking the core in interrupt mode 
                                                else if(interrupt && inter_en)                                                                  //uncomenting out for cheking the core in interrupt mode 
                                                        scl_state<=scl_low;
                                                        scl_state<=scl_low;
                                                else if(halt)
                                                else if(halt)
                                                        scl_state<=scl_low;
                                                        scl_state<=scl_low;
                                                else
                                                else
                                                        scl_state<=scl_high_edge;
                                                        scl_state<=scl_high_edge;
                                        end
                                        end
 
 
                                        else
                                        else
                                                scl_state<=scl_low;
                                                scl_state<=scl_low;
                        end
                        end
 
 
 
 
 
 
 
 
                        scl_high_edge:
                        scl_high_edge:
                        begin
                        begin
                                clk_cnt_rst_sig<=1'b1;
                                clk_cnt_rst_sig<=1'b1;
                                scl_out_sig<=1'b1;
                                scl_out_sig<=1'b1;
                                if(gen_stop)                            //Ravi sm_stop from oring with gen_stop
                                if(gen_stop)                            //Ravi sm_stop from oring with gen_stop
                                        stop_scl_sig<=1'b1;
                                        stop_scl_sig<=1'b1;
 
 
                                else
                                else
                                        stop_scl_sig<=1'b0;
                                        stop_scl_sig<=1'b0;
                                if(!scl_in)
                                if(!scl_in)
                                        scl_state<=scl_high_edge;
                                        scl_state<=scl_high_edge;
                                else
                                else
                                        scl_state<=scl_high;
                                        scl_state<=scl_high;
                        end
                        end
 
 
 
 
 
 
                        scl_high:
                        scl_high:
                        begin
                        begin
                                clk_cnt_enable_sig<=1'b1;
                                clk_cnt_enable_sig<=1'b1;
                                clk_cnt_rst_sig<=1'b0;
                                clk_cnt_rst_sig<=1'b0;
                                scl_out_sig<=1'b1;
                                scl_out_sig<=1'b1;
                                if(clk_cnt == prescale_reg)
                                if(clk_cnt == prescale_reg)
                                begin
                                begin
                                        if(rep_start_sig)
                                        if(rep_start_sig)
                                                scl_state<=scl_start;
                                                scl_state<=scl_start;
                                        else if(stop_scl)
                                        else if(stop_scl)
                                                scl_state<=scl_idle;
                                                scl_state<=scl_idle;
 
 
                                        else
                                        else
                                                scl_state<=scl_low_edge;
                                                scl_state<=scl_low_edge;
                                end
                                end
 
 
                                else
                                else
                                        scl_state<=scl_high;
                                        scl_state<=scl_high;
                        end
                        end
 
 
 
 
                endcase
                endcase
end
end
end
end
 
 
 
 
//Sample the incoming SDA and SCL line with System clock
//Sample the incoming SDA and SCL line with System clock
 
 
/*always@(posedge clk or posedge rst)
/*always@(posedge clk or posedge rst)
begin
begin
 
 
        if(rst)
        if(rst)
        begin
        begin
                //sda_in_sig <= 1'b1;
                //sda_in_sig <= 1'b1;
                scl_in_sig <=1'b1;
                scl_in_sig <=1'b1;
        end
        end
        else
        else
        begin
        begin
                if(!scl)
                if(!scl)
                        scl_in_sig <= 1'b0;
                        scl_in_sig <= 1'b0;
                else
                else
                        scl_in_sig <= 1'b1;
                        scl_in_sig <= 1'b1;
 
 
                if(!sda)
                if(!sda)
                        sda_in_sig <= 1'b0;
                        sda_in_sig <= 1'b0;
                else
                else
                        sda_in_sig <= 1'b1;
                        sda_in_sig <= 1'b1;
 
 
        //sda_out_sig <= sda;
        //sda_out_sig <= sda;
        end
        end
end*/
end*/
 
 
//Generartion of control signal from the command based on processor.
//Generartion of control signal from the command based on processor.
//This will control generation of start and stop signal.
//This will control generation of start and stop signal.
//This will also set the master_slave bit based on MODE signal
//This will also set the master_slave bit based on MODE signal
//if bus is not busy i.e bb = 0
//if bus is not busy i.e bb = 0
 
 
always@(posedge clk or posedge rst or posedge h_rst)
always@(posedge clk or posedge rst or posedge h_rst)
begin
begin
        if(rst || h_rst)
        if(rst || h_rst)
        begin
        begin
                gen_start_sig <= 1'b0;
                gen_start_sig <= 1'b0;
                gen_stop_sig <= 1'b0;
                gen_stop_sig <= 1'b0;
                master_slave_sig <= 1'b0;
                master_slave_sig <= 1'b0;
 
 
        end
        end
 
 
        else
        else
        begin
        begin
                if(posedge_mode_sig)
                if(posedge_mode_sig)
                        gen_start_sig <= 1'b1;
                        gen_start_sig <= 1'b1;
                else if(detect_start)
                else if(detect_start)
                        gen_start_sig <= 1'b0;
                        gen_start_sig <= 1'b0;
 
 
                if(!arbitration_lost && negedge_mode_sig)
                if(!arbitration_lost && negedge_mode_sig)
                        gen_stop_sig <= 1'b1;
                        gen_stop_sig <= 1'b1;
                else if(detect_stop)
                else if(detect_stop)
                        gen_stop_sig <= 1'b0;
                        gen_stop_sig <= 1'b0;
 
 
                if(!bb)
                if(!bb)
                        master_slave_sig <= mode;
                        master_slave_sig <= mode;
                else
                else
                        master_slave_sig <= master_slave;
                        master_slave_sig <= master_slave;
        end
        end
end
end
 
 
//State machine for detection of rising and falling edge of input mode for the generation of START and STOP.
//State machine for detection of rising and falling edge of input mode for the generation of START and STOP.
always@(posedge clk or posedge rst or posedge h_rst)
always@(posedge clk or posedge rst or posedge h_rst)
begin
begin
        if(rst || h_rst)
        if(rst || h_rst)
        begin
        begin
                posedge_mode<=1'b0;
                posedge_mode<=1'b0;
                negedge_mode<=1'b0;
                negedge_mode<=1'b0;
                state<=a;
                state<=a;
        end
        end
 
 
        else
        else
        begin
        begin
                case(state)
                case(state)
 
 
                        a:
                        a:
                                if(mode==1'b0)
                                if(mode==1'b0)
                                begin
                                begin
                                        state<=b;
                                        state<=b;
                                        posedge_mode<=1'b0;
                                        posedge_mode<=1'b0;
                                        negedge_mode<=1'b0;
                                        negedge_mode<=1'b0;
                                end
                                end
 
 
                                else
                                else
                                begin
                                begin
                                        state<=c;
                                        state<=c;
                                        posedge_mode<=1'b1;
                                        posedge_mode<=1'b1;
                                        negedge_mode<=1'b0;
                                        negedge_mode<=1'b0;
                                end
                                end
 
 
                        b:
                        b:
                                if(mode==1'b0)
                                if(mode==1'b0)
                                begin
                                begin
                                        state<=b;
                                        state<=b;
                                        posedge_mode<=1'b0;
                                        posedge_mode<=1'b0;
                                        negedge_mode<=1'b0;
                                        negedge_mode<=1'b0;
                                end
                                end
 
 
                                else
                                else
                                begin
                                begin
                                        state<=a;
                                        state<=a;
                                        posedge_mode<=1'b1;
                                        posedge_mode<=1'b1;
                                        negedge_mode<=1'b0;
                                        negedge_mode<=1'b0;
                                end
                                end
 
 
                        c:
                        c:
                                if(mode==1'b0)
                                if(mode==1'b0)
                                begin
                                begin
                                        state<=a;
                                        state<=a;
                                        posedge_mode<=1'b0;
                                        posedge_mode<=1'b0;
                                        negedge_mode<=1'b1;
                                        negedge_mode<=1'b1;
                                end
                                end
 
 
                                else
                                else
                                begin
                                begin
                                        state<=c;
                                        state<=c;
                                        posedge_mode<=1'b0;
                                        posedge_mode<=1'b0;
                                        negedge_mode<=1'b0;
                                        negedge_mode<=1'b0;
                                end
                                end
 
 
                endcase
                endcase
end
end
end
end
 
 
//This is the main state machine which will be used as both master as well as slave.
//This is the main state machine which will be used as both master as well as slave.
//This gets triggered at falling edge of SCL.
//This gets triggered at falling edge of SCL.
//If stop codition gets detected then it should work as asyn reset.
//If stop codition gets detected then it should work as asyn reset.
 
 
always@(posedge rst or negedge scl_in or posedge detect_stop or posedge core_rst or posedge h_rst)
always@(posedge rst or negedge scl_in or posedge detect_stop or posedge core_rst or posedge h_rst)
begin
begin
 
 
if(rst || core_rst || h_rst)
if(rst || core_rst || h_rst)
begin
begin
        scl_main_state<=scl_main_idle;
        scl_main_state<=scl_main_idle;
        sm_stop_sig<=1'b0;
        sm_stop_sig<=1'b0;
end
end
 
 
else
else
begin
begin
        case(scl_main_state)
        case(scl_main_state)
        scl_main_idle:
        scl_main_idle:
 
 
                if(detect_start)
                if(detect_start)
                        scl_main_state<=scl_address_shift;
                        scl_main_state<=scl_address_shift;
                else if(detect_stop)
                else if(detect_stop)
                begin
                begin
                        scl_main_state<=scl_main_idle;
                        scl_main_state<=scl_main_idle;
                        sm_stop_sig<=1'b0;
                        sm_stop_sig<=1'b0;
                end
                end
 
 
        scl_address_shift:                                      //machine will remain in this state,unless all the bits of address has been transferred. 
        scl_address_shift:                                      //machine will remain in this state,unless all the bits of address has been transferred. 
 
 
                if(bit_cnt == 8'b0000_0111)
                if(bit_cnt == 8'b0000_0111)
                        scl_main_state<=scl_ack_address;
                        scl_main_state<=scl_ack_address;
                else if(detect_stop)
                else if(detect_stop)
                begin
                begin
                        scl_main_state<=scl_main_idle;
                        scl_main_state<=scl_main_idle;
                        sm_stop_sig<=1'b0;
                        sm_stop_sig<=1'b0;
                end
                end
 
 
        scl_ack_address:
        scl_ack_address:
 
 
                //if(arbitration_lost)                                  //if arbitration lost then go to idle state releasing buses.remove this because its a 
                //if(arbitration_lost)                                  //if arbitration lost then go to idle state releasing buses.remove this because its a 
                        //scl_main_state<=scl_main_idle;                //software problem if even after arb_lost it is giving wr/rd then it has to go to respective state.
                        //scl_main_state<=scl_main_idle;                //software problem if even after arb_lost it is giving wr/rd then it has to go to respective state.
                if(detect_stop)
                if(detect_stop)
                begin                                           //Go to idle state if there is stop command
                begin                                           //Go to idle state if there is stop command
                        scl_main_state<=scl_main_idle;
                        scl_main_state<=scl_main_idle;
                        sm_stop_sig<=1'b0;
                        sm_stop_sig<=1'b0;
                end
                end
 
 
                else if(detect_start)
                else if(detect_start)
                begin
                begin
                        scl_main_state<=scl_address_shift;
                        scl_main_state<=scl_address_shift;
                        sm_stop_sig<=1'b0;
                        sm_stop_sig<=1'b0;
                end
                end
                //else if(!sda_in)
                //else if(!sda_in)
                                                        //If ack has been received then,check for slave/master
                                                        //If ack has been received then,check for slave/master
 
 
                        else if(master_slave)
                        else if(master_slave)
                        begin                           //if master then set the direction for master to either transmit 
                        begin                           //if master then set the direction for master to either transmit 
                           if(!master_rw)                               //or receive the data.
                           if(!master_rw)                               //or receive the data.
                                scl_main_state<=scl_rx_data;
                                scl_main_state<=scl_rx_data;
                           else
                           else
                                scl_main_state<=scl_tx_data;    //Ravi: if no detect_stop then check if master send to state depending upon 
                                scl_main_state<=scl_tx_data;    //Ravi: if no detect_stop then check if master send to state depending upon 
                        end                                                                     //tx/rx bit of control register.
                        end                                                                     //tx/rx bit of control register.
 
 
                        else
                        else
                        begin                                           //If slave then check if received address has matched
                        begin                                           //If slave then check if received address has matched
                           //if(addr_match)
                           //if(addr_match)
                           //begin                                      //if address matches then set the direction of communication based 
                           //begin                                      //if address matches then set the direction of communication based 
                              if(add_reg[0])                             //last bit of shift register of address cycle.
                              if(add_reg[0])                             //last bit of shift register of address cycle.
                                   scl_main_state<=scl_tx_data;
                                   scl_main_state<=scl_tx_data;
                              else
                              else
                                    scl_main_state<=scl_rx_data;
                                    scl_main_state<=scl_rx_data;
                         end
                         end
                           //else
                           //else
                                //scl_main_state<=scl_main_idle;
                                //scl_main_state<=scl_main_idle;
                        //end
                        //end
 
 
 
 
                //else
                //else
                //begin
                //begin
                //      scl_main_state<=scl_main_idle;                          //If no ack received go to idle state.  
                //      scl_main_state<=scl_main_idle;                          //If no ack received go to idle state.  
                //if(master_slave)
                //if(master_slave)
                //      sm_stop_sig<=1'b1;
                //      sm_stop_sig<=1'b1;
                //end
                //end
 
 
        scl_rx_data:
        scl_rx_data:
                if(bit_cnt == 8'b0000_0111)
                if(bit_cnt == 8'b0000_0111)
                        scl_main_state<=scl_send_ack;
                        scl_main_state<=scl_send_ack;
                else if(detect_stop)
                else if(detect_stop)
                begin
                begin
                        scl_main_state<=scl_main_idle;
                        scl_main_state<=scl_main_idle;
                        sm_stop_sig<=1'b0;
                        sm_stop_sig<=1'b0;
                end
                end
                else if(detect_start)
                else if(detect_start)
                begin
                begin
                        scl_main_state<=scl_address_shift;
                        scl_main_state<=scl_address_shift;
                        sm_stop_sig<=1'b0;
                        sm_stop_sig<=1'b0;
                end
                end
 
 
 
 
 
 
 
 
        scl_tx_data:
        scl_tx_data:
                if(bit_cnt == 8'b0000_0111)
                if(bit_cnt == 8'b0000_0111)
                        scl_main_state<=scl_wait_ack;
                        scl_main_state<=scl_wait_ack;
                else if(detect_stop)
                else if(detect_stop)
                begin
                begin
                        scl_main_state<=scl_main_idle;
                        scl_main_state<=scl_main_idle;
                        sm_stop_sig<=1'b0;
                        sm_stop_sig<=1'b0;
                end
                end
                else if(detect_start)
                else if(detect_start)
                begin
                begin
                        scl_main_state<=scl_address_shift;
                        scl_main_state<=scl_address_shift;
                        sm_stop_sig<=1'b0;
                        sm_stop_sig<=1'b0;
                end
                end
 
 
 
 
        scl_send_ack:
        scl_send_ack:
                if(detect_stop)
                if(detect_stop)
                begin
                begin
                        scl_main_state<=scl_main_idle;
                        scl_main_state<=scl_main_idle;
                        sm_stop_sig<=1'b0;
                        sm_stop_sig<=1'b0;
                end
                end
 
 
                else
                else
                        scl_main_state<=scl_rx_data;
                        scl_main_state<=scl_rx_data;
 
 
        scl_wait_ack:                                                           //Ravi: Even in this state machine will goto Tx state,if no ack or arb_lost has occur  
        scl_wait_ack:                                                           //Ravi: Even in this state machine will goto Tx state,if no ack or arb_lost has occur  
                //if(arbitration_lost)                                  //This is software part to program the control register so that it will generate stop 
                //if(arbitration_lost)                                  //This is software part to program the control register so that it will generate stop 
                        //scl_main_state<=scl_main_idle;                //and will go in idle state.So removing all clauses except detect stop.
                        //scl_main_state<=scl_main_idle;                //and will go in idle state.So removing all clauses except detect stop.
                if(detect_stop)
                if(detect_stop)
                begin
                begin
                        scl_main_state<=scl_main_idle;
                        scl_main_state<=scl_main_idle;
                        sm_stop_sig<=1'b0;
                        sm_stop_sig<=1'b0;
                end
                end
 
 
 
 
                else
                else
                        scl_main_state<=scl_tx_data;
                        scl_main_state<=scl_tx_data;
                //else
                //else
                //begin
                //begin
                        //if(master_slave)
                        //if(master_slave)
                                //sm_stop_sig<=1'b1;
                                //sm_stop_sig<=1'b1;
                //scl_main_state<=scl_main_idle;
                //scl_main_state<=scl_main_idle;
                //end
                //end
        endcase
        endcase
end
end
end
end
 
 
//Start and stop detect process
//Start and stop detect process
//////////////////////////////
//////////////////////////////
 
 
always@(sda_in or scl_main_state)
always@(sda_in or scl_main_state)
begin
begin
 
 
        if(rst || h_rst)
        if(rst || h_rst)
                detect_start_sig<=1'b0;
                detect_start_sig<=1'b0;
        else if(!sda_in && scl_in)
        else if(!sda_in && scl_in)
                detect_start_sig<=1'b1;
                detect_start_sig<=1'b1;
        else if(scl_address_shift)
        else if(scl_address_shift)
                detect_start_sig<=1'b0;
                detect_start_sig<=1'b0;
        else
        else
                detect_start_sig<=1'b0;
                detect_start_sig<=1'b0;
end
end
 
 
always@(posedge sda_in or posedge detect_start)
always@(posedge sda_in or posedge detect_start)
begin
begin
 
 
        if(rst || h_rst)
        if(rst || h_rst)
                detect_stop_sig<=1'b0;
                detect_stop_sig<=1'b0;
        else if(detect_start)
        else if(detect_start)
                detect_stop_sig<=1'b0;
                detect_stop_sig<=1'b0;
        else if(scl_in)
        else if(scl_in)
                detect_stop_sig<=1'b1;
                detect_stop_sig<=1'b1;
        //else if(detect_start)
        //else if(detect_start)
                //detect_stop_sig<=1'b0;
                //detect_stop_sig<=1'b0;
        else
        else
                detect_stop_sig<=1'b0;
                detect_stop_sig<=1'b0;
end
end
 
 
//generate a delay version of byte_trans signal
//generate a delay version of byte_trans signal
//This will be used for detecting falling edge of byte_trans
//This will be used for detecting falling edge of byte_trans
 
 
always@(posedge clk or posedge rst or posedge h_rst)
always@(posedge clk or posedge rst or posedge h_rst)
begin
begin
        if(rst || h_rst)
        if(rst || h_rst)
                byte_trans_delay_sig <= 1'b0;
                byte_trans_delay_sig <= 1'b0;
        else
        else
        begin
        begin
                byte_trans_delay_sig <= byte_trans;
                byte_trans_delay_sig <= byte_trans;
                byte_trans_fall_sig <= byte_trans_delay && !byte_trans;
                byte_trans_fall_sig <= byte_trans_delay && !byte_trans;
        end
        end
end
end
 
 
 
 
//Processor status bits/////
//Processor status bits/////
//byte_trans bit
//byte_trans bit
//This indicate data is being transferred,This bit will be one only after all 8 bits has
//This indicate data is being transferred,This bit will be one only after all 8 bits has
//been tranferred.i.e on rising pulse of SCL in ack cycle.
//been tranferred.i.e on rising pulse of SCL in ack cycle.
 
 
always@(negedge scl_in or posedge rst or posedge halt_rst or posedge core_rst or posedge h_rst)
always@(negedge scl_in or posedge rst or posedge halt_rst or posedge core_rst or posedge h_rst)
begin
begin
        if(rst || h_rst)
        if(rst || h_rst)
                byte_trans_sig<=1'b0;
                byte_trans_sig<=1'b0;
        else if(halt_rst)
        else if(halt_rst)
                byte_trans_sig <= 1'b0;
                byte_trans_sig <= 1'b0;
        else if(bit_cnt == 8'b0000_1000)
        else if(bit_cnt == 8'b0000_1000)
                byte_trans_sig<=1'b1;
                byte_trans_sig<=1'b1;
        else if(halt_rst || core_rst)                   // after core_rst negate byte_trans bit
        else if(halt_rst || core_rst)                   // after core_rst negate byte_trans bit
                byte_trans_sig<=1'b0;
                byte_trans_sig<=1'b0;
end
end
 
 
//bus_busy
//bus_busy
//This indicates that communication is in progress and bus in not free.
//This indicates that communication is in progress and bus in not free.
//This bit will be set on detection of start and will be cleared on STOP
//This bit will be set on detection of start and will be cleared on STOP
 
 
always@(posedge clk or posedge rst or posedge h_rst)
always@(posedge clk or posedge rst or posedge h_rst)
begin
begin
        if(rst || h_rst)
        if(rst || h_rst)
                bb_sig<=1'b0;
                bb_sig<=1'b0;
        else
        else
        begin
        begin
                if(detect_start)
                if(detect_start)
                        bb_sig<=1'b1;
                        bb_sig<=1'b1;
                if(detect_stop || core_rst)
                if(detect_stop || core_rst)
                        bb_sig<=1'b0;
                        bb_sig<=1'b0;
        end
        end
end
end
 
 
//slave_addressed bit
//slave_addressed bit
//This indicates that slave has been addressed,and after sending ack
//This indicates that slave has been addressed,and after sending ack
//core will switch to slave mode.
//core will switch to slave mode.
//This bit will be set if adds matched in add ack state.
//This bit will be set if adds matched in add ack state.
 
 
always@(posedge clk or posedge rst or posedge h_rst)
always@(posedge clk or posedge rst or posedge h_rst)
begin
begin
        if(rst)                         //Removing h_rst
        if(rst)                         //Removing h_rst
        slave_addressed_sig<=1'b0;
        slave_addressed_sig<=1'b0;
        //else if(scl_main_state == scl_ack_address)
        //else if(scl_main_state == scl_ack_address)
        else if(byte_trans)
        else if(byte_trans)
        slave_addressed_sig<=addr_match;
        slave_addressed_sig<=addr_match;
        else
        else
        slave_addressed_sig<=slave_addressed;
        slave_addressed_sig<=slave_addressed;
        //slave_addressed_sig<= 1'b0;
        //slave_addressed_sig<= 1'b0;
end
end
 
 
//set address match bit if address reg matches with shift register output
//set address match bit if address reg matches with shift register output
/*always@(negedge scl or posedge rst)
/*always@(negedge scl or posedge rst)
begin
begin
        if(rst)
        if(rst)
                addr_match_sig<=1'b0;
                addr_match_sig<=1'b0;
        else if( slave_add[7:1] == add_reg[7:1])
        else if( slave_add[7:1] == add_reg[7:1])
                addr_match_sig <=1'b1;
                addr_match_sig <=1'b1;
        else
        else
                addr_match_sig<=1'b0;
                addr_match_sig<=1'b0;
end*/
end*/
assign addr_match = slave_add[7:1] == add_reg[7:1]? 1'b1:1'b0;
assign addr_match = slave_add[7:1] == add_reg[7:1]? 1'b1:1'b0;
assign add_reg_ld = 1'b0;
assign add_reg_ld = 1'b0;
 
 
//Slave read write
//Slave read write
//This bit indicates slave has been addressed,this indicates
//This bit indicates slave has been addressed,this indicates
//read or write bit sent by processor.
//read or write bit sent by processor.
 
 
always@(posedge clk or posedge rst or posedge h_rst)
always@(posedge clk or posedge rst or posedge h_rst)
begin
begin
        if(rst || h_rst)
        if(rst || h_rst)
                slave_rw_sig<=1'b0;
                slave_rw_sig<=1'b0;
        else if(scl_main_state == scl_ack_address)
        else if(scl_main_state == scl_ack_address)
                slave_rw_sig<=add_reg[0];
                slave_rw_sig<=add_reg[0];
end
end
 
 
//interrupt pending
//interrupt pending
//This will cause an interrupt to processor if interrupt enable is set
//This will cause an interrupt to processor if interrupt enable is set
//This bit will be set in following circumstances:
//This bit will be set in following circumstances:
//1):Byte transfer has been completed.
//1):Byte transfer has been completed.
//2):Arbitration lost.
//2):Arbitration lost.
//3):slave has been addressed and and bytes have been transferred.
//3):slave has been addressed and and bytes have been transferred.
//4):Time out condition has been reached.
//4):Time out condition has been reached.
//5):Repeated start condition.
//5):Repeated start condition.
//Only processor can clear the interrupt.
//Only processor can clear the interrupt.
 
 
always@(posedge clk or posedge rst or posedge h_rst)
always@(posedge clk or posedge rst or posedge h_rst)
begin
begin
        if(rst || h_rst)
        if(rst || h_rst)
        inter_sig<=1'b0;
        inter_sig<=1'b0;
 
 
        else
        else
        begin
        begin
                //if(interrupt_rst)
                //if(interrupt_rst)
                //inter_sig<=1'b0;
                //inter_sig<=1'b0;
 
 
                if(inter_rst)
                if(inter_rst)
                inter_sig<=1'b0;
                inter_sig<=1'b0;
 
 
        //in below else if condition anding byte_trans with master_slave also removing add_reg[]  condition in next clause              
        //in below else if condition anding byte_trans with master_slave also removing add_reg[]  condition in next clause              
                else if((byte_trans && master_slave) || arbitration_lost || (slave_addressed && !master_slave && byte_trans) || rep_start)
                else if((byte_trans && master_slave) || arbitration_lost || (slave_addressed && !master_slave && byte_trans) || rep_start)
                inter_sig<=1'b1;
                inter_sig<=1'b1;
 
 
 
 
 
 
                //else                  //interrupt need to get cleared by processor,so do not reset in else condition
                //else                  //interrupt need to get cleared by processor,so do not reset in else condition
                //inter_sig<=1'b0;
                //inter_sig<=1'b0;
 
 
 
 
        end
        end
end
end
 
 
//generate delay version of detect_stop
//generate delay version of detect_stop
always@(posedge clk or posedge rst or posedge h_rst)
always@(posedge clk or posedge rst or posedge h_rst)
begin
begin
if(rst || h_rst)
if(rst || h_rst)
d_detect_stop_sig <= 1'b0;
d_detect_stop_sig <= 1'b0;
else
else
begin
begin
d1_detect_stop_sig <= detect_stop;
d1_detect_stop_sig <= detect_stop;
d_detect_stop_sig <= d1_detect_stop_sig;
d_detect_stop_sig <= d1_detect_stop_sig;
end
end
end
end
 
 
 
 
always@(posedge clk or posedge rst or posedge h_rst)
always@(posedge clk or posedge rst or posedge h_rst)
begin
begin
        if(rst || h_rst)
        if(rst || h_rst)
        halt_sig <= 1'b0;
        halt_sig <= 1'b0;
 
 
        else
        else
        begin
        begin
                if(halt_rst)
                if(halt_rst)
                        halt_sig<=1'b0;
                        halt_sig<=1'b0;
 
 
                else if(byte_trans && master_slave)
                else if(byte_trans && master_slave)
                        halt_sig<=1'b1;
                        halt_sig<=1'b1;
        end
        end
end
end
 
 
//acknoweldege recieve
//acknoweldege recieve
//This bit indicates the data on SDA line during ack cycle.
//This bit indicates the data on SDA line during ack cycle.
 
 
always@(posedge clk or posedge rst or posedge h_rst)
always@(posedge clk or posedge rst or posedge h_rst)
begin
begin
        if(rst || h_rst)
        if(rst || h_rst)
                ack_rec_sig<=1'b0;
                ack_rec_sig<=1'b0;
        else if((scl_main_state == scl_wait_ack) || (scl_main_state == scl_ack_address) || (scl_main_state == scl_send_ack))
        else if((scl_main_state == scl_wait_ack) || (scl_main_state == scl_ack_address) || (scl_main_state == scl_send_ack))
                ack_rec_sig<=sda_in;
                ack_rec_sig<=sda_in;
end
end
 
 
//Setting control bits of shift registers and counters
//Setting control bits of shift registers and counters
//////////////////////////////////////////////////////
//////////////////////////////////////////////////////
 
 
//Address shift register will just receive the data after start 
//Address shift register will just receive the data after start 
//condition detection.It wont be get loaded.While data shift register
//condition detection.It wont be get loaded.While data shift register
//will receive as well as transmit the data.
//will receive as well as transmit the data.
 
 
//address shift register enable bit
//address shift register enable bit
always@(posedge clk or posedge rst or posedge h_rst)
always@(posedge clk or posedge rst or posedge h_rst)
begin
begin
        if(rst || h_rst)
        if(rst || h_rst)
                add_reg_enable_sig<=1'b0;
                add_reg_enable_sig<=1'b0;
        else if(detect_start || scl_main_state == scl_address_shift)
        else if(detect_start || scl_main_state == scl_address_shift)
                add_reg_enable_sig<=1'b1;
                add_reg_enable_sig<=1'b1;
        else
        else
                add_reg_enable_sig<=1'b0;
                add_reg_enable_sig<=1'b0;
end
end
 
 
 
 
//Data shift register.
//Data shift register.
//This register will be enabled every time when it is either transmitting or receiving the data. 
//This register will be enabled every time when it is either transmitting or receiving the data. 
  always @(posedge clk or posedge rst or posedge h_rst)
  always @(posedge clk or posedge rst or posedge h_rst)
  begin
  begin
    if (rst || h_rst)
    if (rst || h_rst)
    begin
    begin
      data_reg_en_sig <= 1'b0;
      data_reg_en_sig <= 1'b0;
      data_reg_ld_sig <= 1'b0;
      data_reg_ld_sig <= 1'b0;
    end
    end
    else
    else
    begin
    begin
      if (((master_slave && scl_main_state == scl_address_shift) || (scl_main_state ==
      if (((master_slave && scl_main_state == scl_address_shift) || (scl_main_state ==
          scl_rx_data) || (scl_main_state == scl_tx_data)))
          scl_rx_data) || (scl_main_state == scl_tx_data)))
        data_reg_en_sig <= 1'b1;
        data_reg_en_sig <= 1'b1;
      else
      else
        data_reg_en_sig <= 1'b0;
        data_reg_en_sig <= 1'b0;
 
 
         /*if ((master_slave && scl_main_state == scl_idle) || (scl_main_state ==
         /*if ((master_slave && scl_main_state == scl_idle) || (scl_main_state ==
          scl_wait_ack) || (scl_main_state == scl_ack_address &&
          scl_wait_ack) || (scl_main_state == scl_ack_address &&
          !add_reg[0] && !master_slave) || (scl_main_state == scl_ack_address &&
          !add_reg[0] && !master_slave) || (scl_main_state == scl_ack_address &&
          master_rw && master_slave))*/
          master_rw && master_slave))*/
                if(((scl_main_state == scl_main_idle) || byte_trans) && data_en)
                if(((scl_main_state == scl_main_idle) || byte_trans) && data_en)
 
 
                data_reg_ld_sig <= 1'b1;
                data_reg_ld_sig <= 1'b1;
         else
         else
        data_reg_ld_sig <= 1'b0;
        data_reg_ld_sig <= 1'b0;
 
 
    end
    end
 
 
  end
  end
 
 
//logic for generating control bits for bit counter
//logic for generating control bits for bit counter
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
assign bit_cnt_enable = ((scl_main_state == scl_address_shift) || (scl_main_state == scl_rx_data) || (scl_main_state == scl_tx_data));
assign bit_cnt_enable = ((scl_main_state == scl_address_shift) || (scl_main_state == scl_rx_data) || (scl_main_state == scl_tx_data));
assign bit_cnt_rst = ((scl_main_state == scl_main_idle) || (scl_main_state == scl_send_ack) || (scl_main_state == scl_wait_ack) || (scl_main_state == scl_ack_address));
assign bit_cnt_rst = ((scl_main_state == scl_main_idle) || (scl_main_state == scl_send_ack) || (scl_main_state == scl_wait_ack) || (scl_main_state == scl_ack_address));
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
//implementation of timer counter
//implementation of timer counter
 
 
always@(posedge clk or posedge rst or posedge h_rst)
always@(posedge clk or posedge rst or posedge h_rst)
begin
begin
        if(rst || h_rst)
        if(rst || h_rst)
        time_cnt<=8'b0000_0000;
        time_cnt<=8'b0000_0000;
        else if(!scl_in)
        else if(!scl_in)
        time_cnt<=time_cnt + 1'b1;
        time_cnt<=time_cnt + 1'b1;
        else
        else
        time_cnt<=8'b0000_0000;
        time_cnt<=8'b0000_0000;
end
end
 
 
always@(posedge clk or posedge rst or posedge h_rst)
always@(posedge clk or posedge rst or posedge h_rst)
begin
begin
        if(rst || h_rst)
        if(rst || h_rst)
        begin
        begin
                core_rst_sig<=1'b0;
                core_rst_sig<=1'b0;
                time_out_sig<=1'b0;
                time_out_sig<=1'b0;
        end
        end
        else if((time_cnt == time_out_reg) & bb)
        else if((time_cnt == time_out_reg) & bb)
        begin
        begin
                core_rst_sig <= 1'b1;
                core_rst_sig <= 1'b1;
                time_out_sig <= 1'b1;
                time_out_sig <= 1'b1;
        end
        end
        /*else if((time_cnt == time_out_reg) && (scl_state == scl_idle))
        /*else if((time_cnt == time_out_reg) && (scl_state == scl_idle))
        begin
        begin
                core_rst_sig <= 1'b0;
                core_rst_sig <= 1'b0;
                time_out_sig <= 1'b1;
                time_out_sig <= 1'b1;
        end*/
        end*/
        else
        else
        begin
        begin
                core_rst_sig <= 1'b0;
                core_rst_sig <= 1'b0;
                time_out_sig <= 1'b0;
                time_out_sig <= 1'b0;
        end
        end
end
end
 
 
//Process for assigning Master and slave SDA.
//Process for assigning Master and slave SDA.
always@(posedge clk or posedge rst or posedge h_rst)
always@(posedge clk or posedge rst or posedge h_rst)
begin
begin
        if(rst || h_rst)
        if(rst || h_rst)
                master_sda_sig<=1'b1;
                master_sda_sig<=1'b1;
        else if((scl_main_state == scl_address_shift) || (scl_main_state == scl_tx_data))
        else if((scl_main_state == scl_address_shift) || (scl_main_state == scl_tx_data))
                master_sda_sig<=serial_out;
                master_sda_sig<=serial_out;
        else if(scl_main_state == scl_send_ack)
        else if(scl_main_state == scl_send_ack)
                master_sda_sig<=ack;
                master_sda_sig<=ack;
        else
        else
                master_sda_sig<=1'b1;
                master_sda_sig<=1'b1;
end
end
 
 
always@(posedge clk or posedge rst or posedge h_rst)
always@(posedge clk or posedge rst or posedge h_rst)
begin
begin
        if(rst || h_rst)
        if(rst || h_rst)
                slave_sda_sig<=1'b1;
                slave_sda_sig<=1'b1;
        else if(scl_main_state == scl_tx_data)
        else if(scl_main_state == scl_tx_data)
                slave_sda_sig<=serial_out;
                slave_sda_sig<=serial_out;
        else if((addr_match && (scl_main_state == scl_ack_address)) || (scl_main_state == scl_send_ack))
        else if((addr_match && (scl_main_state == scl_ack_address)) || (scl_main_state == scl_send_ack))
                slave_sda_sig<=ack;
                slave_sda_sig<=ack;
        else
        else
                slave_sda_sig<=1'b1;
                slave_sda_sig<=1'b1;
end
end
 
 
//assigning SCL and SDA lines in output conditions.
//assigning SCL and SDA lines in output conditions.
 
 
 
 
assign scl_oe = master_slave ? scl_out : 1'b1;
assign scl_oe = master_slave ? scl_out : 1'b1;
assign sda_sig = (((master_slave == 1'b1 && sda_out == 1'b0) ||
assign sda_sig = (((master_slave == 1'b1 && sda_out == 1'b0) ||
                 (master_slave == 1'b0 && slave_sda == 1'b0) || stop_scl) ? 1'b1 : 1'b0);
                 (master_slave == 1'b0 && slave_sda == 1'b0) || stop_scl) ? 1'b1 : 1'b0);
assign sda_oe = (sda_sig ?1'b0 : 1'b1);
assign sda_oe = (sda_sig ?1'b0 : 1'b1);
 
 
//Presenting data on data_register which is for processor
//Presenting data on data_register which is for processor
always@(posedge clk or posedge rst or posedge h_rst)
always@(posedge clk or posedge rst or posedge h_rst)
begin
begin
        if(rst || h_rst)
        if(rst || h_rst)
                i2c_up<=8'b00000000;
                i2c_up<=8'b00000000;
        else if(scl_main_state == scl_send_ack)
        else if(scl_main_state == scl_send_ack)
                i2c_up<=shift_reg;
                i2c_up<=shift_reg;
        else
        else
                i2c_up<=i2c_up;
                i2c_up<=i2c_up;
end
end
 
 
 
 
 
 
//This process will set arbitration lost signal
//This process will set arbitration lost signal
//////////////////////////////////////////////
//////////////////////////////////////////////
 //   This process checks the master's outgoing SDA with the incoming SDA to determine
 //   This process checks the master's outgoing SDA with the incoming SDA to determine
  //   if control of the bus has been lost. SDA is checked only when SCL is high
  //   if control of the bus has been lost. SDA is checked only when SCL is high
  //   and during the states IDLE, ADD_SHIFT, and TX_DATA to insure that START and STOP
  //   and during the states IDLE, ADD_SHIFT, and TX_DATA to insure that START and STOP
  //   conditions are not set when the bus is busy. Note that this is only done when Master.
  //   conditions are not set when the bus is busy. Note that this is only done when Master.
   always @( posedge (clk) or posedge (rst) or posedge (h_rst) )
   always @( posedge (clk) or posedge (rst) or posedge (h_rst) )
  begin
  begin
    if (rst || h_rst)
    if (rst || h_rst)
    begin
    begin
      arbitration_lost_sig <= 1'b0;
      arbitration_lost_sig <= 1'b0;
     end
     end
    else
    else
    begin
    begin
      if (scl_main_state == scl_idle)
      if (scl_main_state == scl_idle)
      begin
      begin
        arbitration_lost_sig <= 1'b0;
        arbitration_lost_sig <= 1'b0;
      end
      end
      else if ((master_slave))
      else if ((master_slave))
        //   only need to check arbitration in master mode
        //   only need to check arbitration in master mode
        //   check for SCL high before comparing data 
        //   check for SCL high before comparing data 
        if ((scl_in && scl_oe && (scl_main_state == scl_address_shift || scl_main_state
        if ((scl_in && scl_oe && (scl_main_state == scl_address_shift || scl_main_state
            == scl_tx_data || scl_main_state == scl_idle)))
            == scl_tx_data || scl_main_state == scl_idle)))
          //   when master, will check bus in all states except ACK_ADDR and WAIT_ACK
          //   when master, will check bus in all states except ACK_ADDR and WAIT_ACK
          //   this will insure that arb_lost is set if a start or stop condition
          //   this will insure that arb_lost is set if a start or stop condition
          //   is set at the wrong time
          //   is set at the wrong time
                //if(sda_in == 1'b0 && sda_oe == 1'b1) || (detect_stop
                //if(sda_in == 1'b0 && sda_oe == 1'b1) || (detect_stop
 
 
         if (sda_in == 1'b0 && sda_oe == 1'b1)
         if (sda_in == 1'b0 && sda_oe == 1'b1)
          begin
          begin
            arbitration_lost_sig <= 1'b1;
            arbitration_lost_sig <= 1'b1;
 
 
          end
          end
          else
          else
          begin
          begin
            arbitration_lost_sig <= 1'b0;
            arbitration_lost_sig <= 1'b0;
 
 
          end
          end
 
 
        else
        else
        begin
        begin
          arbitration_lost_sig <= arbitration_lost;
          arbitration_lost_sig <= arbitration_lost;
        end
        end
 
 
 
 
    end
    end
 
 
  end
  end
 
 
//setting the arbitration lost bit of status register
//setting the arbitration lost bit of status register
////////////////////////////////////////////////////
////////////////////////////////////////////////////
//this bit will be set when:
//this bit will be set when:
        //arbiration has lost.
        //arbiration has lost.
        //core is in master mode and a generate strat condition has detected while bus is busy 
        //core is in master mode and a generate strat condition has detected while bus is busy 
        //or a stop conditioin has been detected when not requested
        //or a stop conditioin has been detected when not requested
        //or a repeate start has been detected when in slave mode.
        //or a repeate start has been detected when in slave mode.
 
 
always@(posedge clk or posedge rst or posedge core_rst or posedge h_rst)
always@(posedge clk or posedge rst or posedge core_rst or posedge h_rst)
begin
begin
        if(rst || h_rst)
        if(rst || h_rst)
                arb_lost_sig<=1'b0;
                arb_lost_sig<=1'b0;
        else
        else
        begin
        begin
                if(arb_rst)
                if(arb_rst)
                arb_lost_sig<=1'b0;
                arb_lost_sig<=1'b0;
                else if(master_slave)
                else if(master_slave)
                begin
                begin
                        if((arbitration_lost)||(bus_busy && gen_start))
                        if((arbitration_lost)||(bus_busy && gen_start))
                                arb_lost_sig<=1'b1;
                                arb_lost_sig<=1'b1;
                end
                end
 
 
                else if(rep_start)
                else if(rep_start)
                        arb_lost_sig<=1'b1;
                        arb_lost_sig<=1'b1;
                //else if(core_rst && master_slave)
                //else if(core_rst && master_slave)
                        //arb_lost_sig<=1'b0;
                        //arb_lost_sig<=1'b0;
                else
                else
                        arb_lost_sig<=1'b0;
                        arb_lost_sig<=1'b0;
        end
        end
end
end
 
 
always@(posedge clk or posedge rst or posedge h_rst)
always@(posedge clk or posedge rst or posedge h_rst)
begin
begin
if(rst || h_rst)
if(rst || h_rst)
        rep_start_sig<=1'b0;
        rep_start_sig<=1'b0;
else if(scl_main_state == scl_address_shift || scl_main_state == scl_ack_address || scl_main_state == scl_send_ack || scl_main_state == scl_wait_ack)
else if(scl_main_state == scl_address_shift || scl_main_state == scl_ack_address || scl_main_state == scl_send_ack || scl_main_state == scl_wait_ack)
        rep_start_sig<=1'b0;
        rep_start_sig<=1'b0;
else
else
        rep_start_sig<=rep_start;
        rep_start_sig<=rep_start;
end
end
 
 
 
 
 
 
endmodule
endmodule
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.