Email: bknpk@hotmail.com Phone: +972-54-7649119


V

 

An I2C verification environment, which uses memories and VPI (c code) to drive and monitor data to/from DUT, will be described in this work.

  1. In this site many verification environments have been presented, using, specman , VHDL etc....
    The main page of this work is accessed with the following link.
    The verilog code of the project, contains a BFM and also controls the operation of c code. This page describes how APB transaction buffers are prepared by the c code and stored into a read only memory buffers in the verilog test-bench for farther use of its BFM.

  2. The c code main stimuli is an array and its main element structure has three fields namely: Address, write/read expected data and a two bit control array (containing last entry and write indication):

    typedef struct t_mem_init {
      int addr;
      int wdat;
      int ctrl; //pkt_end pwrite
    } t_mem_init;
    t_mem_init a_mem_init[] = {
      //write transactions
      {0x000000e0, 0x000000fa, 0x1},
      {0x000000e0, 0x000000c8, 0x1},
      {0x000000e4, 0x00000000, 0x1},
      //read transactions
      {0x000000e0, 0x000000fa, 0x0},
      {0x00000000, 0x00000000, 0x2} //end entry
    };
    ...

  3. The data extraction from the stimuli c code array to the read only test-bench memory buffers, is controlled by two global variables:

    int mem_ix;
    enum t_mem_field {t_addr, t_wdat, t_ctrl};
    enum t_mem_field mem_field=t_addr;

  4. The verilog test-bench invokes the c-code three times. The c code first writes to address array, second to the write data and last to the control. ...
      stim_sz=sizeof(a_mem_init)/sizeof(t_mem_init);
    ...
      for(mem_ix=0; mem_ix < stim_sz; mem_ix++) {
        h3 = vpi_handle_by_index(argh, ix_addr);
        ar_da.format = vpiIntVal;
    ...
        vpi_printf("C: current mem_field %d \n", (int)mem_field);
        switch (mem_field) {
          case t_addr:
          data_to_a.value.integer=a_mem_init[mem_ix].addr;
          break;
          case t_wdat:
    ...
        ix_addr++;
        if(ix_addr > right_addr) {
          vpi_printf("C: ERROR ix_addr is too large %x %x %x\n", left_addr, right_addr, ix_addr);
        }
      } //for
    ...
      //move filed pointer
      switch (mem_field) {
        case t_addr: mem_field=t_wdat; break;
        case t_wdat: mem_field=t_ctrl; break;
    ...

    Note that if the user specified a stimuli array too large (more than what is defined in the verilog test-bench) an ERROR is printed. In that case the simulation should be stopped as soon as possible. This is because writing outside an array boundaries may lead to unpredictable results.
    To stop a simulation from within the c code, I selected the finish command.

    ix_addr=left_addr;
    for(mem_ix=0; mem_ix < stim_sz; mem_ix++) {
    ...
      if(ix_addr > right_addr) {
        vpi_printf("C: ERROR ix_addr is too large %x %x %x\n", left_addr, right_addr, ix_addr);
        vpi_control(vpiFinish, 1);
        break;
      }

    The importance of the break command in the c code: If the break command is not included, the c code will continue till it ends its current for loop, than returns control to the simulator, which finally do the finish command as opposed to the ASAP stop, due memory overrun.


  5. The verilog test-bench sends messages to c code to instruct it of which APB buffers to prepare (DUT register initialization, data ready poll, etc...). This is explained in the following link.


  ...


Search This Site


Feedback This Site




new pages on this site