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
|