Verilog Interview Questions - ZishanManna/interview-prep-wiki GitHub Wiki
Click here to reveal the answer
-
initial
Block: Executes once at the start of the simulation and is used for setting up initial values. -
always
Block: Continuously repeats whenever the sensitivity list is active and is typically used for describing both combinational and sequential logic.
Click here to reveal the answer
-
wire
: Represents a continuous assignment and is used to model combinational logic. -
reg
: Stores a value and is generally used for sequential logic or procedural assignments insidealways
blocks.
Click here to reveal the answer
module up_counter (
input clk,
input reset,
output reg [3:0] count
);
always @(posedge clk or posedge reset) begin
if (reset)
count <= 4'b0000;
else
count <= count + 1;
end
endmodule
Click here to reveal the answer
-
Blocking (
=
): Executes in the order they appear in the code and completes before moving to the next statement. -
Non-blocking (
<=
): Updates the values at the end of the time step, making it suitable for describing sequential logic.
Click here to reveal the answer
The sensitivity list defines the events that trigger the execution of the always
block. It typically includes clock signals, reset signals, or any other inputs that the block depends on.
Click here to reveal the answer
module d_ff (
input clk,
input reset,
input d,
output reg q
);
always @(posedge clk or posedge reset) begin
if (reset)
q <= 0;
else
q <= d;
end
endmodule
Click here to reveal the answer
The generate
statement is used to create multiple instances of a module or logic based on a loop or conditional constructs. It simplifies repetitive code generation.
Click here to reveal the answer
-
casex
: Treatsx
andz
as don't-care conditions. -
casez
: Treats onlyz
as a don't-care condition, allowing for more precise case matching.
Click here to reveal the answer
The timescale
directive specifies the time unit and precision for the module, such as timescale 1ns/1ps
, where 1ns is the time unit, and 1ps is the time precision.
Click here to reveal the answer
module mux2_1 (
input a,
input b,
input sel,
output y
);
assign y = (sel) ? b : a;
endmodule
Click here to reveal the answer
-
task
: Can have zero or more inputs and outputs and can include timing controls (#
,@
). -
function
: Can have zero or more inputs but only one output and cannot include timing controls. It’s primarily used for combinational logic.
Click here to reveal the answer
module mux4_1 (
input [3:0] d, // 4 data inputs
input [1:0] sel, // 2-bit select line
output y
);
assign y = (sel == 2'b00) ? d[0] :
(sel == 2'b01) ? d[1] :
(sel == 2'b10) ? d[2] : d[3];
endmodule
Click here to reveal the answer
The tri
keyword is used to define tri-state nets, which can have a high-impedance (Z
) state. It’s commonly used in cases where multiple drivers can drive the same wire.
Click here to reveal the answer
module jk_ff (
input clk,
input reset,
input j,
input k,
output reg q
);
always @(posedge clk or posedge reset) begin
if (reset)
q <= 0;
else begin
case ({j, k})
2'b00: q <= q; // No change
2'b01: q <= 0; // Reset
2'b10: q <= 1; // Set
2'b11: q <= ~q; // Toggle
endcase
end
end
endmodule
Click here to reveal the answer
module shift_register (
input clk,
input reset,
input d,
output reg [3:0] q
);
always @(posedge clk or posedge reset) begin
if (reset)
q <= 4'b0000;
else
q <= {q[2:0], d}; // Shift left by 1 and add new data bit
end
endmodule
Click here to reveal the answer
The always_comb
block is used to describe combinational logic in SystemVerilog. It automatically infers the sensitivity list based on the variables used, eliminating potential errors associated with manual sensitivity list declaration in the always @(*)
block.
Click here to reveal the answer
parameter
is used to define constants in Verilog that can be used to configure module behavior. Parameters can be set to specific values, making the code more flexible and reusable without modifying the actual code. They can also be overridden when instantiating the module.
Click here to reveal the answer
module bin_to_bcd (
input [3:0] binary,
output reg [7:0] bcd
);
integer i;
always @(binary) begin
bcd = 0; // Initialize BCD output
for (i = 3; i >= 0; i = i - 1) begin
if (bcd[3:0] >= 5)
bcd[3:0] = bcd[3:0] + 3;
if (bcd[7:4] >= 5)
bcd[7:4] = bcd[7:4] + 3;
bcd = bcd << 1; // Shift left
bcd[0] = binary[i]; // Add next binary bit
end
end
endmodule
Question 19: What is the difference between synthesizable
and non-synthesizable
constructs in Verilog?
Click here to reveal the answer
-
Synthesizable Constructs: These can be translated into hardware and include basic data types,
always
blocks,assign
statements, and module instantiations. They represent hardware logic that can be physically implemented. -
Non-synthesizable Constructs: These include constructs like
initial
blocks,delay
statements, and file I/O operations that cannot be implemented directly in hardware. They are often used for simulation purposes only.
Click here to reveal the answer
module priority_encoder (
input [3:0] a, // 4-bit input
output reg [1:0] y // 2-bit output
);
always @(*) begin
casez (a) // Use casez to treat 'z' as a don't-care condition
4'b1???: y = 2'b11; // Highest priority (input 3)
4'b01??: y = 2'b10; // Next priority (input 2)
4'b001?: y = 2'b01; // Next priority (input 1)
4'b0001: y = 2'b00; // Lowest priority (input 0)
default: y = 2'bxx; // No input active
endcase
end
endmodule
Click here to reveal the answer
The initial
block is used to define behavior that occurs at the start of the simulation. It executes only once and is typically used for initializing variables or setting up conditions before the simulation begins. It is not synthesizable and is used primarily for simulation purposes.
Click here to reveal the answer
module fsm (
input clk,
input reset,
input in,
output reg out
);
typedef enum logic [1:0] {S0, S1, S2} state_t; // Define states
state_t state, next_state;
always @(posedge clk or posedge reset) begin
if (reset)
state <= S0; // Reset to initial state
else
state <= next_state; // Transition to next state
end
always @(*) begin
case (state)
S0: begin
if (in)
next_state = S1;
else
next_state = S0;
out = 0;
end
S1: begin
if (in)
next_state = S2;
else
next_state = S0;
out = 1;
end
S2: begin
next_state = S0; // Transition back to initial state
out = 0;
end
endcase
end
endmodule
Click here to reveal the answer
The defparam
statement is used to override the value of parameters in a module instantiation. This allows designers to customize module behavior without changing the module's source code. It is less commonly used in modern designs, as parameter overrides can often be handled at instantiation.
Click here to reveal the answer
You can create a reg
array in Verilog by declaring a multi-dimensional array. Here's an example:
module reg_array_example;
reg [7:0] data [0:15]; // Declare an array of 16 8-bit registers
initial begin
// Initialize the array
data[0] = 8'hFF;
data[1] = 8'hA5;
// ... other initializations
end
endmodule
Click here to reveal the answer
The generate
statement is used to create multiple instances of modules or to generate repetitive code in a structured manner. It can be used with for
, if
, or case
constructs. This is useful for creating arrays of components or for implementing conditional logic in a cleaner way.
module generate_example;
genvar i;
generate
for (i = 0; i < 4; i = i + 1) begin : gen_block
wire [i:0] my_wire;
// Create instances of a module or logic here
end
endgenerate
endmodule
Click here to reveal the answer
A packed
array in SystemVerilog allows you to define an array of bits that are tightly packed together, without any gaps between the elements. This is useful for creating data structures that require a specific layout in memory.
module packed_array_example;
typedef logic [7:0] byte_t; // Define a byte type
byte_t my_bytes [0:3]; // Declare an array of 4 bytes (packed)
initial begin
my_bytes[0] = 8'hFF;
my_bytes[1] = 8'hA5;
my_bytes[2] = 8'h3C;
my_bytes[3] = 8'hC0;
end
endmodule
Click here to reveal the answer
-
initial
Block: Used for initializing values and executing code once at the start of a simulation. It is useful for setting initial states for registers or signals. -
always
Block: Used to describe behavior that occurs continuously or repeatedly in response to changes in signals. It can represent combinational or sequential logic, depending on the sensitivity list.
Click here to reveal the answer
module clock_divider (
input clk_in, // Input clock
input reset, // Asynchronous reset
output reg clk_out // Divided clock output
);
reg [3:0] counter; // 4-bit counter
always @(posedge clk_in or posedge reset) begin
if (reset) begin
counter <= 0;
clk_out <= 0;
end else begin
counter <= counter + 1;
if (counter == 4'b1111) begin
clk_out <= ~clk_out; // Toggle output clock
counter <= 0; // Reset counter
end
end
end
endmodule
Click here to reveal the answer
-
Blocking Assignments (
=
): These assignments occur in a sequential manner. The next statement will not execute until the current assignment is complete. They are typically used in combinational logic. -
Non-Blocking Assignments (
<=
): These assignments allow for concurrent execution. The right-hand side of the assignment is evaluated immediately, but the left-hand side is updated at the end of the time step. Non-blocking assignments are primarily used in sequential logic.
Click here to reveal the answer
module debounce (
input clk,
input reset,
input noisy,
output reg clean
);
reg [3:0] debounce_counter; // 4-bit counter
reg noisy_reg;
always @(posedge clk or posedge reset) begin
if (reset) begin
debounce_counter <= 0;
clean <= 0;
noisy_reg <= 0;
end else begin
noisy_reg <= noisy; // Sample the noisy input
if (noisy_reg != noisy) begin
debounce_counter <= 0; // Reset counter on change
end else if (debounce_counter < 4'b1111) begin
debounce_counter <= debounce_counter + 1; // Increment counter
end
if (debounce_counter == 4'b1111) begin
clean <= noisy; // Update clean output after debounce
end
end
end
endmodule