Jump to content

what is the best strategy to model A2D converter ? SC or SC-AMS


Recommended Posts

Hello All, 

I am modeling A2D that uses a successive approximation algorithm. I have modeled A2D converter in SystemC and SystemC-AMS. But both of the models give me some errors. 

 

SC model ends up with infinite loop, and SC-AMS model ends with segmentation fault 

 

the models are as follows: 

 

SC models: Location of the while loop could be the serious problem. I have tried changing the location in side switch statement, but error persists. 

 

//error message:

stage 1: start edge

stage 1: start edge
stage 1: start edge
stage 1: start edge
stage 1: start edge
stage 1: start edge
stage 1: start edge ...... infinite loop
 

 

// SC_A2D.h

 

#include<systemc.h>
 
enum adc_state {input, convert};
 
SC_MODULE(A2D_module)
{
  sc_in_clk clk;
  sc_in_clk start;
 
  sc_in<double> ain;
  
  sc_out<sc_logic> eoc;
  sc_out<sc_lv<8> > dout;
 
  sc_signal <adc_state> status;
 
  void conversion_logic();
  //  void next_state_logic();
 
  SC_CTOR(A2D_module)
    {
      SC_CTHREAD(conversion_logic, start.pos());
    }
};
 
//SC_A2D.cpp
 
#include <SC_A2D.h>
 
void A2D_module::conversion_logic()
{
  eoc = SC_LOGIC_0;
  dout = "00000000";
 
  double thresh, Vtemp;
  sc_lv<8> dtemp;
  int bit_cnt = 8;
  status = input;
 
  while(bit_cnt > 0)
    {
      
      switch (status){
cout << "begin !!!";
 
      case input:
if (start == 1)
 {
   cout << "stage 1: start edge" << endl;
   thresh = 5.0;
   Vtemp = ain;
   eoc = SC_LOGIC_0;
   status = convert;
 }
break;
 
      case convert:
if (clk == 1)
 {
   cout << "stage 2: clk edge" << endl;
   thresh = thresh/2.0;
   
   if (Vtemp > thresh)
     {
cout << "stage 3: Vtemp > thresh" << endl;
dtemp[bit_cnt]= '1';
Vtemp = Vtemp- thresh;
     }
   else 
     {
dtemp[bit_cnt]= '0';
     }
   
   if (bit_cnt > 0)
     {
cout << "stage 4: bit_cnt > 0" << endl;
bit_cnt = bit_cnt - 1;
     }
   else
     {
cout << "last stage: conversion" << endl;
dout = dtemp;
status = input;
wait(10, SC_US);
eoc = SC_LOGIC_1;
 
     }
 }
break;
      } // end switch
 
    } // end while
        
} // end method conversion_logic
 

-------------------------------------------------------------------------------------------------------------

 

SC-AMS models: which gives segmentation fault

// Error message:

stage 1: Read Input
stage 3: Convert Input
stage 1: Read Input
stage 2 : start edge
stage 3: Convert Input
stage 4: clk edge !!!
 bit_cnt = 7
stage 1: Read Input
stage 3: Convert Input
stage 1: Read Input
stage 3: Convert Input
stage 4: clk edge !!!
Segmentation fault
 

 

// A2D.h

 

#include <systemc-ams>
#include <systemc>
#include <stdio.h>
using namespace std;
 
//ref: VHDL-AMS Model of A2D converter given in System designer's guide to VHDL-AMS on page 287
 
SCA_TDF_MODULE (a2d_nbit)
 
{
//port declaration
  sca_tdf::sca_in<double> ain; // analog input pin
 
  sca_tdf::sca_de::sca_in<bool> clk; //clock signal
  sca_tdf::sca_de::sca_in<bool> start; //clock signal
 
  sca_tdf::sca_de::sca_out<sc_dt::sc_logic> eoc; //end of conversion pin  
  sca_tdf::sca_de::sca_out<sc_dt::sc_lv<8> > dout; //digitalized output
   
 
  a2d_nbit(sc_core::sc_module_name nm, double Vmax_ = 5.0, double delay_ = 10.0e-6, int bit_range_ = 8, bool start_x_ = 0, bool clk_x_ = 0):
    ain("ain"), start("start"),clk("clk"), eoc("eoc"), dout("dout"), Vmax(Vmax_), delay(delay_), bit_range(bit_range_), start_x(start_x_), clk_x(clk_x_){}
 
  void set_attributes()
  {
    set_timestep(50, sc_core::SC_US);
    eoc.set_delay(1);
  }
 
  void initialize()
  {
    eoc.initialize(sc_dt::SC_LOGIC_0);
  }
 
  void processing();
  
 private:
  
  double delay; // ADC conversion time 
  double Vmax;
  int bit_range; 
  bool clk_x;
  bool start_x;
   
};

 

 

// A2D.cpp

void a2d_nbit :: processing()
  {
    //    double Vin = ain.read();
    double thresh; //Threshold to test input voltage
    double Vtemp; //snapshot of input voltage when conversion starts
    sc_dt::sc_lv<8> dtemp; //temparary output data
    enum state {input, convert}; 
    int bit_cnt;
    state status = input;
 
    switch(status) // ref: systemC state machine example in SystemC user guide on page 171 
     {
     case input : 
cout << "stage 1: Read Input" << endl;
if((start == true) && (start_x == false))
//if (start == true)
 {
   cout << "stage 2 : start edge" << endl;
   bit_cnt = bit_range;
   thresh = Vmax;
   Vtemp = ain;
   eoc = sc_dt::sc_logic('0');
 }
 
case convert:
 cout << "stage 3: Convert Input" << endl;
 if ((clk == true)  && (clk_x == false))    
   //if (clk == true)
     {
cout << "stage 4: clk edge !!!" << endl;
thresh = thresh/2.0;
 
if (Vtemp > thresh)
 {
   dtemp[bit_cnt]= '1';
   Vtemp = Vtemp - thresh;
 }
else 
 {
   dtemp[bit_cnt]= '0';
 }
 
if (bit_cnt > 0)
 {
   bit_cnt = bit_cnt - 1;
   cout << " bit_cnt = " << bit_cnt << endl; 
 }
else 
 {
   dout = dtemp;
   eoc = sc_dt::sc_logic('1');   
   status = input;
 }
break;
     }
     
 
default:
 break;
 
     } // end switch 
    
    start_x = start;
    clk_x = clk;
    
  }
 
----------------------------------------------------------------------------------------------------------------
 
// voltage source: dummy_source.h 
 
#include<systemc-ams>
#include<systemc>
 
#include<iostream.h>
#include<fstream.h>
 
using namespace std;
 
SCA_TDF_MODULE (dummy_src)
 
{
  //  sca_tdf::sca_de::sca_out<double> output; 
  sca_tdf:: sca_out<double> output;
  ifstream infile;
  double val;
 
  dummy_src(sc_core::sc_module_name): output("output"){}
 
    void set_attributes()
    {
      set_timestep(50, sc_core::SC_US);
      infile.open("datalog.txt");
    }
 
    void processing ()
    {
      
      if (infile >> val) {
output.write(val);
      else {
output.write(0.0);
}
      
    }
    
 };
 
-------------------------------------------------------------------------------------------------------------
 
// top_level_entity : interface.h
 
#include<systemc-ams>
#include<systemc>
 
#include<A2D.h>
//#include<SC_A2D.h>
#include<dummy_source.h>
 
using namespace std;
using namespace sc_core;
 
SC_MODULE (interface2)
{
  // A2D_module a2d;
  a2d_nbit a2d;
  dummy_src input_vtg;
  sc_core::sc_clock clk1;
  sc_core::sc_clock start1;
 
  SC_CTOR(interface2)
    :in("in"), out("out"), a2d("a2d"), input_vtg("input_vtg"), clk1("clk1", 100, sc_core::SC_US, 0.5), start1("start1", 200, sc_core::SC_US, 0.5), eoc("eoc")
    {
      input_vtg.output(in);
      
      a2d.ain(in); 
      a2d.start(start1.signal());
      a2d.clk(clk1.signal());
      a2d.eoc(eoc);
      a2d.dout(out);
 
    }
 
    public:
 
  //   sc_core::sc_signal <double> in;
    sca_tdf::sca_signal<double> in;
    sc_core::sc_signal<sc_dt::sc_lv<8> > out;
    sc_core::sc_signal<sc_logic> eoc;
 
};  
 
// top_level_entity: interface2.cpp
 
#include<systemc-ams.h>
#include<systemc.h>
#include<iomanip>
#include<interface2.h>
 
int sc_main(int argc, char* argv[])
{
 
  interface2 if2_dut("if2_dut");
 
  sca_util :: sca_trace_file* atfs = sca_util :: sca_create_tabular_trace_file("if2.dat");
  sca_util :: sca_trace(atfs, if2_dut.clk1, "\tCLK");
  sca_util :: sca_trace(atfs, if2_dut.start1, "\tSTART");
  sca_util :: sca_trace(atfs, if2_dut.in, "\tINPUT");
  sca_util :: sca_trace(atfs, if2_dut.out, "\tOUTPUT");
  sca_util :: sca_trace(atfs, if2_dut.eoc, "\tEOC");
  sc_start(400, SC_US);
  sca_util :: sca_close_tabular_trace_file (atfs);
  return 0;
}
-------------------

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...