File: t_clk_latchgate.v

package info (click to toggle)
verilator 5.038-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 162,552 kB
  • sloc: cpp: 139,204; python: 20,931; ansic: 10,222; yacc: 6,000; lex: 1,925; makefile: 1,260; sh: 494; perl: 282; fortran: 22
file content (180 lines) | stat: -rw-r--r-- 5,093 bytes parent folder | download | duplicates (3)
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
170
171
172
173
174
175
176
177
178
179
180
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2010 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
//
//    --------------------------------------------------------
//    Bug Description:
//
//    Issue:  The gated clock gclk_vld[0] toggles but dvld[0]
//    input to the flop does not propagate to the output
//    signal entry_vld[0] correctly. The value that propagates
//    is the new value of dvld[0] not the one just before the
//    posedge of gclk_vld[0].
//    --------------------------------------------------------

// Define to see the bug with test failing with gated clock 'gclk_vld'
// Comment out the define to see the test passing with ungated clock 'clk'
`define GATED_CLK_TESTCASE 1

// A side effect of the problem is this warning, disabled by default

// Test Bench
module t (/*AUTOARG*/
   // Inputs
   clk
   );
   input clk;

   integer      cyc = 0;
   reg [63:0]   crc;

   // Take CRC data and apply to testblock inputs
   wire [7:0]  dvld = crc[7:0];
   wire [7:0]  ff_en_e1 = crc[15:8];

   /*AUTOWIRE*/
   // Beginning of automatic wires (for undeclared instantiated-module outputs)
   wire [7:0]           entry_vld;              // From test of Test.v
   wire [7:0]           ff_en_vld;              // From test of Test.v
   // End of automatics

   Test test (/*AUTOINST*/
              // Outputs
              .ff_en_vld                (ff_en_vld[7:0]),
              .entry_vld                (entry_vld[7:0]),
              // Inputs
              .clk                      (clk),
              .dvld                     (dvld[7:0]),
              .ff_en_e1                 (ff_en_e1[7:0]));

   reg err_code;
   reg ffq_clk_active;
   reg [7:0] prv_dvld;

   initial begin
     err_code = 0;
     ffq_clk_active = 0;
   end
   always @ (posedge clk) begin
     prv_dvld = test.dvld;
   end
   always @ (negedge test.ff_entry_dvld_0.clk) begin
     ffq_clk_active = 1;
     if (test.entry_vld[0] !== prv_dvld[0]) err_code = 1;
   end

   // Test loop
   always @ (posedge clk) begin
`ifdef TEST_VERBOSE
      $write("[%0t] cyc==%0d crc=%x ", $time, cyc, crc);
      $display(" en=%b fen=%b d=%b ev=%b",
               test.flop_en_vld[0],  test.ff_en_vld[0],
               test.dvld[0],  test.entry_vld[0]);
`endif
      cyc <= cyc + 1;
      crc <= {crc[62:0], crc[63] ^ crc[2] ^ crc[0]};
      if (cyc<3) begin
         crc <= 64'h5aef0c8d_d70a4497;
      end
      else if (cyc==99) begin
         $write("[%0t] cyc==%0d crc=%x\n", $time, cyc, crc);
         if (ffq_clk_active == 0) begin
           $display ("----");
           $display ("%%Error: TESTCASE FAILED with no Clock arriving at FFQs");
           $display ("----");
           $stop;
         end
         else if (err_code) begin
           $display ("----");
           $display ("%%Error: TESTCASE FAILED with invalid propagation of 'd' to 'q' of FFQs");
           $display ("----");
           $stop;
         end
         else begin
           $write("*-* All Finished *-*\n");
           $finish;
        end
      end
   end

endmodule

module llq (clk, d, q);
   parameter WIDTH = 32;
   input clk;
   input [WIDTH-1:0] d;
   output [WIDTH-1:0] q;

   reg [WIDTH-1:0]    qr;

   /* verilator lint_off COMBDLY */
   /* verilator lint_off LATCH */

   always @(clk or d)
     if (clk == 1'b0)
       qr <= d;

   /* verilator lint_on LATCH */
   /* verilator lint_on COMBDLY */

   assign q = qr;
endmodule

module ffq (clk, d, q);
   parameter WIDTH = 32;
   input clk;
   input [WIDTH-1:0] d;
   output [WIDTH-1:0] q;

   reg [WIDTH-1:0]    qr;

   always @(posedge clk)
     qr <= d;

   assign q = qr;
endmodule

// DUT module
module Test (/*AUTOARG*/
   // Outputs
   ff_en_vld, entry_vld,
   // Inputs
   clk, dvld, ff_en_e1
   );
   input clk;

   input [7:0] dvld;
   input [7:0] ff_en_e1;

   output [7:0] ff_en_vld;
   output wire [7:0] entry_vld;

   wire [7:0] gclk_vld;
   wire [7:0] ff_en_vld;
   reg [7:0] flop_en_vld;

   always @(posedge clk) flop_en_vld <= ff_en_e1;

   // clock gating
`ifdef GATED_CLK_TESTCASE
   assign gclk_vld = {8{clk}} & ff_en_vld;
`else
   assign gclk_vld = {8{clk}};
`endif

   // latch for avoiding glitch on the clock gating control
   llq  #(8)  dp_ff_en_vld (.clk(clk), .d(flop_en_vld), .q(ff_en_vld));

   // flops that use the gated clock signal
   ffq  #(1)  ff_entry_dvld_0 (.clk(gclk_vld[0]), .d(dvld[0]), .q(entry_vld[0]));
   ffq  #(1)  ff_entry_dvld_1 (.clk(gclk_vld[1]), .d(dvld[1]), .q(entry_vld[1]));
   ffq  #(1)  ff_entry_dvld_2 (.clk(gclk_vld[2]), .d(dvld[2]), .q(entry_vld[2]));
   ffq  #(1)  ff_entry_dvld_3 (.clk(gclk_vld[3]), .d(dvld[3]), .q(entry_vld[3]));
   ffq  #(1)  ff_entry_dvld_4 (.clk(gclk_vld[4]), .d(dvld[4]), .q(entry_vld[4]));
   ffq  #(1)  ff_entry_dvld_5 (.clk(gclk_vld[5]), .d(dvld[5]), .q(entry_vld[5]));
   ffq  #(1)  ff_entry_dvld_6 (.clk(gclk_vld[6]), .d(dvld[6]), .q(entry_vld[6]));
   ffq  #(1)  ff_entry_dvld_7 (.clk(gclk_vld[7]), .d(dvld[7]), .q(entry_vld[7]));

endmodule