Verilog math functions can be used in place of constant expressions and supports both integer and real maths.
Integer Math Functions
The function $clog2
returns the ceiling of log2 of the given argument. This is typically used to calculate the minimum width required to address a memory of given size.
For example, if the design has 7 parallel adders, then the minimum number of bits required to represent all 7 adders is $clog2
of 7 that yields 3.
module des
#(parameter NUM_UNITS = 7)
// Use of this system function helps to reduce the
// number of input wires to this module
(input [$clog2(NUM_UNITS)-1:0] active_unit);
initial
$monitor("active_unit = %d", active_unit);
endmodule
`define NUM_UNITS 5
module tb;
integer i;
reg [`NUM_UNITS-1:0] active_unit;
des #(.NUM_UNITS(`NUM_UNITS)) u0(active_unit);
initial begin
active_unit = 1;
#10 active_unit = 7;
#10 active_unit = 8;
end
endmodule
Note that the signal active_unit has 3-bits to store total 5 units.
Clocks are fundamental to building digital circuits as it allows different blocks to be in sync with each other.
Properties of a clock
The key properties of a digital clock are its frequency which determines the clock period, its duty cycle and the clock phase in relation to other clocks.
Clock Period
The frequency indicates how many cycles can be found in a certain period of time. And hence the clock period is the time taken to complete 1 cycle.

Clock Duty Cycle
The amount of time the clock is high compared to its time period defines the duty cycle.

Multi-bit Verilog wires and variables can be clubbed together to form a bigger multi-net wire or variable using concatenation operators {
and }
separated by commas. Concatenation is also allowed to have expressions and sized constants as operands in addition to wires and variables.
Size of each operand must be known in order to calculate the complete size of concatenation.
Verilog Concatenation Example
wire a, b; // 1-bit wire
wire [1:0] res; // 2-bit wire to store a and b
// res[1] follows a, and res[0] follows b
assign res = {a, b};
wire [2:0] c;
wire [7:0] res1;
// res[0] follows c[2]
// res[2:1] is always 0
// res[4:3] follows c[1:0]
// res[5] follows a
// res[6] follows b
assign res1 = {b, a, c[1:0], 2'b00, c[2]};
Standard Verilog primitives like nand
and not
may not always be easy or sufficient to represent complex logic. New primitive elements called UDP or user-defined primitives can be defined to model combinational or sequential logic.
All UDPs have exactly one output that can be either 0, 1 or X and never Z (not supported). Any input that has the value Z will be treated as X.
Verilog timescale directive specifies time unit and precision for simulations.
Verilog $timeformat
system function specifies %t
format specifier reporting style in display statements like $display
and $strobe
.