OpenCores
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 + +

powered by: WebSVN 2.1.0

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