In Verilog, a module is the unit for any design entity. SystemVerilog extends this to include other design entities such as an interface, a program block and, last but not the least, a clocking block. An interface separates how a design interacts with the rest of the design from the design itself. A program block separates a test benching function from a silicon implementable design. And a clocking block specifies clock signals and the timing and synchronization requirements of various blocks. A clocking block is helpful in separating clocking activities of a design from its data assignments activities and can be used powerfully in test benching.
A clocking block assembles all the signals that are sampled or synchronized by a common clock and define their timing behaviors with respect to the clock. It is defined by a clocking-endclocking keyword pair. Perhaps an example will describe this best.
clocking clock1 @(posedge clk1);
default input #2ns output #3ns;
input a1, a2;
In the above example,
- The name of the clocking block is clock1. You can have as many clocking blocks in your environment as you want. Also, there may be multiple clocking blocks for the same clock, inputs or outputs in a single design.
- The clock associated with this clocking block is clk1. Each clocking block must have at least one clock associated with it.
- The default keyword defines the default skew for inputs (2 ns) and output (3 ns).
- The input and output keywords define the input and output signals associated with the clock and the skew defined earlier.
- One thing to note here is that input or output declarations inside a clocking module does not specify the data width.
A clocking block is both a declaration and an instance of that declaration and can only occur within a module, interface or program block (in the same scope as an always block). Variables inside a clocking block can be accessed specifying the full pathname. For instance, if the full pathname for clock1 above is top.test.clock1, the full pathname for variable a1 is top.test.clock1.a1.
A clocking block only describes how the inputs and outputs are sampled and synchronized. It does not assign a value to a variable. That is left to a module, interface or program that the clocking module is part of. While the parent block of a clocking module properly assigns a value to a variable, a clocking block defines how inputs are sampled and outputs are synchronized for its parent module. This is why an input or output declaration inside a clocking block does not need to specify any data width since it is only relevant if you assign a value to a variable or read from it.