This page describes the code of the systemc parameterized CRC module.
-
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.
-
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.
-
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();
...
-
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();
-
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();
-
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
...
-
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);
-
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;
}
-
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: |