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

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;
}
-------------------
 
Hello,
Right now, the goal is to get your model(or rather something -- none of these irritating infinite loops or seg faults)
to work, so it really does not matter whether you use SystemC or SystemC-AMS, or a combination. Am I right ?
Then one has to consider the design. Consider a delta-sigma ADC. The actual delta-sigma modulator is purely
analog, no queastions, but the decimation filter is purely digital. So you have no option but to use both SystemC
and SystemC-AMS and use converter ports. Or you might stick only to SystemC-AMS and model the decimation
filter using TDF. So this decision you have to make.
May we suggest that for the time being keep the successive approximation ADC on the back burner. Model a
very simple ADC as flash or single slope ADC. Get that to work just right, no infinite loops, or seg faults. Once
you get one of these working, you can compare what you did in the two designs and find out what exactly is
problem with the successive approximation case. Most likely, some control condition is not getting set/reset.
Have you checked with gdb where the crash occurs ? Even for these simple cases, there are pure analog
and pure digital parts that need to be modelled correctly.  For the flash ADC the resistor chain and comparators
are almost pure analog, but the thermometer encoder is definitely pure digital, For the single slope design,
the comparator is almost pure analog, but the counter is pure digital. Also, for starters, focus on the actual
physical design and experiment how it might be translated to a high level design. The problem with high
level methods is determining how to abstract out the key steps, from the physical design. Hope that helps.
Link to comment
Share on other sites

Hello All, 

 

Can we use "while loops" in SystemC-AMS constructs (TDF modeling) ? 

Can somebody refer a tutorial or a reference code which uses while loop in SC-AMS.

 

thanks, 

Milind.

 

Hello Sir,

There is no need to use a while loop, except

perhaps in some special case, in the TDF

framework. The TDF framework offers a set of

methods that can be overriden and if used

correctly/wisely will remove the need for a

while loop.

In the 'set_attributes()' method, one can

use the built-in 'set_timestep()' method to

set when data is read in from an input port,

or read out to an output port. So at tick or

sub-interval of the total simulation time,

data is read in/out as specified.

But this is what is done in pure SystemC as

well, for a SC_THREAD or SC_CTHREAD. There

A sensitivity list defines the triggering

event, often a clock, at which the thread

has to respond. So the thread is set up as

an infinite loop, that 'waits' for a triggering

event.

So, SystemC-AMS provides a cleaner design

that does not force the designer to explicitly

track the triggering event. In the 'processing'

method, the actual processing is done.

Hope that helps.

  

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