URL
https://opencores.org/ocsvn/i2c_master_slave_core/i2c_master_slave_core/trunk
Subversion Repositories i2c_master_slave_core
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 2 to Rev 3
- ↔ Reverse comparison
Rev 2 → Rev 3
/tags/t1/i2c_master_slave_core/doc/i2c_spec.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
tags/t1/i2c_master_slave_core/doc/i2c_spec.pdf
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: tags/t1/i2c_master_slave_core/doc/i2c_spec.doc
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: tags/t1/i2c_master_slave_core/doc/i2c_spec.doc
===================================================================
--- tags/t1/i2c_master_slave_core/doc/i2c_spec.doc (nonexistent)
+++ tags/t1/i2c_master_slave_core/doc/i2c_spec.doc (revision 3)
tags/t1/i2c_master_slave_core/doc/i2c_spec.doc
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: tags/t1/i2c_master_slave_core/verilog/rtl/shift.v
===================================================================
--- tags/t1/i2c_master_slave_core/verilog/rtl/shift.v (nonexistent)
+++ tags/t1/i2c_master_slave_core/verilog/rtl/shift.v (revision 3)
@@ -0,0 +1,52 @@
+////////////////////////////Shift.v/////////////////////////////////////////////////////////////////////
+// //
+//Design Engineer: Ravi Gupta //
+//Company Name : Toomuch Semiconductor
+//Email : ravi1.gupta@toomuchsemi.com //
+// //
+//Purpose : Used for shifting address and data in both transmit and recieve mode //
+//created : 22-11-07 //
+// //
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/*// synopsys translate_off
+`include "oc8051_timescale.v"
+// synopsys translate_on
+
+`include "oc8051_defines.v"*/
+
+
+module shift(clk,asyn_rst,load,shift_en,serial_in,data_in,serial_out,data_out);
+
+input clk,asyn_rst,load,shift_en,serial_in;
+input [7:0]data_in;
+
+output serial_out;
+output [7:0]data_out;
+
+reg [7:0]data;
+
+always@(posedge clk or posedge asyn_rst or posedge load)
+begin
+ if(asyn_rst)
+ data<=8'h0; //clear the data register upon asynchronous reset.
+
+ else if(load)
+ data<=data_in; //Load the internal register upon insertion of load bit.
+
+ else if(shift_en)
+ data<={data[6:0],serial_in}; //Upon shift_en high every time a new serial data is coming to LSB bit and data will be shifted
+ //to one bit.
+ else
+ data<=data; //Prevent formation of latches
+end
+
+
+assign data_out = data; //Output the data in a data_register
+assign serial_out = data[7]; //MSB is transmitted first in I2C protocol.
+
+
+endmodule
+
+//change loading into asynchronous mode
+
Index: tags/t1/i2c_master_slave_core/verilog/rtl/counter.v
===================================================================
--- tags/t1/i2c_master_slave_core/verilog/rtl/counter.v (nonexistent)
+++ tags/t1/i2c_master_slave_core/verilog/rtl/counter.v (revision 3)
@@ -0,0 +1,41 @@
+//////////////////////////counter.v///////////////////////////////////////////////////////////////////////////////
+ //
+//Designed Engineer: Ravi Gupta //
+//Company Name : Toomuch Semiconductor
+//Email : ravi1.gupta@toomuchsemi.com //
+ //
+//Purpose : Used for counting clock pulses for prescale register and number of bytes transferred //
+//Created : 22-11-07 //
+ //
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/*// synopsys translate_off
+`include "oc8051_timescale.v"
+// synopsys translate_on
+
+`include "oc8051_defines.v"*/
+
+
+module counter (clk,asyn_rst,enable,load,data_in,out);
+
+input clk,asyn_rst,enable,load;
+input [7:0] data_in;
+output [7:0] out;
+
+reg [7:0]data;
+
+always@(posedge clk or posedge asyn_rst)
+begin
+ if(asyn_rst)
+ data<=8'h0; //clear all bits upon asynchronous reset.
+ else if(load)
+ data<=data_in; //load the counter with incoming data if load signal is high
+ else if(enable)
+ data<=data + 1'b1; //Increment the counter if enable bit is high
+ else
+ data<=data; //else hold the data;else part is mention to avoid latch formation
+end
+
+assign out=data;
+
+endmodule
Index: tags/t1/i2c_master_slave_core/verilog/rtl/controller_interface.v
===================================================================
--- tags/t1/i2c_master_slave_core/verilog/rtl/controller_interface.v (nonexistent)
+++ tags/t1/i2c_master_slave_core/verilog/rtl/controller_interface.v (revision 3)
@@ -0,0 +1,546 @@
+////////////////////////////////////////////controller_interface.v////////////////////////////////////////
+// //
+//Design Engineer: Ravi Gupta //
+//Company Name : Toomuch Semiconductor
+//Email : ravi1.gupta@toomuchsemi.com //
+// //
+//Purpose : This core will be used as an interface between I2C core and Processor //
+//Created : 6-12-2007 //
+// //
+// //
+// //
+// //
+// //
+// //
+// //
+// //
+//Modification : Change the control register,added halt reset and inter_rst in control register
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/*// synopsys translate_off
+`include "oc8051_timescale.v"
+// synopsys translate_on
+
+`include "oc8051_defines.v"*/
+
+
+module processor_interface (clk,rst,add_bus,data_in,data_out,as,ds,rw,bus_busy,byte_trans,slave_addressed,arb_lost,slave_rw,inter,ack_rec,
+ core_en,inter_en,mode,master_rw,ack,rep_start,data,i2c_data,slave_add,time_out_reg,prescale,irq,time_out,inter_rst,halt,data_en,time_rst);
+input clk; //System clock
+input rst; //system reset
+
+//signals connecting core to processor
+/////////////////////////////////////
+
+input [7:0]add_bus; //contains address of internal register
+input [7:0]data_in; //trnasport the data for i2c core
+input as; //asserted high indicates vallid address has been placed on the address bus
+input ds; //asserted high indicates valid data on data bus
+input rw; //"1" indicates that processor has to write else read
+output irq; //interrupt to processor
+output inter_rst; //this bit will be written by processor when it will clear the interrupt.
+output [7:0]data_out;
+output halt;
+output data_en;
+input time_rst;
+
+//signals from core to reflect te status of core and buses
+///////////////////////////////////////////////////////////
+
+input bus_busy; //signal from core indicates bus is busy
+input byte_trans; //signal from core indicates byte transfer is in progress
+input slave_addressed; //signal from core indicares core has been identified as slave
+input arb_lost; //signal from core indicates bus error
+input slave_rw; //signal from core indicates operation of slave core
+input inter; //signal from core.this will interrupt the processor if this bit as well as interrupt enable is high
+input ack_rec; //signal from core to reflect the status of ack bit
+input time_out;
+
+//bits of control register
+//////////////////////////
+
+inout core_en; //this bit must be cleared before any other bit of control register have any effect on core
+inout inter_en; //To intrrupt the core this bit must be set when interrupt is pending
+inout mode; //Transaction from "0" to "1" directes core to act as master else slave
+inout master_rw; //set directiion for master either to transmit or receive
+inout ack; //value of acknowledgment bit to be transmitted on SDA line during ack cycle
+inout rep_start; //set this bit if processor wants a repeated start
+
+//data register
+////////////////
+
+inout [7:0]prescale; //contains the value for generating SCL frequency
+inout [7:0]time_out_reg; //contains the value for maximum low period for scl
+inout [7:0]slave_add; //this is the programmble slave address
+inout [7:0]data; //data for i2c core
+input [7:0]i2c_data; //data from core for processor
+
+//defining registers addresses
+/////////////////////////////
+
+`define PRER 8'b0000_0010
+`define CTR 8'b0000_0100
+`define SR 8'b0000_1000
+`define TO 8'b0000_1010
+`define ADDR 8'b0000_1100
+`define DR 8'b0000_1110
+`define RR 8'b0000_0000
+
+/*//defing the machine state
+//////////////////////////
+
+parameter processor_idle=2'b00;
+parameter processor_address=2'b01;
+parameter processor_data=2'b10;
+parameter processor_ack=2'b11;*/
+
+//Definig internal registers and wires
+/////////////////////////////////////
+
+wire core_en,inter_en,mode,master_rw,ack,rep_start,inter_rst,halt;
+wire prescale_reg_en;
+wire ctr_reg_en;
+wire sr_reg_en;
+wire to_reg_en;
+wire addr_reg_en;
+wire dr_reg_en;
+reg [7:0]data_out,sr_reg,ctr_reg,dr_reg,rr_reg;
+wire [7:0]data_in; //if address on add_bus matches with register address then set this high.
+wire data_ie; //this is signal used for enaling the data line in read or write cycle.
+wire as_d; //delay version of address strobe signal for detection of rising and falling edge
+reg as_delay_sig; //same signal.
+wire ds_d; //delayed version of data strobe.
+wire decode;
+wire rr_reg_en;
+
+reg ds_delay_sig;
+
+reg prescale_reg_en_sig;
+assign prescale_reg_en = prescale_reg_en_sig;
+
+reg ctr_reg_en_sig;
+assign ctr_reg_en = ctr_reg_en_sig;
+
+reg sr_reg_en_sig;
+assign sr_reg_en = sr_reg_en_sig;
+
+reg to_reg_en_sig;
+assign to_reg_en = to_reg_en_sig;
+
+reg addr_reg_en_sig;
+assign addr_reg_en = addr_reg_en_sig;
+
+reg dr_reg_en_sig;
+assign dr_reg_en = dr_reg_en_sig;
+
+reg as_d_sig;
+assign as_d = as_d_sig;
+
+reg ds_d_sig;
+assign ds_d = ds_d_sig;
+
+reg data_ie_sig;
+assign data_ie = data_ie_sig;
+
+//reg core_en_sig;
+//assign core_en = core_en_sig;
+
+//reg inter_en_sig;
+//assign inter_en = inter_en_sig;
+
+//reg mode_sig;
+//assign mode = mode_sig;
+
+//reg master_rw_sig;
+//assign master_rw = master_rw_sig;
+
+//reg ack_sig;
+//assign ack = ack_sig;
+
+//reg rep_start_sig;
+//assign rep_start = rep_start_sig;
+
+reg [7:0]data_sig;
+assign data = dr_reg;
+
+reg [7:0]prescale_sig;
+assign prescale = prescale_sig;
+
+reg [7:0]time_out_sig;
+assign time_out_reg = time_out_sig;
+
+reg [7:0]slave_add_sig;
+assign slave_add = slave_add_sig;
+
+//reg [7:0]data_out_sig;
+//assign data_out = data_out_sig;
+
+reg decode_sig;
+assign decode = decode_sig;
+
+//reg inter_rst_sig;
+//assign inter_rst = inter_rst_sig;
+
+//reg halt_sig;
+//assign halt = halt_sig;
+assign data_en = dr_reg_en_sig;
+
+reg rr_reg_en_sig;
+assign rr_reg_en = rr_reg_en_sig;
+
+
+
+assign core_en = ctr_reg [7];
+assign inter_en = ctr_reg [6];
+assign mode = ctr_reg [5];
+assign master_rw = ctr_reg [4];
+assign ack = ctr_reg [3];
+assign rep_start = ctr_reg [2];
+assign inter_rst = ctr_reg [1];
+assign halt = ctr_reg [0];
+
+
+
+
+
+
+//generating delayed version of inputs for detection of rising and falling edge.
+//////////////////////////////////////////////////////////////////////////////
+
+always@(posedge clk or posedge rst)
+begin
+
+if(rst)
+begin
+ as_delay_sig<=1'b0;
+ as_d_sig<=1'b0;
+ ds_delay_sig<=1'b0;
+ ds_d_sig<=1'b0;
+end
+
+else
+begin
+ as_delay_sig<=as;
+ as_d_sig<=as_delay_sig;
+ ds_delay_sig<=ds;
+ ds_d_sig<=ds_delay_sig;
+end
+end
+
+always@(posedge clk or posedge rst)
+begin
+ if(rst)
+ decode_sig<=1'b0;
+ else if(!as_d && as)
+ decode_sig<=1'b1;
+ //else
+ //decode_sig<=1'b0;
+end
+
+//address decoding logic
+///////////////////////
+
+//always@(posedge clk or posedge rst)
+always@(rst or as or add_bus or posedge time_rst)
+begin
+
+if(rst || time_rst)
+begin
+prescale_reg_en_sig<=1'b0;
+ctr_reg_en_sig<=1'b0;
+sr_reg_en_sig<=1'b0;
+to_reg_en_sig<=1'b0;
+addr_reg_en_sig<=1'b0;
+dr_reg_en_sig<=1'b0;
+rr_reg_en_sig <= 1'b0;
+
+//add_match_sig<=1'b0;
+end
+
+
+
+else if(as)
+begin
+ if(add_bus == `PRER)
+ begin
+ rr_reg_en_sig <= 1'b0;
+ prescale_reg_en_sig<=1'b1;
+ ctr_reg_en_sig<=1'b0;
+ sr_reg_en_sig<=1'b0;
+ to_reg_en_sig<=1'b0;
+ addr_reg_en_sig<=1'b0;
+ dr_reg_en_sig<=1'b0;
+ //add_match_sig<=1'b1;
+ end
+
+ else if(add_bus == `CTR)
+ begin
+ rr_reg_en_sig <= 1'b0;
+ prescale_reg_en_sig<=1'b0;
+ ctr_reg_en_sig<=1'b1;
+ sr_reg_en_sig<=1'b0;
+ to_reg_en_sig<=1'b0;
+ addr_reg_en_sig<=1'b0;
+ dr_reg_en_sig<=1'b0;
+ //add_match_sig<=1'b1;
+ end
+
+ else if(add_bus == `SR)
+ begin
+ rr_reg_en_sig <= 1'b0;
+ prescale_reg_en_sig<=1'b0;
+ ctr_reg_en_sig<=1'b0;
+ sr_reg_en_sig<=1'b1;
+ to_reg_en_sig<=1'b0;
+ addr_reg_en_sig<=1'b0;
+ dr_reg_en_sig<=1'b0;
+ //add_match_sig<=1'b1;
+ end
+
+ else if(add_bus == `TO)
+ begin
+ rr_reg_en_sig <= 1'b0;
+ prescale_reg_en_sig<=1'b0;
+ ctr_reg_en_sig<=1'b0;
+ sr_reg_en_sig<=1'b0;
+ to_reg_en_sig<=1'b1;
+ addr_reg_en_sig<=1'b0;
+ dr_reg_en_sig<=1'b0;
+ //add_match_sig<=1'b1;
+ end
+
+ else if(add_bus == `ADDR)
+ begin
+ rr_reg_en_sig <= 1'b0;
+ prescale_reg_en_sig<=1'b0;
+ ctr_reg_en_sig<=1'b0;
+ sr_reg_en_sig<=1'b0;
+ to_reg_en_sig<=1'b0;
+ addr_reg_en_sig<=1'b1;
+ dr_reg_en_sig<=1'b0;
+ //add_match_sig<=1'b1;
+ end
+
+ else if(add_bus == `DR)
+ begin
+
+ prescale_reg_en_sig<=1'b0;
+ ctr_reg_en_sig<=1'b0;
+ sr_reg_en_sig<=1'b0;
+ to_reg_en_sig<=1'b0;
+ addr_reg_en_sig<=1'b0;
+ dr_reg_en_sig<=1'b1;
+ rr_reg_en_sig <= 1'b0;
+ //add_match_sig<=1'b1;
+ end
+
+ else if(add_bus == `RR)
+ begin
+ rr_reg_en_sig <= 1'b1;
+ prescale_reg_en_sig<=1'b0;
+ ctr_reg_en_sig<=1'b0;
+ sr_reg_en_sig<=1'b0;
+ to_reg_en_sig<=1'b0;
+ addr_reg_en_sig<=1'b0;
+ dr_reg_en_sig<=1'b0;
+ //add_match_sig<=1'b1;
+ end
+
+ else
+ begin
+ rr_reg_en_sig <= 1'b0;
+ prescale_reg_en_sig<=1'b0;
+ ctr_reg_en_sig<=1'b0;
+ sr_reg_en_sig<=1'b0;
+ to_reg_en_sig<=1'b0;
+ addr_reg_en_sig<=1'b0;
+ dr_reg_en_sig<=1'b0;
+ //add_match_sig<=1'b0;
+ end
+
+
+end
+else
+begin
+ prescale_reg_en_sig<=1'b0;
+ ctr_reg_en_sig<=1'b0;
+ sr_reg_en_sig<=1'b0;
+ to_reg_en_sig<=1'b0;
+ addr_reg_en_sig<=1'b0;
+ dr_reg_en_sig<=1'b0;
+ rr_reg_en_sig <= 1'b0;
+ end
+
+end
+
+//assigning value of data_ie line
+//////////////////////////////////
+always@(posedge clk or posedge rst)
+begin
+ if(rst)
+ data_ie_sig<=1'b0;
+ else if(!ds_d && ds)
+ data_ie_sig<=1'b1;
+
+end
+
+
+//read data to/from the register specified by processor addrress.
+
+
+//always@(rst or addr_reg_en or ctr_reg_en or dr_reg_en or sr_reg_en or prescale_reg_en or to_reg_en or data_ie or rw or data_in )
+
+always@(posedge clk or posedge rst)
+begin
+if(rst)
+begin
+ sr_reg <= 8'b0;
+ dr_reg <= 8'b0;
+ rr_reg <= 8'b0;
+//ctr_reg <= 8'b0;
+end
+
+/*else if(ctr_reg_en)
+begin
+ //sr_reg <= {byte_trans,slave_addressed,bus_busy,arb_lost,time_out,slave_rw,inter,ack_rec};
+ ctr_reg <= data_in;
+end*/
+else
+begin
+ sr_reg <= {byte_trans,slave_addressed,bus_busy,arb_lost,time_out,slave_rw,inter,ack_rec};
+ rr_reg <= i2c_data;
+end
+end
+
+always@(posedge clk or posedge rst or posedge time_rst)
+begin
+ if(rst || time_rst)
+ begin
+ //initializing control register
+ ctr_reg <= 8'b0;
+ /*core_en_sig <= 1'b0;
+ inter_en_sig <= 1'b0;
+ mode_sig <= 1'b0;
+ master_rw_sig <= 1'b0;
+ ack_sig <= 1'b0;
+ rep_start_sig <= 1'b0;
+ inter_rst_sig<=1'b0;*/
+ //initializing data and timer register
+ data_sig <= 8'b00000000;
+ prescale_sig <= 8'b00000000;
+ time_out_sig <= 8'b00000000;
+ data_out <= 8'b00000000;
+ end
+
+ else if (data_ie)
+ begin
+ //address register
+ if(addr_reg_en) //if address matches with slave address register
+ begin
+ if(rw) //processor write cycle
+ slave_add_sig <= {data_in[7:1] , 1'b0};
+ else //processor read cycle
+ data_out <= slave_add;
+ end
+
+ //control register
+ if(ctr_reg_en) //if address matches with cntrol register
+ begin
+ if(rw) //processor write cycle
+ //begin
+ /*core_en_sig <= #2 ctr_reg [7];
+ inter_en_sig <= #2 ctr_reg [6];
+ mode_sig <= #2 ctr_reg [5];
+ master_rw_sig <= #2 ctr_reg [4];
+ ack_sig <= #2 ctr_reg [3];
+ rep_start_sig <= #2 ctr_reg [2];
+ inter_rst_sig <= #2 ctr_reg [1];
+ halt_sig <= #2 ctr_reg [0];*/
+ //end
+
+ //else
+ ctr_reg <= data_in; //processor read cycle
+ else
+ data_out <= ctr_reg;
+ end
+
+ else if(!byte_trans && bus_busy)
+ ctr_reg[1:0] <= 2'b0;
+ //data register
+
+ if(dr_reg_en)
+ begin
+ if(rw)
+ dr_reg <= data_in;
+ else
+ data_out <= dr_reg;
+ end
+
+ if(rr_reg_en)
+ begin
+ data_out <= rr_reg;
+ end
+
+ //staus register
+
+ if(sr_reg_en)
+ begin
+ if(!rw)
+ //begin
+ //if(data_in[0]==1'b0)
+ //inter_rst_sig <= 1'b0;
+ //else
+ //inter_rst_sig <= 1'b1;
+ //end
+ //else
+ //begin
+ data_out <= sr_reg;
+ //inter_rst_sig<=1'b0;
+ //end
+ //else
+ //inter_rst_sig<=1'b0;
+
+ end
+
+
+ //prescale register
+
+ if(prescale_reg_en)
+ begin
+ if(rw)
+ prescale_sig <= data_in;
+ else
+ data_out <= prescale;
+ end
+
+ //time_out register
+
+ if(to_reg_en)
+ begin
+ if(rw)
+ time_out_sig <= data_in;
+ else
+ data_out <= time_out_reg;
+ end
+ end
+end
+
+//assigning values to bidirectional bus
+//////////////////////////////////////
+
+//assign data_bus = (!rw && data_ie) ? data_out : 8'bzzzzzzzz;
+//assign data_in = (rw) ? data_bus : 8'bzzzzzzzz;
+
+//interuupt pin to processor
+assign irq = (inter && inter_en) ? 1'b1 : 1'b0;
+endmodule
+
+
+
+
+
+
+
+
+
+
Index: tags/t1/i2c_master_slave_core/verilog/rtl/i2c_blk.v
===================================================================
--- tags/t1/i2c_master_slave_core/verilog/rtl/i2c_blk.v (nonexistent)
+++ tags/t1/i2c_master_slave_core/verilog/rtl/i2c_blk.v (revision 3)
@@ -0,0 +1,172 @@
+//////////////////////////////////////////////////////////////////////////////////////////
+//Design Engineer: Ravi Gupta //
+//Company Name : Toomuch Semiconductor
+//Email : ravi1.gupta@toomuchsemi.com //
+// //
+// //
+//Purpose : This module will simply interconnect controller interface // //
+// controller_interface with ms_core. //
+// //
+// //
+//Date : 11-12-07 //
+// //
+// //
+// //
+// //
+// //
+// //
+// //
+//////////////////////////////////////////////////////////////////////////////////////////
+/*// synopsys translate_off
+`include "oc8051_timescale.v"
+// synopsys translate_on
+
+`include "oc8051_defines.v"*/
+
+
+module block(scl_oe,scl_in,scl_o,sda_oe,sda_in,sda_o,wb_add_i,wb_data_i,wb_data_o,wb_we_i,wb_stb_i,wb_cyc_i,irq,trans_comp,wb_clk_i,wb_rst_i,wb_ack_o);
+
+//inout scl; //Bi-directional lines to follow i2c protocol for data transfer.
+input sda_in; //sda input
+output sda_oe; //control line for bidirectional buffer
+output sda_o; //input line for bi_firectional buffer
+input scl_in;
+output scl_o;
+output scl_oe;
+input [7:0]wb_data_i; //Bi-direction buses for transfering data to/from processor.
+input [7:0]wb_add_i; //Transfer the addresses of intenal registers.
+input wb_we_i; //signal from processor to indicate whether its a read or write cycle.
+input wb_stb_i; //when asserted indicates address is valid.
+input wb_cyc_i; //when asserted indicates data is valid.
+output irq; //interupt signal to processor.
+input wb_clk_i; //system clock.
+input wb_rst_i; //asynchrnous reset active high.
+inout trans_comp; //temprory signal for testing the core
+output [7:0]wb_data_o;
+output wb_ack_o;
+
+//declaratiion of internal signals
+//////////////////////////////////
+
+ // control register
+ wire [7:0] slave_add; // I2C address
+ wire arb_lost; // indicates that arbitration for the i2c bus is lost
+ wire bus_busy; // indicates the i2c bus is busy
+ wire [7:0] i2c_up; // i2c data register
+ wire [7:0] data; // uC data register
+ wire core_en; // i2c enable - used as i2c reset
+ wire inter_en; // interrupt enable
+ wire inter; // interrupt pending
+ wire mode; // i2c master/slave select
+ wire master_rw; // master read/write
+ wire rep_start; // generate a repeated start
+ wire ack_rec; // value of received acknowledge
+ wire slave_rw; // slave read/write
+ wire ack; // value of acknowledge to be transmitted
+ wire byte_trans; // indicates that one byte of data is being transferred
+ wire slave_addressed; // address of core matches with address transferred
+ wire time_out; // max low period for SCL has excedded
+ wire [7:0]time_out_reg; // programmable max time for SCL low period
+ wire [7:0]prescale;
+ wire inter_rst;
+ wire [7:0]wb_data_o;
+ wire halt;
+ wire data_en;
+ wire time_rst;
+ reg wb_ack_o;
+ wire rst;
+
+assign trans_comp = byte_trans;
+
+always@(posedge wb_clk_i)
+begin
+ wb_ack_o <= #1 wb_stb_i & wb_cyc_i & ~wb_ack_o;
+end
+
+//port map for i2c controller
+////////////////////////////
+
+core i2c_core
+
+ (
+ .clk(wb_clk_i),
+ .rst(core_en),
+ .sda_oe(sda_oe),
+ .sda_in(sda_in),
+ .sda_o(sda_o),
+ .scl_oe(scl_oe),
+ .scl_o(scl_o),
+ .scl_in(scl_in),
+ .ack(ack),
+ .mode(mode),
+ .rep_start(rep_start),
+ .master_rw(master_rw),
+ .data_in(data[7:0]),
+ .slave_add(slave_add[7:0]),
+ .bus_busy(bus_busy),
+ .byte_trans(byte_trans),
+ .slave_addressed(slave_addressed),
+ .arb_lost(arb_lost),
+ .slave_rw(slave_rw),
+ .time_out(time_out),
+ .inter(inter),
+ .ack_rec(ack_rec),
+ .i2c_up(i2c_up[7:0]),
+ .time_out_reg(time_out_reg[7:0]),
+ .prescale_reg(prescale[7:0]),
+ .inter_en(inter_en),
+ .inter_rst(inter_rst),
+ .data_en(data_en),
+ .halt_rst(halt),
+ .h_rst(wb_rst_i),
+ .time_rst(time_rst));
+
+
+//port map for controller interface
+///////////////////////////////////
+
+processor_interface processor_interface
+
+ (
+ .clk(wb_clk_i),
+ .rst(wb_rst_i),
+ .add_bus(wb_add_i[7:0]),
+ .data_in(wb_data_i[7:0]),
+ .as(wb_stb_i),
+ .ds(wb_cyc_i),
+ .rw(wb_we_i),
+ .bus_busy(bus_busy),
+ .byte_trans(byte_trans),
+ .slave_addressed(slave_addressed),
+ .arb_lost(arb_lost),
+ .slave_rw(slave_rw),
+ .inter(inter),
+ .ack_rec(ack_rec),
+ .core_en(core_en),
+ .inter_en(inter_en),
+ .mode(mode),
+ .master_rw(master_rw),
+ .ack(ack),
+ .rep_start(rep_start),
+ .data(data[7:0]),
+ .i2c_data(i2c_up[7:0]),
+ .slave_add(slave_add),
+ .time_out_reg(time_out_reg[7:0]),
+ .prescale(prescale[7:0]),
+ .irq(irq),
+ .time_out(time_out),
+ .inter_rst(inter_rst),
+ .halt(halt),
+ .data_en(data_en),
+ .time_rst(time_rst),
+ .data_out(wb_data_o));
+
+//always@(scl or sda)
+//$display($time,"scl=%b\tsda=%b\t\n",scl,sda);
+
+
+endmodule
+
+
+
+
Index: tags/t1/i2c_master_slave_core/verilog/rtl/ms_core.v
===================================================================
--- tags/t1/i2c_master_slave_core/verilog/rtl/ms_core.v (nonexistent)
+++ tags/t1/i2c_master_slave_core/verilog/rtl/ms_core.v (revision 3)
@@ -0,0 +1,1157 @@
+///////////////////////////////////////ms_core.v////////////////////////////////////////////////////////////////////////
+// //
+//Design engineer: Ravi Gupta //
+//Company Name : Toomuch Semiconductor
+//Email : ravi1.gupta@toomuchsemi.com //
+// //
+//Purpose : This is the core which will be used to interface I2C bus. //
+//Created : 23-11-07 //
+ //
+//Modification : Changes made in data_reg_ld //
+ //
+//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 : After core reset(time out feature) core will go in idle escaping stop generation so need to clear //
+//all //
+//of status register. //
+ //
+//Modification : Remove the sm_state clause,so that even if there is no acknowledegement it will not stop the //
+//generation of SCL and SDA //
+//untill it gets command to generate stop from processor. //
+ //
+//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);
+
+////////////////////////////////////////////////signal defination////////////////////////////////////////////////////////////////
+
+input clk; //System Clock
+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
+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 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
+output scl_o; //SCL output line to be connected to input of bidirectional line
+input ack; //Acknowledgement signal from control register
+input mode; //master/slave mode select
+input rep_start; //repeated start
+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]slave_add; //I2C slave address
+input data_en;
+output time_rst;
+input h_rst;
+
+//status signal:
+
+output bus_busy; //bus busy
+inout byte_trans; //transfer of byte is in progress_reg_en
+
+inout slave_addressed; //addressed as slave
+inout arb_lost; //arbitration has lost
+inout slave_rw; //indicates the operation by slave
+inout time_out; //indicates that SCL LOW time has been exceeded
+output inter; //interrupt pending,will be used for interrupting processor
+input inter_rst; //use to clear the interrupt
+input inter_en; //processor wants to take interrupt or not
+
+//signal for processor
+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 [7:0]i2c_up; //I2C data for micro processor
+//timing control registers
+input [7:0]time_out_reg; //max SCL low period.
+input [7:0]prescale_reg; //clock divider for generating SCL frequency.
+
+/////////////////////////////////////////End of port defination//////////////////////////////////////////////////////////////////
+
+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 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 posedge_mode,negedge_mode;
+reg [2:0]scl_state;
+reg [1:0]state;
+reg [2:0]scl_main_state;
+wire [7:0] add_reg,shift_reg;
+wire [7:0]clk_cnt,bit_cnt;
+reg [7:0]time_cnt;
+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 [7:0]zero;
+wire [7:0]reg_clr;
+
+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_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 bit_counter(neg_scl,rst,bit_cnt_enable,bit_cnt_rst,zero,bit_cnt); //Implementation of bit counter
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+reg clk_cnt_enable_sig;
+assign clk_cnt_enable = clk_cnt_enable_sig;
+
+reg clk_cnt_rst_sig;
+assign clk_cnt_rst = clk_cnt_rst_sig;
+
+
+//reg sda_in_sig;
+//assign sda_in = sda_in_sig;
+
+reg sm_stop_sig;
+assign sm_stop = sm_stop_sig;
+
+//reg scl_in_sig;
+//assign scl_in = scl_in_sig;
+
+reg gen_start_sig;
+assign gen_start = gen_start_sig;
+
+reg gen_stop_sig;
+assign gen_stop = gen_stop_sig;
+
+reg master_slave_sig;
+assign master_slave = master_slave_sig;
+
+reg detect_start_sig;
+assign detect_start=detect_start_sig;
+
+reg detect_stop_sig;
+assign detect_stop=detect_stop_sig;
+
+reg byte_trans_sig;
+assign byte_trans= byte_trans_sig;
+
+reg bb_sig;
+assign bb=bb_sig;
+
+reg slave_addressed_sig;
+assign slave_addressed=slave_addressed_sig;
+
+reg slave_rw_sig;
+assign slave_rw=slave_rw_sig;
+
+reg inter_sig;
+assign inter=inter_sig;
+assign interrupt=inter_sig;
+
+reg time_out_sig;
+assign time_out=time_out_sig;
+
+reg ack_rec_sig;
+assign ack_rec=ack_rec_sig;
+
+reg add_reg_enable_sig;
+assign add_reg_en=add_reg_enable_sig;
+
+reg data_reg_en_sig;
+assign data_reg_en=data_reg_en_sig;
+
+reg data_reg_ld_sig;
+assign data_reg_ld=data_reg_ld_sig;
+
+reg stop_scl_sig;
+assign stop_scl=stop_scl_sig;
+
+reg core_rst_sig;
+assign core_rst=core_rst_sig;
+
+reg sda_out_sig;
+assign sda_out=sda_out_sig;
+
+reg scl_out_sig;
+assign scl_out=scl_out_sig;
+
+reg master_sda_sig;
+assign master_sda=master_sda_sig;
+
+reg slave_sda_sig;
+assign slave_sda=slave_sda_sig;
+
+reg arbitration_lost_sig;
+assign arbitration_lost=arbitration_lost_sig;
+
+reg arb_lost_sig;
+assign arb_lost=arb_lost_sig;
+
+reg byte_trans_delay_sig;
+assign byte_trans_delay=byte_trans_delay_sig;
+
+reg byte_trans_fall_sig;
+assign byte_trans_fall=byte_trans_fall_sig;
+
+reg halt_sig;
+assign halt = halt_sig;
+
+reg arb_rst_sig;
+assign arb_rst=arb_rst_sig;
+
+reg interrupt_rst_sig;
+assign interrupt_rst=interrupt_rst_sig;
+
+reg rep_start_sig;
+assign time_rst = core_rst;
+
+reg d_detect_stop_sig;
+assign d_detect_stop = d_detect_stop_sig;
+
+reg d1_detect_stop_sig;
+
+
+assign bus_busy = bb;
+assign reg_clr=8'b00000000;
+assign neg_scl_sig=(~scl_in);
+assign neg_scl=neg_scl_sig;
+assign zero=8'b00000000;
+assign posedge_mode_sig=posedge_mode;
+assign negedge_mode_sig=negedge_mode;
+assign sda_o = 1'b0; //assign this to 0 always
+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_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;
+
+////////////////////SCL Generator///////////////////////////////
+//This machine will generate SCL and SDA when in master mode.It will
+//also generate START and STOP condition.
+
+//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
+// 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)
+begin
+
+//State machine initial conditions
+
+if(rst || h_rst)
+begin
+ scl_state<=scl_idle;
+ scl_out_sig<=1'b1;
+ sda_out_sig<=1'b1;
+ stop_scl_sig<=1'b0;
+ clk_cnt_enable_sig<=1'b0;
+ clk_cnt_rst_sig<=1'b1;
+ //bit_cnt_rst_sig<=1'b0;
+ //bit_cnt_enable_sig<=1'b0;
+end
+
+else if(core_rst)
+begin
+
+ scl_state<=scl_idle;
+ scl_main_state <= scl_main_idle;
+ scl_out_sig<=1'b1;
+ sda_out_sig<=1'b1;
+ stop_scl_sig<=1'b0;
+ clk_cnt_enable_sig<=1'b0;
+ clk_cnt_rst_sig<=1'b1;
+ slave_addressed_sig<=1'b0;
+end
+
+
+else
+begin
+
+ case (scl_state)
+
+ scl_idle:
+ begin
+ arb_rst_sig <= 1'b1;
+ interrupt_rst_sig<=1'b1;
+ sda_out_sig<=1'b1;
+ stop_scl_sig<=1'b0;
+
+ if(master_slave && !bb && gen_start)
+ begin
+ scl_state<=scl_start;
+
+ end
+ end
+
+
+ scl_start:
+ begin
+ arb_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_rst_sig<=1'b0;
+ //sda_out_sig<=1'b0; //generating start condition
+ stop_scl_sig<=1'b0;
+ if(clk_cnt == prescale_reg / 3)
+ sda_out_sig<= 1'b0;
+
+ if(clk_cnt == prescale_reg) //wait for prescale value to over
+ scl_state<=scl_low_edge;
+ else
+ scl_state<=scl_start;
+ end
+
+ scl_low_edge:
+ begin
+ 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_rst_sig<=1'b0; //also reseting the timer counter in this state.
+ scl_out_sig<=1'b0;
+ scl_state<=scl_low;
+ stop_scl_sig<=1'b0;
+ end
+
+ scl_low:
+ begin
+ clk_cnt_enable_sig<=1'b1; //enable the clock counter
+ clk_cnt_rst_sig<=1'b0;
+ scl_out_sig<=1'b0;
+
+ if(arbitration_lost)
+ stop_scl_sig<=1'b0;
+ else if(rep_start_sig)
+ begin
+ sda_out_sig<=1'b1;
+ stop_scl_sig<=1'b0;
+ end
+
+
+ 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
+ begin
+ sda_out_sig<=1'b0;
+ stop_scl_sig<=1'b1;
+
+ end
+
+ /*else if(rep_start)
+ begin
+ sda_out_sig<=1'b1;
+ stop_scl_sig<=1'b0;
+ end*/
+ else if(clk_cnt == prescale_reg / 3)
+ begin
+ sda_out_sig<=master_sda;
+ stop_scl_sig<=1'b0;
+
+ end
+
+ else
+ stop_scl_sig<=1'b0;
+
+
+ //determine next state.
+
+ if(clk_cnt == prescale_reg)
+ begin
+ if(bit_cnt == 8'b0000_0111 && arbitration_lost )
+ scl_state<=scl_idle;
+ else if(interrupt && inter_en) //uncomenting out for cheking the core in interrupt mode
+ scl_state<=scl_low;
+ else if(halt)
+ scl_state<=scl_low;
+ else
+ scl_state<=scl_high_edge;
+ end
+
+ else
+ scl_state<=scl_low;
+ end
+
+
+
+
+ scl_high_edge:
+ begin
+ clk_cnt_rst_sig<=1'b1;
+ scl_out_sig<=1'b1;
+ if(gen_stop) //Ravi sm_stop from oring with gen_stop
+ stop_scl_sig<=1'b1;
+
+ else
+ stop_scl_sig<=1'b0;
+ if(!scl_in)
+ scl_state<=scl_high_edge;
+ else
+ scl_state<=scl_high;
+ end
+
+
+
+ scl_high:
+ begin
+ clk_cnt_enable_sig<=1'b1;
+ clk_cnt_rst_sig<=1'b0;
+ scl_out_sig<=1'b1;
+ if(clk_cnt == prescale_reg)
+ begin
+ if(rep_start_sig)
+ scl_state<=scl_start;
+ else if(stop_scl)
+ scl_state<=scl_idle;
+
+ else
+ scl_state<=scl_low_edge;
+ end
+
+ else
+ scl_state<=scl_high;
+ end
+
+
+ endcase
+end
+end
+
+
+//Sample the incoming SDA and SCL line with System clock
+
+/*always@(posedge clk or posedge rst)
+begin
+
+ if(rst)
+ begin
+ //sda_in_sig <= 1'b1;
+ scl_in_sig <=1'b1;
+ end
+ else
+ begin
+ if(!scl)
+ scl_in_sig <= 1'b0;
+ else
+ scl_in_sig <= 1'b1;
+
+ if(!sda)
+ sda_in_sig <= 1'b0;
+ else
+ sda_in_sig <= 1'b1;
+
+ //sda_out_sig <= sda;
+ end
+end*/
+
+//Generartion of control signal from the command based on processor.
+//This will control generation of start and stop signal.
+//This will also set the master_slave bit based on MODE signal
+//if bus is not busy i.e bb = 0
+
+always@(posedge clk or posedge rst or posedge h_rst)
+begin
+ if(rst || h_rst)
+ begin
+ gen_start_sig <= 1'b0;
+ gen_stop_sig <= 1'b0;
+ master_slave_sig <= 1'b0;
+
+ end
+
+ else
+ begin
+ if(posedge_mode_sig)
+ gen_start_sig <= 1'b1;
+ else if(detect_start)
+ gen_start_sig <= 1'b0;
+
+ if(!arbitration_lost && negedge_mode_sig)
+ gen_stop_sig <= 1'b1;
+ else if(detect_stop)
+ gen_stop_sig <= 1'b0;
+
+ if(!bb)
+ master_slave_sig <= mode;
+ else
+ master_slave_sig <= master_slave;
+ end
+end
+
+//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)
+begin
+ if(rst || h_rst)
+ begin
+ posedge_mode<=1'b0;
+ negedge_mode<=1'b0;
+ state<=a;
+ end
+
+ else
+ begin
+ case(state)
+
+ a:
+ if(mode==1'b0)
+ begin
+ state<=b;
+ posedge_mode<=1'b0;
+ negedge_mode<=1'b0;
+ end
+
+ else
+ begin
+ state<=c;
+ posedge_mode<=1'b1;
+ negedge_mode<=1'b0;
+ end
+
+ b:
+ if(mode==1'b0)
+ begin
+ state<=b;
+ posedge_mode<=1'b0;
+ negedge_mode<=1'b0;
+ end
+
+ else
+ begin
+ state<=a;
+ posedge_mode<=1'b1;
+ negedge_mode<=1'b0;
+ end
+
+ c:
+ if(mode==1'b0)
+ begin
+ state<=a;
+ posedge_mode<=1'b0;
+ negedge_mode<=1'b1;
+ end
+
+ else
+ begin
+ state<=c;
+ posedge_mode<=1'b0;
+ negedge_mode<=1'b0;
+ end
+
+ endcase
+end
+end
+
+//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.
+//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)
+begin
+
+if(rst || core_rst || h_rst)
+begin
+ scl_main_state<=scl_main_idle;
+ sm_stop_sig<=1'b0;
+end
+
+else
+begin
+ case(scl_main_state)
+ scl_main_idle:
+
+ if(detect_start)
+ scl_main_state<=scl_address_shift;
+ else if(detect_stop)
+ begin
+ scl_main_state<=scl_main_idle;
+ sm_stop_sig<=1'b0;
+ end
+
+ scl_address_shift: //machine will remain in this state,unless all the bits of address has been transferred.
+
+ if(bit_cnt == 8'b0000_0111)
+ scl_main_state<=scl_ack_address;
+ else if(detect_stop)
+ begin
+ scl_main_state<=scl_main_idle;
+ sm_stop_sig<=1'b0;
+ end
+
+ scl_ack_address:
+
+ //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.
+ if(detect_stop)
+ begin //Go to idle state if there is stop command
+ scl_main_state<=scl_main_idle;
+ sm_stop_sig<=1'b0;
+ end
+
+ else if(detect_start)
+ begin
+ scl_main_state<=scl_address_shift;
+ sm_stop_sig<=1'b0;
+ end
+ //else if(!sda_in)
+ //If ack has been received then,check for slave/master
+
+ else if(master_slave)
+ begin //if master then set the direction for master to either transmit
+ if(!master_rw) //or receive the data.
+ scl_main_state<=scl_rx_data;
+ else
+ 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.
+
+ else
+ begin //If slave then check if received address has matched
+ //if(addr_match)
+ //begin //if address matches then set the direction of communication based
+ if(add_reg[0]) //last bit of shift register of address cycle.
+ scl_main_state<=scl_tx_data;
+ else
+ scl_main_state<=scl_rx_data;
+ end
+ //else
+ //scl_main_state<=scl_main_idle;
+ //end
+
+
+ //else
+ //begin
+ // scl_main_state<=scl_main_idle; //If no ack received go to idle state.
+ //if(master_slave)
+ // sm_stop_sig<=1'b1;
+ //end
+
+ scl_rx_data:
+ if(bit_cnt == 8'b0000_0111)
+ scl_main_state<=scl_send_ack;
+ else if(detect_stop)
+ begin
+ scl_main_state<=scl_main_idle;
+ sm_stop_sig<=1'b0;
+ end
+ else if(detect_start)
+ begin
+ scl_main_state<=scl_address_shift;
+ sm_stop_sig<=1'b0;
+ end
+
+
+
+
+ scl_tx_data:
+ if(bit_cnt == 8'b0000_0111)
+ scl_main_state<=scl_wait_ack;
+ else if(detect_stop)
+ begin
+ scl_main_state<=scl_main_idle;
+ sm_stop_sig<=1'b0;
+ end
+ else if(detect_start)
+ begin
+ scl_main_state<=scl_address_shift;
+ sm_stop_sig<=1'b0;
+ end
+
+
+ scl_send_ack:
+ if(detect_stop)
+ begin
+ scl_main_state<=scl_main_idle;
+ sm_stop_sig<=1'b0;
+ end
+
+ else
+ 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
+ //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.
+ if(detect_stop)
+ begin
+ scl_main_state<=scl_main_idle;
+ sm_stop_sig<=1'b0;
+ end
+
+
+ else
+ scl_main_state<=scl_tx_data;
+ //else
+ //begin
+ //if(master_slave)
+ //sm_stop_sig<=1'b1;
+ //scl_main_state<=scl_main_idle;
+ //end
+ endcase
+end
+end
+
+//Start and stop detect process
+//////////////////////////////
+
+always@(sda_in or scl_main_state)
+begin
+
+ if(rst || h_rst)
+ detect_start_sig<=1'b0;
+ else if(!sda_in && scl_in)
+ detect_start_sig<=1'b1;
+ else if(scl_address_shift)
+ detect_start_sig<=1'b0;
+ else
+ detect_start_sig<=1'b0;
+end
+
+always@(posedge sda_in or posedge detect_start)
+begin
+
+ if(rst || h_rst)
+ detect_stop_sig<=1'b0;
+ else if(detect_start)
+ detect_stop_sig<=1'b0;
+ else if(scl_in)
+ detect_stop_sig<=1'b1;
+ //else if(detect_start)
+ //detect_stop_sig<=1'b0;
+ else
+ detect_stop_sig<=1'b0;
+end
+
+//generate a delay version of byte_trans signal
+//This will be used for detecting falling edge of byte_trans
+
+always@(posedge clk or posedge rst or posedge h_rst)
+begin
+ if(rst || h_rst)
+ byte_trans_delay_sig <= 1'b0;
+ else
+ begin
+ byte_trans_delay_sig <= byte_trans;
+ byte_trans_fall_sig <= byte_trans_delay && !byte_trans;
+ end
+end
+
+
+//Processor status bits/////
+//byte_trans bit
+//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.
+
+always@(negedge scl_in or posedge rst or posedge halt_rst or posedge core_rst or posedge h_rst)
+begin
+ if(rst || h_rst)
+ byte_trans_sig<=1'b0;
+ else if(halt_rst)
+ byte_trans_sig <= 1'b0;
+ else if(bit_cnt == 8'b0000_1000)
+ byte_trans_sig<=1'b1;
+ else if(halt_rst || core_rst) // after core_rst negate byte_trans bit
+ byte_trans_sig<=1'b0;
+end
+
+//bus_busy
+//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
+
+always@(posedge clk or posedge rst or posedge h_rst)
+begin
+ if(rst || h_rst)
+ bb_sig<=1'b0;
+ else
+ begin
+ if(detect_start)
+ bb_sig<=1'b1;
+ if(detect_stop || core_rst)
+ bb_sig<=1'b0;
+ end
+end
+
+//slave_addressed bit
+//This indicates that slave has been addressed,and after sending ack
+//core will switch to slave mode.
+//This bit will be set if adds matched in add ack state.
+
+always@(posedge clk or posedge rst or posedge h_rst)
+begin
+ if(rst) //Removing h_rst
+ slave_addressed_sig<=1'b0;
+ //else if(scl_main_state == scl_ack_address)
+ else if(byte_trans)
+ slave_addressed_sig<=addr_match;
+ else
+ slave_addressed_sig<=slave_addressed;
+ //slave_addressed_sig<= 1'b0;
+end
+
+//set address match bit if address reg matches with shift register output
+/*always@(negedge scl or posedge rst)
+begin
+ if(rst)
+ addr_match_sig<=1'b0;
+ else if( slave_add[7:1] == add_reg[7:1])
+ addr_match_sig <=1'b1;
+ else
+ addr_match_sig<=1'b0;
+end*/
+assign addr_match = slave_add[7:1] == add_reg[7:1]? 1'b1:1'b0;
+assign add_reg_ld = 1'b0;
+
+//Slave read write
+//This bit indicates slave has been addressed,this indicates
+//read or write bit sent by processor.
+
+always@(posedge clk or posedge rst or posedge h_rst)
+begin
+ if(rst || h_rst)
+ slave_rw_sig<=1'b0;
+ else if(scl_main_state == scl_ack_address)
+ slave_rw_sig<=add_reg[0];
+end
+
+//interrupt pending
+//This will cause an interrupt to processor if interrupt enable is set
+//This bit will be set in following circumstances:
+//1):Byte transfer has been completed.
+//2):Arbitration lost.
+//3):slave has been addressed and and bytes have been transferred.
+//4):Time out condition has been reached.
+//5):Repeated start condition.
+//Only processor can clear the interrupt.
+
+always@(posedge clk or posedge rst or posedge h_rst)
+begin
+ if(rst || h_rst)
+ inter_sig<=1'b0;
+
+ else
+ begin
+ //if(interrupt_rst)
+ //inter_sig<=1'b0;
+
+ if(inter_rst)
+ inter_sig<=1'b0;
+
+ //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)
+ inter_sig<=1'b1;
+
+
+
+ //else //interrupt need to get cleared by processor,so do not reset in else condition
+ //inter_sig<=1'b0;
+
+
+ end
+end
+
+//generate delay version of detect_stop
+always@(posedge clk or posedge rst or posedge h_rst)
+begin
+if(rst || h_rst)
+d_detect_stop_sig <= 1'b0;
+else
+begin
+d1_detect_stop_sig <= detect_stop;
+d_detect_stop_sig <= d1_detect_stop_sig;
+end
+end
+
+
+always@(posedge clk or posedge rst or posedge h_rst)
+begin
+ if(rst || h_rst)
+ halt_sig <= 1'b0;
+
+ else
+ begin
+ if(halt_rst)
+ halt_sig<=1'b0;
+
+ else if(byte_trans && master_slave)
+ halt_sig<=1'b1;
+ end
+end
+
+//acknoweldege recieve
+//This bit indicates the data on SDA line during ack cycle.
+
+always@(posedge clk or posedge rst or posedge h_rst)
+begin
+ if(rst || h_rst)
+ 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))
+ ack_rec_sig<=sda_in;
+end
+
+//Setting control bits of shift registers and counters
+//////////////////////////////////////////////////////
+
+//Address shift register will just receive the data after start
+//condition detection.It wont be get loaded.While data shift register
+//will receive as well as transmit the data.
+
+//address shift register enable bit
+always@(posedge clk or posedge rst or posedge h_rst)
+begin
+ if(rst || h_rst)
+ add_reg_enable_sig<=1'b0;
+ else if(detect_start || scl_main_state == scl_address_shift)
+ add_reg_enable_sig<=1'b1;
+ else
+ add_reg_enable_sig<=1'b0;
+end
+
+
+//Data shift register.
+//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)
+ begin
+ if (rst || h_rst)
+ begin
+ data_reg_en_sig <= 1'b0;
+ data_reg_ld_sig <= 1'b0;
+ end
+ else
+ begin
+ if (((master_slave && scl_main_state == scl_address_shift) || (scl_main_state ==
+ scl_rx_data) || (scl_main_state == scl_tx_data)))
+ data_reg_en_sig <= 1'b1;
+ else
+ data_reg_en_sig <= 1'b0;
+
+ /*if ((master_slave && scl_main_state == scl_idle) || (scl_main_state ==
+ scl_wait_ack) || (scl_main_state == scl_ack_address &&
+ !add_reg[0] && !master_slave) || (scl_main_state == scl_ack_address &&
+ master_rw && master_slave))*/
+ if(((scl_main_state == scl_main_idle) || byte_trans) && data_en)
+
+ data_reg_ld_sig <= 1'b1;
+ else
+ data_reg_ld_sig <= 1'b0;
+
+ end
+
+ end
+
+//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_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
+
+always@(posedge clk or posedge rst or posedge h_rst)
+begin
+ if(rst || h_rst)
+ time_cnt<=8'b0000_0000;
+ else if(!scl_in)
+ time_cnt<=time_cnt + 1'b1;
+ else
+ time_cnt<=8'b0000_0000;
+end
+
+always@(posedge clk or posedge rst or posedge h_rst)
+begin
+ if(rst || h_rst)
+ begin
+ core_rst_sig<=1'b0;
+ time_out_sig<=1'b0;
+ end
+ else if((time_cnt == time_out_reg) & bb)
+ begin
+ core_rst_sig <= 1'b1;
+ time_out_sig <= 1'b1;
+ end
+ /*else if((time_cnt == time_out_reg) && (scl_state == scl_idle))
+ begin
+ core_rst_sig <= 1'b0;
+ time_out_sig <= 1'b1;
+ end*/
+ else
+ begin
+ core_rst_sig <= 1'b0;
+ time_out_sig <= 1'b0;
+ end
+end
+
+//Process for assigning Master and slave SDA.
+always@(posedge clk or posedge rst or posedge h_rst)
+begin
+ if(rst || h_rst)
+ master_sda_sig<=1'b1;
+ else if((scl_main_state == scl_address_shift) || (scl_main_state == scl_tx_data))
+ master_sda_sig<=serial_out;
+ else if(scl_main_state == scl_send_ack)
+ master_sda_sig<=ack;
+ else
+ master_sda_sig<=1'b1;
+end
+
+always@(posedge clk or posedge rst or posedge h_rst)
+begin
+ if(rst || h_rst)
+ slave_sda_sig<=1'b1;
+ else if(scl_main_state == scl_tx_data)
+ slave_sda_sig<=serial_out;
+ else if((addr_match && (scl_main_state == scl_ack_address)) || (scl_main_state == scl_send_ack))
+ slave_sda_sig<=ack;
+ else
+ slave_sda_sig<=1'b1;
+end
+
+//assigning SCL and SDA lines in output conditions.
+
+
+assign scl_oe = master_slave ? scl_out : 1'b1;
+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);
+assign sda_oe = (sda_sig ?1'b0 : 1'b1);
+
+//Presenting data on data_register which is for processor
+always@(posedge clk or posedge rst or posedge h_rst)
+begin
+ if(rst || h_rst)
+ i2c_up<=8'b00000000;
+ else if(scl_main_state == scl_send_ack)
+ i2c_up<=shift_reg;
+ else
+ i2c_up<=i2c_up;
+end
+
+
+
+//This process will set arbitration lost signal
+//////////////////////////////////////////////
+ // 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
+ // 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.
+ always @( posedge (clk) or posedge (rst) or posedge (h_rst) )
+ begin
+ if (rst || h_rst)
+ begin
+ arbitration_lost_sig <= 1'b0;
+ end
+ else
+ begin
+ if (scl_main_state == scl_idle)
+ begin
+ arbitration_lost_sig <= 1'b0;
+ end
+ else if ((master_slave))
+ // only need to check arbitration in master mode
+ // check for SCL high before comparing data
+ if ((scl_in && scl_oe && (scl_main_state == scl_address_shift || scl_main_state
+ == scl_tx_data || scl_main_state == scl_idle)))
+ // 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
+ // 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)
+ begin
+ arbitration_lost_sig <= 1'b1;
+
+ end
+ else
+ begin
+ arbitration_lost_sig <= 1'b0;
+
+ end
+
+ else
+ begin
+ arbitration_lost_sig <= arbitration_lost;
+ end
+
+
+ end
+
+ end
+
+//setting the arbitration lost bit of status register
+////////////////////////////////////////////////////
+//this bit will be set when:
+ //arbiration has lost.
+ //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 repeate start has been detected when in slave mode.
+
+always@(posedge clk or posedge rst or posedge core_rst or posedge h_rst)
+begin
+ if(rst || h_rst)
+ arb_lost_sig<=1'b0;
+ else
+ begin
+ if(arb_rst)
+ arb_lost_sig<=1'b0;
+ else if(master_slave)
+ begin
+ if((arbitration_lost)||(bus_busy && gen_start))
+ arb_lost_sig<=1'b1;
+ end
+
+ else if(rep_start)
+ arb_lost_sig<=1'b1;
+ //else if(core_rst && master_slave)
+ //arb_lost_sig<=1'b0;
+ else
+ arb_lost_sig<=1'b0;
+ end
+end
+
+always@(posedge clk or posedge rst or posedge h_rst)
+begin
+if(rst || h_rst)
+ 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)
+ rep_start_sig<=1'b0;
+else
+ rep_start_sig<=rep_start;
+end
+
+
+
+endmodule
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+