[sv-ec] More on clocking domains and related stuff...


Subject: [sv-ec] More on clocking domains and related stuff...
From: Stefen Boyd (stefen@boyd.com)
Date: Tue Jan 28 2003 - 14:17:32 PST


Given some more thoughts (i.e. nightmares) about clocking
domains all the related stuff (cruft?)...

After my comments, I've got some proposals that fix
the problems with clocking domains, remove the need for the
separate verification phase, and remove the need for a
program block.

I see that we need to go one of two directions with
the clocking domains:
   * Get rid of them because they aren't needed and
         they aren't necessary to access the design.
   * Fix them so they really provide an extensible way
         to access the design.

1) It's too verbose
         Taking the example from 13.2:
         clocking bus @(posedge clock1);
           default input #10ns output #2ns
           input data, ready, enable = top.mem1.enable;
           output negedge ack;
           input #1step addr;
         endclocking

         If I want to use one of these signals in verification code,
         I have to write bus.xxx everywhere...

         As an alternative (Verilog 2001 code):
         `define negclk @(negedge clock1)
         `define posclk @(posedge clock1)
         wire #10ns data, ready, enable = top.mem1.enable;
         wire #1step addr;

         initial begin
           ...
           `posclk
           ... // do something intellegent ;}
           ack <= `negclk newvala;
           addr <= #1step newvalb;
           ...
         end

         Note:
           * I don't need hierarchical references to names as they
             stay in my scope.
           * Input side is easy to do much more compactly than clocking
             domain, although outputs are a bit more work, it's about
             as much extra typing as having to put the hierarchical
             reference to the clocking domain.

         The bottom line is that I don't get a big benefit in code
         reduction from adding this clocking domain construct.

2) It forces the addition of the design phase
         I may not understand this correctly, but it looks
         like the equivalent Verilog code looks something like:
         always @(posedge clk) begin: equiv_if
           reg data;
           data = design.data;
         end

         Since data get's the updated value in the active events, we
         have to wait to start using it until sometime after the
         posedge clk... I suppose we could wait until nba time so
         long as the clock edge happens as an active event and not
         an nba.

         But now that we're using these sampled values instead
         of directly using the value, we're stuck waiting 'till
         later to run our verification code that uses this signal.

         So not only does it not make a significant reduction in
         typing, but when I have no delays, it forces my verification
         code to have to run later... So long as my design uses
         nbas for flops, I could have run my code in the active
         events... but now I'm stuck waiting. Granted if you don't
         use nbas for flops, you have other problems that won't
         be fixed by design & verification phases.

3) It isn't extensible
         If I have a 24 port GEth DUT I'm testing, I could use an
         instance array of interfaces to pass to verification tasks
         that would access each port. But if I wanted to use a
         clock domain to do the same kind of work, I'd have to have
         24 clock domains defined and either pass all the variables
         to the same task, or write 24 almost identical tasks to
         access each port.

4) What I'd like to see
         * Shorthand notation for interfaces
           The only value of clocking domains is to allow easy
           *non-zero* setup samples and driving holds.

           Making this a shorthand notation that cuts down on
           typing is attractive, but the current syntax doesn't
           achieve this goal.

           Since interfaces *are* extensible, I would add the shorthand
           to interfaces... I would try putting it on modports:

           interface simple_bus; // Define the interface
             logic req, gnt;
             logic [7:0] addr, data;
             logic [1:0] mode;
             logic start, rdy;
             modport dut (input req, addr, mode, start, clk,
                         output gnt, rdy,
                         inout data);
             modport tb @(posedge clk) (input #1step gnt, rdy, clk,
                                     output #2 req, addr, mode, start,
                                     inout data);
           endinterface: simple_bus

           Rules:

> Looks like from the bnf that we can't put skew on inout
              in clocking domain, so it wouldn't be allowed here either...

> Basically, the syntax I'm proposing is very similar to
              the proposed clocking syntax, so we should be able to have
              the default, etc.

> The signals sampled or driven would

> The clock isn't required. If you already dealt with your
              timing control happening on clock edges, this would simply
              get you old values of inputs and would delay writes to
              outputs.

> Writes to outputs (even when no clock is specified) would still
              happen in the queue associated with that type of assignment.
              Blocking assignments would go into active events (e.g. #2 time
              units later) and non-blocking events would go into the nba
              queue.

         * implicit interface modport connections
           The previous unification of clocking with interfaces makes
           clocking domains extensible, but doesn't solve the verbosity
           problem. You still have to write clocking_domain.signal Although
           using really short clocking domains helps reduce the typing, the
           names become useless. What I would like to see is the ability
           to use an interface in a way that exposes the signals of
           that interface's modport so they can be accessed without the
           hierarchical reference.

           Proposal:
                 Instances may use an interface with a modport and make
                 all the signals of the modport available in the same
                 scope.
                 Example:
                   module chip_test(simple_bus.tb(.*));
                     ...
                   endmodule
                 Rules
> If the modport names clash with other
                    identifiers at the module scope (including
                    other implicit modports), an error will be
                    generated.

         * ##0
           The problem with the program block is that it solves
           a general problem in a very restricted and limited way.
           The biggest reason for it's existence is that it provides
           a special place to execute code in the verification phase.
           The problem of needing to wait for a "stable" point
           in the simulation is a general one. Dennis B. and Jay have
           mentioned that this is a general request they often receive.
           I submit that what we need is to simply define a new part
           of the event queue, just before rosync. In the HDL you
           could reach this by using ##0. Presumably, the PLI will
           be enhanced to support waiting until this time. Assertions
           could be defined to wait until this time to evaluate.

Regards,
   Stefen

--------------------
Stefen Boyd Boyd Technology, Inc.
stefen@BoydTechInc.com (408)739-BOYD
www.BoydTechInc.com (408)739-1402 (fax)



This archive was generated by hypermail 2b28 : Tue Jan 28 2003 - 14:17:45 PST