URL
https://opencores.org/ocsvn/i2c_master_slave_core/i2c_master_slave_core/trunk
Subversion Repositories i2c_master_slave_core
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 4 to Rev 5
- ↔ Reverse comparison
Rev 4 → Rev 5
/tags/t2/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
tags/t2/i2c_master_slave_core/i2c_master_slave_core/doc/i2c_spec.pdf
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: tags/t2/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
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/doc/i2c_core_verification_plan.pdf
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/doc/i2c_core_verification_plan.pdf (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/doc/i2c_core_verification_plan.pdf (revision 5)
tags/t2/i2c_master_slave_core/i2c_master_slave_core/doc/i2c_core_verification_plan.pdf
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: tags/t2/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
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/doc/i2c_spec.doc
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/doc/i2c_spec.doc (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/doc/i2c_spec.doc (revision 5)
tags/t2/i2c_master_slave_core/i2c_master_slave_core/doc/i2c_spec.doc
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/shift.v
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/shift.v (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/shift.v (revision 5)
@@ -0,0 +1,52 @@
+////////////////////////////Shift.v/////////////////////////////////////////////////////////////////////
+// //
+//Design Engineer: Ravi Gupta //
+//Company Name : Toomuch Semiconductor
+//Email : ravi1.gupta@toomuchsemi.com //
+// //
+//Purpose : Used for shifting address and data in both transmit and recieve mode //
+//created : 22-11-07 //
+// //
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/*// synopsys translate_off
+`include "oc8051_timescale.v"
+// synopsys translate_on
+
+`include "oc8051_defines.v"*/
+
+
+module shift(clk,asyn_rst,load,shift_en,serial_in,data_in,serial_out,data_out);
+
+input clk,asyn_rst,load,shift_en,serial_in;
+input [7:0]data_in;
+
+output serial_out;
+output [7:0]data_out;
+
+reg [7:0]data;
+
+always@(posedge clk or posedge asyn_rst or posedge load)
+begin
+ if(asyn_rst)
+ data<=8'h0; //clear the data register upon asynchronous reset.
+
+ else if(load)
+ data<=data_in; //Load the internal register upon insertion of load bit.
+
+ else if(shift_en)
+ data<={data[6:0],serial_in}; //Upon shift_en high every time a new serial data is coming to LSB bit and data will be shifted
+ //to one bit.
+ else
+ data<=data; //Prevent formation of latches
+end
+
+
+assign data_out = data; //Output the data in a data_register
+assign serial_out = data[7]; //MSB is transmitted first in I2C protocol.
+
+
+endmodule
+
+//change loading into asynchronous mode
+
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/counter.v
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/counter.v (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/counter.v (revision 5)
@@ -0,0 +1,41 @@
+//////////////////////////counter.v///////////////////////////////////////////////////////////////////////////////
+ //
+//Designed Engineer: Ravi Gupta //
+//Company Name : Toomuch Semiconductor
+//Email : ravi1.gupta@toomuchsemi.com //
+ //
+//Purpose : Used for counting clock pulses for prescale register and number of bytes transferred //
+//Created : 22-11-07 //
+ //
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/*// synopsys translate_off
+`include "oc8051_timescale.v"
+// synopsys translate_on
+
+`include "oc8051_defines.v"*/
+
+
+module counter (clk,asyn_rst,enable,load,data_in,out);
+
+input clk,asyn_rst,enable,load;
+input [7:0] data_in;
+output [7:0] out;
+
+reg [7:0]data;
+
+always@(posedge clk or posedge asyn_rst)
+begin
+ if(asyn_rst)
+ data<=8'h0; //clear all bits upon asynchronous reset.
+ else if(load)
+ data<=data_in; //load the counter with incoming data if load signal is high
+ else if(enable)
+ data<=data + 1'b1; //Increment the counter if enable bit is high
+ else
+ data<=data; //else hold the data;else part is mention to avoid latch formation
+end
+
+assign out=data;
+
+endmodule
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/controller_interface.v
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/controller_interface.v (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/controller_interface.v (revision 5)
@@ -0,0 +1,546 @@
+////////////////////////////////////////////controller_interface.v////////////////////////////////////////
+// //
+//Design Engineer: Ravi Gupta //
+//Company Name : Toomuch Semiconductor
+//Email : ravi1.gupta@toomuchsemi.com //
+// //
+//Purpose : This core will be used as an interface between I2C core and Processor //
+//Created : 6-12-2007 //
+// //
+// //
+// //
+// //
+// //
+// //
+// //
+// //
+//Modification : Change the control register,added halt reset and inter_rst in control register
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/*// synopsys translate_off
+`include "oc8051_timescale.v"
+// synopsys translate_on
+
+`include "oc8051_defines.v"*/
+
+
+module processor_interface (clk,rst,add_bus,data_in,data_out,as,ds,rw,bus_busy,byte_trans,slave_addressed,arb_lost,slave_rw,inter,ack_rec,
+ core_en,inter_en,mode,master_rw,ack,rep_start,data,i2c_data,slave_add,time_out_reg,prescale,irq,time_out,inter_rst,halt,data_en,time_rst);
+input clk; //System clock
+input rst; //system reset
+
+//signals connecting core to processor
+/////////////////////////////////////
+
+input [7:0]add_bus; //contains address of internal register
+input [7:0]data_in; //trnasport the data for i2c core
+input as; //asserted high indicates vallid address has been placed on the address bus
+input ds; //asserted high indicates valid data on data bus
+input rw; //"1" indicates that processor has to write else read
+output irq; //interrupt to processor
+output inter_rst; //this bit will be written by processor when it will clear the interrupt.
+output [7:0]data_out;
+output halt;
+output data_en;
+input time_rst;
+
+//signals from core to reflect te status of core and buses
+///////////////////////////////////////////////////////////
+
+input bus_busy; //signal from core indicates bus is busy
+input byte_trans; //signal from core indicates byte transfer is in progress
+input slave_addressed; //signal from core indicares core has been identified as slave
+input arb_lost; //signal from core indicates bus error
+input slave_rw; //signal from core indicates operation of slave core
+input inter; //signal from core.this will interrupt the processor if this bit as well as interrupt enable is high
+input ack_rec; //signal from core to reflect the status of ack bit
+input time_out;
+
+//bits of control register
+//////////////////////////
+
+inout core_en; //this bit must be cleared before any other bit of control register have any effect on core
+inout inter_en; //To intrrupt the core this bit must be set when interrupt is pending
+inout mode; //Transaction from "0" to "1" directes core to act as master else slave
+inout master_rw; //set directiion for master either to transmit or receive
+inout ack; //value of acknowledgment bit to be transmitted on SDA line during ack cycle
+inout rep_start; //set this bit if processor wants a repeated start
+
+//data register
+////////////////
+
+inout [7:0]prescale; //contains the value for generating SCL frequency
+inout [7:0]time_out_reg; //contains the value for maximum low period for scl
+inout [7:0]slave_add; //this is the programmble slave address
+inout [7:0]data; //data for i2c core
+input [7:0]i2c_data; //data from core for processor
+
+//defining registers addresses
+/////////////////////////////
+
+`define PRER 8'b0000_0010
+`define CTR 8'b0000_0100
+`define SR 8'b0000_1000
+`define TO 8'b0000_1010
+`define ADDR 8'b0000_1100
+`define DR 8'b0000_1110
+`define RR 8'b0000_0000
+
+/*//defing the machine state
+//////////////////////////
+
+parameter processor_idle=2'b00;
+parameter processor_address=2'b01;
+parameter processor_data=2'b10;
+parameter processor_ack=2'b11;*/
+
+//Definig internal registers and wires
+/////////////////////////////////////
+
+wire core_en,inter_en,mode,master_rw,ack,rep_start,inter_rst,halt;
+wire prescale_reg_en;
+wire ctr_reg_en;
+wire sr_reg_en;
+wire to_reg_en;
+wire addr_reg_en;
+wire dr_reg_en;
+reg [7:0]data_out,sr_reg,ctr_reg,dr_reg,rr_reg;
+wire [7:0]data_in; //if address on add_bus matches with register address then set this high.
+wire data_ie; //this is signal used for enaling the data line in read or write cycle.
+wire as_d; //delay version of address strobe signal for detection of rising and falling edge
+reg as_delay_sig; //same signal.
+wire ds_d; //delayed version of data strobe.
+wire decode;
+wire rr_reg_en;
+
+reg ds_delay_sig;
+
+reg prescale_reg_en_sig;
+assign prescale_reg_en = prescale_reg_en_sig;
+
+reg ctr_reg_en_sig;
+assign ctr_reg_en = ctr_reg_en_sig;
+
+reg sr_reg_en_sig;
+assign sr_reg_en = sr_reg_en_sig;
+
+reg to_reg_en_sig;
+assign to_reg_en = to_reg_en_sig;
+
+reg addr_reg_en_sig;
+assign addr_reg_en = addr_reg_en_sig;
+
+reg dr_reg_en_sig;
+assign dr_reg_en = dr_reg_en_sig;
+
+reg as_d_sig;
+assign as_d = as_d_sig;
+
+reg ds_d_sig;
+assign ds_d = ds_d_sig;
+
+reg data_ie_sig;
+assign data_ie = data_ie_sig;
+
+//reg core_en_sig;
+//assign core_en = core_en_sig;
+
+//reg inter_en_sig;
+//assign inter_en = inter_en_sig;
+
+//reg mode_sig;
+//assign mode = mode_sig;
+
+//reg master_rw_sig;
+//assign master_rw = master_rw_sig;
+
+//reg ack_sig;
+//assign ack = ack_sig;
+
+//reg rep_start_sig;
+//assign rep_start = rep_start_sig;
+
+reg [7:0]data_sig;
+assign data = dr_reg;
+
+reg [7:0]prescale_sig;
+assign prescale = prescale_sig;
+
+reg [7:0]time_out_sig;
+assign time_out_reg = time_out_sig;
+
+reg [7:0]slave_add_sig;
+assign slave_add = slave_add_sig;
+
+//reg [7:0]data_out_sig;
+//assign data_out = data_out_sig;
+
+reg decode_sig;
+assign decode = decode_sig;
+
+//reg inter_rst_sig;
+//assign inter_rst = inter_rst_sig;
+
+//reg halt_sig;
+//assign halt = halt_sig;
+assign data_en = dr_reg_en_sig;
+
+reg rr_reg_en_sig;
+assign rr_reg_en = rr_reg_en_sig;
+
+
+
+assign core_en = ctr_reg [7];
+assign inter_en = ctr_reg [6];
+assign mode = ctr_reg [5];
+assign master_rw = ctr_reg [4];
+assign ack = ctr_reg [3];
+assign rep_start = ctr_reg [2];
+assign inter_rst = ctr_reg [1];
+assign halt = ctr_reg [0];
+
+
+
+
+
+
+//generating delayed version of inputs for detection of rising and falling edge.
+//////////////////////////////////////////////////////////////////////////////
+
+always@(posedge clk or posedge rst)
+begin
+
+if(rst)
+begin
+ as_delay_sig<=1'b0;
+ as_d_sig<=1'b0;
+ ds_delay_sig<=1'b0;
+ ds_d_sig<=1'b0;
+end
+
+else
+begin
+ as_delay_sig<=as;
+ as_d_sig<=as_delay_sig;
+ ds_delay_sig<=ds;
+ ds_d_sig<=ds_delay_sig;
+end
+end
+
+always@(posedge clk or posedge rst)
+begin
+ if(rst)
+ decode_sig<=1'b0;
+ else if(!as_d && as)
+ decode_sig<=1'b1;
+ //else
+ //decode_sig<=1'b0;
+end
+
+//address decoding logic
+///////////////////////
+
+//always@(posedge clk or posedge rst)
+always@(rst or as or add_bus or posedge time_rst)
+begin
+
+if(rst || time_rst)
+begin
+prescale_reg_en_sig<=1'b0;
+ctr_reg_en_sig<=1'b0;
+sr_reg_en_sig<=1'b0;
+to_reg_en_sig<=1'b0;
+addr_reg_en_sig<=1'b0;
+dr_reg_en_sig<=1'b0;
+rr_reg_en_sig <= 1'b0;
+
+//add_match_sig<=1'b0;
+end
+
+
+
+else if(as)
+begin
+ if(add_bus == `PRER)
+ begin
+ rr_reg_en_sig <= 1'b0;
+ prescale_reg_en_sig<=1'b1;
+ ctr_reg_en_sig<=1'b0;
+ sr_reg_en_sig<=1'b0;
+ to_reg_en_sig<=1'b0;
+ addr_reg_en_sig<=1'b0;
+ dr_reg_en_sig<=1'b0;
+ //add_match_sig<=1'b1;
+ end
+
+ else if(add_bus == `CTR)
+ begin
+ rr_reg_en_sig <= 1'b0;
+ prescale_reg_en_sig<=1'b0;
+ ctr_reg_en_sig<=1'b1;
+ sr_reg_en_sig<=1'b0;
+ to_reg_en_sig<=1'b0;
+ addr_reg_en_sig<=1'b0;
+ dr_reg_en_sig<=1'b0;
+ //add_match_sig<=1'b1;
+ end
+
+ else if(add_bus == `SR)
+ begin
+ rr_reg_en_sig <= 1'b0;
+ prescale_reg_en_sig<=1'b0;
+ ctr_reg_en_sig<=1'b0;
+ sr_reg_en_sig<=1'b1;
+ to_reg_en_sig<=1'b0;
+ addr_reg_en_sig<=1'b0;
+ dr_reg_en_sig<=1'b0;
+ //add_match_sig<=1'b1;
+ end
+
+ else if(add_bus == `TO)
+ begin
+ rr_reg_en_sig <= 1'b0;
+ prescale_reg_en_sig<=1'b0;
+ ctr_reg_en_sig<=1'b0;
+ sr_reg_en_sig<=1'b0;
+ to_reg_en_sig<=1'b1;
+ addr_reg_en_sig<=1'b0;
+ dr_reg_en_sig<=1'b0;
+ //add_match_sig<=1'b1;
+ end
+
+ else if(add_bus == `ADDR)
+ begin
+ rr_reg_en_sig <= 1'b0;
+ prescale_reg_en_sig<=1'b0;
+ ctr_reg_en_sig<=1'b0;
+ sr_reg_en_sig<=1'b0;
+ to_reg_en_sig<=1'b0;
+ addr_reg_en_sig<=1'b1;
+ dr_reg_en_sig<=1'b0;
+ //add_match_sig<=1'b1;
+ end
+
+ else if(add_bus == `DR)
+ begin
+
+ prescale_reg_en_sig<=1'b0;
+ ctr_reg_en_sig<=1'b0;
+ sr_reg_en_sig<=1'b0;
+ to_reg_en_sig<=1'b0;
+ addr_reg_en_sig<=1'b0;
+ dr_reg_en_sig<=1'b1;
+ rr_reg_en_sig <= 1'b0;
+ //add_match_sig<=1'b1;
+ end
+
+ else if(add_bus == `RR)
+ begin
+ rr_reg_en_sig <= 1'b1;
+ prescale_reg_en_sig<=1'b0;
+ ctr_reg_en_sig<=1'b0;
+ sr_reg_en_sig<=1'b0;
+ to_reg_en_sig<=1'b0;
+ addr_reg_en_sig<=1'b0;
+ dr_reg_en_sig<=1'b0;
+ //add_match_sig<=1'b1;
+ end
+
+ else
+ begin
+ rr_reg_en_sig <= 1'b0;
+ prescale_reg_en_sig<=1'b0;
+ ctr_reg_en_sig<=1'b0;
+ sr_reg_en_sig<=1'b0;
+ to_reg_en_sig<=1'b0;
+ addr_reg_en_sig<=1'b0;
+ dr_reg_en_sig<=1'b0;
+ //add_match_sig<=1'b0;
+ end
+
+
+end
+else
+begin
+ prescale_reg_en_sig<=1'b0;
+ ctr_reg_en_sig<=1'b0;
+ sr_reg_en_sig<=1'b0;
+ to_reg_en_sig<=1'b0;
+ addr_reg_en_sig<=1'b0;
+ dr_reg_en_sig<=1'b0;
+ rr_reg_en_sig <= 1'b0;
+ end
+
+end
+
+//assigning value of data_ie line
+//////////////////////////////////
+always@(posedge clk or posedge rst)
+begin
+ if(rst)
+ data_ie_sig<=1'b0;
+ else if(!ds_d && ds)
+ data_ie_sig<=1'b1;
+
+end
+
+
+//read data to/from the register specified by processor addrress.
+
+
+//always@(rst or addr_reg_en or ctr_reg_en or dr_reg_en or sr_reg_en or prescale_reg_en or to_reg_en or data_ie or rw or data_in )
+
+always@(posedge clk or posedge rst)
+begin
+if(rst)
+begin
+ sr_reg <= 8'b0;
+ dr_reg <= 8'b0;
+ rr_reg <= 8'b0;
+//ctr_reg <= 8'b0;
+end
+
+/*else if(ctr_reg_en)
+begin
+ //sr_reg <= {byte_trans,slave_addressed,bus_busy,arb_lost,time_out,slave_rw,inter,ack_rec};
+ ctr_reg <= data_in;
+end*/
+else
+begin
+ sr_reg <= {byte_trans,slave_addressed,bus_busy,arb_lost,time_out,slave_rw,inter,ack_rec};
+ rr_reg <= i2c_data;
+end
+end
+
+always@(posedge clk or posedge rst or posedge time_rst)
+begin
+ if(rst || time_rst)
+ begin
+ //initializing control register
+ ctr_reg <= 8'b0;
+ /*core_en_sig <= 1'b0;
+ inter_en_sig <= 1'b0;
+ mode_sig <= 1'b0;
+ master_rw_sig <= 1'b0;
+ ack_sig <= 1'b0;
+ rep_start_sig <= 1'b0;
+ inter_rst_sig<=1'b0;*/
+ //initializing data and timer register
+ data_sig <= 8'b00000000;
+ prescale_sig <= 8'b00000000;
+ time_out_sig <= 8'b00000000;
+ data_out <= 8'b00000000;
+ end
+
+ else if (data_ie)
+ begin
+ //address register
+ if(addr_reg_en) //if address matches with slave address register
+ begin
+ if(rw) //processor write cycle
+ slave_add_sig <= {data_in[7:1] , 1'b0};
+ else //processor read cycle
+ data_out <= slave_add;
+ end
+
+ //control register
+ if(ctr_reg_en) //if address matches with cntrol register
+ begin
+ if(rw) //processor write cycle
+ //begin
+ /*core_en_sig <= #2 ctr_reg [7];
+ inter_en_sig <= #2 ctr_reg [6];
+ mode_sig <= #2 ctr_reg [5];
+ master_rw_sig <= #2 ctr_reg [4];
+ ack_sig <= #2 ctr_reg [3];
+ rep_start_sig <= #2 ctr_reg [2];
+ inter_rst_sig <= #2 ctr_reg [1];
+ halt_sig <= #2 ctr_reg [0];*/
+ //end
+
+ //else
+ ctr_reg <= data_in; //processor read cycle
+ else
+ data_out <= ctr_reg;
+ end
+
+ else if(!byte_trans && bus_busy)
+ ctr_reg[1:0] <= 2'b0;
+ //data register
+
+ if(dr_reg_en)
+ begin
+ if(rw)
+ dr_reg <= data_in;
+ else
+ data_out <= dr_reg;
+ end
+
+ if(rr_reg_en)
+ begin
+ data_out <= rr_reg;
+ end
+
+ //staus register
+
+ if(sr_reg_en)
+ begin
+ if(!rw)
+ //begin
+ //if(data_in[0]==1'b0)
+ //inter_rst_sig <= 1'b0;
+ //else
+ //inter_rst_sig <= 1'b1;
+ //end
+ //else
+ //begin
+ data_out <= sr_reg;
+ //inter_rst_sig<=1'b0;
+ //end
+ //else
+ //inter_rst_sig<=1'b0;
+
+ end
+
+
+ //prescale register
+
+ if(prescale_reg_en)
+ begin
+ if(rw)
+ prescale_sig <= data_in;
+ else
+ data_out <= prescale;
+ end
+
+ //time_out register
+
+ if(to_reg_en)
+ begin
+ if(rw)
+ time_out_sig <= data_in;
+ else
+ data_out <= time_out_reg;
+ end
+ end
+end
+
+//assigning values to bidirectional bus
+//////////////////////////////////////
+
+//assign data_bus = (!rw && data_ie) ? data_out : 8'bzzzzzzzz;
+//assign data_in = (rw) ? data_bus : 8'bzzzzzzzz;
+
+//interuupt pin to processor
+assign irq = (inter && inter_en) ? 1'b1 : 1'b0;
+endmodule
+
+
+
+
+
+
+
+
+
+
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/i2c_blk.v
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/i2c_blk.v (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/i2c_blk.v (revision 5)
@@ -0,0 +1,172 @@
+//////////////////////////////////////////////////////////////////////////////////////////
+//Design Engineer: Ravi Gupta //
+//Company Name : Toomuch Semiconductor
+//Email : ravi1.gupta@toomuchsemi.com //
+// //
+// //
+//Purpose : This module will simply interconnect controller interface // //
+// controller_interface with ms_core. //
+// //
+// //
+//Date : 11-12-07 //
+// //
+// //
+// //
+// //
+// //
+// //
+// //
+//////////////////////////////////////////////////////////////////////////////////////////
+/*// synopsys translate_off
+`include "oc8051_timescale.v"
+// synopsys translate_on
+
+`include "oc8051_defines.v"*/
+
+
+module block(scl_oe,scl_in,scl_o,sda_oe,sda_in,sda_o,wb_add_i,wb_data_i,wb_data_o,wb_we_i,wb_stb_i,wb_cyc_i,irq,trans_comp,wb_clk_i,wb_rst_i,wb_ack_o);
+
+//inout scl; //Bi-directional lines to follow i2c protocol for data transfer.
+input sda_in; //sda input
+output sda_oe; //control line for bidirectional buffer
+output sda_o; //input line for bi_firectional buffer
+input scl_in;
+output scl_o;
+output scl_oe;
+input [7:0]wb_data_i; //Bi-direction buses for transfering data to/from processor.
+input [7:0]wb_add_i; //Transfer the addresses of intenal registers.
+input wb_we_i; //signal from processor to indicate whether its a read or write cycle.
+input wb_stb_i; //when asserted indicates address is valid.
+input wb_cyc_i; //when asserted indicates data is valid.
+output irq; //interupt signal to processor.
+input wb_clk_i; //system clock.
+input wb_rst_i; //asynchrnous reset active high.
+inout trans_comp; //temprory signal for testing the core
+output [7:0]wb_data_o;
+output wb_ack_o;
+
+//declaratiion of internal signals
+//////////////////////////////////
+
+ // control register
+ wire [7:0] slave_add; // I2C address
+ wire arb_lost; // indicates that arbitration for the i2c bus is lost
+ wire bus_busy; // indicates the i2c bus is busy
+ wire [7:0] i2c_up; // i2c data register
+ wire [7:0] data; // uC data register
+ wire core_en; // i2c enable - used as i2c reset
+ wire inter_en; // interrupt enable
+ wire inter; // interrupt pending
+ wire mode; // i2c master/slave select
+ wire master_rw; // master read/write
+ wire rep_start; // generate a repeated start
+ wire ack_rec; // value of received acknowledge
+ wire slave_rw; // slave read/write
+ wire ack; // value of acknowledge to be transmitted
+ wire byte_trans; // indicates that one byte of data is being transferred
+ wire slave_addressed; // address of core matches with address transferred
+ wire time_out; // max low period for SCL has excedded
+ wire [7:0]time_out_reg; // programmable max time for SCL low period
+ wire [7:0]prescale;
+ wire inter_rst;
+ wire [7:0]wb_data_o;
+ wire halt;
+ wire data_en;
+ wire time_rst;
+ reg wb_ack_o;
+ wire rst;
+
+assign trans_comp = byte_trans;
+
+always@(posedge wb_clk_i)
+begin
+ wb_ack_o <= #1 wb_stb_i & wb_cyc_i & ~wb_ack_o;
+end
+
+//port map for i2c controller
+////////////////////////////
+
+core i2c_core
+
+ (
+ .clk(wb_clk_i),
+ .rst(core_en),
+ .sda_oe(sda_oe),
+ .sda_in(sda_in),
+ .sda_o(sda_o),
+ .scl_oe(scl_oe),
+ .scl_o(scl_o),
+ .scl_in(scl_in),
+ .ack(ack),
+ .mode(mode),
+ .rep_start(rep_start),
+ .master_rw(master_rw),
+ .data_in(data[7:0]),
+ .slave_add(slave_add[7:0]),
+ .bus_busy(bus_busy),
+ .byte_trans(byte_trans),
+ .slave_addressed(slave_addressed),
+ .arb_lost(arb_lost),
+ .slave_rw(slave_rw),
+ .time_out(time_out),
+ .inter(inter),
+ .ack_rec(ack_rec),
+ .i2c_up(i2c_up[7:0]),
+ .time_out_reg(time_out_reg[7:0]),
+ .prescale_reg(prescale[7:0]),
+ .inter_en(inter_en),
+ .inter_rst(inter_rst),
+ .data_en(data_en),
+ .halt_rst(halt),
+ .h_rst(wb_rst_i),
+ .time_rst(time_rst));
+
+
+//port map for controller interface
+///////////////////////////////////
+
+processor_interface processor_interface
+
+ (
+ .clk(wb_clk_i),
+ .rst(wb_rst_i),
+ .add_bus(wb_add_i[7:0]),
+ .data_in(wb_data_i[7:0]),
+ .as(wb_stb_i),
+ .ds(wb_cyc_i),
+ .rw(wb_we_i),
+ .bus_busy(bus_busy),
+ .byte_trans(byte_trans),
+ .slave_addressed(slave_addressed),
+ .arb_lost(arb_lost),
+ .slave_rw(slave_rw),
+ .inter(inter),
+ .ack_rec(ack_rec),
+ .core_en(core_en),
+ .inter_en(inter_en),
+ .mode(mode),
+ .master_rw(master_rw),
+ .ack(ack),
+ .rep_start(rep_start),
+ .data(data[7:0]),
+ .i2c_data(i2c_up[7:0]),
+ .slave_add(slave_add),
+ .time_out_reg(time_out_reg[7:0]),
+ .prescale(prescale[7:0]),
+ .irq(irq),
+ .time_out(time_out),
+ .inter_rst(inter_rst),
+ .halt(halt),
+ .data_en(data_en),
+ .time_rst(time_rst),
+ .data_out(wb_data_o));
+
+//always@(scl or sda)
+//$display($time,"scl=%b\tsda=%b\t\n",scl,sda);
+
+
+endmodule
+
+
+
+
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/ms_core.v
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/ms_core.v (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/verilog/rtl/ms_core.v (revision 5)
@@ -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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/Readme
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/Readme (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/Readme (revision 5)
@@ -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.
+
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_stimulus_packet.sv
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_stimulus_packet.sv (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_stimulus_packet.sv (revision 5)
@@ -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
+
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_sb_pkt.sv
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_sb_pkt.sv (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_sb_pkt.sv (revision 5)
@@ -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
+
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_scoreboard.sv
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_scoreboard.sv (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_scoreboard.sv (revision 5)
@@ -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
+
+
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_slave_driver.sv
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_slave_driver.sv (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_slave_driver.sv (revision 5)
@@ -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
+
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_monitor.sv
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_monitor.sv (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_monitor.sv (revision 5)
@@ -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
+
+
+
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_env.sv
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_env.sv (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_env.sv (revision 5)
@@ -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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/config.sv
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/config.sv (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/config.sv (revision 5)
@@ -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
+
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_program1_test.sv
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_program1_test.sv (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_program1_test.sv (revision 5)
@@ -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
+
+
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_scenario_packet.sv
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_scenario_packet.sv (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_scenario_packet.sv (revision 5)
@@ -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
+
+
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_coverage.sv
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_coverage.sv (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_coverage.sv (revision 5)
@@ -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
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_driver.sv
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_driver.sv (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_driver.sv (revision 5)
@@ -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
+
+
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_reg_pkt.sv
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_reg_pkt.sv (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_reg_pkt.sv (revision 5)
@@ -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
+
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_callback.sv
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_callback.sv (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_callback.sv (revision 5)
@@ -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
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_data_packet.sv
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_data_packet.sv (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_data_packet.sv (revision 5)
@@ -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
+
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_interface.sv
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_interface.sv (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_interface.sv (revision 5)
@@ -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
+
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_top.sv
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_top.sv (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_top.sv (revision 5)
@@ -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
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/sb_callback.sv
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/sb_callback.sv (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/sb_callback.sv (revision 5)
@@ -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
+
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_clkgen.sv
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_clkgen.sv (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_clkgen.sv (revision 5)
@@ -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
+
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_mon_pkt.sv
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_mon_pkt.sv (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_mon_pkt.sv (revision 5)
@@ -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
+
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_scenario_generator.sv
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_scenario_generator.sv (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_i2c_scenario_generator.sv (revision 5)
@@ -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
+
+
+
Index: tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_program_test.sv
===================================================================
--- tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_program_test.sv (nonexistent)
+++ tags/t2/i2c_master_slave_core/i2c_master_slave_core/svtb/vmm_svtb/vmm_program_test.sv (revision 5)
@@ -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
+
+