2

I have implemented a 4 bit adder with delay in its output port.

SC_MODULE(adder4){
  sc_in<sc_uint<4>>   A,B;
  sc_out<sc_uint<4>>  OUT;
  
  sc_event ev;

  sc_uint<4> val_a,val_b,val_s;
  
  void add(){
    val_a = A.read();
    val_b = B.read();
  
    val_s = val_a + val_b;
    ev.notify(2,SC_NS);
  }

  void write(){
    OUT.write(val_s);
    ev.cancel();
  }
  
  SC_CTOR(adder4){
    SC_METHOD(add);
    dont_initialize();
    sensitive<<A<<B;
    
    SC_METHOD(write);
    dont_initialize();
    sensitive<<ev;
  }
};

My question is:

  • Is there any better way to implement a delay in a method?
  • Is there any direct/indirect disadvantages of using the sc_event?
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
IVIaster
  • 21
  • 4
  • My original answer to this appears to have a bug in it or at least am not convinced it doesn't. Will test it later today and repost when convinced it is correct – systemcpro Jul 21 '20 at 17:22

1 Answers1

0

This is an edited version of original answer that had an event dependency missing in the adder thread. This code has that dependency added.

Better is subjective I guess and is always subject to "better under what criteria". Here is an alternative method which is something like I would use. I say something like as it's all mushed into a bunch of templates but if you untangle them it comes out to something morally equivalent to the code below.

Since we are dealing with time I have added a system clock and a driver module to provide the inputs to the adder. I have also traced the signals to a vcd file so we can inspect the waveforms for correct delay against the system clock.

#include <systemc.h>

using data_t = sc_uint<4>;
const auto delay = sc_time(2.0, SC_NS);

// Asynchronous adder with output propagation delay
SC_MODULE(adder4){
    sc_in<data_t>   A,B;
    sc_out<data_t>  OUT;

    void add(){

       while(true){
         wait(A.default_event() | B.default_event());
         auto sum = A.read() + B.read();  //calculate sum
         wait(delay);                     //wait delay
         OUT.write(sum);                  //write sum after delay
       }
    }

    SC_CTOR(adder4){
        SC_THREAD(add)  //thread instead of process         
    }
};

SC_MODULE(driver){
    unsigned a,b;                //internal data values
    sc_in<bool> clk_in;          //system clock  input
    sc_out<data_t> out_a, out_b; //driver data outputs

    void proc(){
        out_a.write(a);
        out_b.write(b);

        //change internal data to drive test device. just increment
        a += 1;
        b += 2;
    }
    SC_CTOR(driver){
        a = b = 0;
        SC_METHOD(proc);
        sensitive << clk_in.pos();
        dont_initialize();
    }
};

using signal_t = sc_signal<data_t>;

int sc_main(int, char**){
    sc_clock clk("clk", 5, SC_NS); //system clock
    driver drv("driver");          //test case driver
    adder4 adder("adder");         //device under test

    //connect devices
    signal_t s1, s2, s3;
    drv.clk_in(clk);
    drv.out_a(s1);
    drv.out_b(s2);
    adder.A(s1);
    adder.B(s2);
    adder.OUT(s3);
    
    //trace signals to waveforms.vcd
    sc_trace_file *tf = sc_create_vcd_trace_file("waveforms");
    sc_trace(tf, clk, "clk");
    sc_trace(tf, s1, "A");
    sc_trace(tf, s2, "B");
    sc_trace(tf, s3, "OUT");

    sc_start(40, SC_NS);

    sc_close_vcd_trace_file(tf);

    return 0;
}

Executing this generates the vcd file "waveforms.vcd" which I have displayed in GTKViewer, an image of which is shown below. It can be clearly seen that the adder output is delayed by 2ns. Is this "the best" or "better"? I can't say but it is, more or less, a standard(ish) method of meeting your requirements. Leastwise it fulfills the requirement of being an alternative method as you asked. There are surely countably infinite ways of achieving the same result but, as I say, it's a standard(ish) method.

GTKViewer System Wavefroms

systemcpro
  • 856
  • 1
  • 7
  • 15
  • Previously I had trouble implementing as `SC_THREAD` because the input sensitivity was being missed. I see yourself got the same problem and cleared it. This helps me understand my mistake, Thanks. – IVIaster Jul 23 '20 at 11:52
  • 1
    I would like to see if there would be not other ways to do the same. – IVIaster Jul 23 '20 at 11:52