Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

A simple question on testbench stimulus

Status
Not open for further replies.

promach

Advanced Member level 4
Joined
Feb 22, 2016
Messages
1,199
Helped
2
Reputation
4
Reaction score
5
Trophy points
1,318
Activity points
11,636
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?

Screenshot_ROlyd53.png


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

 

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

race condition with the blocking assignments in the testbench

Would you mind elaborating ? Which blocking statements specifically ?
 

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
 

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

 

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
 
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:

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.
 
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

 

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.
 

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



Screenshot_I6eFhKQ.png
 

because you're using blocking assignments in the testbench. Use non-blocking.
 
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.
 

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.
 

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 ?
 

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/papers/CummingsSNUG2000SJ_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.
 
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 ?
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top