+ Post New Thread
Results 1 to 17 of 17
  1. #1
    Full Member level 5
    Points: 1,606, Level: 9

    Join Date
    Feb 2016
    Posts
    287
    Helped
    0 / 0
    Points
    1,606
    Level
    9

    A simple question on testbench stimulus

    For https://paste.ubuntu.com/p/cR6rtvxs7x/ and https://i.imgur.com/ROlyd53.png , why doesn't rCount increment its value at t=50ns when rState=2'd1 and CHNL_RX_DATA_VALID=1?

    Click image for larger version. 

Name:	Screenshot_ROlyd53.png 
Views:	7 
Size:	106.8 KB 
ID:	145144

    Code Verilog - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    
    // ----------------------------------------------------------------------
    // Copyright (c) 2016, The Regents of the University of California All
    // rights reserved.
    // 
    // Redistribution and use in source and binary forms, with or without
    // modification, are permitted provided that the following conditions are
    // met:
    // 
    //     * Redistributions of source code must retain the above copyright
    //       notice, this list of conditions and the following disclaimer.
    // 
    //     * Redistributions in binary form must reproduce the above
    //       copyright notice, this list of conditions and the following
    //       disclaimer in the documentation and/or other materials provided
    //       with the distribution.
    // 
    //     * Neither the name of The Regents of the University of California
    //       nor the names of its contributors may be used to endorse or
    //       promote products derived from this software without specific
    //       prior written permission.
    // 
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL REGENTS OF THE
    // UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY DIRECT, INDIRECT,
    // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
    // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
    // OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
    // TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
    // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
    // DAMAGE.
    // ----------------------------------------------------------------------
    //----------------------------------------------------------------------------
    // Filename:            chnl_tester.v
    // Version:             1.00.a
    // Verilog Standard:    Verilog-2001
    // Description:         Sample RIFFA channel user module. Designed to exercise
    //                      the RIFFA TX and RX interfaces. Receives data on the
    //                      RX interface and saves the last value received. Sends
    //                      the same amount of data back on the TX interface. The
    //                      returned data starts with the last value received, 
    //                      resets and increments to end with a value equal to the
    //                      number of (4 byte) words sent back on the TX interface.
    // Author:              Matt Jacobsen
    // History:             @mattj: Version 2.0
    //-----------------------------------------------------------------------------
    `timescale 1ns/1ns
    module chnl_tester #(
        parameter C_PCI_DATA_WIDTH = 9'd32
    )
    (
        input CLK,
        input RST,
        output CHNL_RX_CLK, 
        input CHNL_RX, 
        output CHNL_RX_ACK, 
        input CHNL_RX_LAST, 
        input [31:0] CHNL_RX_LEN, 
        input [30:0] CHNL_RX_OFF, 
        input [C_PCI_DATA_WIDTH-1:0] CHNL_RX_DATA, 
        input CHNL_RX_DATA_VALID, 
        output CHNL_RX_DATA_REN,
        
        output CHNL_TX_CLK, 
        output CHNL_TX, 
        input CHNL_TX_ACK, 
        output CHNL_TX_LAST, 
        output [31:0] CHNL_TX_LEN, 
        output [30:0] CHNL_TX_OFF, 
        output [C_PCI_DATA_WIDTH-1:0] CHNL_TX_DATA, 
        output CHNL_TX_DATA_VALID, 
        input CHNL_TX_DATA_REN
    );
     
    reg [C_PCI_DATA_WIDTH-1:0] rData={C_PCI_DATA_WIDTH{1'b0}};
    reg [31:0] rLen=0;
    reg [31:0] rCount=0;
    reg [1:0] rState=0;
     
    assign CHNL_RX_CLK = CLK;
    assign CHNL_RX_ACK = (rState == 2'd1);
    assign CHNL_RX_DATA_REN = (rState == 2'd1);
     
    assign CHNL_TX_CLK = CLK;
    assign CHNL_TX = (rState == 2'd3);
    assign CHNL_TX_LAST = 1'd1;
    assign CHNL_TX_LEN = rLen; // in words
    assign CHNL_TX_OFF = 0;
    assign CHNL_TX_DATA = rData;
    assign CHNL_TX_DATA_VALID = (rState == 2'd3);
     
    always @(posedge CLK or posedge RST) begin
        if (RST) begin
            rLen <= 0;
            rCount <= 0;
            rState <= 0;
            rData <= 0;
        end
        else begin
            case (rState)
            
            2'd0: begin // Wait for start of RX, save length
                if (CHNL_RX) begin
                    rLen <= CHNL_RX_LEN;
                    rCount <= 0;
                    rState <= 2'd1;
                end
            end
            
            2'd1: begin // Wait for last data in RX, save value
                if (CHNL_RX_DATA_VALID) begin
                    rData <= CHNL_RX_DATA;
                    rCount <= rCount + (C_PCI_DATA_WIDTH/32);
                end
                if (rCount >= rLen)
                    rState <= 2'd2;
            end
     
            2'd2: begin // Prepare for TX
                rCount <= (C_PCI_DATA_WIDTH/32);
                rState <= 2'd3;
            end
     
            2'd3: begin // Start TX with save length and data value
                if (CHNL_TX_DATA_REN & CHNL_TX_DATA_VALID) begin
                  rData <= {rCount + 2'd4, rCount + 2'd3, rCount + 2'd2, rCount + 2'd1};
                    rCount <= rCount + (C_PCI_DATA_WIDTH/32);
                    if (rCount >= rLen)
                        rState <= 2'd0;
                end
            end
            
            endcase
        end
    end
     
    /*
    wire [35:0] wControl0;
    chipscope_icon_1 cs_icon(
        .CONTROL0(wControl0)
    );
     
    chipscope_ila_t8_512 a0(
        .CLK(CLK), 
        .CONTROL(wControl0), 
        .TRIG0({3'd0, (rCount >= 800), CHNL_RX, CHNL_RX_DATA_VALID, rState}),
        .DATA({442'd0,
                CHNL_TX_DATA_REN, // 1
                CHNL_TX_ACK, // 1
                CHNL_RX_DATA, // 64
                CHNL_RX_DATA_VALID, // 1
                CHNL_RX, // 1
                rState}) // 2
    );
    */
     
    endmodule

    Code Verilog - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    
    // Testbench
    module test;
     
      parameter C_PCI_DATA_WIDTH = 9'd128;  // NUMBER_OF_BITS_PER_TRANSACTION
      
      reg CLK;
      reg RST;
      wire CHNL_RX_CLK;
      reg CHNL_RX;
      wire CHNL_RX_ACK;
      reg CHNL_RX_LAST;
      reg [31:0] CHNL_RX_LEN;
      reg [30:0] CHNL_RX_OFF;
      reg [C_PCI_DATA_WIDTH-1:0] CHNL_RX_DATA;
      reg CHNL_RX_DATA_VALID;
      wire CHNL_RX_DATA_REN;
      
      wire CHNL_TX_CLK;
      wire CHNL_TX;
      reg CHNL_TX_ACK;
      wire CHNL_TX_LAST;
      wire [31:0] CHNL_TX_LEN;
      wire [30:0] CHNL_TX_OFF;
      wire [C_PCI_DATA_WIDTH-1:0] CHNL_TX_DATA;
      wire CHNL_TX_DATA_VALID;
      reg CHNL_TX_DATA_REN;
      
      // Instantiate design under test
      chnl_tester #(
        .C_PCI_DATA_WIDTH(C_PCI_DATA_WIDTH)
      ) 
      riffa_channel (
        /*Signals to receive from PC via RIFFA core, transmit to FPGA via this chnl_tester module*/
        .CLK(CLK),
        .RST(RST),
        .CHNL_RX_CLK(CHNL_RX_CLK), 
        .CHNL_RX(CHNL_RX), 
        .CHNL_RX_ACK(CHNL_RX_ACK), 
        .CHNL_RX_LAST(CHNL_RX_LAST), 
        .CHNL_RX_LEN(CHNL_RX_LEN), 
        .CHNL_RX_OFF(CHNL_RX_OFF), 
        .CHNL_RX_DATA(CHNL_RX_DATA), 
        .CHNL_RX_DATA_VALID(CHNL_RX_DATA_VALID), 
        .CHNL_RX_DATA_REN(CHNL_RX_DATA_REN),
     
        /*Signals to transmit to PC via RIFFA core, receive from FPGA via this chnl_tester module*/
        .CHNL_TX_CLK(CHNL_TX_CLK), 
        .CHNL_TX(CHNL_TX), 
        .CHNL_TX_ACK(CHNL_TX_ACK), 
        .CHNL_TX_LAST(CHNL_TX_LAST), 
        .CHNL_TX_LEN(CHNL_TX_LEN), 
        .CHNL_TX_OFF(CHNL_TX_OFF), 
        .CHNL_TX_DATA(CHNL_TX_DATA), 
        .CHNL_TX_DATA_VALID(CHNL_TX_DATA_VALID), 
        .CHNL_TX_DATA_REN(CHNL_TX_DATA_REN)
      );
              
      initial begin
        // Dump waves
        $dumpfile("dump.vcd");
        $dumpvars(0);
        
        CLK = 0;
        RST = 0;
        CHNL_RX = 0;
        CHNL_RX_LAST = 1;
        CHNL_RX_LEN = 0;
        CHNL_RX_OFF = 0;
        CHNL_RX_DATA = 10;
        CHNL_RX_DATA_VALID = 0;
        
        CHNL_TX_ACK = 0;
        CHNL_TX_DATA_REN = 0;
        
        #20 RST = 1;
        #20 RST = 0;
        #10 CHNL_RX = 1; CHNL_RX_LEN = 4; CHNL_RX_DATA_VALID = 1;
        #20 CHNL_RX_DATA_VALID = 0;
        #80 CHNL_TX_ACK = 1;
        #20 CHNL_TX_ACK = 0;  CHNL_TX_DATA_REN = 1; CHNL_RX = 0;
        #40 CHNL_TX_DATA_REN = 0;
        
        #400 $finish;
        
      end
      
      always@(posedge CLK) begin
        if(CHNL_RX_DATA_VALID && CHNL_RX_DATA_REN) 
            CHNL_RX_DATA <= CHNL_RX_DATA + 1;
      end
      
      always #10 CLK <= !CLK;
     
    endmodule

  2. #2
    Advanced Member level 3
    Points: 5,248, Level: 17

    Join Date
    Feb 2015
    Posts
    872
    Helped
    250 / 250
    Points
    5,248
    Level
    17

    Re: A simple question on testbench stimulus

    my guess would be a race condition with the blocking assignments in the testbench. Perhaps you could use @(posedge clk)



  3. #3
    Full Member level 5
    Points: 1,606, Level: 9

    Join Date
    Feb 2016
    Posts
    287
    Helped
    0 / 0
    Points
    1,606
    Level
    9

    Re: A simple question on testbench stimulus

    race condition with the blocking assignments in the testbench
    Would you mind elaborating ? Which blocking statements specifically ?



    •   Alt7th March 2018, 08:18

      advertising

        
       

  4. #4
    Advanced Member level 5
    Points: 36,062, Level: 46
    Achievements:
    7 years registered

    Join Date
    Jun 2010
    Posts
    6,589
    Helped
    1924 / 1924
    Points
    36,062
    Level
    46

    Re: A simple question on testbench stimulus

    The clock transition occurs after CHNL_RX_DATA_VALID is set to one - this is the race condition. Instead of using absolute times for the stimulus, you should make them synchronous to the clock



  5. #5
    Full Member level 5
    Points: 1,606, Level: 9

    Join Date
    Feb 2016
    Posts
    287
    Helped
    0 / 0
    Points
    1,606
    Level
    9

    Re: A simple question on testbench stimulus

    The clock transition occurs after CHNL_RX_DATA_VALID is set to one - this is the race condition
    I do not get what you exactly mean by the above quote.

    Someone else helped me to modify the state machine to as below with the same testbench, the problem disappeared. Could anyone explain why ?

    Code Verilog - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    
    // ----------------------------------------------------------------------
    // Copyright (c) 2016, The Regents of the University of California All
    // rights reserved.
    // 
    // Redistribution and use in source and binary forms, with or without
    // modification, are permitted provided that the following conditions are
    // met:
    // 
    //     * Redistributions of source code must retain the above copyright
    //       notice, this list of conditions and the following disclaimer.
    // 
    //     * Redistributions in binary form must reproduce the above
    //       copyright notice, this list of conditions and the following
    //       disclaimer in the documentation and/or other materials provided
    //       with the distribution.
    // 
    //     * Neither the name of The Regents of the University of California
    //       nor the names of its contributors may be used to endorse or
    //       promote products derived from this software without specific
    //       prior written permission.
    // 
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL REGENTS OF THE
    // UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY DIRECT, INDIRECT,
    // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
    // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
    // OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
    // TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
    // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
    // DAMAGE.
    // ----------------------------------------------------------------------
    //----------------------------------------------------------------------------
    // Filename:            chnl_tester.v
    // Version:             1.00.a
    // Verilog Standard:    Verilog-2001
    // Description:         Sample RIFFA channel user module. Designed to exercise
    //                      the RIFFA TX and RX interfaces. Receives data on the
    //                      RX interface and saves the last value received. Sends
    //                      the same amount of data back on the TX interface. The
    //                      returned data starts with the last value received, 
    //                      resets and increments to end with a value equal to the
    //                      number of (4 byte) words sent back on the TX interface.
    // Author:              Matt Jacobsen
    // History:             @mattj: Version 2.0
    //-----------------------------------------------------------------------------
    `timescale 1ns/1ns
    module chnl_tester #(
        parameter C_PCI_DATA_WIDTH = 9'd32
    )
    (
        input CLK,
        input RST,
        output CHNL_RX_CLK, 
        input CHNL_RX, 
        output CHNL_RX_ACK, 
        input CHNL_RX_LAST, 
        input [31:0] CHNL_RX_LEN, 
        input [30:0] CHNL_RX_OFF, 
        input [C_PCI_DATA_WIDTH-1:0] CHNL_RX_DATA, 
        input CHNL_RX_DATA_VALID, 
        output CHNL_RX_DATA_REN,
        
        output CHNL_TX_CLK, 
        output CHNL_TX, 
        input CHNL_TX_ACK, 
        output CHNL_TX_LAST, 
        output [31:0] CHNL_TX_LEN, 
        output [30:0] CHNL_TX_OFF, 
        output [C_PCI_DATA_WIDTH-1:0] CHNL_TX_DATA, 
        output CHNL_TX_DATA_VALID, 
        input CHNL_TX_DATA_REN
    );
     
      reg [C_PCI_DATA_WIDTH-1:0] rData={C_PCI_DATA_WIDTH{1'b0}};
      reg [C_PCI_DATA_WIDTH-1:0] rDataNext={C_PCI_DATA_WIDTH{1'b0}};
      
      reg [31:0] rLen=0, rLenNext=0;
      reg [31:0] rCount=0, rCountNext=0;
      reg [1:0] rState=0, rStateNext=0;
     
      assign CHNL_RX_CLK = CLK;
      assign CHNL_RX_ACK = (rState == 2'd1);
      assign CHNL_RX_DATA_REN = (rState == 2'd1);
     
      assign CHNL_TX_CLK = CLK;
      assign CHNL_TX = (rState == 2'd3);
      assign CHNL_TX_LAST = 1'd1;
      assign CHNL_TX_LEN = rLen; // in words
      assign CHNL_TX_OFF = 0;
      assign CHNL_TX_DATA = rData;
      assign CHNL_TX_DATA_VALID = (rState == 2'd3);
     
      always @(posedge CLK or posedge RST) begin
          if (RST) begin
              rLen <= 0;
              rCount <= 0;
              rState <= 0;
              rData <= 0;
          end
          else begin
            rData <= rDataNext;
            rLen  <= rLenNext;
            rCount <= rCountNext;
            rState <= rStateNext;
     
          end  
      end
      
      always @ * begin
          case (rState)
     
            2'd0: begin // Wait for start of RX, save length
              if (CHNL_RX) begin
                rLenNext = CHNL_RX_LEN;
                rCountNext = 0;
                rStateNext = 2'd1;
              end
            end
     
            2'd1: begin // Wait for last data in RX, save value
              if (CHNL_RX_DATA_VALID) begin
                rDataNext = CHNL_RX_DATA;
                rCountNext = rCount + (C_PCI_DATA_WIDTH/32);
              end
              if (rCount >= rLen)
                rStateNext = 2'd2;
            end
     
            2'd2: begin // Prepare for TX
              rCountNext = (C_PCI_DATA_WIDTH/32);
              rStateNext = 2'd3;
            end
     
            2'd3: begin // Start TX with save length and data value
              if (CHNL_TX_DATA_REN & CHNL_TX_DATA_VALID) begin
                rDataNext = {rCount + 2'd4, rCount + 2'd3, rCount + 2'd2, rCount + 2'd1};
                rCountNext = rCount + (C_PCI_DATA_WIDTH/32);
                if (rCount >= rLen)
                  rStateNext = 2'd0;
              end
            end
            
          endcase
      end
     
    /*
    wire [35:0] wControl0;
    chipscope_icon_1 cs_icon(
        .CONTROL0(wControl0)
    );
     
    chipscope_ila_t8_512 a0(
        .CLK(CLK), 
        .CONTROL(wControl0), 
        .TRIG0({3'd0, (rCount >= 800), CHNL_RX, CHNL_RX_DATA_VALID, rState}),
        .DATA({442'd0,
                CHNL_TX_DATA_REN, // 1
                CHNL_TX_ACK, // 1
                CHNL_RX_DATA, // 64
                CHNL_RX_DATA_VALID, // 1
                CHNL_RX, // 1
                rState}) // 2
    );
    */
     
    endmodule



  6. #6
    Advanced Member level 5
    Points: 36,062, Level: 46
    Achievements:
    7 years registered

    Join Date
    Jun 2010
    Posts
    6,589
    Helped
    1924 / 1924
    Points
    36,062
    Level
    46

    Re: A simple question on testbench stimulus

    Code:
    #10 CHNL_RX = 1; CHNL_RX_LEN = 4; CHNL_RX_DATA_VALID = 1;
    ....
    #10 CLK <= !CLK;
    Here, the clock edge and setting CHNL_RX_DATA_VALID to 1 occur at the same time. So when the UUT detects the clock edge it will also see that CHNL_RX_DATA_VALID is 1.
    In a testbench, only the clock should use # times. EVERYTHING ELSE should change relative to the clock

    Code:
    initial begin
        // Dump waves
        $dumpfile("dump.vcd");
        $dumpvars(0);
        
        CLK = 0;
        RST = 0;
        CHNL_RX = 0;
        CHNL_RX_LAST = 1;
        CHNL_RX_LEN = 0;
        CHNL_RX_OFF = 0;
        CHNL_RX_DATA = 10;
        CHNL_RX_DATA_VALID = 0;
        
        CHNL_TX_ACK = 0;
        CHNL_TX_DATA_REN = 0;
        
        repeat(2) @(posedge clk);
        RST = 1;
    
        repeat(2) @(posedge clk);
        RST = 0;
    
        //etc


    1 members found this post helpful.

  7. #7
    Full Member level 5
    Points: 1,606, Level: 9

    Join Date
    Feb 2016
    Posts
    287
    Helped
    0 / 0
    Points
    1,606
    Level
    9

    Re: A simple question on testbench stimulus

    In a testbench, only the clock should use # times. EVERYTHING ELSE should change relative to the clock
    I am not really sure how your example testbench code applies for CHNL_RX_DATA_VALID which is only asserted for ONE clock cycle.

    Besides, how is #5 able to go around this race condition ? It seems to me that it is stabilizing the combinatorial logic output by introducing one extra register layer for rState, rCount, rData and rLen. But I am not fully sure. Could anyone advise further ?
    Last edited by promach; 7th March 2018 at 09:56.



  8. #8
    Super Moderator
    Points: 244,657, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    42,502
    Helped
    12950 / 12950
    Points
    244,657
    Level
    100

    Re: A simple question on testbench stimulus

    I am not really sure how your example testbench code applies for CHNL_RX_DATA_VALID which is only asserted for ONE clock cycle.
    It's an example how to generate stimuli relative to clock edge. The method has to be adapted for CHNL_RX_DATA_VALID respectively.

    Of course you can generate all test bench signals with absolute timing if you prefer it for some reason. But you need to care yourself that you don't generate race conditions.

    More generally I would ask, which kind of input signals should be modelled by your test bench? If they are considered as output of another module running with the same clock, the timing should be modelled correctly, means all signals must be set at least one simulation cycle behind the clock edge, never simultaneously. If they are asynchronous signals expected to change at arbitrary times, it's the DUT's job to synchronize it to the system clock before reading it.

    Besides, how is #5 able to go around this race condition ?
    The always(*) block is delaying count_next by one simulation cycle, so it arrives at the synchronous block behind the clock edge. I would say, removing the failure this way is rather a side effect than a straightforward solution.

    - - - Updated - - -

    Looking at the #5 code again, I fear that the correct function depends on a specific scheduling order of both always blocks, the solution can still fail under circumstances.


    1 members found this post helpful.

    •   Alt7th March 2018, 10:27

      advertising

        
       

  9. #9
    Full Member level 5
    Points: 1,606, Level: 9

    Join Date
    Feb 2016
    Posts
    287
    Helped
    0 / 0
    Points
    1,606
    Level
    9

    Re: A simple question on testbench stimulus

    I have modified the testbench accordingly, yet rCount is still not incremented. Why ?

    Code Verilog - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    
    // Testbench
    module test;
     
      parameter C_PCI_DATA_WIDTH = 9'd128;  // NUMBER_OF_BITS_PER_TRANSACTION
      
      reg CLK;
      reg RST;
      wire CHNL_RX_CLK;
      reg CHNL_RX;
      wire CHNL_RX_ACK;
      reg CHNL_RX_LAST;
      reg [31:0] CHNL_RX_LEN;
      reg [30:0] CHNL_RX_OFF;
      reg [C_PCI_DATA_WIDTH-1:0] CHNL_RX_DATA;
      reg CHNL_RX_DATA_VALID;
      wire CHNL_RX_DATA_REN;
      
      wire CHNL_TX_CLK;
      wire CHNL_TX;
      reg CHNL_TX_ACK;
      wire CHNL_TX_LAST;
      wire [31:0] CHNL_TX_LEN;
      wire [30:0] CHNL_TX_OFF;
      wire [C_PCI_DATA_WIDTH-1:0] CHNL_TX_DATA;
      wire CHNL_TX_DATA_VALID;
      reg CHNL_TX_DATA_REN;
      
      // Instantiate design under test
      chnl_tester #(
        .C_PCI_DATA_WIDTH(C_PCI_DATA_WIDTH)
      ) 
      riffa_channel (
        /*Signals to receive from PC via RIFFA core, transmit to FPGA via this chnl_tester module*/
        .CLK(CLK),
        .RST(RST),
        .CHNL_RX_CLK(CHNL_RX_CLK), 
        .CHNL_RX(CHNL_RX), 
        .CHNL_RX_ACK(CHNL_RX_ACK), 
        .CHNL_RX_LAST(CHNL_RX_LAST), 
        .CHNL_RX_LEN(CHNL_RX_LEN), 
        .CHNL_RX_OFF(CHNL_RX_OFF), 
        .CHNL_RX_DATA(CHNL_RX_DATA), 
        .CHNL_RX_DATA_VALID(CHNL_RX_DATA_VALID), 
        .CHNL_RX_DATA_REN(CHNL_RX_DATA_REN),
     
        /*Signals to transmit to PC via RIFFA core, receive from FPGA via this chnl_tester module*/
        .CHNL_TX_CLK(CHNL_TX_CLK), 
        .CHNL_TX(CHNL_TX), 
        .CHNL_TX_ACK(CHNL_TX_ACK), 
        .CHNL_TX_LAST(CHNL_TX_LAST), 
        .CHNL_TX_LEN(CHNL_TX_LEN), 
        .CHNL_TX_OFF(CHNL_TX_OFF), 
        .CHNL_TX_DATA(CHNL_TX_DATA), 
        .CHNL_TX_DATA_VALID(CHNL_TX_DATA_VALID), 
        .CHNL_TX_DATA_REN(CHNL_TX_DATA_REN)
      );
              
      initial begin
        // Dump waves
        $dumpfile("dump.vcd");
        $dumpvars(0);
        
        CLK = 0;
        RST = 0;
        CHNL_RX = 0;
        CHNL_RX_LAST = 1;
        CHNL_RX_LEN = 0;
        CHNL_RX_OFF = 0;
        CHNL_RX_DATA = 10;
        CHNL_RX_DATA_VALID = 0;
        
        CHNL_TX_ACK = 0;
        CHNL_TX_DATA_REN = 0;
        
        repeat(2) @(posedge CLK);
        RST = 1;
     
        repeat(2) @(posedge CLK);
        RST = 0;
        
        repeat(1) @(posedge CLK) begin
            CHNL_RX = 1; CHNL_RX_LEN = 4; CHNL_RX_DATA_VALID = 1;
        end
        
        repeat(1) @(posedge CLK);
        CHNL_RX_DATA_VALID = 0;
        
        repeat(4) @(posedge CLK);
        CHNL_TX_ACK = 1;
        
        repeat(1) @(posedge CLK) begin
            CHNL_TX_ACK = 0;  CHNL_TX_DATA_REN = 1; CHNL_RX = 0;
        end
        
        repeat(2) @(posedge CLK);
        CHNL_TX_DATA_REN = 0;
        
        repeat(20) @(posedge CLK);
        $finish;
        
        /*
        #20 RST = 1;
        #20 RST = 0;
        #10 CHNL_RX = 1; CHNL_RX_LEN = 4; 
        #20 CHNL_RX_DATA_VALID = 1;
        #20 CHNL_RX_DATA_VALID = 0;
        #60 CHNL_TX_ACK = 1;
        #20 CHNL_TX_ACK = 0;  CHNL_TX_DATA_REN = 1; CHNL_RX = 0;
        #40 CHNL_TX_DATA_REN = 0;
        
        #150 $finish;
        */   
        
      end
      
      always@(posedge CLK) begin
        if(CHNL_RX_DATA_VALID && CHNL_RX_DATA_REN) 
            CHNL_RX_DATA <= CHNL_RX_DATA + 1;
      end
      
      always #10 CLK <= !CLK;
     
    endmodule



  10. #10
    Advanced Member level 5
    Points: 36,062, Level: 46
    Achievements:
    7 years registered

    Join Date
    Jun 2010
    Posts
    6,589
    Helped
    1924 / 1924
    Points
    36,062
    Level
    46

    Re: A simple question on testbench stimulus

    If you checked the new waveform, you'll see CHNL_RX_DATA_VALID is set when the state is 0, as you assert CHNL_RX at the same time CHNL_RX_DATA_VALID.



  11. #11
    Full Member level 5
    Points: 1,606, Level: 9

    Join Date
    Feb 2016
    Posts
    287
    Helped
    0 / 0
    Points
    1,606
    Level
    9

    Re: A simple question on testbench stimulus

    assert CHNL_RX at the same time CHNL_RX_DATA_VALID.
    Why does rState transition to next state at the same clock edge at which CHNL_RX is asserted ?

    Code Verilog - [expand]
    1
    2
    3
    4
    5
    6
    7
    
    2'd0: begin // Wait for start of RX, save length
                if (CHNL_RX) begin
                    rLen <= CHNL_RX_LEN;
                    rCount <= 0;
                    rState <= 2'd1;
                end
            end

    Modified testbench

    Code Verilog - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    
    // Testbench
    module test;
     
      parameter C_PCI_DATA_WIDTH = 9'd128;  // NUMBER_OF_BITS_PER_TRANSACTION
      
      reg CLK;
      reg RST;
      wire CHNL_RX_CLK;
      reg CHNL_RX;
      wire CHNL_RX_ACK;
      reg CHNL_RX_LAST;
      reg [31:0] CHNL_RX_LEN;
      reg [30:0] CHNL_RX_OFF;
      reg [C_PCI_DATA_WIDTH-1:0] CHNL_RX_DATA;
      reg CHNL_RX_DATA_VALID;
      wire CHNL_RX_DATA_REN;
      
      wire CHNL_TX_CLK;
      wire CHNL_TX;
      reg CHNL_TX_ACK;
      wire CHNL_TX_LAST;
      wire [31:0] CHNL_TX_LEN;
      wire [30:0] CHNL_TX_OFF;
      wire [C_PCI_DATA_WIDTH-1:0] CHNL_TX_DATA;
      wire CHNL_TX_DATA_VALID;
      reg CHNL_TX_DATA_REN;
      
      // Instantiate design under test
      chnl_tester #(
        .C_PCI_DATA_WIDTH(C_PCI_DATA_WIDTH)
      ) 
      riffa_channel (
        /*Signals to receive from PC via RIFFA core, transmit to FPGA via this chnl_tester module*/
        .CLK(CLK),
        .RST(RST),
        .CHNL_RX_CLK(CHNL_RX_CLK), 
        .CHNL_RX(CHNL_RX), 
        .CHNL_RX_ACK(CHNL_RX_ACK), 
        .CHNL_RX_LAST(CHNL_RX_LAST), 
        .CHNL_RX_LEN(CHNL_RX_LEN), 
        .CHNL_RX_OFF(CHNL_RX_OFF), 
        .CHNL_RX_DATA(CHNL_RX_DATA), 
        .CHNL_RX_DATA_VALID(CHNL_RX_DATA_VALID), 
        .CHNL_RX_DATA_REN(CHNL_RX_DATA_REN),
     
        /*Signals to transmit to PC via RIFFA core, receive from FPGA via this chnl_tester module*/
        .CHNL_TX_CLK(CHNL_TX_CLK), 
        .CHNL_TX(CHNL_TX), 
        .CHNL_TX_ACK(CHNL_TX_ACK), 
        .CHNL_TX_LAST(CHNL_TX_LAST), 
        .CHNL_TX_LEN(CHNL_TX_LEN), 
        .CHNL_TX_OFF(CHNL_TX_OFF), 
        .CHNL_TX_DATA(CHNL_TX_DATA), 
        .CHNL_TX_DATA_VALID(CHNL_TX_DATA_VALID), 
        .CHNL_TX_DATA_REN(CHNL_TX_DATA_REN)
      );
              
      initial begin
        // Dump waves
        $dumpfile("dump.vcd");
        $dumpvars(0);
        
        CLK = 0;
        RST = 0;
        CHNL_RX = 0;
        CHNL_RX_LAST = 1;
        CHNL_RX_LEN = 0;
        CHNL_RX_OFF = 0;
        CHNL_RX_DATA = 0;
        CHNL_RX_DATA_VALID = 0;
        
        CHNL_TX_ACK = 0;
        CHNL_TX_DATA_REN = 0;
        
        repeat(2) @(posedge CLK);
        RST = 1;
     
        repeat(2) @(posedge CLK);
        RST = 0;
        CHNL_RX = 1; 
        CHNL_RX_DATA_VALID = 1;
        
        repeat(1) @(posedge CLK);
        CHNL_RX_LEN = 4;
        
        repeat(1) @(posedge CLK);
        CHNL_RX_DATA_VALID = 0;
        
        repeat(4) @(posedge CLK);
        CHNL_TX_ACK = 1;
        
        repeat(1) @(posedge CLK) begin
            CHNL_TX_ACK = 0;  CHNL_TX_DATA_REN = 1; CHNL_RX = 0;
        end
        
        repeat(2) @(posedge CLK);
        CHNL_TX_DATA_REN = 0;
        
        repeat(10) @(posedge CLK);
        $finish;
        
        /*
        #20 RST = 1;
        #20 RST = 0;
        #10 CHNL_RX = 1; CHNL_RX_LEN = 4; 
        #20 CHNL_RX_DATA_VALID = 1;
        #20 CHNL_RX_DATA_VALID = 0;
        #60 CHNL_TX_ACK = 1;
        #20 CHNL_TX_ACK = 0;  CHNL_TX_DATA_REN = 1; CHNL_RX = 0;
        #40 CHNL_TX_DATA_REN = 0;
        
        #150 $finish;
        */   
        
      end
      
      always@(posedge CLK) begin
        if(CHNL_RX_DATA_VALID && CHNL_RX_DATA_REN) 
            CHNL_RX_DATA <= CHNL_RX_DATA + 1;
      end
      
      always #10 CLK <= !CLK;
     
    endmodule

    Click image for larger version. 

Name:	Screenshot_I6eFhKQ.png 
Views:	6 
Size:	115.5 KB 
ID:	145152



  12. #12
    Advanced Member level 5
    Points: 36,062, Level: 46
    Achievements:
    7 years registered

    Join Date
    Jun 2010
    Posts
    6,589
    Helped
    1924 / 1924
    Points
    36,062
    Level
    46

    Re: A simple question on testbench stimulus

    because you're using blocking assignments in the testbench. Use non-blocking.


    1 members found this post helpful.

  13. #13
    Super Moderator
    Points: 244,657, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    42,502
    Helped
    12950 / 12950
    Points
    244,657
    Level
    100

    Re: A simple question on testbench stimulus

    because you're using blocking assignments in the testbench. Use non-blocking.
    You did use blocking assignments in post #6 as well, I already wondered if this correct.

    Question is if the statement following @(posedge CLK); is scheduled in the same or next simulation cycle.

    I get expected behavior (state changing in next clock cycle) in Modelsim, by the way.

    - - - Updated - - -

    A possible problem is caused by releasing RES and setting CHNL_RX at same clock edge.



  14. #14
    Super Moderator
    Points: 29,067, Level: 41
    ads-ee's Avatar
    Join Date
    Sep 2013
    Location
    USA
    Posts
    6,686
    Helped
    1604 / 1604
    Points
    29,067
    Level
    41

    Re: A simple question on testbench stimulus

    Quote Originally Posted by FvM View Post
    You did use blocking assignments in post #6 as well, I already wondered if this correct.
    the blocking assignments in the tb after @(posedge clk) are fine. I would get rid of the begin-end on those two @(posedge clk) lines they serve no useful purpose.

    Question is if the statement following @(posedge CLK); is scheduled in the same or next simulation cycle.
    only if the simulator is broken, if they are using some other simulator besides modelsim/vivado the use of the begin-end around the assignments could be causing the scheduling problem for that simulator.

    I get expected behavior (state changing in next clock cycle) in Modelsim, by the way.
    Works as expected when running with Vivado simulator too.

    OP, are you using icarus by chance? I would avoid running a tb with blocking assignments that don't have a #delay value before the assignments to the signals.
    Code:
    @(posedge clk);
    #some_delay; // to keep the signals applied to the DUT away from the clock edge
    sig1 = 1;
    sig2 = 0;
    etc
    I'm not entirely convinced that simulator follows the LRM as well as it should.

    Overall it's better to avoid any simulation scheduling pitfalls and keep your tb signals away from the active edge of the clock.



  15. #15
    Full Member level 5
    Points: 1,606, Level: 9

    Join Date
    Feb 2016
    Posts
    287
    Helped
    0 / 0
    Points
    1,606
    Level
    9

    Re: A simple question on testbench stimulus

    Looking at the #5 code again, I fear that the correct function depends on a specific scheduling order of both always blocks, the solution can still fail under circumstances.
    @FvM Would you mind elaborating on your statement above ?



  16. #16
    Super Moderator
    Points: 244,657, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    42,502
    Helped
    12950 / 12950
    Points
    244,657
    Level
    100

    Re: A simple question on testbench stimulus

    Presently it's only a guess. Suggest to read about side effects of blocking statements in the classical Cummings paper http://www.sunburst-design.com/paper...2000SJ_NBA.pdf

    Please consider also my question in post #8. Which kind of input signals do you want to model in the test bench? If it's about synchronous signals originated in the same clock domain, the solution given by ads-ee is guaranteed to work across any possible scheduling order problem or simulator flaw.


    1 members found this post helpful.

    •   Alt8th March 2018, 07:41

      advertising

        
       

  17. #17
    Full Member level 5
    Points: 1,606, Level: 9

    Join Date
    Feb 2016
    Posts
    287
    Helped
    0 / 0
    Points
    1,606
    Level
    9

    Re: A simple question on testbench stimulus

    The always(*) block is delaying count_next by one simulation cycle, so it arrives at the synchronous block behind the clock edge. I would say, removing the failure this way is rather a side effect than a straightforward solution.
    @Fvm

    I do not understand this. How is the workaround a side effect ?



--[[ ]]--