// 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 //verilator lint_on IMPERFECTSCH // 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 /*verilator clock_enable*/; 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