Clock gating support?
What is the status of clock gating support? The documentation mentions putting clock_enable on clock enable signals, but it says the feature is experimental.I am getting failures with clock gating and I am pretty sure it's glitch related.
Here is my clock gating construct.
always @ (/*AS*/clk or en) if(~clk) en_sh <=en;
assign qclk = clk & en_sh
In some simulators there would usually be a way to debug these phantom glitches by "expanding an event". What would be the best way to debug this problem in verilator generated code. It might be a good thing to add to the FAQ.
#1 Updated by Andreas Olofsson almost 5 years ago
After looking at the _eval event loop generated by verilator , I don't see how generated clocks could work consistently when there is feedback in the design. There seems to be a definite ordering of the events inside eval loop and I see my different generated clocks in there. I apologize if I misunderstood the internal workings of the verilator in some way.
To support latches and gated clocks I think verilator needs support for an expanded event queue. Maybe not as elaborate as the Verilog standard, but at least support for "non-blocking" events. Let me know if I can help out in any way. You don't want me touching the code:-) but I can definitely help in testing and brain storming.
The verilog standard event queue.
1.) Events that occur at the current simulation time and can be processed in any order. These are the active events. 2) Events that occur at the current simulation time, but that shall be processed after all the active events are processed. These are the inactive events. 3) Events that have been evaluated during some previous simulation time, but that shall be assigned at this simulation time after all the active and inactive events are processed. These are the nonblocking assign update events. 4) Events that shall be processed after all the active, inactive, and nonblocking assign update events are processed. These are the monitor events. 5) Events that occur at some future simulation time. These are the future events. Future events are divided into future inactive events, and future nonblocking assignment update events.
#2 Updated by Wilson Snyder almost 5 years ago
First, using the clock_enable pragma is fine. I updated the docs for next release.
You're right how the event queue works for an event simulator. However Verilator instead computes the event ordering internally then optimizes; this is a lot more complicated (and bug prone) but more than 2x faster.
As for your problem, can you reduce it to a little testcase as described in the manual and post it (search for t_EXAMPLE)? It ouldn't be shocking if there is a latch bugs, as latches now days are relatively rarely encountered.
#3 Updated by Andreas Olofsson almost 5 years ago
Thanks for the quick reply. I find it ironic (and quite funny) that your open source support is faster than most commercial EDA support:-)
I will work on a test case packaged up the right way. Here is the code of the test case. (I verified it with Icarus). There is a race at flop3 when handing off data from flop2.
Is there a better way of dealing with generated clocks? In this case, driving all clocks at the interface is not an option.
/*verilator lint_off UNOPTFLAT*/ /*verilator lint_off COMBDLY*/
reg en1_sh; reg en2_sh;
reg flop1; reg flop2; reg flop3;
wire clk1; wire clk2; wire clkdiv3;
always @(/*AS*/clk or flop1) if(~clk) en1_sh <=flop1;
always @(/*AS*/clk or flop2) if(~clk) en2_sh <=flop2;
assign clkdiv3 = clk & en2_sh;
//Divide by 3 circuit always @(posedge clk or posedge stim_reset) if(stim_reset) flop1 <= 1'b0; else flop1 <= flop2;
always @(posedge clk or posedge stim_reset) if(stim_reset) flop2 <= 1'b0; else flop2 <= ~(flop1 | flop2);
always @(posedge clkdiv3 or posedge stim_reset) if(stim_reset) flop3 <= 1'b0; else flop3 <= flop2;