Project

General

Profile

[logo] 
 
Home
News
Activity
About/Contact
Major Tools
  Dinotrace
  Verilator
  Verilog-mode
  Verilog-Perl
Other Tools
  BugVise
  CovVise
  Force-Gate-Sim
  Gspice
  IPC::Locker
  Rsvn
  SVN::S4
  Voneline
  WFH
General Info
  Papers

Issue #50

Clock gating support?

Added by Andreas Olofsson over 10 years ago. Updated over 9 years ago.

Status:
Feature
Priority:
Normal
Assignee:
-
Category:
-
% Done:

0%


Description

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.

Andreas

History

#1 Updated by Andreas Olofsson over 10 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 over 10 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 over 10 years ago

Hi Wilson,

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.

TESTCASE:

/*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;

#4 Updated by Wilson Snyder over 9 years ago

  • Status changed from New to Feature

Also available in: Atom