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

Subversion Repositories i2c_master_slave_core

[/] [i2c_master_slave_core/] [trunk/] [i2c_master_slave_core/] [i2c_master_slave_core/] [svtb/] [vmm_svtb/] [vmm_i2c_monitor.sv] - Rev 6

Compare with Previous | Blame | View Log

//////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                                                                              //
//      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                        



Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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