// // -------------------------------------------------------------------------------------
// // CHECKS
// // -------------------------------------------------------------------------------------
// integer error_count;
// integer warn_count;
// integer pass_count;
// 
// initial begin
//    error_count = 0;
//    warn_count = 0;
//    pass_count = 0;
// end
// 
// // ----------------------------------------------------------------------------------------
// // MISC
// // ----------------------------------------------------------------------------------------
// task END_SIM;
//    begin
//       #500;
//       $display("\n\n");
//       $display("%% -----------------------------------------");
//       if (error_count > 0) begin
//          $display("%% Simulation Completed with Errors!!"); 
//          $display("%% %0d Error(s) and %0d Warning(s) Detected", error_count,warn_count);
//       end
//       else if (warn_count > 0) begin
//          $display("%% Simulation Completed with Warnings!!");
//          $display("%% %0d Warning(s) Detected",warn_count);
//       end
//       else begin
//          $display("%% Simulation Completed Successfully");  
//       end
// 
//       $display("%%");
//       $display("%% END_SIM called @ Time = %0d", $time);
//       $display("%% %0d Checks done", pass_count + error_count);
//       $display("%% %0d Checks successful", pass_count);
//       $display("%% %0d Checks failed", error_count);
//       $display("%% -----------------------------------------");
//       $display("\n\n");
//       $finish(2);  // CPU time and memory used
//    end
// endtask // END_SIM
// 
// // ----------------------------------------------------------------------------------------
// // DISPLAY
// // ----------------------------------------------------------------------------------------
// task COMMENT;
//    input [128*8:1] comment_string;
//    begin
//       $write("\n%% INFO @ %0d ns: %0s", $time, comment_string); 
//    end
// endtask // COMMENT
// 
// task PRINT_WARN;
//    input [128*8:1] warning_string;
//    begin
//       warn_count = warn_count + 1;
//       $write("\n%% WARN #%3d @ %0d ns: %0s", warn_count, $time, warning_string);
//    end
// endtask // PRINT_WARN
// 
// task PRINT_ERROR;
//    input [128*8:1] error_string;
//    begin
//       error_count = error_count + 1;
//       $write("\n%% ERROR #%3d @ %0d ns: %0s", error_count, $time, error_string);
// `ifdef END_ON_ERROR
//       END_SIM;
// `endif
//    end
// endtask // PRINT_ERROR
// 
// task PRINT_PASS;
//    input [128*8:1] pass_string;
//    begin
//       pass_count = pass_count + 1;
//       $write("\n%% PASS #%3d @ %0d ns: %0s", pass_count, $time, pass_string);
//    end
// endtask // PRINT_PASS
// 
// // ----------------------------------------------------------------------------------------
// // check_digital_net_id
// // ----------------------------------------------------------------------------------------
// task check_digital_net_id;
//   input [255:0] id;  // 32 characters (32x8=256)
//   input signal;
//   input expected;
// 
// integer        signal;
// integer        expected;
// 
// begin
// 
//   if (expected !== signal)
//     begin
//       error_count = error_count + 1;
//       $write("\n%% ERROR #%3d @ %0d ns: %0s : incorrect digital value", error_count, $time, id);
//       $display("\n%% Measured digital value %h, Expected digital value %h\n", signal, expected);
// `ifdef END_ON_ERROR
//       END_SIM;
// `endif
//     end
//   else
//     begin
//       pass_count = pass_count + 1;
//       $write("\n%% PASS #%3d @ %0d ns: %0s : correct digital value", pass_count, $time, id);
//       $display("\n%% Measured digital value %h, Expected digital value %h\n", signal, expected);
//     end
// end
// endtask
// 
// // ----------------------------------------------------------------------------------------
// // check_digital_net
// // ----------------------------------------------------------------------------------------
// task check_digital_net;
//   input signal;
//   input expected;
// 
// integer        signal;
// integer        expected;
// 
// begin
//   if (expected !== signal)
//     begin
//       error_count = error_count + 1;
//       $write("\n%% ERROR #%3d @ %0d ns : incorrect digital value", error_count, $time);
//       $display("\n%% Measured digital value %h, Expected digital value %h\n", signal, expected);
// `ifdef END_ON_ERROR
//       END_SIM;
// `endif
//     end
//   else
//     begin
//       pass_count = pass_count + 1;
//       $write("\n%% PASS #%3d @ %0d ns : correct digital value", pass_count, $time);
//       $display("\n%% Measured digital value %h, Expected digital value %h\n", signal, expected);
//     end
// end
// endtask

// ----------------------------------------------------------------------------------------
// owi_write_regs_fields    **CMD=000010**
// ----------------------------------------------------------------------------------------
 task owi_write_regs_fields; 

 reg [5:0] this_reg;
 reg [5:0] parity;
 reg [5:0] cmd;
 integer j;
 integer addr;
 
 begin
     #0; // this is needed to make sure the wire update event is 
         // scheduled first
    cmd = 6'b000010;
    owi_master.owiWr(cmd,2'b00); 
    #(owi_master.owi_bit_length);
    parity = 6'b000010;
    COMMENT("");
    $display("OWI Cmd: Write regs Cmd= %d", cmd);
    
    addr = 7;
    for (j = 0; j < 6 ; j = j + 1) begin
       this_reg[j] = owi_fields[6*addr+j];
    end       
    owi_master.owiWr(this_reg,2'b01);  //vth    
    #(owi_master.owi_bit_length);
    parity = parity ^ this_reg;    
    COMMENT("");
    $display("OWI Reg. %3d Write: Data %b", addr, this_reg);
    
    addr = 8;    
    for (j = 0; j < 6 ; j = j + 1) begin
       this_reg[j] = owi_fields[6*addr+j];
    end     
    owi_master.owiWr(this_reg,2'b01);  //vcl
    #(owi_master.owi_bit_length);
    parity = parity ^ this_reg;    
    COMMENT("");
    $display("OWI Reg. %3d Write: Data %b", addr, this_reg);
    
    addr = 9;    
    for (j = 0; j < 6 ; j = j + 1) begin
       this_reg[j] = owi_fields[6*addr+j];
    end  
    owi_master.owiWr(this_reg,2'b01);  //cmd
    #(owi_master.owi_bit_length);
    parity = parity ^ this_reg;    
    COMMENT("");
    $display("OWI Reg. %3d Write: Data %b", addr, this_reg);
    
    addr = 10;    
    for (j = 0; j < 6 ; j = j + 1) begin
       this_reg[j] = owi_fields[6*addr+j];
    end  
    owi_master.owiWr(6'b000000,2'b01);  //sense
    #(owi_master.owi_bit_length);
    parity = parity ^ this_reg;    
    COMMENT("");
    $display("OWI Reg.%3d Write: Data 000000", addr );
    
   //parity
    owi_master.owiWr(parity,2'b10);  
    #(owi_master.owi_bit_length);
    COMMENT("");
    $display("OWI Parity: Parity=  %b", parity);   
     
 end
 endtask // owi_write_regs_fields
 
// ----------------------------------------------------------------------------------------
// owi_write_ext_regs_fields     **CMD=000100**
// ----------------------------------------------------------------------------------------
 task owi_write_ext_regs_fields; 

 reg [5:0] this_reg;
 reg [5:0] parity;
 reg [5:0] cmd;
 integer j;
 integer addr;
 
   begin
     #0; // this is needed to make sure the wire update event is 
         // scheduled first
    cmd =  6'b000101;    
    owi_master.owiWr(cmd,2'b00); 
    #(owi_master.owi_bit_length);
    parity = cmd;
    COMMENT("");
    $display("OWI Cmd: Write extended regs Cmd= %d", parity);
    
    addr = 11;
    for (j = 0; j < 6 ; j = j + 1) begin
       this_reg[j] = owi_fields[6*addr+j];
    end       
    owi_master.owiWr(this_reg,2'b01);  //cfg    
    #(owi_master.owi_bit_length);
    parity = parity ^ this_reg;    
    COMMENT("");
    $display("OWI Reg. %3d Write: Data %b", addr, this_reg);
    
    //current lim;         
    owi_master.owiWr(6'b001111,2'b01);  //current lim
    #(owi_master.owi_bit_length);
    parity = parity ^ 6'b001111 ;    
    COMMENT("");
    $display("OWI Reg current lim Write: Data 001111" );
    
    addr = 12;    
    for (j = 0; j < 6 ; j = j + 1) begin
       this_reg[j] = owi_fields[6*addr+j];
    end  
    owi_master.owiWr(6'b000000,2'b01);  //interrupt
    #(owi_master.owi_bit_length);
    parity = parity ^ 6'b000000;    
    COMMENT("");
    $display("OWI Reg. %3d Write: Data 000000", addr );
    
    //imped lim;          
    owi_master.owiWr(6'b000101,2'b01);  //imped lim
    #(owi_master.owi_bit_length);
    parity = parity ^ 6'b000101;    
    COMMENT("");
    $display("OWI Reg imped lim Write: Data 000101" );
    
   //parity
    owi_master.owiWr(parity,2'b10);  
    #(owi_master.owi_bit_length);
    COMMENT("");
    $display("OWI Parity: Parity=  %b", parity);   
     
   end
 endtask // owi_write_ext_regs_fields 
 

// ----------------------------------------------------------------------------------------
// owi_read_regs_fields       **CMD=000001**
// ----------------------------------------------------------------------------------------
 task owi_read_regs_fields; 

 reg [5:0] return_val;
 reg [5:0] expect_val;
 reg [5:0] cmd;
 reg [5:0] parity;
 integer j;
 integer addr;

   begin
    #0; // this is needed to make sure the wire update event is scheduled first
        // the mask_val contains a 1 for the bits to compare against 
    cmd = 6'b000001;
    owi_master.owiWr(cmd,2'b00); 
    COMMENT("");
    $display("OWI Cmd: Read regs Cmd= %d", cmd);
    // Read vth
    owi_master.owiRd ;      
    return_val = owi_master.owi_rdback_val;
    addr = 7;
    for (j = 0; j < 6 ; j = j + 1) begin     
      expect_val[j] = owi_fields [6*addr+j]; 
    end    
    read_comp("vth reg", return_val, expect_val);  
    parity = return_val;
    // Read vcl
    owi_master.owiRd ; 
    return_val = owi_master.owi_rdback_val;    
    addr = 8;
    for (j = 0; j < 6 ; j = j + 1) begin     
      expect_val[j] = owi_fields [6*addr+j]; 
    end    
    read_comp("vcl reg", return_val, expect_val);  
    parity = parity ^ return_val;   
    // Read cmd         
    owi_master.owiRd ;      
    return_val = owi_master.owi_rdback_val;    
    addr = 9;
    for (j = 0; j < 6 ; j = j + 1) begin     
      expect_val[j] = owi_fields [6*addr+j]; 
    end    
    read_comp("vcmd reg", return_val, expect_val);  
    parity = parity ^ return_val;   
    // Read sense         
    owi_master.owiRd ;  
    addr = 10;
    return_val = owi_master.owi_rdback_val;    
    for (j = 0; j < 6 ; j = j + 1) begin     
      expect_val[j] = owi_fields [6*addr+j]; 
    end    
    read_comp("sense reg", return_val, expect_val);  
    parity = parity ^ return_val;              
    // Read parity         
    owi_master.owiRd ;   
    return_val = owi_master.owi_rdback_val;    
    read_comp("parity", return_val, parity);  

   end
 endtask // owi_read_regs_fields  
 
// ----------------------------------------------------------------------------------------
// owi_read_ext_regs_fields       **CMD=000100**
// ----------------------------------------------------------------------------------------
 task owi_read_ext_regs_fields;
 input [5:0] mask_val;           //for interrupts only!!
 
 reg [5:0] return_val;
 reg [5:0] actual_val;
 reg [5:0] expect_val;
 reg [5:0] cmd;
 reg [5:0] parity;
 integer j;
 integer addr;

   begin
    #0; // this is needed to make sure the wire update event is scheduled first
        // the mask_val contains a 1 for the bits to compare against 
    cmd = 6'b000100;
    owi_master.owiWr(cmd,2'b00); 
    COMMENT("");
    $display("OWI Cmd: Read extended regs Cmd= %d", cmd);
    // Read config
    owi_master.owiRd ;      
    return_val = owi_master.owi_rdback_val;
    addr = 11;
    for (j = 0; j < 6 ; j = j + 1) begin     
      expect_val[j] = owi_fields [6*addr+j]; 
    end    
    read_comp( "config reg",return_val, expect_val);  
    parity = return_val;
    // Read current limit
    owi_master.owiRd ; 
    return_val = owi_master.owi_rdback_val;    
    expect_val = 6'b001111;   //hardcoded
    read_comp("current limit", return_val, expect_val);              
    parity = parity ^ return_val;   
    // Read interrupts         
    owi_master.owiRd ;      
    return_val = owi_master.owi_rdback_val;    
    addr = 12;
    for (j = 0; j < 6 ; j = j + 1) begin     
      expect_val[j] = owi_fields [6*addr+j] & mask_val [j]; 
      actual_val[j] = return_val [j]        & mask_val [j]; 
    end    
    read_comp_mask(mask_val, return_val, actual_val, expect_val, addr);  
    parity = parity ^ return_val;   
    // Read impedance limit         
    owi_master.owiRd ;  
    return_val = owi_master.owi_rdback_val;    
    expect_val = 6'b000101;   //hardcoded  
    read_comp("imped limit", return_val, expect_val);              
    parity = parity ^ return_val;              
    // Read parity         
    owi_master.owiRd ;   
    return_val = owi_master.owi_rdback_val;            
    read_comp("parity", return_val, parity);  

   end
 endtask // owi_read_regs_fields  
 
// ----------------------------------------------------------------------------------------
// owi_read_data_fields       **CMD=000000**
// ----------------------------------------------------------------------------------------
 task owi_read_data_fields;
 input [5:0] mask_val;        //for status only
 
 reg [5:0] return_val;
 reg [5:0] actual_val;
 reg [5:0] expect_val;
 reg [5:0] cmd;
 reg [5:0] parity;
 integer j;
 integer addr;

   begin
    #0; // this is needed to make sure the wire update event is scheduled first
        // the mask_val contains a 1 for the bits to compare against 
    cmd = 6'b000000;
    owi_master.owiWr(cmd,2'b00);
//    #(owi_master.owi_bit_length);
    COMMENT("");
    $display("OWI Cmd: Read data Cmd= %d", cmd);
    // Read status
    owi_master.owiRd ;      
    return_val = owi_master.owi_rdback_val;
    addr = 0;
    for (j = 0; j < 6 ; j = j + 1) begin     
      expect_val[j] = owi_fields [6*addr+j] & mask_val [j]; 
      actual_val[j] = return_val [j]        & mask_val [j]; 
    end    
    read_comp_mask(mask_val, return_val, actual_val, expect_val, addr);  
    parity = return_val;
    // Read vin_lsb
    owi_master.owiRd ; 
    return_val = owi_master.owi_rdback_val;    
    addr = 1;
    for (j = 0; j < 6 ; j = j + 1) begin     
      expect_val[j] = owi_fields [6*addr+j]; 
    end    
    read_comp( "vin_lsb reg",return_val, expect_val);  
    parity = parity ^ return_val;   
    // Read vin_msb         
    owi_master.owiRd ;      
    return_val = owi_master.owi_rdback_val;    
    addr = 2;
    for (j = 0; j < 6 ; j = j + 1) begin     
      expect_val[j] = owi_fields [6*addr+j]; 
    end    
    read_comp( "vin_msb reg",return_val, expect_val);  
    parity = parity ^ return_val;   
    // Read iin_lsb         
    owi_master.owiRd ;  
    addr = 3;
    return_val = owi_master.owi_rdback_val;    
    for (j = 0; j < 6 ; j = j + 1) begin     
      expect_val[j] = owi_fields [6*addr+j]; 
    end    
    read_comp( "iin_lsb reg",return_val, expect_val);  
    parity = parity ^ return_val;              
    // Read iin_msb         
    owi_master.owiRd ;  
    addr = 4;
    return_val = owi_master.owi_rdback_val;    
    for (j = 0; j < 6 ; j = j + 1) begin     
      expect_val[j] = owi_fields [6*addr+j]; 
    end    
    read_comp( "iin_msb reg",return_val, expect_val);  
    parity = parity ^ return_val;    
    // Read temp_lsb         
    owi_master.owiRd ;  
    addr = 5;
    return_val = owi_master.owi_rdback_val;    
    for (j = 0; j < 6 ; j = j + 1) begin     
      expect_val[j] = owi_fields [6*addr+j]; 
    end    
    read_comp( "temp_lsb reg",return_val, expect_val);  
    parity = parity ^ return_val;              
    // Read temp_msb         
    owi_master.owiRd ;  
    addr = 6;
    return_val = owi_master.owi_rdback_val;    
    for (j = 0; j < 6 ; j = j + 1) begin     
      expect_val[j] = owi_fields [6*addr+j]; 
    end    
    read_comp( "temp_msb reg",return_val, expect_val);  
    parity = parity ^ return_val;               
    // Read offset_lsb         
    owi_master.owiRd ;  
    return_val = owi_master.owi_rdback_val;    
    expect_val = 6'b000000;   //hardcoded  
    read_comp("offset lsb", return_val, expect_val);              
    parity = parity ^ return_val;          
    // Read offset_msb         
    owi_master.owiRd ;  
    return_val = owi_master.owi_rdback_val;    
    expect_val = 6'b000000;   //hardcoded  
    read_comp("offset msb", return_val, expect_val);              
    parity = parity ^ return_val;  
    // Read parity         
    owi_master.owiRd ;   
    return_val = owi_master.owi_rdback_val;    
    read_comp("parity", return_val, parity);  

   end
 endtask // owi_read_data_fields 

// ----------------------------------------------------------------------------------------
// owi_read_status_fields       **CMD=000011**
// ----------------------------------------------------------------------------------------
 task owi_read_status_fields;
 input [5:0] mask_val;        //for status only
 
 reg [5:0] return_val;
 reg [5:0] actual_val;
 reg [5:0] expect_val;
 reg [5:0] cmd;
 integer j;
 integer addr;

   begin
    #0; // this is needed to make sure the wire update event is scheduled first
        // the mask_val contains a 1 for the bits to compare against 
    cmd = 6'b000011;
    owi_master.owiWr(cmd,2'b00); 
    COMMENT("");
    $display("OWI Cmd: Read status Cmd= %d", cmd);
    // Read status
    owi_master.owiRd ;      
    return_val = owi_master.owi_rdback_val;
    addr = 0;
    for (j = 0; j < 6 ; j = j + 1) begin     
      expect_val[j] = owi_fields [6*addr+j] & mask_val [j]; 
      actual_val[j] = return_val [j]        & mask_val [j]; 
    end    
    read_comp_mask(mask_val, return_val, actual_val, expect_val, addr);  

   end
 endtask // owi_read_status_fields 
 
// ----------------------------------------------------------------------------------------
// owi_read_revid_fields       **CMD=000110**
// ----------------------------------------------------------------------------------------
 task owi_read_revid_fields;
 
 reg [5:0] return_val;
 reg [5:0] expect_val;
 reg [5:0] cmd;
 integer j;
 integer addr;

   begin
    #0; // this is needed to make sure the wire update event is scheduled first
        // the mask_val contains a 1 for the bits to compare against 
    cmd = 6'b000110;
    owi_master.owiWr(cmd,2'b00); 
    COMMENT("");
    $display("OWI Cmd: Read rev_id Cmd= %d", cmd);
    // Read revid
    owi_master.owiRd ;      
    return_val = owi_master.owi_rdback_val;
    addr = 13;
    for (j = 0; j < 6 ; j = j + 1) begin     
      expect_val[j] = owi_fields [6*addr+j]; 
    end    
    read_comp("revid reg", return_val, expect_val);              

   end
 endtask // owi_read_revid_fields   
 
// ----------------------------------------------------------------------------------------
// owi_read_data_iv_fields       **CMD=000111**
// ----------------------------------------------------------------------------------------
 task owi_read_data_iv_fields;
  
 reg [5:0] return_val;
 reg [5:0] expect_val;
 reg [5:0] cmd;
 reg [5:0] parity;
 integer j;
 integer addr;

   begin
    #0; // this is needed to make sure the wire update event is scheduled first
        // the mask_val contains a 1 for the bits to compare against 
    cmd = 6'b000111;
    owi_master.owiWr(cmd,2'b00); 
    COMMENT("");
    $display("OWI Cmd: Read data IV Cmd= %d", cmd);
    // Read vin_lsb
    owi_master.owiRd ; 
    return_val = owi_master.owi_rdback_val;    
    addr = 1;
    for (j = 0; j < 6 ; j = j + 1) begin     
      expect_val[j] = owi_fields [6*addr+j]; 
    end    
    read_comp( "vin_lsb reg",return_val, expect_val);  
    parity = return_val;
    // Read vin_msb         
    owi_master.owiRd ;      
    return_val = owi_master.owi_rdback_val;    
    addr = 2;
    for (j = 0; j < 6 ; j = j + 1) begin     
      expect_val[j] = owi_fields [6*addr+j]; 
    end    
    read_comp( "vin_msb reg",return_val, expect_val);  
    parity = parity ^ return_val;   
    // Read iin_lsb         
    owi_master.owiRd ;  
    addr = 3;
    return_val = owi_master.owi_rdback_val;    
    for (j = 0; j < 6 ; j = j + 1) begin     
      expect_val[j] = owi_fields [6*addr+j]; 
    end    
    read_comp( "iin_lsb reg",return_val, expect_val);  
    parity = parity ^ return_val;              
    // Read iin_msb         
    owi_master.owiRd ;  
    addr = 4;
    return_val = owi_master.owi_rdback_val;    
    for (j = 0; j < 6 ; j = j + 1) begin     
      expect_val[j] = owi_fields [6*addr+j]; 
    end    
    read_comp( "iin_msb reg",return_val, expect_val);  
    parity = parity ^ return_val;     
    // Read parity         
    owi_master.owiRd ;   
    return_val = owi_master.owi_rdback_val;    
    read_comp("parity", return_val, parity);  
   end
 endtask // owi_read_data_iv_fields 


 // ----------------------------------------------------------------------------------------
// read_comp_mak
// ----------------------------------------------------------------------------------------
task read_comp_mask;
 input [5:0] mask_val;
 input [5:0] return_val;
 input [5:0] actual_val;
 input [5:0] expect_val;
 input   addr;
 
 integer addr;

 begin
  if (expect_val !== actual_val) begin
    PRINT_ERROR("");
    $display("FAIL: OWI Reg. %3d Read Check ERROR.", addr);
    $display("%%\t\tBit #:    54_3210");
    $display("%%\t\t          -------");
    $display("%%\t\tMask:     %b,", mask_val);
    $display("%%\t\tRead:     %b,", return_val);
    $display("%%\t\tExpected: %b" , expect_val);
  end
  else begin
    PRINT_PASS("");
    $display("PASS: OWI Reg. %3d Read Check PASS.", addr);
  end
 end 
endtask //read_comp_mask

// ----------------------------------------------------------------------------------------
// read_comp
// ----------------------------------------------------------------------------------------
task read_comp;
 input [255:0] id;  // 32 characters (32x8=256)
 input [5:0] return_val;
 input [5:0] expect_val;
 
 begin
  if (expect_val !== return_val) begin
    PRINT_ERROR("");
    $display("FAIL: OWI %0s Read Check ERROR.", id);
    $display("%%\t\tBit #:    54_3210");
    $display("%%\t\t          -------");
    $display("%%\t\tRead:     %b,", return_val);
    $display("%%\t\tExpected: %b" , expect_val);
  end
  else begin
    PRINT_PASS("");
    $display("PASS: OWI %0s Read Check PASS.", id);
  end
 end 
endtask //read_comp

// // ----------------------------------------------------------------------------------------
// // groupby4
// // ----------------------------------------------------------------------------------------
// function [80 : 1] groupby4;
//    input [8:1] regin;
//    input changez;
//    integer i;
// 
//    begin
//       i = 8;
//       groupby4 = 0;
//       while (i >= 1)
//         begin
//            case (regin[i])
//            1'b0 : groupby4[8:1] = "0";
//            1'b1 : groupby4[8:1] = "1";
//            1'bx : groupby4[8:1] = "x";
//            1'bz : groupby4[8:1] = changez ? "?" : "z";
//            default : groupby4[8:1] = "u";
//            endcase
// 
//            groupby4 = groupby4 << 8;
//            i = i - 1;
//            if ( i !=0 &&  !(i % 4))
//              begin
//                 groupby4[8:1] = "_";
//                 groupby4 = groupby4 << 8;
//              end
//         end
//    end
// endfunction // groupby4


