OpenCores

Subversion Repositories i2c_master_slave_core

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 5 to Rev 6
    Reverse comparison

Rev 5 → Rev 6

/i2c_master_slave_core/trunk/i2c_master_slave_core/doc/i2c_spec.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
i2c_master_slave_core/trunk/i2c_master_slave_core/doc/i2c_spec.pdf Property changes : Added: svn:mime-type + application/octet-stream
/i2c_master_slave_core/trunk/i2c_master_slave_core/doc/i2c_spec.doc Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
i2c_master_slave_core/trunk/i2c_master_slave_core/doc/i2c_spec.doc Property changes : Added: svn:mime-type + application/octet-stream
/i2c_master_slave_core/trunk/i2c_master_slave_core/verilog/rtl/shift.v New file
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
 
/i2c_master_slave_core/trunk/i2c_master_slave_core/verilog/rtl/counter.v New file
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
/i2c_master_slave_core/trunk/i2c_master_slave_core/verilog/rtl/controller_interface.v New file
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
 
 
 
 
 
/i2c_master_slave_core/trunk/i2c_master_slave_core/verilog/rtl/i2c_blk.v New file
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
 
/i2c_master_slave_core/trunk/i2c_master_slave_core/verilog/rtl/ms_core.v New file
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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/doc/i2c_spec.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/doc/i2c_spec.pdf Property changes : Added: svn:mime-type + application/octet-stream
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/doc/i2c_core_verification_plan.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/doc/i2c_spec.doc Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/doc/i2c_spec.doc Property changes : Added: svn:mime-type + application/octet-stream
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/shift.v New file
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
 
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/counter.v New file
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
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/controller_interface.v New file
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
 
 
 
 
 
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/i2c_blk.v New file
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
 
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/ms_core.v New file
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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/Readme New file
0,0 → 1,18
 
This Directory contains all files which are required to run this VMM testbench.
Scripts are not given as it vary from compiler to compiler.
 
The Basic structure of file system is given below.
 
vmm_i2c_top.sv
|
|--- vmm_clkgen.sv
|--- vmm_program_test.sv
|
|--- vmm_i2c_env.sv (This is the environment file and all transactors and packet files
are included in this file)
 
Please note that for transition coverage in register testcase (write-write-read), another file is
availabe which is vmm_program1_test.sv. In this file Scenario_generator_class is extended and
program and top level module is also available.
 
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_stimulus_packet.sv New file
0,0 → 1,69
//////////////////////////////////////////////////////////////////////////////////////////
// //
// Verification Engineer: Atish Jaiswal //
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. //
// //
// Description of the Source File: //
// This file defines Stimulus packet class for Scenario Generator. //
// The Packet Randomizes intr_en to enable/disable interrupt, byte_count to transfer //
// Random no. of data_bytes, register_address and data for register testcase. It also //
// randomize slave address. Other fields get assigned in Scenario generator class. //
// Constraint block called reg_add is used to contrain randomized fields. //
// //
// //
//////////////////////////////////////////////////////////////////////////////////////////
 
`include "vmm.sv"
 
class stimulus_packet extends vmm_data;
vmm_log log;
 
rand bit intr_en ; // 1 for Interrupt enable and 0 for disable
rand int byte_count; // no. of bytes to be transfered
rand bit [7:0] register_data; // to check register read/write
rand bit [7:0] register_addr; // to select the address of internal register
rand bit [6:0] slave_address; // slave address to be checked
bit [7:0] data_packet[]; // data packets to be transfered
bit master_slave; // 1 for master and 0 for slave
bit tr; // 1 for trasmit and 0 for receive
bit register_check; // 1 to check registers writing and 0 for not.
bit reset_check; // 1 to check reset test and 0 for not.
int temp_count;
 
constraint reg_add {
register_addr inside {8'h02, 8'h04, 8'h0A, 8'h0C, 8'h0E};
byte_count inside {[2:10]};
slave_address < 7'b111_1111;
intr_en dist {0 := 1, 1 :=1};
}
function new();
super.new(this.log);
this.log = new("Stimulus Data", "class");
endfunction
 
function void display();
this.log.start_msg(vmm_log::NOTE_TYP);
void'(this.log.text($psprintf("Master/Slave mode is = %b\n", master_slave)));
void'(this.log.text($psprintf("tr = %d\n", tr)));
void'(this.log.text($psprintf("register_check = %b\n", register_check)));
void'(this.log.text($psprintf("reset_check = %b\n", reset_check)));
void'(this.log.text($psprintf("Interrupt Enable is = %b\n", intr_en)));
void'(this.log.text($psprintf("byte_count = %d\n", byte_count)));
void'(this.log.text($psprintf("register_addr = %b\n", register_addr)));
void'(this.log.text($psprintf("register_data = %b\n", register_data)));
void'(this.log.text($psprintf("slave_address = %b\n", slave_address)));
this.log.end_msg();
temp_count = byte_count;
endfunction
 
 
function vmm_data copy(vmm_data to = null);
copy = new this;
endfunction
endclass
`vmm_channel(stimulus_packet) // This macro defined in VMM Methodology creates channel named stimulus_packet_channel
 
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_sb_pkt.sv New file
0,0 → 1,43
//////////////////////////////////////////////////////////////////////////////////////////
// //
// Verification Engineer: Atish Jaiswal //
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. //
// //
// Description of the Source File: //
// This source code defines Scoreboard Packet. This packet will be sent to Scoreboard //
// and Coverage Module from Both W/B Driver and I2C M/S Driver through vmm_callback. //
// //
// //
//////////////////////////////////////////////////////////////////////////////////////////
 
`include "vmm.sv"
 
class scoreboard_pkt extends vmm_data;
 
vmm_log log;
bit master_slave; // 1 for Master; 0 for Slave;
bit tx_rx; // 1 for Tx; 0 for Rx
bit [6:0] slave_address; // 7-bit Slave Address
bit [7:0] data_byte; // 8-bit Data Byte
 
function new();
super.new(this.log);
this.log = new("Sb Data", "class");
endfunction
 
function vmm_data copy(vmm_data to = null);
copy = new this;
endfunction
 
 
function void display();
this.log.start_msg(vmm_log::NOTE_TYP);
void'(this.log.text($psprintf("master_slave is %0b", this.master_slave)));
void'(this.log.text($psprintf("tx_rx is %0b", this.tx_rx)));
void'(this.log.text($psprintf("slave_address is %b", this.slave_address)));
void'(this.log.text($psprintf("data_byte is %b", this.data_byte)));
this.log.end_msg();
endfunction
 
endclass
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_scoreboard.sv New file
0,0 → 1,146
//////////////////////////////////////////////////////////////////////////////////////////
// //
// Verification Engineer: Atish Jaiswal //
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. //
// //
// Description of the Source File: //
// This source code implements Scoreboard. //
// Scoreboard contains queues for data_bytes comparision and Associative Array for //
// Register values comparision for read/write test-cases. //
// Whenever any transaction starts, through pre_txn callback it gets oject and //
// save that object into queue. Once transaction is done, it get another objects //
// through post_txn call backs from dirvers. In Scoreboard it compares both object's //
// data_byte and reports MATCH or MISMATCH of data. //
// For Register testcases it saves register value whenever any data gets written //
// to DUT register into associative array with register address as an index. Now, //
// When Register-read test occurs, it compares the data read from internal register //
// with Assocative Array's dat of same index. If register was not written previously //
// it compread read data with initial value of that register. //
// //
//////////////////////////////////////////////////////////////////////////////////////////
 
`include "vmm.sv"
 
class i2c_scoreboard extends vmm_xactor;
 
scoreboard_pkt sb_pre_txn_q[$]; // Queue of scoreboard_pkt for pre_transaction
scoreboard_pkt sb_post_txn_q[$]; // Queue of scoreboard_pkt for post_transaction
vmm_log log;
scoreboard_pkt sb_pre_obj; // Scoreoard_pkt's instance for pre_transaction
scoreboard_pkt sb_pre_obj1; // Scoreoard_pkt's instance for pre_transaction
scoreboard_pkt sb_post_obj; // Scoreoard_pkt's instance for post_transaction
scoreboard_pkt sb_post_obj1; // Scoreoard_pkt's instance for post_transaction
 
register_pkt reg_pkt; // registet_pkt's instance
register_pkt reg_pkt1; // register_pkt's instance
 
typedef bit [7:0] reg_addr;
bit [7:0] initial_reg [*]; // 8-bit wide Associative Array of to store initial_register's value
bit [7:0] wr_reg [*]; // 8-bit wide Associative Array of to store data which were written in DUT reigsters
bit [7:0] ref_reg_value; // 8-bit wide register for storing reference data to be compared.
// Constructor Class
function new (string name, string instance);
super.new("I2C_Scoreboard", "SCOREBOARD");
this.log = new("Scoreboard", "SCOREBOARD");
endfunction
 
 
// Write_reg Task. It saves the data written to internal register of DUT into Associative Array wr_reg
task write_reg(register_pkt reg_pkt);
// $display("Scoreboard: inside write_reg at %t", $time);
// if(reg_pkt.reset_bit)
// begin
// wr_reg.delete;
// for (int i = 0; i < sb_pre_txn_q.size ; i++)
// sb_pre_txn_q.delete(i);
// for (int j = 0; j < sb_post_txn_q.size ; j++)
// sb_post_txn_q.delete(j);
// end
// else
// begin
$cast(reg_pkt1,reg_pkt.copy());
wr_reg[reg_pkt1.reg_address] = reg_pkt1.data_byte;
// end
endtask
 
 
// Read_reg task. It Check whether data is previously written to internal register (Checks Whether data already exists for the given index,
// which is internal register's address in this case). If data already exists, it compare this data with the read data. If data with same index
// doesn't exists, it will compare this read data with initial data of that index.
task read_reg(register_pkt reg_pkt);
$cast(reg_pkt1,reg_pkt.copy());
if(wr_reg.exists(reg_pkt1.reg_address)) // Data Already written into internal register of given index(address)
begin
ref_reg_value = wr_reg[reg_pkt1.reg_address];
if(reg_pkt1.reg_address == 8'h0C)
if(ref_reg_value[7:1] == reg_pkt1.data_byte[7:1])
`vmm_note(log, "Scoreboard: Date written into Register MATCH with Date read from Register");
else
`vmm_error(log, "Scoreboard: Date written into Register DO NOT MATCH with Date read from Register");
else if (reg_pkt1.reg_address == 8'h04)
if(ref_reg_value[7:2] == reg_pkt1.data_byte[7:2])
`vmm_note(log, "Scoreboard: Date written into Register MATCH with Date read from Register");
else
`vmm_error(log, "Scoreboard: Date written into Register DO NOT MATCH with Date read from Register");
else
if(ref_reg_value == reg_pkt1.data_byte)
`vmm_note(log, "Scoreboard: Date written into Register MATCH with Date read from Register");
else
`vmm_error(log, "Scoreboard: Date written into Register DO NOT MATCH with Date read from Register");
end
else
begin // Data was not written before
if(reg_pkt1.data_byte == 8'h00)
`vmm_note(log, "Scoreboard: Date written into Register MATCH with Initial Valre of Register");
else
`vmm_error(log, "Scoreboard: Date written into Register DO NOT MATCH with Initial Value of Register");
end
endtask
// Pre_txn_push task. This task will push back the data packet(object) been received by callback.
task pre_txn_push(scoreboard_pkt sb_pre_obj);
$cast(sb_pre_obj1,sb_pre_obj.copy());
this.sb_pre_obj1.display();
this.sb_pre_txn_q.push_back(sb_pre_obj1);
endtask
 
// Post_txn_push Task. This task is used to compare both data_byte, the one to be transmitter before starting transmission and
// the one which was received after completion of transation. This task will check whether any object is already available
// in the queue(If size > 0). If object is alread there, It will pop_out that object and check the data_byte of both objects.
task post_txn_push(scoreboard_pkt sb_post_obj);
if(sb_pre_txn_q.size > 0)
begin
sb_post_obj1 = this.sb_pre_txn_q.pop_front();
if(sb_post_obj1.data_byte == sb_post_obj.data_byte)
`vmm_note(log, $psprintf("DATA TRANSMITED AND RECEIVED MATCH WITH EACH OTHER AT TIME %t", $time));
else
`vmm_error(log, $psprintf("DATA TRANSMITED AND RECEIVED DO NOT MATCH WITH EACH OTHER AT TIME %t", $time));
end
endtask
 
 
// This task it used to display all contents of queue.
task sb_display();
this.log.start_msg(vmm_log::NOTE_TYP);
void'(this.log.text($psprintf("****************************")));
void'(this.log.text($psprintf("*****SCOREBOARD REPORT*****")));
void'(this.log.text($psprintf("****************************")));
void'(this.log.text($psprintf("\n*****PACKETS TRANSMITTED*****")));
for (int i = 0; i < this.sb_pre_txn_q.size ; i++)
begin
void'(this.log.text($psprintf("Master/Slave = %0b Data_Transmitted = %b", sb_pre_txn_q[i].master_slave, sb_pre_txn_q[i].data_byte)));
end
void'(this.log.text($psprintf("\n*****PACKETS RECEIVED*****")));
for (int i = 0; i < this.sb_post_txn_q.size ; i++)
begin
void'(this.log.text($psprintf("Master/Slave = %0b Data_Received = %b", sb_post_txn_q[i].master_slave, sb_post_txn_q[i].data_byte)));
end
this.log.end_msg();
endtask
 
endclass
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_slave_driver.sv New file
0,0 → 1,717
//////////////////////////////////////////////////////////////////////////////////////////
// //
// Verification Engineer: Atish Jaiswal //
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. //
// //
// Description of the Source File: //
// This source code implements I2C M/S Driver. //
// Driver will be receiving Scenario packets from Stimulus gen and accordingly it //
// will keep on monitoring/driving interface signals. //
// //
// //
//////////////////////////////////////////////////////////////////////////////////////////
 
 
`include "vmm.sv"
 
class i2c_slave_driver extends vmm_xactor;
 
vmm_log log = new("lOG", "SLAVE_DRIVER");
 
virtual i2c_pin_if pif; // Virtual Interface
stimulus_packet_channel s_stim_req_chan; // Scenario_gen to Driver Channel
stimulus_packet s_stim_packet; // Stimulus Packet's Instance
stimulus_packet s_temp_stim_packet; // Stimulus Packet's Temprary Instance
stimulus_packet s_response_packet;
scoreboard_pkt s_sb_pkt; // Scoreboard Packet's Instance
 
 
// Class Constructor
function new(string name, string instance, virtual i2c_pin_if pif, stimulus_packet_channel s_stim_req_chan = null);
super.new("slave_driver","i2c_slave_driver");
if(s_stim_req_chan == null) s_stim_req_chan = new("slave_stimulus_packet_channel", "s_stim_req_chan");
this.s_stim_req_chan = s_stim_req_chan;
s_stim_packet = new;
s_temp_stim_packet = new;
s_response_packet = new;
s_sb_pkt = new;
this.pif = pif;
endfunction
 
 
reg [6:0] slave_address; // Stores slave addess
reg [7:0] mem_in ; // memory reg which receives data
reg [7:0] mem_out; // memory data output
reg [2:0] bit_cnt; // 3-bit down counter
reg [2:0] state; // State when this core is in slave mode
reg [7:0] sr; // 8bit shift register
reg sta, d_sta; // Local Start and delayed Start Signal
reg sto, d_sto; // Local Stop and delayed Stop Signal
reg rw; // read/write direction
reg ld; // load downcounter
reg sda_o; // sda-drive level
reg scl_o; // sca-drive level
reg my_adr, my_adr_flag ; // address match flags
reg i2c_reset; // i2c-state machine reset
reg acc_done; // Checks whethere 8-bits transmission done
reg sda_dly; // delayed version of sda
int byte_count; // Byte count
reg core_master_slave; // Selects Master/Slave configuration of this driver
reg tr; // Selects Transmit/Receive Operation of this driver
reg [7:0] data_out; // memory data output
bit [7:0] slave_data_out[]; // memory data output
bit load_data; // Load new data into mem_out
int sent_data_count; // Count no. of bytes already been sent
int received_data_count; // Count no. of bytes already been received
int slave_bit_count; // Control Slave bit count while sending address to DUT
bit slave_start_sig; // Local Start signal for generating Start
bit slave_stop_sig; // Local Stop Signal for generating Stop
bit slave_ack; // Checks Acknowledgment from DUT
reg [2:0] slave_state; // Slave State when this core is in master mode
int i =0;
reg temp; // Temp signal to be assigned on sda_oe
reg shift_data_out; // Control Shifting of data
reg load_first_data_flag;
 
// Initialize the local variables of driver
task i2c_slave_driver_initialize;
sda_o = 1'b1;
scl_o = 1'b1;
pif.scl_oe = 1'b1;
state = 3'b000;
slave_state = 3'b000;
slave_start_sig = 1'b1;
sta = 1'b0;
sto = 1'b0;
endtask
 
// This task will invoke parallel threads which will be running continuously throughout the simulation. //
task set_always;
fork
shift_reg;
set_sda;
set_scl;
bit_count;
detect_start;
detect_stop;
set_mem_out;
delayed_start;
acc_done_check;
address_check;
generate_scl;
generate_start;
set_data_out;
set_load_first_data_flag;
join
endtask
 
// This Task will be shifting sr register. On every scl clock it will get the data from sda line and //
// that data will be copied to lsb of sr register and data will be shifted left bit by bit. //
task shift_reg;
forever @(posedge pif.scl)
begin
if (sta) sr = #1 {sr[6:0],pif.sda};
end
endtask
 
// This task will be counting no. of scl clock events. When ld (load Count) is one, it will initialize //
// the counter, otherwise it will decrement the count by one on every posedge of scl //
task bit_count;
forever @(posedge pif.scl)
begin
if(ld)
bit_cnt = #1 3'b111;
else
bit_cnt = #1 bit_cnt - 3'b001;
end
endtask
 
// This task will be comparing the slave address being received on sda line and the address assigned to //
// this transactor. It sets the flag when addresses match. //
task address_check;
forever @(posedge pif.clk)
begin
my_adr_flag = (sr[7:1] == slave_address);
if (my_adr_flag && !(my_adr))
my_adr = #1 1'b1;
end
endtask
 
// This task will set the flag load_first_data_flag
task set_load_first_data_flag;
forever @(posedge pif.scl)
begin
load_first_data_flag = my_adr;
end
endtask
 
// This task will check whether 8 bits have been transmitted or received. In other words it checks the //
// bit-Count. Sets the flag when 8 bits transaction is done. //
task acc_done_check;
forever @(posedge pif.clk)
begin
acc_done = !(|bit_cnt);
end
endtask
 
// This task will detect start signal on sda line. It sets flags when start signal is detected. //
task detect_start;
forever @(negedge pif.sda)
if(pif.scl)
begin
sta = #1 1'b1;
d_sta = #1 1'b0;
sto = #1 1'b0;
my_adr = 1'b0;
end
else sta = #1 sta;
endtask
 
// This task will detect stop signal on sda line. It sets flags when stop signal is detected. //
task detect_stop;
forever @(posedge pif.sda);
if(pif.scl)
begin
sta = #1 1'b0;
sto = #1 1'b1;
end
else sto = #1 1'b0;
endtask
 
// This task assign start signal to delayed version of start. //
task delayed_start;
forever @(posedge pif.scl)
d_sta = #1 sta;
endtask
 
// This task shifts bitwise data of mem_out. MSB of this register is transmitted when I2C M/S works as //
// a Trasnmitter. //
task set_mem_out;
forever @(posedge pif.scl)
begin
if(!acc_done && rw)
mem_out = #1 {mem_out[6:0],1'b1};
end
endtask
// This task assign sda_o (local sda_o data) to interface sda_oe. //
task set_sda;
begin
forever
begin
#5;
temp = slave_start_sig & sda_o;
if(slave_stop_sig)
begin
if(!pif.scl)
pif.sda_oe = 1'b0;
else
#100 pif.sda_oe = 1'b1;
end
else
pif.sda_oe = temp;
end
end
endtask
 
// This task assigns value of local scl_o to interface port scl_o //
task set_scl;
forever begin
#10; pif.scl_oe = scl_o;
end
endtask
 
 
// This task will generate SCL clk when I2C Master/Slave Driver (this one) is working in Master mode.
task generate_scl;
int s_clk_gen_count = 0;
forever @(posedge pif.clk)
begin
if(core_master_slave == 1'b0)
begin
if(s_clk_gen_count == 49)
begin
scl_o = ~scl_o;
s_clk_gen_count = 0;
end
else
s_clk_gen_count++;
end
end
endtask
 
// This task will generate Start Signal on sda line when This Driver is working in Master Mode.
task generate_start;
if(core_master_slave == 1'b0)
begin
#100;
forever
begin
if(sta != 1'b1 && !(core_master_slave) && !(s_temp_stim_packet.reset_check) && !(s_temp_stim_packet.reset_check))
begin
@(posedge pif.scl)
begin
if(sta != 1'b1 && !(core_master_slave))
begin
#100 slave_start_sig = 1'b0;
end
end
@(negedge pif.scl) slave_start_sig = 1'b1;
end
#100;
end
end
endtask
 
// This task will set data out on posedge of scl //
task set_data_out;
forever @(posedge pif.scl)
begin
if(!acc_done || shift_data_out)
begin
data_out = #1 {data_out[6:0],1'b1};
#2;
end
end
endtask
 
 
// process task
task process;
forever
begin
s_stim_packet = new;
s_stim_req_chan.peek(s_stim_packet);
$cast(s_temp_stim_packet,s_stim_packet.copy());
`vmm_note(log, "***********Packet Received inside I2C_SLAVE_DRIVER from GENERATOR************");
s_temp_stim_packet.display();
slave_address = s_temp_stim_packet.slave_address;
byte_count = s_temp_stim_packet.byte_count;
slave_data_out = new[byte_count];
slave_data_out = s_temp_stim_packet.data_packet;
core_master_slave = s_temp_stim_packet.master_slave;
tr = s_temp_stim_packet.tr;
#1;
// $display("begining of task process mem_out is %b and byte_count is %d and slave_address is %b", mem_out, byte_count, slave_address);
i = 0;
if(my_adr_flag && !(load_first_data_flag))
begin
mem_out = slave_data_out[0];
end
 
// If load_data is set, it will copy a new data byte from slave_data_out array to mem_out register.
// This mem_out register's data will be outputed on sda line.
if(load_data)
begin
mem_out = slave_data_out[byte_count - sent_data_count];
// `vmm_callback
if(core_master_slave == 1)
begin
s_sb_pkt.master_slave = 1'b1;
s_sb_pkt.tx_rx = 1'b0;
end
else
begin
s_sb_pkt.master_slave = 1'b0;
s_sb_pkt.tx_rx = 1'b1;
end
s_sb_pkt.slave_address = s_temp_stim_packet.slave_address;
s_sb_pkt.data_byte = mem_out;
// $display("Callback for pre_transaction in slave driver at %t", $time);
`vmm_callback(i2c_callback,pre_transaction(s_sb_pkt));
// vmm_callback
load_data = 1'b0;
end
 
// When reset_check test case is begin run on W/B driver side (DUT) this driver will not do any operation.
if(s_temp_stim_packet.reset_check)
begin
`vmm_note(log, $psprintf("SLave_Driver: Checking reset operation of DUT at %t", $time));
repeat (10) @(posedge pif.clk);
i2c_slave_driver_initialize;
s_stim_req_chan.get(s_stim_packet);
end
 
// When register_check test case is begin run on W/B driver side (DUT) this driver will not do any operation.
else if(s_temp_stim_packet.register_check)
begin
`vmm_note(log, $psprintf("SLave_Driver: Checking register test operation of DUT at %t", $time));
repeat (10) @(posedge pif.clk);
i2c_slave_driver_initialize;
s_stim_req_chan.get(s_stim_packet);
end
 
// Data-Transmisstion test-case is being run now. This Core (I2C M/S) is working as a Slave Device
else if(core_master_slave) //In slave mode
begin
@(negedge pif.scl or posedge sto)
begin
if(sto || (sta && !d_sta))
begin
sda_o = #1 1'b1;
//scl_o = #1 1'b1;
ld = #1 1'b1;
state = #1 3'b000;
end
else
begin
sda_o = #1 1'b1;
ld = #1 1'b0;
end
 
// Case 000 will be checking whether 8 bits of transaction is done, Address matches and rd/wr bit. //
// It will assign next state to state 001, which is Address Acknowledgment State. //
case (state)
3'b000:
begin
if(acc_done && my_adr)
begin
rw = #1 sr[0];
sda_o = #5 1'b0;
#2;
if(rw)
begin
sent_data_count = byte_count;
// if(sent_data_count != 0)
//s_rsp_port.put(1);
// #1;
end
else if (!rw)
begin
received_data_count = byte_count;
end
state = #1 3'b001;
end
end
 
// Case 001 is Acknowledgment state for address. It checks rd/wr bit received with slave address //
// Then for I2C M/S Core(this dirver) as a Transmitter, next state will be assigned to 010 and send //
// slave address acknowledgment signal. For I2C M/S Core (This driver) as a Receiver, next state //
// will be assigned to 011. Then it sets load_count bit. //
3'b001:
begin
if(rw)
begin
state = #1 3'b010; // read state
// `vmm_callback
s_sb_pkt.master_slave = 1'b1;
s_sb_pkt.tx_rx = 1'b0;
s_sb_pkt.slave_address = s_temp_stim_packet.slave_address;
s_sb_pkt.data_byte = mem_out;
// $display("Callback for pre_transaction in slave driver at %t", $time);
`vmm_callback(i2c_callback,pre_transaction(s_sb_pkt));
sda_o = #1 mem_out[7];
end
else
state = #1 3'b011; // write state
ld = #2 1'b1;
end
 
// When I2C M/S DUT is acting as a Master trasnmitter and access is done, it will send msb of //
// mem_out to sda_o which will get assigned to sda_oe line on interface. When Access is done, //
// next State will be assigned to 100, which is Data Acknowledgment state. It also checks //
// whether byte_count is 0. If it is not 0, load_data will be set to 1 for next byte. //
3'b010:
begin
if(rw)
#1 sda_o = mem_out[7];
if(acc_done)
begin
sda_o = #1 rw;
state = #1 3'b100; // Data Acknoledgment
if(rw)
begin
sent_data_count --;
if(sent_data_count != 0)
load_data = 1'b1;
end
end
end
 
// When I2C M/S core (this core) is acting as a receiver and access is done, it will get data_byte //
// from shift register sr and send acknowledgement signal to interface through sda_o signal. Next //
// State will be assigned to 100, which is Data Acknowledgment state. //
3'b011:
begin
if(acc_done)
begin
mem_in = #1 sr;
sda_o = #1 1'b0;
// `vmm_callback
s_sb_pkt.master_slave = 1'b1;
s_sb_pkt.tx_rx = 1'b0;
s_sb_pkt.slave_address = s_temp_stim_packet.slave_address;
s_sb_pkt.data_byte = mem_in;
// $display("Callback for post_transaction in slave driver when DUT is in master at %t", $time);
`vmm_callback(i2c_callback,post_transaction(s_sb_pkt));
// vmm_callback
state = #1 3'b100; // Data Acknoledgment
end
// #1;
end
 
// This is Data Acknowledgment State. When I2C M/S Core (this driver) is acting as a trasmitter and when after //
// sending data byte it doesn't get acknowledgment from Master DUT, next state will assigned to 000. //
// If it gets the acknoeledgment, next state will be assigned to 010. Similerly when I2C M/S core (this core) //
// as a receiver, next state will be assigned to 011. //
3'b100:
begin
ld = #1 1'b1;
if(rw)
begin
if(sr[0]) // read and master send NACK
begin
sda_o = #1 1'b1;
state = 3'b000;
end
else
begin
sda_o = mem_out[7];
//if(byte_count == 0)
if(sent_data_count == 0)
begin
state = 3'b000;
ld = 1'b0;
#5000 s_stim_req_chan.get(s_stim_packet);
i2c_slave_driver_initialize;
end
else
state = 3'b010;
end
end
else
begin
received_data_count--;
if(received_data_count != 0)
begin
state = #1 3'b011;
sda_o = #1 1'b1;
end
else
begin
#5000 s_stim_req_chan.get(s_stim_packet);
i2c_slave_driver_initialize;
end
end
end
default : $display("default case");
endcase
end // @(negedge pif.scl or posedge sto)
end // (s_stim_packet.master_slave))
 
// Data Transmission test-case and this core (I2C M/S Core) is working as a Master Device.
else if(core_master_slave == 1'b0) // This core works as in master mode (DUT core in slave mode)
begin
#100;
rw = tr;
shift_data_out = 1'b1;
@(negedge pif.scl)
begin
if(sto || (sta && !d_sta))
begin
data_out = {slave_address,!tr};
ld = 1'b1;
slave_state = #1 3'b000;
end
else
begin
ld = 1'b0;
end
 
case(slave_state)
 
// State 000 will be generating SCL and then check Ack bit and accordingly set next state. //
// For I2C M/S Core(this driver) as a Transmitter it will be setting next state to 001 and //
// for I2C M/S Core(this dirver) to be a Receiver this will be setting next state to 010. //
3'b000:
begin
if(acc_done && slave_bit_count > 7)
begin
sent_data_count = byte_count;
received_data_count = byte_count;
ld = #2 1'b1;
slave_state = 3'b001;
sda_o = 1'b1;
@(posedge pif.scl)
begin
slave_ack = pif.sda;
if(!slave_ack && tr) // This slave will be sending data to DUT core
begin
mem_out = slave_data_out[0];
end
else if (!slave_ack && !tr) // This slave will be receiving data from DUT core
begin
// $display("slave ack is 0 and tr is 1 at %t", $time);
end
end
end
else
begin
if(sta)
begin
sda_o = data_out[7];
slave_bit_count++;
end
end
end
 
// Case 001 is Acknowledgment state for address. It checks rd/wr bit received with slave address //
// Then for I2C M/S Core(this dirver) as a Transmitter, next state will be assigned to 010 and send //
// slave address acknowledgment signal. For I2C M/S Core (This driver) as a Receiver, next state //
// will be assigned to 011. Then it sets load_count bit. //
3'b001:
begin
if(rw)
begin
slave_state = #1 3'b010; // I2C M/S Core (this dirver) transmit state
// `vmm_callback
s_sb_pkt.master_slave = 1'b0;
s_sb_pkt.tx_rx = 1'b1;
s_sb_pkt.slave_address = s_temp_stim_packet.slave_address;
s_sb_pkt.data_byte = mem_out;
// $display("Callback for pre_transaction in slave driver when DUT is in slave mode at %t", $time);
`vmm_callback(i2c_callback,pre_transaction(s_sb_pkt));
// vmm_callback
sda_o = #1 mem_out[7];
end
else
slave_state = #1 3'b011; // I2C M/S Core (this dirver) receive state
 
ld = #2 1'b1;
end
// State 010 will be transmitting serial data from mem_out to sda_o. //
// If 8 bits are transmitted (acc_done set) it will decrese the sent_data_count. //
// If sent_data_count is not 0, it will set load_data to load new data into mem_out. //
3'b010:
begin
#1 sda_o = mem_out[7];
if(acc_done)
begin
slave_state = 3'b100;
sent_data_count--;
if(sent_data_count != 0)
load_data = 1'b1;
end
end
// State 011 will be receiving data from sda_in. //
// If 8 bits are received (acc_done set) it will copy sr into mem_in and //
// decrese the received_data_count. //
3'b011:
begin
if(acc_done)
begin
mem_in = #1 sr;
sda_o = #1 1'b0;
// `vmm_callback
s_sb_pkt.master_slave = 1'b0;
s_sb_pkt.tx_rx = 1'b0;
s_sb_pkt.slave_address = s_temp_stim_packet.slave_address;
s_sb_pkt.data_byte = mem_in;
// $display("Callback for post_transaction in driver when DUT is in slave mode at %t", $time);
`vmm_callback(i2c_callback,post_transaction(s_sb_pkt));
// vmm_callback
slave_state = #1 3'b100; // Data Acknoledgment
end
// #1;
end
 
 
// State 100 is for acknowledgment of data byte tx/rx //
// In transmit mode it will check ack from DUT and then if sent_data_count is not zero, //
// It will set the next state to 010. If sent_data_count is 0, it will set next state //
// to 000 and set all local variable to their initial values. //
// Similerly, In Receive mode when received_data_count is not 0, it will set next state //
// to 011. If its 0, next state will be set to 000 and set all local variable to their //
// initial values. //
3'b100:
begin
if(rw)
begin
sda_o = mem_out[7];
if(sent_data_count == 0)
begin
slave_state = 3'b000;
ld = 1'b0;
if(sto != 1'b1)
#10 slave_stop_sig = 1'b1;
else
begin
@(posedge pif.scl);
begin
#1000 slave_stop_sig = 1'b0;
end
end
#1000 slave_stop_sig = 1'b0;
slave_bit_count = 0;
sda_o =1'b1;
scl_o = 1'b1;
sta = 1'b0;
s_stim_req_chan.get(s_stim_packet);
end
else
begin
ld = #1 1'b1;
slave_state = 3'b010;
end
end
else
begin
received_data_count--;
if(received_data_count != 0)
begin
slave_state = #1 3'b011;
sda_o = #1 1'b1;
ld = 1'b1;
end
else
begin
slave_state = 3'b000;
ld = 1'b0;
if(sto != 1'b1)
#10 slave_stop_sig = 1'b1;
else
begin
@(posedge pif.scl);
begin
#1000 slave_stop_sig = 1'b0;
end
end
#1000 slave_stop_sig = 1'b0;
slave_bit_count = 0;
sda_o = 1'b1;
scl_o = 1'b1; // to check scl generation when this core's mode got changed from m to s ...
sta = 1'b0;
s_stim_req_chan.get(s_stim_packet);
end
end
end
endcase
end
end
else
begin
#10;
// $display("Slave Driver: no condition matches");
end
end
endtask
 
virtual protected task main();
super.main();
begin
fork
i2c_slave_driver_initialize;
set_always;
process;
join
end
endtask
 
endclass
 
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_monitor.sv New file
0,0 → 1,205
//////////////////////////////////////////////////////////////////////////////////////////
// //
// Verification Engineer: Atish Jaiswal //
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. //
// //
// Description of the Source File: //
// This source code implements I2C Master-Slave Monitor. //
// Monitor does protocol validations. It checks generation of Start, Stop, interrupt //
// request, slave and data acknowledgment for every trnasaction. It will create //
// monitor packet on every transaction and send that packet to Coverage Module. //
// //
//////////////////////////////////////////////////////////////////////////////////////////
 
`include "vmm.sv"
 
class i2c_monitor extends vmm_xactor;
vmm_log log = new("lOG", "MONITOR");
virtual i2c_pin_if pif; // Virtual Interface
stimulus_packet mon_stim_packet; // Stimulus Packet
stimulus_packet temp_mon_stim_packet; // Stimulus Packet
monitor_pkt mon_pkt; // Monitor Packet
 
// Class Constructor
function new(string name, string instance, virtual i2c_pin_if pif);
super.new("Monitor","I2C_MONITOR");
mon_stim_packet = new;
temp_mon_stim_packet = new;
mon_pkt = new;
this.pif = pif;
endfunction
 
reg sta, d_sta; // Local Variable of start and delayed start
reg sto, d_sto; // Local variable of stop and delayed stop
reg slave_ack; // Local Variable for Slave Acknowledgment
reg data_ack; // Local variable for Data Acknowledgment
reg intr_ack; // Local variable for Genaration of Interrupt
reg first_stop_flag; // Local variable for First Stop bit
integer local_byte_count; // Track byte_count
integer ack_count; // Track Acknowledgment pulse count
integer intr_count; // Track Interrupt Count
reg [3:0] bit_count; // 3-bit Counter
reg load_counter; // load_counter flag
 
 
// This task gets packet from driver. Though this call monitor will be aware of what kind of test-case is being run.
task get_packet_from_driver(stimulus_packet mon_stim_packet);
`vmm_note(log, $psprintf("Received Packet IN MONITOR at time %t", $time));
$cast(temp_mon_stim_packet, mon_stim_packet.copy());
temp_mon_stim_packet.display();
endtask
// Initialize the local variables of Monitor
task initialize;
sta = 1'b0;
d_sta = 1'b0;
sto = 1'b0;
d_sto = 1'b0;
slave_ack = 1'b0;
data_ack = 1'b0;
intr_ack = 1'b0;
bit_count = 4'h0;
load_counter = 1'b0;
ack_count = 0;
intr_count = 0;
endtask
 
 
// This task will be counting no. of scl clock events. When load_counter is one, it will initialize //
// the counter, otherwise it will decrement the count by one on every posedge of scl //
task bit_counter;
forever @(posedge pif.scl)
begin
if(load_counter)
bit_count = 4'h8;
else
bit_count = bit_count - 4'h1;
end
endtask
// This task will detect start signal on sda line. It sets flags when start signal is detected. //
task detect_start;
forever @(negedge pif.sda)
if(pif.scl)
begin
sta = #1 1'b1;
d_sta = #1 1'b0;
sto = #1 1'b0;
load_counter = 1'b1;
end
else sta = #1 sta;
endtask
// This task will detect stop signal on sda line. It sets flags when stop signal is detected. //
task detect_stop;
forever @(posedge pif.sda)
if(pif.scl)
begin
sto = #1 1'b1;
end
else sto = #1 1'b0;
endtask
// This task assign start signal to delayed version of start. //
task delayed_start;
forever @(posedge pif.scl)
d_sta = #1 sta;
endtask
// This task assign stop signal to delayed version of start. //
task delayed_stop;
forever @(posedge pif.clk)
d_sto = #1 sto;
endtask
 
// This task will detect interrupt signal on sda line. If bit_count is 0, it will increment intr_count. //
task detect_intr;
forever @(posedge pif.irq)
begin
if(bit_count == 0)
intr_count++;
else if(bit_count != 0 && temp_mon_stim_packet.intr_en && !(temp_mon_stim_packet.register_check) && !(temp_mon_stim_packet.reset_check))
`vmm_error(log, "INTERRUPT SIGNAL NOT GENERATED ON RIGHT TIME");
end
endtask
 
// Process Task
task process;
forever @(posedge pif.scl or posedge sto)
begin
if(sta && !(d_sta) && !(sto)) // First SCL posedge after Start pulse
begin
load_counter = 1'b0;
`vmm_note(log, $psprintf("START DETECTED IN MONITOR AT %t", $time));
end
else if (sta && d_sta && !(sto))
begin
load_counter = 1'b0;
// It checks the value of sda line when bit_count is 0 for acknowledgment. First Acknowledgment pulse is Slave Acknowledgment
// and from then it will be Data acknowldgment.
if(bit_count == 4'h0 && !pif.sda)
begin
if(ack_count == 0)
`vmm_note(log,$psprintf("SLAVE ADDRESS ACKNOWLEDGMENT DETECTED AT %t", $time));
else
`vmm_note(log,$psprintf("DATA ACKNOWLEDGMENT DETECTED AT %t", $time));
ack_count++;
load_counter = 1'b1;
end
end
else if (sto && !(d_sto))
begin
if(!first_stop_flag)
first_stop_flag = 1'b1;
else
begin
// Checks whether the testcase being run is not of register_check or reset_check type.
if(!(temp_mon_stim_packet.register_check) && !(temp_mon_stim_packet.reset_check))
begin
`vmm_note(log, $psprintf("STOP DETECTED IN MONITOR AT %t", $time));
if(!(sta || d_sta))
`vmm_error(log, "START PULSE NOT DETECTED");
if(temp_mon_stim_packet.byte_count != (ack_count-1))
`vmm_error(log, "ACKNOWLEDGMENT NOT DETECTED");
if(temp_mon_stim_packet.intr_en && temp_mon_stim_packet.byte_count != (intr_count-1))
`vmm_error(log, "INTERRUPT BIT NOT CLEARED FOR ALL INTERRUPT MODE TRANSACTIONS");
if (sta)
begin
// Create a monitor pkt and sent it to and coverage module through callback
mon_pkt.start_bit = 1'b1;
mon_pkt.stop_bit = 1'b1;
mon_pkt.slave_ack = 1'b1;
mon_pkt.data_ack = 1'b1;
mon_pkt.intr_ack = 1'b1;
`vmm_callback(i2c_callback,protocol_checks_coverage(mon_pkt));
@(posedge pif.clk) initialize;
end
end
end
end
end
endtask
 
// Main Task
virtual protected task main();
super.main();
begin
first_stop_flag = 1'b0;
fork
initialize;
bit_counter;
delayed_start;
delayed_stop;
detect_start;
detect_stop;
detect_intr;
process;
join
end
endtask
 
endclass
 
 
 
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_env.sv New file
0,0 → 1,187
//////////////////////////////////////////////////////////////////////////////////////////
// //
// Verification Engineer: Atish Jaiswal //
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. //
// //
// Description of the Source File: //
// This source code Creates VMM Environment of the I2C M/S Core. //
// //
// //
// //
//////////////////////////////////////////////////////////////////////////////////////////
 
`include "vmm.sv"
`include "config.sv"
`include "vmm_i2c_interface.sv"
//`include "debug_if.sv"
`include "vmm_i2c_sb_pkt.sv"
`include "vmm_i2c_mon_pkt.sv"
`include "vmm_i2c_reg_pkt.sv"
`include "vmm_i2c_scenario_packet.sv"
`include "vmm_i2c_stimulus_packet.sv"
`include "vmm_i2c_data_packet.sv"
`include "vmm_i2c_scenario_generator.sv"
`include "sb_callback.sv"
`include "vmm_i2c_driver.sv"
`include "vmm_i2c_slave_driver.sv"
 
class i2c_env extends vmm_env;
 
vmm_log log = new("log", "ENV");
virtual i2c_pin_if pif; // Virtual Interface
i2c_scenario_generator sc_gen; // Scenario Generator
configuration cfg; // Configuration Class
stimulus_packet_channel m_stim_req_chan; // Scenarion_gen to W/B Driver Channel
stimulus_packet_channel s_stim_req_chan; // Scenarion_gen to I2C M/S Driver Channel
i2c_master_driver m_driver_xactor; // W/B Driver Xactor
i2c_slave_driver s_driver_xactor; // I2C Driver Xactor
i2c_scoreboard i2c_sb; // Scoreboard
sb_callback sb_c; // Sb_Callback
i2c_coverage i2c_cov; // Coverage_Module
i2c_monitor i2c_mon; // Monitor
 
bit rand_tran = 1'b0; // Rand_mode
integer transaction_count; // No. of Transaction
 
// Class Constructor
function new(virtual i2c_pin_if pif);
super.new("MY_ENV");
this.pif = pif;
// this.d_if = d_if;
$value$plusargs("transaction_count=%d",transaction_count);
$value$plusargs("rand_trans=%b",rand_tran);
cfg = new();
endfunction
 
 
//Gen Config Function. If rand_trans is 1 then this will randomize trasaction_count in config class
virtual function void gen_cfg();
super.gen_cfg();
`vmm_note(log, "inside gen_cfg");
if(rand_tran)
begin
if(!cfg.randomize())
`vmm_error(log,"Configuration Randomization Failed");
transaction_count = cfg.transaction_count;
end
endfunction
 
// Build function to all Connections Initializaion
virtual function void build();
super.build();
m_stim_req_chan = new("master_stimulus_packet_channel", "m_stim_req_chan");
s_stim_req_chan = new("slave_stimulus_packet_channel", "s_stim_req_chan");
sc_gen = new("scenario_generator", "generator", m_stim_req_chan, s_stim_req_chan);
m_driver_xactor = new("i2c_master_driver", "m_driver_xactor", this.pif, m_stim_req_chan);
s_driver_xactor = new("i2c_slave_driver", "s_driver_xactor", this.pif, s_stim_req_chan);
sc_gen.transaction_count = transaction_count;
i2c_sb = new("I2C_Scoreboard", "SCOREBOARD");
i2c_cov = new("I2C_Coverage", "COVERAGE");
i2c_mon = new("I2C_Monitor", "MONITOR",this.pif);
sb_c = new(i2c_sb, i2c_cov, i2c_mon);
m_driver_xactor.append_callback(sb_c);
s_driver_xactor.append_callback(sb_c);
i2c_mon.append_callback(sb_c);
endfunction
 
// Reset DUT task. It will reset dut for 5 system clk cycle
virtual task reset_dut();
super.reset_dut();
m_driver_xactor.set_enable_signals;
pif.rst = 1;
repeat(5)
begin
@(posedge pif.clk);
pif.rst = 0;
end
`vmm_note(log, "inside reset_dut");
endtask
 
// cfg dut task for configuration of DUT.
virtual task cfg_dut();
super.cfg_dut();
`vmm_note(log, "inside cfg_dut");
endtask
 
// Start Transactor task. This will start all transactor in the Environment.
virtual task start();
super.start();
sc_gen.start_xactor();
m_driver_xactor.start_xactor();
s_driver_xactor.start_xactor();
i2c_mon.start_xactor();
`vmm_note(log, "inside start");
endtask
 
// Wait for end task. It will wait for Done signal from Scenario Generartor.
virtual task wait_for_end();
super.wait_for_end();
`vmm_note(log, "inside wait_for_end");
`vmm_note(log, "inside wait_for_end: before wait for done");
this.sc_gen.notify.wait_for(this.sc_gen.DONE);
`vmm_note(log, "inside wait_for_end: Affter wait for done");
endtask
// Report Task
virtual task report();
super.report();
// i2c_sb.sb_display();
`vmm_note(log, "inside report");
endtask
 
// Clean-up task
virtual task cleanup();
super.cleanup();
`vmm_note(log, "inside cleanup");
endtask
 
endclass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/config.sv New file
0,0 → 1,27
//////////////////////////////////////////////////////////////////////////////////////////
// //
// Verification Engineer: Atish Jaiswal //
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. //
// //
// Description of the Source File: //
// This source code is used to configure the test-case. //
// This class randmomize the no. of transactions. //
// //
// //
//////////////////////////////////////////////////////////////////////////////////////////
 
`include "vmm.sv"
 
class configuration;
 
rand int transaction_count; // No. of transaction to be done
 
function new();
endfunction
 
constraint valid {
transaction_count inside {[0:44]};
}
 
endclass
 
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_program1_test.sv New file
0,0 → 1,134
//////////////////////////////////////////////////////////////////////////////////////////
// //
// Verification Engineer: Atish Jaiswal //
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. //
// //
// Description of the Source File: //
// This source code is written to apply directed test-case to I2C M/S core. //
// This test-case will be written to apply write-write-read operation on register //
// test-case. //
// //
//////////////////////////////////////////////////////////////////////////////////////////
 
`include "vmm.sv"
`include "vmm_i2c_env.sv"
`include "vmm_clkgen.sv"
 
class i2c_scenario_generator1 extends i2c_scenario_generator;
int transaction_count;
byte reg_addr[5] = {8'h02, 8'h04, 8'h0A, 8'h0C, 8'h0E};
 
function new( string name, string instance_name, stimulus_packet_channel m_req_chan = null, stimulus_packet_channel s_req_chan = null);
super.new("scenario_generator ", "scenario_generator");
if(m_req_chan == null) m_req_chan = new("master_stimulus_packet_channel", "m_req_chan");
this.m_req_chan = m_req_chan;
if(s_req_chan == null) s_req_chan = new("slave_stimulus_packet_channel", "s_req_chan");
this.s_req_chan = s_req_chan;
this.DONE = this.notify.configure(1,vmm_notify::ON_OFF);
sc_packet = new;
stim_packet = new;
d_pkt = new;
$value$plusargs("transaction_count=%d",transaction_count);
$value$plusargs("rand_gen=%b",rand_gen);
$value$plusargs("master_slave=%b",master_slave);
$value$plusargs("register_check=%b",register_check);
$value$plusargs("reset_check=%b",reset_check);
$value$plusargs("tx_rx=%b",tx_rx);
endfunction
 
 
// Main task
virtual protected task main();
begin
stim_packet.master_slave = 1'b1;
stim_packet.tr = 1'b1;
stim_packet.register_check = 1'b1;
stim_packet.reset_check = 1'b0;
// For all internal register
foreach (reg_addr[i])
begin
stim_packet.register_addr = reg_addr[i];
// Writing into registers twice
for (int j = 1; j <=2 ; j++)
begin
stim_packet.register_data = {reg_addr[i]+j};
stim_packet.intr_en = 1'b1;
this.m_req_chan.put(stim_packet); // sending packet to master driver
this.s_req_chan.put(stim_packet); // sending packet to slave driver
end
// Reading Registers
stim_packet.intr_en = 1'b0;
this.m_req_chan.put(stim_packet); // sending packet to master driver
this.s_req_chan.put(stim_packet); // sending packet to slave driver
end
notify.indicate(DONE);
end
endtask
 
endclass
 
 
//-------------------- Program Block --------------------------
program program_test(i2c_pin_if pif);
 
i2c_scenario_generator1 i2c_sc_gen1;
initial begin
i2c_env env;
env = new(pif);
env.build();
i2c_sc_gen1 = new("new_scenario_generator", "generator", env.m_stim_req_chan, env.s_stim_req_chan);
env.sc_gen = i2c_sc_gen1; // Assigning a new Scenario Generator to handle of Old Scenarion Gen in env.
env.run();
end
endprogram
//-------------------------------------------------------------
 
 
 
//---------------------- Module Top --------------------
module top;
 
i2c_pin_if pif();
clkgen c_gen(pif);
program_test p_test(pif);
 
wire dut_sda_o;
wire dut_sda_oe;
wire dut_sda_in;
wire dut_scl_o;
wire dut_scl_oe;
wire dut_scl_in;
wire temp;
wire temp_scl;
assign dut_sda_o = 1'b0;
 
assign temp = pif.sda_oe & dut_sda_oe;
assign temp_scl = pif.scl_oe & dut_scl_oe;
assign pif.sda = temp ? 1'bz : 1'b0;
assign pif.scl = temp_scl ? 1'bz : 1'b0;
pullup p1_if(pif.sda);
pullup p2_if(pif.scl);
 
block i2c_core( .scl_in(pif.scl),
.scl_o(dut_scl_o),
.scl_oe(dut_scl_oe),
.sda_in(pif.sda),
.sda_o(dut_sda_o),
.sda_oe(dut_sda_oe),
.wb_add_i(pif.addr_in),
.wb_data_i(pif.data_in),
.wb_data_o(pif.data_out),
.wb_stb_i(pif.wb_stb_i),
.wb_cyc_i(pif.wb_cyc_i),
.wb_we_i(pif.we),
.wb_ack_o(pif.ack_o),
.irq(pif.irq),
.trans_comp(pif.trans_comp),
.wb_clk_i(pif.clk),
.wb_rst_i(pif.rst)
);
 
endmodule
 
 
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_scenario_packet.sv New file
0,0 → 1,57
//////////////////////////////////////////////////////////////////////////////////////////
// //
// Verification Engineer: Atish Jaiswal //
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. //
// //
// Description of the Source File: //
// This file is the packet class for Scenario Generator. //
// The Packet Randomizes Master/Slave bit,(1 for configuring DUT as a Master and 0 for //
// Slave), tx_rx bit, which determines the direction of data to be transfered. //
// It also randomize reset_check and register_check to enable/disable reset or register//
// testcases. Transacation_count will be assigned from environment itself. //
// //
// //
//////////////////////////////////////////////////////////////////////////////////////////
 
 
`include "vmm.sv"
 
class scenario_packet extends vmm_data;
vmm_log log;
 
randc bit master_slave ; // 1 for master and and 0 for slave
int transaction_count; // No. of transaction to be done
rand bit register_check; // to check register read/write
rand bit reset_check; // to check reset
rand bit tx_rx ; // 1 for transmit and and 0 for receive
function new();
super.new(this.log);
this.log = new("Scenario data", "class");
endfunction
 
function void display();
this.log.start_msg(vmm_log::NOTE_TYP);
void'(this.log.text($psprintf("Master/Slave mode is = %b\n", master_slave)));
void'(this.log.text($psprintf("transaction_count = %d\n", transaction_count)));
void'(this.log.text($psprintf("register_check = %b\n", register_check)));
void'(this.log.text($psprintf("reset_check = %b\n", reset_check)));
void'(this.log.text($psprintf("tx_rx = %b\n", tx_rx)));
this.log.end_msg();
endfunction
 
 
function vmm_data copy(vmm_data to = null);
copy = new this;
endfunction
constraint valid_scenario {
reset_check dist {1 := 1 , 0 := 20};
register_check dist { 1 := 1 , 0 := 20};
}
 
endclass: scenario_packet
 
 
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_coverage.sv New file
0,0 → 1,181
//////////////////////////////////////////////////////////////////////////////////////////
// //
// Verification Engineer: Atish Jaiswal //
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. //
// //
// Description of the Source File: //
// This Source Code Implements Coverage Collector. //
// This Coverage Module contains 3 Covergroups. CG1 for data transaction and modes of //
// of operation, CG2 for Register read-write testcases and CG3 for Protocol validation.//
// All Covergroups are sampled on events which are triggered in different tasks. //
// //
//////////////////////////////////////////////////////////////////////////////////////////
 
`include "vmm.sv"
 
class i2c_coverage extends vmm_xactor;
 
scoreboard_pkt cov_pkt; // Scoreboard_pkt's instance
register_pkt reg_pkt; // register_pkt's instance
monitor_pkt mon_pkt; // Monitor_pkt's instance
event start_cov; // Event data_tye to sample cg1
event start_cov_reg; // Event data type to sample cg2
event start_protocol_checks_cov; // Event data type to sample cg3
 
// local variables which gets assigned object's data members in tasks
bit [7:0] data_byte;
bit master_slave;
bit tx_rx;
bit [6:0] slave_address;
bit start_bit;
bit stop_bit;
bit slave_ack;
bit data_ack;
bit intr_ack;
bit [7:0] reg_address;
bit wr_rd;
bit reset_bit;
bit [8:0] reg_addr_txn;
 
 
// Covergroup CG1. This Covergroup Generate Coverage for modes of operation. their cross coverpoint is defined as well.
// This covergroup will be sampled on every event of start_cov variable. This event will be triggered in task pre_txn_start_cov.
covergroup cg1 @start_cov;
data_in : coverpoint data_byte {
bins low = {[8'h00 : 8'h40]};
bins mid = {[8'h41 : 8'h80]};
bins high = {[8'h81: 8'hff]};
}
m_s : coverpoint master_slave;
tx_rx : coverpoint tx_rx;
slave_addr: coverpoint slave_address {
bins low = {[7'h00 : 7'h20]};
bins mid = {[7'h21 : 7'h40]};
bins high = {[7'h41: 7'h7f]};
}
data_mode_cross : cross data_in, m_s, tx_rx;
endgroup : cg1
 
// Covergroup CG2. This covergroup generate fucntion coverage for all register read-write operations. Cross Coverage is written
// to check both read and write operation of all reigsters. Transaction Coverage is wrritten for write-write-read operations.
// This covergroup is sampled on every event of start_cov_reg.
covergroup cg2 @start_cov_reg;
register_addr : coverpoint reg_address {
bins prescale = {8'h02};
bins control = {8'h04};
bins timeout = {8'h0A};
bins address = {8'h0C};
bins data_tx = {8'h0E};
}
write_read : coverpoint wr_rd {
bins write = {1'b1};
bins read = {1'b0};
}
cross_reg_addr_wr : cross register_addr, write_read;
reset_test: coverpoint reset_bit {
bins reset = {1'b1};
}
prescale_txn : coverpoint wr_rd iff(reg_address == 8'h02) {
bins wr_wr_rd = ( 1 => 1 => 0);
}
control_txn : coverpoint wr_rd iff(reg_address == 8'h04) {
bins wr_wr_rd = ( 1'b1 => 1'b1 => 1'b0);
}
timeout_txn : coverpoint wr_rd iff(reg_address == 8'h0A) {
bins wr_wr_rd = ( 1'b1 => 1'b1 => 1'b0);
}
address_txn : coverpoint wr_rd iff(reg_address == 8'h0C) {
bins wr_wr_rd = ( 1'b1 => 1'b1 => 1'b0);
}
data_tx_txn : coverpoint wr_rd iff(reg_address == 8'h0E) {
bins wr_wr_rd = ( 1'b1 => 1'b1 => 1'b0);
}
txn: coverpoint reg_addr_txn {
bins pre = (9'h102 => 9'h102 => 9'h002);
bins con = (9'h104 => 9'h104 => 9'h004);
bins tim = (9'h10A => 9'h10A => 9'h00A);
bins add = (9'h10C => 9'h10C => 9'h00C);
bins dat = (9'h10E=> 9'h10E => 9'h00E);
}
endgroup
 
 
// Covergroup CG3. This Covergroup is used to check fucntion coverage of all protocol validation. Cross Coverage is written to check
// all protocol checks in every possible mode of operation. This Cover Group is sampled on every even of start_protocol_checks_cov.
covergroup cg3 @start_protocol_checks_cov;
start_bit : coverpoint start_bit {
bins sta = {1'b1};
}
stop_bit : coverpoint stop_bit {
bins sto = {1'b1};
}
slave_ack : coverpoint slave_ack {
bins sl_ac = {1'b1};
}
data_ack : coverpoint data_ack {
bins da_ac = {1'b1};
}
intr_ack : coverpoint intr_ack {
bins int_ac = {1'b1};
}
start_mode_cross : cross start_bit, master_slave, tx_rx;
stop_mode_corss : cross stop_bit, master_slave, tx_rx;
sack_mode_cross : cross slave_ack, master_slave, tx_rx;
dack_mode_cross : cross data_ack, master_slave, tx_rx;
inack_mode_cross : cross intr_ack, master_slave, tx_rx;
endgroup
 
 
// Class Constructor
function new(string name, string instance);
super.new("fifo_coverage_gen","COVERAGE_GEN");
cg1 = new;
cg2 = new;
cg3 = new;
endfunction
 
 
// This task will assign values of object's(cov_pkt) fields to local variables and then trigger the event start_cov to sample Covergroup CG1.
task pre_txn_start_cov (scoreboard_pkt cov_pkt);
this.cov_pkt = cov_pkt;
data_byte = cov_pkt.data_byte;
slave_address = cov_pkt.slave_address;
master_slave = cov_pkt.master_slave;
tx_rx = cov_pkt.tx_rx;
-> start_cov;
endtask
 
// This task will assign values of object's(reg_pkt) fields to local variables and then trigger the event start_cov_reg to sample Covergroup CG2.
task write_reg_cov (register_pkt reg_pkt);
this.reg_pkt = reg_pkt;
reg_address = reg_pkt.reg_address;
wr_rd = reg_pkt.wr_rd;
reset_bit = reg_pkt.reset_bit;
reg_addr_txn = {wr_rd,reg_address};
-> start_cov_reg;
endtask
 
// This task will assign values of object's(reg_pkt) fields to local variables and then trigger the event start_cov_reg to sample Covergroup CG2.
task read_reg_cov (register_pkt reg_pkt);
this.reg_pkt = reg_pkt;
reg_address = reg_pkt.reg_address;
wr_rd = reg_pkt.wr_rd;
reg_addr_txn = {wr_rd,reg_address};
-> start_cov_reg;
endtask
// This task will assign values of object's(mon_pkt) fields to local variables and then trigger the event start_protocol_checks_cov to
// sample Covergroup CG2.
task protocol_checks_cov (monitor_pkt mon_pkt);
this.mon_pkt = mon_pkt;
start_bit = mon_pkt.start_bit;
stop_bit = mon_pkt.stop_bit;
slave_ack = mon_pkt.slave_ack;
data_ack = mon_pkt.data_ack;
intr_ack = mon_pkt.intr_ack;
-> start_protocol_checks_cov;
endtask
 
endclass
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_driver.sv New file
0,0 → 1,734
//////////////////////////////////////////////////////////////////////////////////////////
// //
// Verification Engineer: Atish Jaiswal //
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. //
// //
// Description of the Source File: //
// This source code implements W/B M/S Driver. //
// Driver will be receiving Scenario packets from Stimulus gen and accordingly it //
// will drive W/B ports of interface to configure DUT in different modes. //
// In every mode of operation whenever DUT is configured in interupt mode, this driver //
// waits for posedge of interrupt and then write commands/data to internal reigster of //
// DUT. In normal mode where interrupt will not be generated, it keeps on checking //
// Status register of DUT and act accordingly. //
// //
// //
//////////////////////////////////////////////////////////////////////////////////////////
 
`include "vmm.sv"
 
class i2c_master_driver extends vmm_xactor;
vmm_log log = new("lOG", "MASTER_DRIVER");
virtual i2c_pin_if pif; // Virtual Interface
stimulus_packet_channel m_stim_req_chan; // Scenario Generator to Diver Channel
stimulus_packet stim_packet; // Stimulus Packet's Instance
stimulus_packet temp_stim_packet; // Stimulus Packet's Instance
stimulus_packet response_packet;
scoreboard_pkt sb_pkt; // Scoreboard Packet's instance for callback
register_pkt reg_pkt; // Register Packet's instance for callback
 
 
// Class Constructor
function new(string name, string instance, virtual i2c_pin_if pif, stimulus_packet_channel m_stim_req_chan = null);
super.new("driver","i2c_master_driver");
if(m_stim_req_chan == null) m_stim_req_chan = new("master_stimulus_packet_channel", "m_stim_req_chan");
this.m_stim_req_chan = m_stim_req_chan;
stim_packet = new;
temp_stim_packet = new;
response_packet = new;
sb_pkt = new;
reg_pkt = new;
this.pif = pif;
endfunction
 
 
/* task for initial setting */
task set_enable_signals;
pif.rst = 1'b1;
pif.clk = 1'b0;
pif.wb_stb_i = 1'b0;
pif.ack_o = 1'b0;
pif.wb_cyc_i = 1'b0;
#10 pif.rst = 1'b0;
#20 write_inf(1,8'h04, 8'hD0);
#40 write_inf(1,8'h04, 8'h00);
endtask
/* task for initial setting */
 
// Task to Enable core
task enable_core;
#20 write_inf(1,8'h04, 8'h80);
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'hD0;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
#40 write_inf(1,8'h04, 8'h00);
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'h00;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
endtask
// Task to reset Core. This task is called from ENV.
task set_reset;
pif.rst = 1'b1;
pif.clk = 1'b0;
pif.wb_stb_i = 1'b0;
pif.ack_o = 1'b0;
pif.wb_cyc_i = 1'b0;
repeat(2) @(posedge pif.clk);
pif.rst = 1'b0;
endtask
// Task to set TimeOut Register's Value
task set_timeout_reg;
#40 write_inf(1,8'h0A, 8'hff);
reg_pkt.reg_address = 8'h0A;
reg_pkt.data_byte = 8'hff;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
endtask
 
/* Write Task to write data and address on interface */
task write_inf;
input delay;
input [7:0] reg_addr;
input [7:0] reg_value;
integer delay;
begin
repeat(delay) @(posedge pif.clk)
#1;
pif.addr_in = reg_addr;
pif.data_in = reg_value;
pif.we = 1'b1;
pif.wb_stb_i = 1'b1;
pif.wb_cyc_i = 1'b1;
@(posedge pif.clk)
while (~pif.ack_o) @(posedge pif.clk)
#1;
pif.addr_in = {3{1'bx}};
pif.data_in = {8{1'bx}};
pif.we = 1'bx;
pif.wb_stb_i = 1'bx;
pif.wb_cyc_i = 1'b0;
end
endtask
 
// Task to Set Prescale Register's Value
task set_prescale_register;
#40 write_inf(1,8'h02, 8'h64);
reg_pkt.reg_address = 8'h02;
reg_pkt.data_byte = 8'h64;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
endtask
/* Read Task to read data from the design core through interface */
task read_inf;
input delay;
input [7:0] reg_addr;
output [7:0] reg_value;
integer delay;
repeat(delay) @(posedge pif.clk)
#1;
pif.addr_in = reg_addr;
pif.we = 1'b0;
pif.wb_stb_i = 1'b1;
pif.wb_cyc_i = 1'b1;
pif.data_in = {8{1'bx}};
 
@(posedge pif.clk)
while (~pif.ack_o) @(posedge pif.clk)
#1;
pif.wb_cyc_i = 1'b0;
pif.we = 1'bx;
pif.wb_stb_i = 1'bx;
pif.addr_in = {3{1'bx}};
pif.data_in = {8{1'bx}};
reg_value = pif.data_out;
endtask
 
 
// task process;
 
virtual protected task main();
super.main();
begin
stimulus_packet stim_packet;
int byte_count;
reg intr_check;
reg register_check;
reg register_write;
string s;
reg [7:0] status_reg;
reg [7:0] reg_data_register;
forever
begin
m_stim_req_chan.peek(stim_packet);
$cast(temp_stim_packet,stim_packet.copy());
`vmm_note(log, "***********Packet Received inside I2C_DRIVER from GENERATOR************");
temp_stim_packet.display();
byte_count = temp_stim_packet.byte_count;
register_write = temp_stim_packet.intr_en;
`vmm_callback(i2c_callback,send_pkt_to_monitor(temp_stim_packet)); // Sending packet to monitor
 
// Reset test-case. Driver will driver high on pif.rst to Reset DUT
// This will set reset_bit of reg_pkt and then invoke callback for scoreboad.
if(temp_stim_packet.reset_check) // reset check
begin
repeat (10)
begin
@(posedge pif.clk)
pif.rst = 1'b1;
end
@(posedge pif.clk)
pif.rst = 1'b0;
reg_pkt.reg_address = 8'h00;
reg_pkt.data_byte = 8'h00;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b1;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
m_stim_req_chan.get(stim_packet); // get(remove) the packet from channel
end // reset check
 
// Register Test-case. If register_write is 1, it will write internal register, set fields of reg_pkt and invoke callback.
// If register_write is 0, it will read value of internal register, set fields of reg_pkt and invoke callback for
// comparision of register datas in Scoreboard.
else if(temp_stim_packet.register_check) //Internal register read and write check
begin
if(register_write) // write
begin
write_inf(1,temp_stim_packet.register_addr,temp_stim_packet.register_data);
reg_pkt.reg_address = temp_stim_packet.register_addr;
reg_pkt.data_byte = temp_stim_packet.register_data;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
end
else //read
begin
read_inf(1,temp_stim_packet.register_addr,reg_data_register);
reg_pkt.reg_address = temp_stim_packet.register_addr;
reg_pkt.data_byte = reg_data_register;
reg_pkt.wr_rd = 1'b0;
`vmm_callback(i2c_callback,read_reg(reg_pkt));
end
m_stim_req_chan.get(stim_packet); // get (remove) packet from channel
end //Internal register read and write check
 
// Data Transfer test-case starts
else //Data Transfer check
begin
m_stim_req_chan.get(stim_packet); // get (remove) packet from channel
enable_core;
set_prescale_register;
set_timeout_reg;
 
// DUT (W/B Driver) is in Master Mode.
if(temp_stim_packet.master_slave) //Core in Master Mode
begin
// DUT (W/B Driver) in Master Mode and Transmitting data.
if(temp_stim_packet.tr == 1) // Writing data packets to slave device
begin
 
// DUT (W/B Driver) in Master/Transmiter and in Interrupt mode.
// Driver will configure DUT in given mode and then write data to Tx reg of DUT on each posedge of irq after slave acknowledgment.
// After transmission of last byte it will configure DUT to generate Stop Signal
if(temp_stim_packet.intr_en) // Interrupt Mode
begin
write_inf(1,8'h0E, {{temp_stim_packet.slave_address},{1'b0}}); // Slave Address + rd/wr bit
reg_pkt.reg_address = 8'h0E;
reg_pkt.data_byte = {{temp_stim_packet.slave_address},{1'b0}};
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
write_inf(1,8'h04, 8'h70); //Enable the core,set mode into interrupt and tx and generate Start
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'h70;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
while(byte_count != 0)
begin
@(posedge pif.irq)
begin
write_inf(1,8'h0E, temp_stim_packet.data_packet[byte_count-1]);
reg_pkt.reg_address = 8'h0E;
reg_pkt.data_byte = temp_stim_packet.data_packet[byte_count-1];
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
// vmm_callback
sb_pkt.master_slave = 1'b1;
sb_pkt.tx_rx = 1'b1;
sb_pkt.slave_address = temp_stim_packet.slave_address;
sb_pkt.data_byte = temp_stim_packet.data_packet[byte_count-1];
`vmm_callback(i2c_callback,pre_transaction(sb_pkt));
// vmm_callback
write_inf(1,8'h04, 8'h73);
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'h73;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
end
byte_count-- ;
end
read_inf(1,8'h08,status_reg);
while (!status_reg[7] && !status_reg[0])
begin
read_inf(1,8'h08,status_reg);
end
if(byte_count == 0 && status_reg[7])
write_inf(1,8'h04, 8'h01); // Generate Stop Command
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'h01;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
#1200; response_packet.tr = 1'b1;
end // Interrupt Mode
 
// DUT (W/B Driver) in Master/Transmiter and in Non-Interrupt mode.
//Driver will configure DUT in given mode,then it will keep on checking status register and wait for bit 7 of Status Register (TIP) to be set,
// After Slave Acknowledgment detection, it will write data to Transmit Register of DUT.
// After transmission of last byte it will configure DUT to generate Stop Signal
else // Non-Interrupt Mode
begin
write_inf(1,8'h0E, {{temp_stim_packet.slave_address},{1'b0}});
reg_pkt.reg_address = 8'h0E;
reg_pkt.data_byte = {{temp_stim_packet.slave_address},{1'b0}};
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
write_inf(1,8'h04, 8'h30); //Enable the core,set mode into non-interrupt and tx and generate Start
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'h30;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
while(byte_count != 0)
begin
read_inf(1,8'h08,status_reg);
while(!status_reg[7])
begin
read_inf(1,8'h08,status_reg);
end
write_inf(1,8'h0E, temp_stim_packet.data_packet[byte_count-1]);
reg_pkt.reg_address = 8'h0E;
reg_pkt.data_byte = temp_stim_packet.data_packet[byte_count-1];
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
read_inf(1,8'h08,status_reg);
while (!status_reg[7] && !status_reg[0])
begin
read_inf(1,8'h08,status_reg);
end
// vmm_callback
sb_pkt.master_slave = 1'b1;
sb_pkt.tx_rx = 1'b1;
sb_pkt.slave_address = temp_stim_packet.slave_address;
sb_pkt.data_byte = temp_stim_packet.data_packet[byte_count-1];
`vmm_callback(i2c_callback,pre_transaction(sb_pkt));
// vmm_callback
write_inf(1,8'h04, 8'h31);
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'h31;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
byte_count-- ;
read_inf(1,8'h08,status_reg);
while (!status_reg[7] && !status_reg[0])
begin
read_inf(1,8'h08,status_reg);
end
if(byte_count == 0 && status_reg[7])
write_inf(1,8'h04, 8'h01); // Generate Stop Signal
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'h01;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
end
#1200; response_packet.tr = 1'b1;
end // Non-Interrupt Mode
end
 
// DUT (W/B Driver) in Master/Receiver and in Interrupt mode.
// Driver will configure DUT in given mode and then After Slave Acknowledgment detection, it will read data from Receive Register on
// on every posedge of irq. After Reception of last byte it will configure DUT to generate Stop Signal
else // Reading Data Packets from Slave Address
begin
if(stim_packet.intr_en) // Interrupt Mode
begin
write_inf(1,8'h0E, {{temp_stim_packet.slave_address},{1'b1}});
reg_pkt.reg_address = 8'h0E;
reg_pkt.data_byte = {{temp_stim_packet.slave_address},{1'b1}};
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
write_inf(1,8'h04, 8'h63); //Enable the core,set mode into interrupt and tx and generate Start
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'h63;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
@(posedge pif.irq)
while(byte_count != 0)
begin
write_inf(1,8'h04, 8'h63);
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'h63;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
@(posedge pif.irq)
begin
read_inf(1,8'h00,status_reg);
// $display("In Driver - Received Data in interrupt mode is %b",status_reg);
// vmm_callback
sb_pkt.master_slave = 1'b1;
sb_pkt.tx_rx = 1'b1;
sb_pkt.slave_address = temp_stim_packet.slave_address;
sb_pkt.data_byte = status_reg;
`vmm_callback(i2c_callback,post_transaction(sb_pkt));
// vmm_callback
end
byte_count--;
end
read_inf(1,8'h08,status_reg);
while (!status_reg[7])
read_inf(1,8'h08,status_reg);
if(byte_count == 0)
write_inf(1,8'h04, 8'h43); //Generate Stop Signal
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'h43;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
#1200; response_packet.tr = 1'b1;
end
 
// DUT (W/B Driver) in Master/Receiver and in Non-Interrupt mode.
// Driver will configure DUT in given mode,then it will keep on checking status register and wait for bit 7 of Status Register (TIP) to be set,
// After Slave Acknowledgment detection, it will read data from Receive Register everytime TIP bit is set.
// After Reception of last byte it will configure DUT to generate Stop Signal
else // non-interrupt mode
begin
write_inf(1,8'h0E, {{temp_stim_packet.slave_address},{1'b1}});
reg_pkt.reg_address = 8'h0E;
reg_pkt.data_byte = {{temp_stim_packet.slave_address},{1'b1}};
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
write_inf(1,8'h04, 8'h20); //Enable the core,set mode into interrupt and tx and generate Start
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'h20;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
read_inf(1,8'h08,status_reg);
while(!status_reg[7])
read_inf(1,8'h08,status_reg);
while(byte_count != 0)
begin
write_inf(1,8'h04, 8'h21);
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'h21;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
read_inf(1,8'h08,status_reg);
while(!status_reg[7])
read_inf(1,8'h08,status_reg);
read_inf(1,8'h08,status_reg);
while (!status_reg[7] && !status_reg[0])
begin
read_inf(1,8'h08,status_reg);
end
read_inf(1,8'h00,status_reg);
// $display("In Driver - Received Data in non-interrupt mode is %b",status_reg);
// vmm_callback
sb_pkt.master_slave = 1'b1;
sb_pkt.tx_rx = 1'b1;
sb_pkt.slave_address = temp_stim_packet.slave_address;
sb_pkt.data_byte = status_reg;
`vmm_callback(i2c_callback,post_transaction(sb_pkt));
// vmm_callback
byte_count--;
read_inf(1,8'h08,status_reg);
while (!status_reg[7])
read_inf(1,8'h08,status_reg);
if(byte_count == 0 && status_reg[7] )
write_inf(1,8'h04, 8'h01); // Generate Stop signal
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'h01;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
end
#1200; response_packet.tr = 1'b1;
end
end
 
end
 
// DUT (W/B Driver) in Slave mode.
else // core in slave mode
begin
// DUT (W/B Driver) in Slave Mode and Transmitting data.
if(temp_stim_packet.tr == 1) // Core in Slave mode: Receiving
begin
 
// DUT (W/B Driver) in Slave/Receiver and in Interrupt mode.
// Driver will configure DUT in given mode, on posedge on irq it will again configure core to receive data and
// then it will read data from Receive Register on every posedge of irq.
if (temp_stim_packet.intr_en) // Interrupt Mode
begin
write_inf(1,8'h0C, {{temp_stim_packet.slave_address},{1'b1}}); // Slave Address + 1'b1 bit
reg_pkt.reg_address = 8'h0C;
reg_pkt.data_byte = {{temp_stim_packet.slave_address},{1'b1}};
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
write_inf(1,8'h04, 8'h40); //Enable the core,keep it in slave mode
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'h40;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
@(posedge pif.irq)
while(byte_count != 0)
begin
write_inf(1,8'h04, 8'h43);
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'h43;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
@(posedge pif.irq)
begin
read_inf(1,8'h00,status_reg);
// $display("In Driver - When core is in slave mode: Received Data in interrupt mode is %b",status_reg);
// vmm_callback
sb_pkt.master_slave = 1'b0;
sb_pkt.tx_rx = 1'b1;
sb_pkt.slave_address = temp_stim_packet.slave_address;
sb_pkt.data_byte = status_reg;
`vmm_callback(i2c_callback,post_transaction(sb_pkt));
// vmm_callback
end
byte_count--;
end
end
 
// DUT (W/B Driver) in Slave/Receiver and in Non-Interrupt mode.
// Driver will configure DUT in given mode, it will keep on waiting for tip bit (bit 7) of Status Register to be set.
// After first occurance of tip to be set it will again configure DUT core to receive data and then it will read data
// from Receive Register every time tip bit of Status Register is set.
else // Non-interrupt mode
begin
write_inf(1,8'h0C, {{temp_stim_packet.slave_address},{1'b1}}); // Slave Address + 1'b1 bit
reg_pkt.reg_address = 8'h0C;
reg_pkt.data_byte = {{temp_stim_packet.slave_address},{1'b1}};
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
write_inf(1,8'h04, 8'h00); //Enable the core,keep it in slave mode , non-interrupt mode
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'h00;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
read_inf(1,8'h08,status_reg);
while(!status_reg[7])
read_inf(1,8'h08,status_reg);
while(byte_count != 0)
begin
write_inf(1,8'h04, 8'h01);
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'h01;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
read_inf(1,8'h08,status_reg);
while(!status_reg[7])
read_inf(1,8'h08,status_reg);
read_inf(1,8'h08,status_reg);
while (!status_reg[7] && !status_reg[0])
begin
read_inf(1,8'h08,status_reg);
end
read_inf(1,8'h00,status_reg);
// $display("In Driver - When core is in slave mode: Received Data in non-interrupt mode is %b",status_reg);
// vmm_callback
sb_pkt.master_slave = 1'b0;
sb_pkt.tx_rx = 1'b1;
sb_pkt.slave_address = temp_stim_packet.slave_address;
sb_pkt.data_byte = status_reg;
`vmm_callback(i2c_callback,post_transaction(sb_pkt));
// vmm_callback
byte_count--;
read_inf(1,8'h08,status_reg);
while (!status_reg[7])
read_inf(1,8'h08,status_reg);
if(byte_count == 0 && status_reg[7] )
write_inf(1,8'h04, 8'h01);
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'h01;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
end
end
end
// DUT (W/B Driver) in Slave/Transmiter Mode.
else // Core in Slave Mode: Transmitting
begin
 
// DUT (W/B Driver) in Slave/Transmiter and in Interrupt mode.
// Driver will configure DUT in given mode and then it will write data to Transmit Register of DUT on every posedge of irq.
if (temp_stim_packet.intr_en) // Interrupt Mode
begin
write_inf(1,8'h0C, {{temp_stim_packet.slave_address},{1'b1}}); // Slave Address + 1'b1 bit
reg_pkt.reg_address = 8'h0C;
reg_pkt.data_byte = {{temp_stim_packet.slave_address},{1'b1}};
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
write_inf(1,8'h04, 8'h40); //Enable the core,keep it in slave mode , non-interrupt mode
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'h40;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
while(byte_count != 0)
begin
@(posedge pif.irq)
begin
write_inf(1,8'h0E, temp_stim_packet.data_packet[byte_count-1]);
reg_pkt.reg_address = 8'h0E;
reg_pkt.data_byte = temp_stim_packet.data_packet[byte_count-1];
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
write_inf(1,8'h04, 8'h43);
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'h43;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
// vmm_callback
sb_pkt.master_slave = 1'b0;
sb_pkt.tx_rx = 1'b0;
sb_pkt.slave_address = temp_stim_packet.slave_address;
sb_pkt.data_byte = temp_stim_packet.data_packet[byte_count-1];
`vmm_callback(i2c_callback,pre_transaction(sb_pkt));
// vmm_callback
end
byte_count-- ;
end
read_inf(1,8'h08,status_reg);
while (!status_reg[7])
read_inf(1,8'h08,status_reg);
if(byte_count == 0 && status_reg[7] )
begin
write_inf(1,8'h0E, 8'hFF);
reg_pkt.reg_address = 8'h0E;
reg_pkt.data_byte = 8'hFF;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
end
end
 
// DUT (W/B Driver) in Slave/Transmiter and in Non-Interrupt mode.
// Driver will configure DUT in given mode it will keep on waiting for tip bit (bit 7) of Status Register to be set
// and then it will write data to transmit register of DUT.
else // Non-Interrupt Mode
begin
write_inf(1,8'h0C, {{temp_stim_packet.slave_address},{1'b1}}); // Slave Address + 1'b1 bit
reg_pkt.reg_address = 8'h0C;
reg_pkt.data_byte = {{temp_stim_packet.slave_address},{1'b1}};
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
write_inf(1,8'h04, 8'h00); //Enable the core,keep it in slave mode , non-interrupt mode
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'h00;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
while(byte_count != 0)
begin
read_inf(1,8'h08,status_reg);
while(!status_reg[7])
begin
read_inf(1,8'h08,status_reg);
end
write_inf(1,8'h0E, temp_stim_packet.data_packet[byte_count-1]);
reg_pkt.reg_address = 8'h0E;
reg_pkt.data_byte = temp_stim_packet.data_packet[byte_count-1];
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
write_inf(1,8'h04, 8'h01);
reg_pkt.reg_address = 8'h04;
reg_pkt.data_byte = 8'h01;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
// vmm_callback
sb_pkt.master_slave = 1'b0;
sb_pkt.tx_rx = 1'b0;
sb_pkt.slave_address = temp_stim_packet.slave_address;
sb_pkt.data_byte = temp_stim_packet.data_packet[byte_count-1];
`vmm_callback(i2c_callback,pre_transaction(sb_pkt));
// vmm_callback
read_inf(1,8'h08,status_reg);
while (!status_reg[7] && !status_reg[0])
begin
read_inf(1,8'h08,status_reg);
end
//write_inf(1,8'h04, 8'h01);
byte_count-- ;
end
read_inf(1,8'h08,status_reg);
while (!status_reg[7] && !status_reg[0])
begin
read_inf(1,8'h08,status_reg);
end
if(byte_count == 0 && status_reg[7])
write_inf(1,8'h0E, 8'hFF);
reg_pkt.reg_address = 8'h0E;
reg_pkt.data_byte = 8'hFF;
reg_pkt.wr_rd = 1'b1;
reg_pkt.reset_bit = 1'b0;
`vmm_callback(i2c_callback,write_reg(reg_pkt));
#1200; response_packet.tr = 1'b1;
end
end
end
end
end
 
end
endtask
 
 
endclass : i2c_master_driver
 
 
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_reg_pkt.sv New file
0,0 → 1,44
//////////////////////////////////////////////////////////////////////////////////////////
// //
// Verification Engineer: Atish Jaiswal //
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. //
// //
// Description of the Source File: //
// This source code defines Register Packet. This packet will be used while running //
// Register Read-Write Testcases and this packet will be sent to Scoreboard from W/B //
// Master Driver to Scoreboard and Coverage Module. //
// //
// //
//////////////////////////////////////////////////////////////////////////////////////////
 
`include "vmm.sv"
 
class register_pkt extends vmm_data;
 
vmm_log log;
bit [7:0] reg_address;
bit [7:0] data_byte;
bit wr_rd;
bit reset_bit;
 
function new();
super.new(this.log);
this.log = new("Reg Data", "class");
endfunction
 
function vmm_data copy(vmm_data to = null);
copy = new this;
endfunction
 
 
function void display();
this.log.start_msg(vmm_log::NOTE_TYP);
void'(this.log.text($psprintf("slave_address is %b", this.reg_address)));
void'(this.log.text($psprintf("data_byte is %b", this.data_byte)));
void'(this.log.text($psprintf("write_read is %b", this.wr_rd)));
void'(this.log.text($psprintf("reset_bit is %b", this.reset_bit)));
this.log.end_msg();
endfunction
 
endclass
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_callback.sv New file
0,0 → 1,24
`include "vmm.sv"
 
class i2c_callback extends vmm_xactor_callbacks;
 
virtual task pre_transaction(scoreboard_pkt sb_pkt);
endtask
virtual task post_transaction(scoreboard_pkt sb_pkt);
endtask
virtual task write_reg(register_pkt reg_pkt);
endtask
virtual task read_reg(register_pkt reg_pkt);
endtask
 
virtual task send_pkt_to_monitor(stimulus_packet mon_stim_pkt);
endtask
virtual task protocol_checks_coverage(monitor_pkt mon_pkt);
endtask
 
endclass
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_data_packet.sv New file
0,0 → 1,41
//////////////////////////////////////////////////////////////////////////////////////////
// //
// Verification Engineer: Atish Jaiswal //
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. //
// //
// Description of the Source File: //
// This file is the data packet class for Scenario Generator. //
// The Packet Randomizes data_pkt whose size will be assigned in Scenario Generator. //
// //
// //
//////////////////////////////////////////////////////////////////////////////////////////
 
`include "vmm.sv"
 
class i2c_data_packet extends vmm_data;
vmm_log log;
rand bit [7:0] data_pkt[]; // data packets to be transfered
 
function new();
super.new(this.log);
this.log = new("Data_packet", "class");
endfunction
 
function void display();
int i;
this.log.start_msg(vmm_log::NOTE_TYP);
while( i < data_pkt.size)
begin
void'(this.log.text($psprintf("Data_Byte[%0d] is %b", i, this.data_pkt[i])));
i++;
end
this.log.end_msg();
endfunction
 
 
function vmm_data copy(vmm_data to = null);
copy = new this;
endfunction
 
endclass : i2c_data_packet
 
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_interface.sv New file
0,0 → 1,107
//////////////////////////////////////////////////////////////////////////////////////////
// //
// Verification Engineer: Atish Jaiswal //
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. //
// //
// Description of the Source File: //
// This source code is used to declare interface. //
// //
// //
//////////////////////////////////////////////////////////////////////////////////////////
 
 
interface i2c_pin_if();
 
reg clk; // System_clk
logic rst; // Reset
logic [7:0] addr_in; // W/B Address Input lines
logic [7:0] data_in; // W/B Data Input lines
wire [7:0] data_out; // W/B Data Output lines
logic wb_stb_i; // W/B Strobe
logic wb_cyc_i; // W/B Cycle valid
logic we; // W/B Write Enable
wire trans_comp; // Transacation Complete
logic ack_o; // W/B Acknowledgment
wire irq; // Interrupt from DUT
logic scl_o; // SCL O/P
reg scl_oe; // SCL O/P Enable
wire scl; // SCL I/P
logic sda_o; // SDL O/P
logic sda_oe; // SDA O/P Enable
wire sda; // SDA I/P
 
 
modport dut_mp (
input clk,
input rst,
input addr_in,
input data_in,
output data_out,
input wb_stb_i,
input wb_cyc_i,
input we,
output ack_o,
output trans_comp,
output irq,
output scl ,
output scl_o,
output scl_oe,
output sda_o,
output sda_oe,
output sda
);
 
 
modport driver_mp (
input clk,
input rst,
input addr_in,
input data_in,
output data_out,
input wb_stb_i,
input wb_cyc_i,
input we,
output trans_comp,
output ack_o,
output irq,
output scl ,
output scl_o,
output scl_oe,
output sda_o,
output sda_oe,
output sda
);
 
 
modport monitor_mp (
input clk,
input rst,
input addr_in,
input data_in,
input data_out,
input wb_stb_i,
input wb_cyc_i,
input we,
input ack_o,
input trans_comp,
input irq,
input scl ,
input sda ,
input scl_o,
input scl_oe,
input sda_o,
input sda_oe
);
 
modport slave_mp (
output scl ,
output sda ,
output scl_o ,
output scl_oe,
output sda_o ,
output sda_oe
);
 
endinterface : i2c_pin_if
 
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_top.sv New file
0,0 → 1,61
//////////////////////////////////////////////////////////////////////////////////////////
// //
// Verification Engineer: Atish Jaiswal //
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. //
// //
// Description of the Source File: //
// This source code implements I2C M/S Core's Top Module. //
// Top Module instantiates program block and DUT and connects them with each other. //
// sda and scl lines are anded with scl and sda lines from both sides (DUT as well as //
// Environment). Both sda and scl lines are pulled up by verilog pullup construct. //
// //
//////////////////////////////////////////////////////////////////////////////////////////
 
`include "vmm_clkgen.sv"
`include "vmm_program_test.sv"
 
 
module top;
 
i2c_pin_if pif(); // Interface
clkgen c_gen(pif); // Clock Generator
program_test p_test(pif); // Program Block
 
wire dut_sda_o;
wire dut_sda_oe;
wire dut_sda_in;
wire dut_scl_o;
wire dut_scl_oe;
wire dut_scl_in;
wire temp_sda;
wire temp_scl;
assign dut_sda_o = 1'b0;
assign temp_sda = pif.sda_oe & dut_sda_oe;
assign temp_scl = pif.scl_oe & dut_scl_oe;
assign pif.sda = temp_sda ? 1'bz : 1'b0;
assign pif.scl = temp_scl ? 1'bz : 1'b0;
pullup p1_if(pif.sda); // Pull up sda line
pullup p2_if(pif.scl); // Pull up scl line
 
// I2C Core (DUT)
block i2c_core( .scl_in(pif.scl),
.scl_o(dut_scl_o),
.scl_oe(dut_scl_oe),
.sda_in(pif.sda),
.sda_o(dut_sda_o),
.sda_oe(dut_sda_oe),
.wb_add_i(pif.addr_in),
.wb_data_i(pif.data_in),
.wb_data_o(pif.data_out),
.wb_stb_i(pif.wb_stb_i),
.wb_cyc_i(pif.wb_cyc_i),
.wb_we_i(pif.we),
.wb_ack_o(pif.ack_o),
.irq(pif.irq),
.trans_comp(pif.trans_comp),
.wb_clk_i(pif.clk),
.wb_rst_i(pif.rst)
);
 
endmodule
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/sb_callback.sv New file
0,0 → 1,72
//////////////////////////////////////////////////////////////////////////////////////////
// //
// Verification Engineer: Atish Jaiswal //
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. //
// //
// Description of the Source File: //
// This source code implements all callback function defined in faced class named //
// vmm_i2c_callback. All callback functions invoke another function/task in Scoreboard //
// and Coverage Collector Module. //
// //
//////////////////////////////////////////////////////////////////////////////////////////
 
 
`include "vmm.sv"
`include "vmm_i2c_scoreboard.sv"
`include "vmm_i2c_coverage.sv"
`include "vmm_i2c_callback.sv"
`include "vmm_i2c_monitor.sv"
 
class sb_callback extends i2c_callback;
 
vmm_log log = new("scorebd_cb","CALLBACK");
scoreboard_pkt sb_pkt; // Scoreboard Packet
register_pkt reg_pkt; // Register Packet
stimulus_packet mon_stim_pkt; // Stimulus Packet
monitor_pkt mon_pkt; // Monitor Packet
i2c_scoreboard i2c_sb; // Scoreboard's Instance
i2c_coverage i2c_cov; // Coverage Instance
i2c_monitor i2c_mon; // Monitor's Instance
 
function new(i2c_scoreboard i2c_sb, i2c_coverage i2c_cov, i2c_monitor i2c_mon);
this.i2c_sb = i2c_sb;
this.i2c_cov = i2c_cov;
this.i2c_mon = i2c_mon;
endfunction
 
 
// This task invoke pre_txn_push task in Scoreboard and pre_txn_start_cov task in Coverage module and send sb_pkt as a formal argument.
virtual task pre_transaction(scoreboard_pkt sb_pkt);
this.i2c_sb.pre_txn_push(sb_pkt);
this.i2c_cov.pre_txn_start_cov(sb_pkt);
endtask
// This task invoke post_txn_push task in Scoreboard and send sb_pkt as a formal argument.
virtual task post_transaction(scoreboard_pkt sb_pkt);
this.i2c_sb.post_txn_push(sb_pkt);
endtask
// This task invoke write_reg task in Scoreboard and write_reg_cov task in Coverage module and send reg_pkt as a formal argument.
virtual task write_reg(register_pkt reg_pkt);
this.i2c_sb.write_reg(reg_pkt);
this.i2c_cov.write_reg_cov(reg_pkt);
endtask
// This task invoke read_reg task in Scoreboard and read_reg_cov task in Coverage module and send reg_pkt as a formal argument.
virtual task read_reg(register_pkt reg_pkt);
this.i2c_sb.read_reg(reg_pkt);
this.i2c_cov.read_reg_cov(reg_pkt);
endtask
 
// This task invoke get_packet_from_driver task in Monitor and send mon_stim_pkt as a formal argument.
virtual task send_pkt_to_monitor(stimulus_packet mon_stim_pkt);
this.i2c_mon.get_packet_from_driver(mon_stim_pkt);
endtask
 
// This task invoke protocol_checks_cov task in Coverage Module and send mon_pkt as a formal argument.
virtual task protocol_checks_coverage(monitor_pkt mon_pkt);
this.i2c_cov.protocol_checks_cov(mon_pkt);
endtask
 
endclass
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_clkgen.sv New file
0,0 → 1,21
//////////////////////////////////////////////////////////////////////////////////////////
// //
// Verification Engineer: Atish Jaiswal //
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. //
// //
// Description of the Source File: //
// This source code generates clock for the interface. //
// //
//////////////////////////////////////////////////////////////////////////////////////////
 
module clkgen(i2c_pin_if i);
 
initial begin
forever begin
#5 i.clk = 1;
#5 i.clk = 0;
end
end
 
endmodule
 
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_mon_pkt.sv New file
0,0 → 1,46
//////////////////////////////////////////////////////////////////////////////////////////
// //
// Verification Engineer: Atish Jaiswal //
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. //
// //
// Description of the Source File: //
// This source code defines Monitor Packet. This packet will be sent to Scoreboard and //
// Coverage Module from Monitor Transactor. //
// //
// //
//////////////////////////////////////////////////////////////////////////////////////////
 
`include "vmm.sv"
 
class monitor_pkt extends vmm_data;
 
vmm_log log;
bit start_bit; // Start bit
bit stop_bit; // Stop bit
bit slave_ack; // Slave Acknowledgment
bit data_ack; // Data Acknowledgment
bit intr_ack; // Interrupt Generation Acknowledgment
 
// Class Constructor
function new();
super.new(this.log);
this.log = new("Monitor Data", "class");
endfunction
 
function vmm_data copy(vmm_data to = null);
copy = new this;
endfunction
 
// Display Function
function void display();
this.log.start_msg(vmm_log::NOTE_TYP);
void'(this.log.text($psprintf("start_bit is %0b", this.start_bit)));
void'(this.log.text($psprintf("stop_bit is %0b", this.stop_bit)));
void'(this.log.text($psprintf("slave_ack is %b", this.slave_ack)));
void'(this.log.text($psprintf("data_ack is %b", this.data_ack)));
void'(this.log.text($psprintf("intr_ack is %b", this.intr_ack)));
this.log.end_msg();
endfunction
 
endclass
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_scenario_generator.sv New file
0,0 → 1,132
//////////////////////////////////////////////////////////////////////////////////////////
// //
// Verification Engineer: Atish Jaiswal //
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. //
// //
// Description of the Source File: //
// This source code implements Scenario Generator. Please note that this Scenario //
// Generator is coded and its different than the one getting created by using macro //
// `vmm_scenario_gen(defined in VMM). //
// //
// If type of test-case to be run is given in command line(rand_gen=0) and other //
// variable are assgined then it will use those values and then randomize only stimlus //
// packet and data packet and then stimulus packet will be sent to both drivers. //
// //
// When type of test-case to be run is not given in command line (rand_gen=1) then it //
// will randomize Scenario Packet first to find out what kind of test-case it to be run//
// Accordingly it will randomized stimulus and data_pkt and then Stimulus packet will //
// be sent to both drivers. //
// //
//////////////////////////////////////////////////////////////////////////////////////////
 
`include "vmm.sv"
class i2c_scenario_generator extends vmm_xactor;
 
vmm_log log = new("lOG", "GENERATOR");
 
scenario_packet sc_packet; // Scenario Packet
stimulus_packet stim_packet; // Stimulus Packet
i2c_data_packet d_pkt; // Data Packet
stimulus_packet_channel m_req_chan; // Scenario_Gen to W/B Driver
stimulus_packet_channel s_req_chan; // Scenario_Gen to I2C Master/Slave Driver
int stop_after_n_inst;
static int DONE; // Done to check whether all scenarios have been sent
bit rand_gen = 1'b0;
integer transaction_count;
bit master_slave;
bit register_check;
bit reset_check;
bit tx_rx;
function new( string name, string instance_name, stimulus_packet_channel m_req_chan = null, stimulus_packet_channel s_req_chan = null);
super.new("scenario_generator ", "scenario_generator");
if(m_req_chan == null) m_req_chan = new("master_stimulus_packet_channel", "m_req_chan");
this.m_req_chan = m_req_chan;
if(s_req_chan == null) s_req_chan = new("slave_stimulus_packet_channel", "s_req_chan");
this.s_req_chan = s_req_chan;
this.DONE = this.notify.configure(1,vmm_notify::ON_OFF);
sc_packet = new;
stim_packet = new;
d_pkt = new;
$value$plusargs("rand_gen=%b",rand_gen); // Gets value of read_gen from Command line
$value$plusargs("master_slave=%b",master_slave); // Gets value of master_slave from Command line
$value$plusargs("register_check=%b",register_check); // Gets value of register_check bit from Command line
$value$plusargs("reset_check=%b",reset_check); // Gets vlaue of reset_check bit from Command line
$value$plusargs("tx_rx=%b",tx_rx); // Gets value of tx_rx from Command line
endfunction
 
 
 
virtual protected task main();
super.main();
begin
string str;
stimulus_packet m_response;
stimulus_packet s_response;
`vmm_note(log,"I2C Scenario from Scenario generator");
 
while (transaction_count != 0)
begin
if(!rand_gen) // If type of test-cases to run is assigned in command line
begin
sc_packet.master_slave = master_slave;
sc_packet.transaction_count = transaction_count;
sc_packet.register_check = register_check;
sc_packet.tx_rx = tx_rx;
end
else // If type of test-cases to run is to be randomized.
begin
if(sc_packet.randomize()); else `vmm_error(log, "I2C Scenario Generator : Randomization of I2C Scenario Packet Packet Failed");
master_slave = sc_packet.master_slave;
sc_packet.transaction_count = transaction_count;
register_check = sc_packet.register_check;
reset_check = sc_packet.reset_check;
tx_rx = sc_packet.tx_rx;
end
sc_packet.display();
`vmm_note(log, $psprintf("Scenario Generator: packet to Driver @ %t", $time));
 
// If register read_write testcase are to be run, it will randomize stimulus packet for register data and addres and read/write operation.
// Other fields of stimulus packet will be assigned here only.
if(register_check) // Register test-case to be run
begin
stim_packet.master_slave = master_slave;
stim_packet.tr = tx_rx;
stim_packet.register_check = register_check;
stim_packet.reset_check = reset_check;
if(stim_packet.randomize()); else `vmm_error(log, "I2C Master Stimulus: Randomization of I2C Stimulus Packet Failed");
stim_packet.display();
this.m_req_chan.put(stim_packet); // sending packet to master driver
this.s_req_chan.put(stim_packet); // sending packet to slave driver
end
 
// If data transacation test-caser are to be run, it will stimulus packet, get the size of data_bytes(no of bytes) and again randomized
// data_pkt class for data_bytes. All fields of stimulus packet wil be assigned here and then sent to both dirvers.
 
else // Data Transacation test-case to be run
begin
stim_packet.master_slave = master_slave;
stim_packet.tr = tx_rx;
stim_packet.register_check = register_check;
stim_packet.reset_check = reset_check;
if(stim_packet.randomize()); else `vmm_error(log, "I2C Master Stimulus: Randomization of I2C Stimulus Packet Failed");
d_pkt.data_pkt = new[stim_packet.byte_count];
if(d_pkt.randomize()); else `vmm_error(log, "I2C Master Stimulus: Randomization of I2C Data Packet Failed");
stim_packet.data_packet = d_pkt.data_pkt;
stim_packet.display();
d_pkt.display();
this.m_req_chan.put(stim_packet); // sending packet to master driver
this.s_req_chan.put(stim_packet); // sending packet to slave driver
end
transaction_count--;
end
notify.indicate(DONE); // Indicate Enviorment that all scenarios have been sent to drivers.
end
endtask
 
 
endclass
 
 
/i2c_master_slave_core/trunk/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_program_test.sv New file
0,0 → 1,24
//////////////////////////////////////////////////////////////////////////////////////////
// //
// Verification Engineer: Atish Jaiswal //
// Company Name : TooMuch Semiconductor Solutions Pvt Ltd. //
// //
// Description of the Source File: //
// This source code implements I2C M/S Core's Program Block. //
// This Program Block instantiate i2c_env and run the main thread of environment. //
// //
// //
//////////////////////////////////////////////////////////////////////////////////////////
`include "vmm_i2c_env.sv"
 
program program_test(i2c_pin_if pif);
 
initial begin
i2c_env env;
env = new(pif);
env.run();
end
 
endprogram
 
 
i2c_master_slave_core/trunk Property changes : Added: svn:mergeinfo
i2c_master_slave_core/web_uploads Property changes : Added: svn:mergeinfo
i2c_master_slave_core/branches Property changes : Added: svn:mergeinfo
/i2c_master_slave_core/tags/t1/i2c_master_slave_core/doc/i2c_spec.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
i2c_master_slave_core/tags/t1/i2c_master_slave_core/doc/i2c_spec.pdf Property changes : Added: svn:mime-type + application/octet-stream
/i2c_master_slave_core/tags/t1/i2c_master_slave_core/doc/i2c_spec.doc Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
i2c_master_slave_core/tags/t1/i2c_master_slave_core/doc/i2c_spec.doc Property changes : Added: svn:mime-type + application/octet-stream
/i2c_master_slave_core/tags/t1/i2c_master_slave_core/verilog/rtl/shift.v New file
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
 
/i2c_master_slave_core/tags/t1/i2c_master_slave_core/verilog/rtl/counter.v New file
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
/i2c_master_slave_core/tags/t1/i2c_master_slave_core/verilog/rtl/controller_interface.v New file
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
 
 
 
 
 
/i2c_master_slave_core/tags/t1/i2c_master_slave_core/verilog/rtl/i2c_blk.v New file
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
 
/i2c_master_slave_core/tags/t1/i2c_master_slave_core/verilog/rtl/ms_core.v New file
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;