Give the code for a mod-3 counter
A modulo-3 counter has 3 states (0, 1, 2) and requires 23 number of flip-flops.
module cntr_mod3 (input clk, rstn, output reg [1:0] out); always @(posedge clk) begin if (!rstn) out <= 0; else if (&out) out <= 0; else out <= out + 1; end endmodule
- Difference between $stop and $finish.
- Design frequency/2 circuit using D flip flop
- What is $random in Verilog ?
- What is the default value of wire and reg?
- Difference between inter and intra assignment delay.
- Illustrate how the infinite loops get created in the looping constructs like while and for.
- Illustrate the side-effects of a function return type without a range.
- What is #0 in Verilog and its usage?
- How to generate two different clocks in testbench ?
- Implement flip-flop using 2:1 MUX
Difference between $stop and $finish.
$stop is used to suspend the simulation at the point where it is called, simulator license is not released and still runs as a process in host operating system. User has to restart it, typically by manually resuming the simulation from the paused point.
$finish immediately terminates the simulation process and passes control back to the operating system, and license is released because simulation has exited.
$stop is useful for debugging and inspection of intermediate results in the design, allowing designers to examine signals, waveforms, or variables at a specific point in execution, while
$finish is used at the end of the simulation, indicating that the design has completed its operation.
Design frequency/2 circuit using D flip flop
A frequency divider by 2 can be designed using a D flip-flop as follows:
_________________ | ________ | | | | | '--->|D Q'|---' | | | Q |---- clk/2 |___^____| | clk _______|
The input clock signal Clk is connected to the D input of the D flip-flop. The output of the flip-flop, Q, is connected back to the D input through an inverter to create a divide-by-2 circuit.
- When the clock rises from low to high, the D flip-flop captures the value of the D input and outputs it on Q.
- At the same time, the inverted output Q' feeds it back to the D input.
- Thus, the output Q changes state on every positive edge of the clock, resulting in a frequency that is half of the input frequency.
Note that the input clock signal should have a duty cycle close to 50% to ensure reliable operation of the flip-flop. It is also important to ensure that the setup and hold times of the flip-flop are met to avoid timing errors.
What is $random in Verilog ?
$random is a system task that generates a new 32-bit random integer on every call with a seed value of 0 by default. The optional seed value is used to specify the starting point for the random number generator, and if specified,
$random generates the same sequence of random numbers every time it is called with the same seed value. It has the following syntax:
What is the default value of wire and reg?
In Verilog, the default value of an uninitialized wire is 'z' or high-impedance and the default value of an uninitialized reg is 'x' or unknown. Read more on Verilog Data Types.
Difference between inter and intra assignment delay.
An intra-assignment delay specifies a delay that occurs within an assignment statement. It is specified using the
# delay operator immediately following the driver in the assignment statement.
assign #5 a = b;
An inter-assignment delay specifies the delay between assignments to a signal. It is specified using the
wait (delay) constructs.
initial begin @(posedge clk) // This waits for a positive clock edge with a delay of 1 unit a = b; #2 // This introduces an inter-assignment delay of 2 time units a = c; end
Read more on Verilog Inter and Intra Assignment Delay.
Illustrate how the infinite loops get created in the looping constructs like while and for.
Infinite loops occur in programming when a loop does not have a condition to stop the iteration. Let's take a look at how infinite loops can get created in various looping constructs.
reg over; initial begin over = 0; while (!over) begin #10 $display("[%0t] In Loop", $time); end end
The while loop will only exit if some other process changes over to 1, and it will run forever if this does not happen.
Here is another example with
for loop which will run forever because of a width mismatch in the looping variable. The looping variable i goes from 0 to 7, wraps back to 0, counts up again and never reach the exit loop condition.
reg [2:0] i; initial begin for (i = 0; i < 16; i = i+1) begin $display("[%0t] i = %0d", i); end end
Illustrate the side-effects of a function return type without a range.
If the range of the function return type is not specified, Verilog assumes it to be a 1 bit scalar value. There would not be any compilation errors but it will result in a functional error.
module tb; // Should have been function [3:0] add(input [31:0] a, b); // Returns 1 bit value by default function add(input [3:0] a, b); return a + b; endfunction initial begin $display("Sum = %0d", add(4, 5)); // Returns 1 end endmodule
Read more on Verilog Functions.
What is #0 in Verilog and its usage?
In Verilog, #0 is a delay specifier that represents zero time delay. It is processed after all active events at the current simulation time have been processed, and its usage is generally not recommended. Like all delays, it is not synthesizable either in designs.
module tb; reg [3:0] x; initial begin $monitor("[%0t] x = %0d", $time, x); x = 0; #10 x = 10; end initial begin #10; #0 x = 15; end endmodule
In the above code, the #0 delay will make the variable x get value 15 at the end of 10 time units.
How to generate two different clocks in testbench ?
To generate two different clocks in a testbench, you can use two different initial or always blocks to toggle the two clock signals. Here's an example Verilog code for generating two clock signals with different frequencies using initial blocks:
module tb; reg clk1; reg clk2; initial begin clk1 = 1'b0; forever #10 clk1 = ~clk1; // Generate a clock with 50% duty cycle and 100ns frequency end initial begin clk2 = 1'b0; forever #5 clk2 = ~clk2; // Generate a clock with 50% duty cycle and 50ns frequency end // Rest of the testbench code endmodule
In this code, two initial blocks are used to generate two clock signals, clk1 and clk2 . The forever loops in each block toggle the clock signal at a specific frequency using the `#` delay operator. You can use these clock signals to drive different components in your design or to test the asynchronous behavior of your design.
Implement flip-flop using 2:1 MUX
A flip-flop can be implemented using a 2:1 MUX (multiplexer). Here's how you can implement a D flip-flop using a 2:1 MUX in Verilog:
module dff_using_mux(input d, clk, output q); wire out1; assign out1 = ~clk ? d : out1; assign q = clk ? q : out1; endmodule
What are the main data types in Verilog ?
In Verilog, there are several data types that can be used to represent different types of data. The main data types in Verilog include:
- Wire: A wire is used for simple connectivity between Verilog modules. It represents a net that can only have one driver and will be used as an output from one module and input to another.
- Reg: A reg is used to represent registers or memory elements in a Verilog design. It is used to store and manipulate data within a Verilog module.
- Integer: An integer is a data type used to represent signed integers in Verilog. It has a range of -2147483648 to 2147483647.
Read more on Verilog Data Types.
- Illustrate a few important considerations in Verilog simulation regressions.
- Illustrate the side effect of specifying delays in assign statements.
- Illustrate the side effects of multiple processes writing to the same variable.
- Same variable used in two loops running simultaneously
- Illustrate the side effect of an implicit 1 bit wire declaration of a multi-bit port during instantiation
- Explain what happens when width of state registers is not increased as more states gets added in a state machine.
- What is the purpose of DPI ? Give an example.
- What is a parameter in Verilog?
- Illustrate the side effect of not connecting all the ports during instantiation
- Illustrate the side effect of leaving an input port unconnected that influences a logic to an output port.
Illustrate a few important considerations in Verilog simulation regressions.
Simulation regressions are a vital part of the design cycle for digital circuits. Simulation regressions involve running a wide range of tests on a circuit design to determine how it behaves under different conditions.
There are several important considerations to keep in mind when executing simulation regressions, including:
- Test Coverage: The goal of a simulation regression is to test the circuit design thoroughly to ensure that it meets the required specifications. Therefore, test coverage is crucial to ensure that all the possible scenarios are simulated.
- Scalability: As the design of a digital circuit becomes more complex, the number of tests required to verify its functionality increases. Therefore, it is essential to ensure that simulation regressions are scalable, and the testbench can be easily modified as per the design.
- Debugging Capabilities: It is essential to have a comprehensive debugging capability to identify the faults encountered during simulation regression.
- Simulation Accuracy: The accuracy of the simulation directly impacts the breadth and depth of test coverage.
Illustrate the side effect of specifying delays in assign statements.
Delays are not synthesizable and synthesis tools ignore any kind of delays specified in assignment, blocking or non-blocking procedural statements. If the functionality depends upon the presence of the delay, then a mismatch in functional simulation will be seen between the model and the synthesized netlist.
z <= #5 x; // #5 will be ignored #10 z <= x; // #10 will be ignored
Illustrate the side effects of multiple processes writing to the same variable.
Some potential side effects of multiple processes writing to the same variable include:
- Data Races: Concurrent access to the same variable without proper synchronization can lead to data races. A data race occurs when two or more processes access the same shared variable and at least one of the processes modifies the variable. This can result in unpredictable output or program crashes.
- Inconsistent Values: Multiple updates to the same variable by different processes can result in inconsistent data values. For example, one process might read the variable before another process has finished modifying it, resulting in the use of an outdated value.
- Non-Atomic Updates: Updating a shared variable is not necessarily an atomic operation, meaning that the update can require several steps to complete. If two or more processes try to update the same variable simultaneously, this can result in partial updates, corrupt data, or race conditions in simulations.
- Deadlocks: When multiple processes try to update the same variable in a circular manner, it can result in a deadlock. Deadlock is a situation where two or more processes are waiting for each other to release a resource, but neither process can make any progress.
Most of the linting and synthesis tools can detect this and throw an error.
Same variable used in two loops running simultaneously
The following code will have functional problems as the same variable is used and updated by two concurrent blocks, although it is syntactically correct.
module tb; integer i; // Same variable updated by different initial blocks initial begin for (i = 0; i < 5; i = i+1) begin #5 $display("Loop#1 : i=%0d", i); end end initial begin for (i = 0; i < 10; i = i+1) begin #10 $display("Loop#2 : i=%0d", i); end end endmodule
SystemVerilog allows you to declare the variable within the
for loop thereby creating two different variables with "local" scope.
module tb; initial begin for (int i = 0; i < 5; i = i++) begin #5 $display("Loop#1 : i=%0d", i); end end initial begin for (int i = 0; i < 10; i = i++) begin #10 $display("Loop#2 : i=%0d", i); end end endmodule
Illustrate the side effect of an implicit 1 bit wire declaration of a multi-bit port during instantiation
In hardware description languages, it is common to connect multi-bit ports between modules through wires. However, if the connection is made without explicitly declaring a wire with the correct number of bits, the language may interpret the connection as an implicit 1-bit wire. This can have unintended consequences.
For example, consider a module with a 4-bit output port that is connected to a 4-bit input port of another module. If the connection is declared as follows:
module ModuleA( output [3:0] out ); ModuleB B(.in(out[3:0])); endmodule module ModuleB( input [3:0] in ); // ... endmodule
Then the connection between the two modules is made with an implicit 1-bit wire, which means only the least significant bit will be used in the transfer. This can cause unexpected behavior because only one bit of the 4-bit output from ModuleA will be used in ModuleB , which can lead to incorrect results.
To avoid this issue, it is important to explicitly declare the number of bits in the wire that connects the two modules, as shown below:
module ModuleA( output [3:0] out ); wire [3:0] w; assign w = out; ModuleB B(.in(w)); endmodule module ModuleB( input [3:0] in ); // ... endmodule
Explain what happens when width of state registers is not increased as more states gets added in a state machine.
In a state machine, the state register is used to store the current state of the machine. The number of state bits required in the register depends on the number of states in the machine. Forgetting to increase the width of state registers as more states get added in a state machine can lead to unintended consequences.
For example, if the number of state bits in the register is less than the number of states in the machine, some state bits will be lost. This truncation will cause some states to have the same encoding, resulting in incorrect behavior. This phenomenon is called state overlap. State overlap may go unnoticed during simulation or synthesis, but it can cause significant problems in hardware. It can result in incorrect operation, and in worst cases, it may cause the system to fail completely.
// BUG! If cur_state is not updated to a 4-bit variable // there will be functional failure logic [2:0] cur_state; ... case(cur_state) 4'b0100 : // Move into Write phase 4'b1100 : // Move into Read phase ...
To avoid state overlap, the width of the state register should be increased as more states get added in the state machine. The number of bits required for the state register can be calculated by using the formula 2n >= number of states, where n is the number of bits in the state register.
What is the purpose of DPI ? Give an example.
DPI stands for Direct Programming Interface, and it is a feature of SystemVerilog that allows communication between the hardware design being simulated and external software applications. The purpose of DPI is to enable the hardware design being simulated to interact with software modules.
One example of the use of DPI is in co-simulation, where a hardware design is simulated alongside a software application that interacts with it. The software application could be running on a different platform or operating system, and it communicates with the hardware through the DPI interface. This allows software engineers to test their application with the hardware design in a controlled environment.
Another example of the use of DPI is for modeling user-defined protocols or interfaces. A SystemVerilog design can have modules that interact with other modules using DPI, allowing users to implement their own communication protocols or interfaces.
For instance, let's assume a SystemVerilog design has a module that performs cryptographic operations. The design can have a DPI function that interacts with software modules written in higher-level languages like Python or C, which perform data input/output (I/O) for this design. In this case, the software modules perform I/O operations such as reading inputs like cryptography keys or plaintext data from the user at runtime, which are fed to the module using the DPI interface. Once the cryptographic module completes its operation, it can return the output to the software through the same interface, allowing for efficient and flexible communication.
What is a parameter in Verilog?
In Verilog, a parameter is a named constant that is used to simplify the design by allowing commonly used values to be defined once and then used throughout the code. Parameters are defined using the
parameter keyword and are typically declared at the beginning of the Verilog module.
For example, consider the following Verilog code that defines a simple NAND gate:
module nand_gate(output reg y, input a, input b); parameter delay = 1; // Delay value for the gate always @(a, b) begin y = ~(a & b); // NAND gate implementation #delay y = y; // Delay the output by the specified time end endmodule
In this code, the delay parameter is defined with a value of 1, which is then used to delay the output by one time unit in the
Read more on Verilog Parameters.
Illustrate the side effect of not connecting all the ports during instantiation
An unconnected port in a module is called a dangling port or floating port, and unconnected input ports have high impedance and are evaluated to Z . If the input port is used in
if else conditions with
== operator, then it will evaluate to a logical false.
Leaving a port unconnected can lead to excessive power consumption and unwanted coupling between nearby signals. Furthermore, it may lead to timing issues, such as setup and hold time violations, which can cause incorrect data transfer or latching.
Read more on Verilog Module Instantiations.
Illustrate the side effect of leaving an input port unconnected that influences a logic to an output port.
An input port that is unconnected will have high impedance or the logic level Z in functional simulation, and synthesis tools will optimize away the logic that propagates beyond a floating input.
module X (input a, b, output c, d); assign c = a & b; assign d = a | b; endmodule module Y (input m, n, output o, p); X u_x ( .a (), // input is left floating .b (n), .c (o), .d (p)); endmodule
The above example will get synthesized such that m is not connected to any logic within the module Y and b is directly connected to d in X.
- What is a sensitivity list ?
- Explain $monitor, $display and $strobe.
- What does transport delay mean in Verilog ?
- What is meant by inertial delay ?
- What are good practices of writing FSM code ?
- Explain force and release commands in Verilog.
- Explain stages in the setup of a regression environment for simulations?
- What does timescale 1ns/1ps mean?
- What are some of the features in VHDL?
- What is PLI ?
What is a sensitivity list ?
In Verilog, a sensitivity list is a list of signals that are used to trigger the execution of a procedural block, such as an
always block or
initial block. The sensitivity list determines which signal changes will cause the procedural block to execute.
When a signal in the sensitivity list changes, the procedural block is executed. If no signal in the sensitivity list changes, the procedural block is not executed.
The sensitivity list is declared using the
@ symbol followed by a list of signal names in brackets "()", separated by commas. The sensitivity list must include all inputs to the procedural block which are used to operate on, so that any change in these signals will trigger its executable code.
For example, consider the following always block:
always @(posedge clock or posedge reset) begin if (reset) register <= 0; else register <= data; end
In the above example, the sensitivity list is "(posedge clock or posedge reset)", which means that the always block will be executed whenever there is a positive edge on the clock signal or a positive edge on the reset signal.
Explain $monitor, $display and $strobe.
In Verilog, $monitor, $display, and $strobe are built-in system tasks used for printing information about the simulation. Here's an explanation of each one:
$monitor is a system task used to display variable values every time there's a change in the value of the specified variables. This task takes the form:
where format specifies the format in which the variables are to be displayed, and list_of_variables includes the variables whose values should be displayed. When any of the variables in the list_of_variables changes value, the formatted values of all variables listed will be displayed.
integer count = 0; $monitor("Count = %d", count);
The above code will print the value of count every time it changes.
$display is a system task used to display a message along with the values of specified variables. It takes the form:
The format specifies the message to be displayed with optional formatting options, and list_of_variables includes the variables whose values should be displayed in the message.
integer count = 0; $display("The value of %d is %d", count, count);
The above code will display the message "The value of count is 0".
$strobe is a system task used to display a message only once at the end of the timestep. It takes the form:
The message specifies the message to be displayed at the end of the current timestep.
$strobe("Current timestep finished.");
The above code will display the message "Current timestep finished." at the end of the timestep.
Read more on Verilog Display Tasks.
What does transport delay mean in Verilog ?
In Verilog, transport delay is a type of delay that represents the time that it takes for a signal to propagate through a real circuit. It is defined using the
# symbol, followed by a numerical delay value, in units of time, and then the signal that the delay is applied to. For example:
a = #5 b;
In this example, the signal a will be assigned the value of signal b after a delay of 5 time units.
Transport delay models propagate all signals to an output after any input signals change. It is commonly used to model circuit behavior, particularly at the level of gate or module instantiation.
What is meant by inertial delay ?
Inertial delay is a type of delay modeling in Verilog that is used to simulate signals with a certain level of noise or fluctuations. It is a type of delay with some built-in filtering to account for the fact that not all changes in a signal are necessarily significant or indicative of a real state change.
During the simulation, if an input pulse is shorter than the module delay, it is ignored and does not propagate through the circuit. This filtering helps to simulate the lack of response from the circuit to small fluctuations or noise in the input signal that don't indicate a true state change.
What are good practices of writing FSM code ?
Here are some good practices to follow when writing FSM (Finite State Machine) code in Verilog:
- Use a clear and consistent naming convention for state and output signals to make the code more readable and easier to follow.
- Use enumerations to define the set of states and other parameters associated with the FSM. This approach can help to reduce the risk of errors and increase the readability of the code.
- Avoid using complex expressions or nesting of conditional statements in the logic of the FSM. This can make the code difficult to read, debug, and maintain.
- Write separate blocks of code for the next state logic and output generation. This helps to separate the two different concerns and makes the code easier to read.
- Use one-hot encodings for representing state variables, which can reduce the amount of logic required to implement state transitions and also simplifies debugging, verification, and testing of the FSM.
- Use assertions or simulation-based testing to verify the correctness of the FSM implementation. This helps to ensure that the implementation doesn't have logical errors, and the FSM behaves as expected.
Explain force and release commands in Verilog.
forcecommand is used to force a specific value onto a signal in a simulation until released, which overrides any other value that may be set for that variable or signal in the simulation. It does not change the value of the actual signal or variable represented in the hardware, but only changes the value in the simulation.
The syntax of the deposit command is as follows:
// "signal" is the signal to set to "value" force [signal] = [value];
releasecommand is used to allow the signal to resume any other value that may be set for that variable or signal in the simulation.
// "signal" is the signal to be released from a prior force release [signal];
Explain stages in the setup of a regression environment for simulations?
Designing a regression environment for simulations in Verilog involves several stages, and different coding constructs can be utilized at various stages. The following are some coding constructs of Verilog that can be used during the different stages of designing a regression environment for simulations:
- Module Definition: At the beginning of the design cycle, the first step is to define the various modules that are part of the circuit design. In Verilog, module definitions can be used to build modules for different parts of the circuit design, which can then be used to construct the testbenches.
- Testbench Construction: After module definitions have been created, testbench construction can begin. Testbenches are written in Verilog to simulate different scenarios that the circuit may encounter. Verilog constructs such as "initial" and "always" blocks can be used to define the behavior of the testbench.
- Test Vector Generation: Test vectors are input signals that are designed to stimulate the circuit and detect any malfunctions. Verilog constructs such as "generate" and "for loops" can be used to generate multiple input signal patterns or combinations automatically.
- Coverage Collection: Once the testbench has been constructed and test vectors generated, the next stage is to analyze the coverage of the testbench. Coverage collection is important to ensure that all the possible scenarios are simulated. Verilog constructs such as "coverpoint" and "cross" can be used to define the coverage goals with the scope of the different scenarios.
- Result Reporting: After the simulation regression is completed, the results are analyzed to determine if the circuit design meets the required specifications. Information related to the simulation result is displayed through reporting features, such as Verilog's "assertions,'' "finish" statement, and "display" statement.
What does timescale 1ns/1ps mean?
In SystemVerilog, the
`timescale keyword is used to set the units of time for a simulation. The timescale specifies the ratio of simulation time units to real time units.
Here, time_unit is the base unit of time used for simulation and precision_unit is a unit of measurement for simulation resolution.
For example, if the timescale is set to `1ns/1ps`, this means that one simulated second is equivalent to one real-time nanosecond (time_unit ) and that the simulation resolution is in picoseconds (precision_unit ).
This means that within the simulation, any delays or timing constraints specified in the code are treated as being relative to the timescale, i.e., any delay specified as "1" within the code will be interpreted as "1ns/1ps" in real-time units.
The choice of timescale depends on the design and the requirements of the simulation. In general, it's a good practice to use the smallest possible timescale that still satisfies the design requirements, since smaller timescales can improve the accuracy of the simulation.
Read more on Verilog Timescale.
What are some of the features in VHDL?
VHDL is a hardware description language used to model digital circuits and systems. Some of the features of VHDL include:
- Strong typing: VHDL is a strongly typed language, which means that every object must be declared with a specific data type before it can be used in the design.
- Concurrency: VHDL supports the design of concurrent systems, where multiple processes or threads execute simultaneously within a design. This allows designers to model complex systems with many interacting components.
- Modularity: VHDL supports the concept of modular design, which allows designers to create reusable components that can be assembled together to build larger systems. Modules can be instantiated multiple times within a design, making it easier to create more complex circuits.
- Parameterization: VHDL allows the creation of modules with parameters that can be set at instantiation time. This helps to create more flexible and reusable designs.
- Process-based modeling: VHDL uses processes to describe the behavior of a circuit or system. Processes can be created to model combinational or sequential logic, and can be used to specify complex behaviors within a design.
- Hierarchical design: VHDL allows the creation of hierarchical designs, where modules can be instantiated within other modules. This makes it easier to create and manage complex designs by breaking them down into smaller, more manageable parts.
- Simulation and synthesis: VHDL supports both simulation and synthesis, which means that a design can be tested and debugged using simulation tools, and then synthesized to create a physical implementation of the design. This allows designers to develop and optimize a design using simulation tools before committing to a physical implementation.
What is PLI ?
PLI stands for Programming Language Interface, which is an interface that allows software developers to access and control simulation data within a Verilog or VHDL simulation environment.
The PLI is a set of functions and routines that enable developers to extend the capabilities of the simulation environment by creating new data types, customizing the behavior of primitives, and adding data analysis routines. Essentially, the PLI provides a way for developers to interact with and manipulate the simulation data and results.
The PLI is commonly used in hardware verification and validation, where simulation is used to test the functional behavior and performance of digital circuits and systems. Developers can create custom data analysis routines or data export functions using the PLI to analyze simulation results and generate relevant reports or data exports.
There are several types of PLI interfaces, including the VPI (Verilog Programming Interface), VHPI (VHDL Programming Interface), and DPI (Direct Programming Interface). These interfaces provide different levels of control and flexibility, and can be used for specific applications depending on the requirements of the simulation and the developer's needs.