简体   繁体   中英

Is there a better/alternate way to implement delay in SystemC Modules

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?

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 系统 Wavefroms

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM