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


V

 

This page describes the code of the systemc parameterized CRC module.

  1. This generic serial CRC module, optionally gets input from user and during elaborate phase, it dynamically instantiates the required components, registers and x-or gates and connects them all.


  2. I have learned a lot from this project.
    First the goal was to be able to create a highly generic systemc component.
    When working with pointers, memory run over may occurs. In my case resulting in segmentation fault error. This is best debugged using a debugger. I selected GDB. Of great help was the debugger command bt: back trace.

  3. The user may select to control the used polynum and its length form the command line. In that case the values are checked. When non-valid choices are made, it is fixed by the code. An assertion in the automatically insertion code makes sure, that a wrong value did not selected.
    ...
    int sc_main(int argc, char* argv[]) {
      unsigned pol_len = 32;

      if (argc > 1) pol_len = atoi (argv[1]);
      if (pol_len < 4) pol_len = 4;
      if (pol_len > 32) pol_len = 32;
      cout << "crc_aut_inst pol_len=" << pol_len << " a=" << argc << endl;
    ...
    //connect clock to every flop register
    regp->pclk(pclk);

    if( i == 0 ) {
      if( (pol & 0x1) == 0 ) {
        cout << "crc_aut_inst error x(0) of polynum must be 1 " << sc_time_stamp() << endl;
        sc_stop();
    ...

  4. The function sc_stop() can be replaced by SC_REPORT_ERROR to stop and print an error message.
    crc_aut_inst(
      sc_module_name name, unsigned pol, unsigned pol_len, sc_trace_file* _tf
    ): sc_module(name), tf(_tf) {
      char inst_buf[10];
      static const char* MSGID = "crc_auto_inst MDG";
      ...
        cout << "crc_aut_inst error x(0) of polynum must be 1 " << sc_time_stamp() << endl;
        SC_REPORT_ERROR(MSGID, "crc_aut_inst errorst");
        //sc_stop();

  5. The test-bench includes a generator, which drives stimuli. To make thing simple, I created an array of bytes and have them initialized. The data is taken from an ethernet project, which is also available at this site: IP STACK ethernet project .

    The generator is implemented using the statement SC_THREAD so later I can wait one cycle using the simple statement wait() .
    //SC_HAS_PROCESS(pkt_drive);
    //pkt_drive(sc_module_name name): sc_module(name)
    SC_CTOR(pkt_drive) {
      //SC_METHOD(gen_p);
      SC_THREAD(gen_p);
      sensitive << pclk.pos();

  6. Per each polynum coefficient, a register is instantiated. Depending on coefficient value a x-or gate may be instantiated (1 means instantiate). The string inst_buf is used for selecting the instance name. A register gets the name u_[0-9]* and x-or gate is named x_[0-9]*.
    char inst_buf[10];
    ...
    //auto inst
    for (unsigned i=0; i < pol_len; i++) {
      sprintf(inst_buf, "u_%d", i); //instance name
      reg* regp = new reg(inst_buf);
      cout << "crc_aut_inst inst=" << inst_buf << endl;

      //connect clock to every flop register
      regp->pclk(pclk);
    ...
    if( (pol & 0x1) == 0 ) {
      regp->data_in(*data_pr);
    } else {
    sc_signal<bool>* sig_xor_o = new sc_signal<bool>;
    sprintf(inst_buf, "x_%d", i); //instance name
    bool_xor* u_xor = new bool_xor(inst_buf);
    u_xor->a(data_in);
    u_xor->b(*data_pr);
    u_xor->o(*sig_xor_o);

    regp->data_in(*sig_xor_o);//tmp
    ...

  7. VCD waves are recorded both at the highest level and in crc_auto_inst module. A c_trace_file *tf pointer is passed to the module.
    sc_trace_file *tf;
    tf = sc_create_vcd_trace_file("crc_auto_inst");

    //26, 23, 22, 16, 12, 11, 10, 8, 7, 5, 4, 2, 1, 0
    //33222222222211111111110000000000
    //10987654321098765432109876543210
    //00000100110000010001110110110111
    crc_aut_inst u_dut("u_dut", 0x04c11db7, pol_len, tf);
    ...
    //crc auto instance
    class crc_aut_inst : public sc_module {
    public:
      sc_trace_file *tf;
    ...
      crc_aut_inst(
        sc_module_name name, unsigned pol, unsigned pol_len, sc_trace_file* _tf
      ): sc_module(name), tf(_tf) {
      char inst_buf[10];

      sc_signal* data_pr = 0;//previous data
      //sc_trace(tf, pclk, "clk");
      br>   sprintf(inst_buf, "s_%d", i); //instance name
      sc_trace(tf, *data_pr, inst_buf);

  8. To debug one can print the instance name:
    class reg : public sc_module {
    ...
      void main() {
        data_ou = data_in.read();
        cout << "reg " << name() << " " << sc_time_stamp() << endl;
      }

  9. If a break point in the auto instance component is required, one can add the following code and put there a break point:
    if(strcmp(name(), "u_dut.u_26")) {//no match
      cout << "reg1 " << name() << " " << sc_time_stamp() << endl;
    } else {//match
      //Place a break point on this line.
      cout << "reg2 " << name() << " " << sc_time_stamp() << endl;
    }


To go to main project page: systemc parameterized CRC module .

Contact me now at:

  ...


I would be happy to offer my services. Call ASAP !


Home

An extension to the systemc example from cadance of producer consumer.

SD slave with Samsung flash (vhdl project).






Search This Site


Feedback This Site




new pages on this site