+ Post New Thread
Results 1 to 6 of 6
  1. #1
    Member level 2
    Points: 223, Level: 2

    Join Date
    Jul 2019
    Posts
    47
    Helped
    0 / 0
    Points
    223
    Level
    2

    $urandom for error insertion in Systemverilog

    Hi,

    I am making use of $urandom to insert an error in random bits of data. To begin with, I am inserting a 1 bit error, where the position bit is randomly chosen and flipped. I am new to SystemVerilog and I noticed that it only executes once. I give data to the module through my testbench, and I want it to iteratively add errors to the same data at different bit positions. I made use of repeat(50), but it does the final work only on the last data.

    Code:
    module error_inject (data_in, parity_in, data_out, parity_out);
    
        parameter DATA_WIDTH = 13; 
        parameter ERROR_WIDTH = $clog2(DATA_WIDTH);
    
        input [7:0] data_in;
        input [4:0] parity_in;
        output reg [7:0] data_out;
        output reg [4:0] parity_out;
    
        reg [ERROR_WIDTH-1:0] BIT_to_flip;
        reg [DATA_WIDTH-1:0] int_data;
    
        always @(*)
        repeat(50)
        begin 
        int_data = {data_in, parity_in};
    
        idx_to_flip = $urandom_range(0, DATA_WIDTH-1);
        $display("Flipping data bit %d", BIT_to_flip);
    
        int_data[BIT_to_flip] = !int_data[BIT_to_flip];
        $display("bad data = %b",int_data);
    
        data_out = int_data[12:5];
    
        parity_out = int_data[4:0];
    
        end 
    endmodule

    •   AltAdvertisement

        
       

  2. #2
    Super Moderator
    Points: 31,315, Level: 43
    ads-ee's Avatar
    Join Date
    Sep 2013
    Location
    USA
    Posts
    7,232
    Helped
    1710 / 1710
    Points
    31,315
    Level
    43

    Re: $urandom for error insertion in Systemverilog

    Only the last one because Verilog/Systemverilog loops are unrolled at compile time. They represent multiple instances of whatever is in the loop and not sequential operations.

    You also have a typo as there isn't any signal called idx_to_flip.

    I also would not use an always @(*) for doing this, I'd put this in a task or create a test FSM to run the test sequence if I needed it to be synthesizable.

    I wouldn't write software style assignments like you have in this code your relying on Systemverilog's event scheduling working exactly the way software programs run code. I would generate the errors by doing something straightforward and simple like this:
    Code Verilog - [expand]
    1
    2
    
    BIT_to_flip = 1'b1 << $urandom_range(0, DATA_WIDTH-1);   // set an error bit in a random location
    data_out = int_data ^ BIT_to_flip;   // invert the selected bit



    •   AltAdvertisement

        
       

  3. #3
    Member level 2
    Points: 223, Level: 2

    Join Date
    Jul 2019
    Posts
    47
    Helped
    0 / 0
    Points
    223
    Level
    2

    Re: $urandom for error insertion in Systemverilog

    Hi Ads-ee,

    Thank you for your reply. I made a few changes in the code. I initially had a different module for error injection. Now I made it a part of the top test bench and directly connected to other modules that send and receive data from this module. I also just made it a part of an initial block now. The error gets placed in the data now for as many number of times as is specified in the repeat statement. But it wont receive any inputs anymore. So all the other signals are high impedance.



    •   AltAdvertisement

        
       

  4. #4
    Super Moderator
    Points: 31,315, Level: 43
    ads-ee's Avatar
    Join Date
    Sep 2013
    Location
    USA
    Posts
    7,232
    Helped
    1710 / 1710
    Points
    31,315
    Level
    43

    Re: $urandom for error insertion in Systemverilog

    Can't help you if I don't see the code.



  5. #5
    Member level 2
    Points: 223, Level: 2

    Join Date
    Jul 2019
    Posts
    47
    Helped
    0 / 0
    Points
    223
    Level
    2

    Re: $urandom for error insertion in Systemverilog

    Hi,

    This is the code with a seperate module. Here, every module is able to interact with each other and send data. The for loop in the error module produces different data with different error bits but the final print statment only executes for the last data. I want it to execute for every iteration.

    Code:
    module test_bench ();
    
        parameter DATA_WIDTH = 13; 
        parameter IDX_WIDTH = $clog2(DATA_WIDTH);
    
        wire [4:0] parity_out_enc;
    
        wire [7:0] corr_data_out;
        wire [4:0] syndrome;
        wire uncorr, corr;
        wire flag;
        wire [4:0]      vxh;
        wire [4:0] parity_out;
        wire [7:0] data_dec;
        wire [4:0] parity_dec;
        wire [IDX_WIDTH-1:0] idx_to_flip;
    
        reg [7:0] data_enc;
        
        initial 
        begin 
    
            $display ("time\t parity_out_enc data_enc  idx_flip data_dec   parity_dec corr_data_out syndrome uncorr  corr vxh    flag  parity_out");  
            $monitor ("%g\t %b          %b  %d       %b   %b      %b      %b    %b        %b   %b  %b     %b", $time, parity_out_enc, data_enc, idx_to_flip, data_dec, parity_dec, corr_data_out, syndrome, uncorr, corr, vxh,                     flag, parity_out);
    
            data_enc = 8'b10101010;
    
        end 
    
        secded_8_enc encoder (parity_out_enc, data_enc);
        error_inject error_module (data_enc, parity_out_enc, data_dec, parity_dec, idx_to_flip);
        secded_8_dec decoder (corr_data_out, syndrome, uncorr, corr, vxh, flag, parity_out, data_dec, parity_dec);
    
    endmodule 
    
    module error_inject (data_in, parity_in, data_out, parity_out, idx_to_flip);
    
        parameter DATA_WIDTH = 13; 
        parameter IDX_WIDTH = $clog2(DATA_WIDTH);
    
        input [7:0] data_in;
        input [4:0] parity_in;
        output reg [7:0] data_out;
        output reg [4:0] parity_out;
        int i;
    
        output reg [IDX_WIDTH-1:0] idx_to_flip;
        reg [DATA_WIDTH-1:0] int_data;
    
        always@(*)
        begin 
        for (i=0;i<10;i=i+1)
        //repeat(10)
        begin 
        int_data = {data_in, parity_in};
    
        idx_to_flip = $urandom_range(DATA_WIDTH-1);
        $display("Flipping data bit %d", idx_to_flip);
    
        int_data[idx_to_flip] = !int_data[idx_to_flip];
        $display("bad data = %b",int_data);
    
         data_out = int_data[12:5];
    
         parity_out = int_data[4:0];
        end 
        end 
    endmodule



    •   AltAdvertisement

        
       

  6. #6
    Super Moderator
    Points: 31,315, Level: 43
    ads-ee's Avatar
    Join Date
    Sep 2013
    Location
    USA
    Posts
    7,232
    Helped
    1710 / 1710
    Points
    31,315
    Level
    43

    Re: $urandom for error insertion in Systemverilog

    I'm not sure what you are expecting, but the for loop is going to cycle through all 10 iterations in 0 ns.

    The entire structure of this testbench doesn't make a lot of sense to me and is more complicated than the one I wrote years ago for checking a hsaio (72,64) code.

    I would structure it with a clocked always block generating data and generating an error mask. The data generator would feed the encoder and the output of the encoder is XOR'd with the error mask and fed to the decoder. The output of the decoder is then checked against the generated data. I randomize the input data and the error mask along with keeping track of the number of errors and the position of the errors.

    Burying the error generation as a separate module with an always block and a for loop is not a good approach and it doesn't work due to the lack of any time control statements in the loop.



--[[ ]]--