Just like systemverilog, verilog interview questions focus on conceptual understanding and their application. But, one key difference with Verilog is that, since it is used in RTL coding, the interviewers usually are inclied to ask synthesis and basic design level questions. Still yet, Verilog is also used for coding testebenches, so its always better to be prepared to answer any questions from that point of view.
/* Listed below are the primary differences between fucntions and tasks: 1. Functions are not allowed to have any delay based keywords or blocks, while tasks can have delays. 2. Tasks can return multiple values depending on how many <>output<> arguments have been passed, while functions can only return one value. 3. Functions can only call functions while tasks can call both functions and tasks. */
/* Naming each thread using <>named block<> concept and the making sure before a block completes execution, it kills all the other blocks. */ fork begin : A #( ($urandom%100)+1 ); $display( $time, "A finished" ); disable B; end : A begin : B #( ($urandom%100)+1 ); $display( $time, "B finished" ); disable A; end : B join $display( $time, "Finished" ); /* Alternatively you can use the event datatype and place waits to trigger a disable in a third thread */
/* Followings are brief descriptions of the differences between case, casex and casez: 1. <>case -<> This is the regular case construct of verilog. The <>case(<expression/variable>)<> evaluats its argument as a 4 state value and does strict comparison. 2. <>casez -<> Here, "z" & "?" are considered wildcard or don't cares in comparisons. Which means, they are considered as 0 and 1 both. So, for example 4'b110? will match with both 4'b1100 and 4'1101, but depending on which case item is coded first, that particular item will be executed. 3. <>casex -<> Like casez, casex treats "x" as wildcard as well. */
module FA_RANDOM_WIDTH # ( parameter WIDTH = rand_width() )( input [WIDTH-1:0] A, B, output [WIDTH:0] OUT ); function integer rand_width(); return ( ( $urandom % 8 ) + 1 ); endfunction assign OUT = A + B; endmodule
module top; int A; initial begin A = $urandom & ( {~( 31'd0 ),1'b0} ); $display( "Number : %0d", A ); end endmodule
module DFF #( parameter WIDTH = 1 )( input clk, input rst_n, input wire [WIDTH-0:0] d_in, output reg [WIDTH-1:0] d_out ); always@( posedge clk or negedge rst_n ) begin if( !rst_n ) begin d_out <= 0; end else begin d_out <= d_in; end end endmodule
module FA #( parameter D_WIDTH = 4 )( input wire [D_WIDTH-1:0] INA, INB, output wire [D_WIDTH-1:0] SUM_OUT, output wire [0:0] CARRY_OUT ); assign {CARRY_OUT,SUM_OUT} = INA + INB; endmodule
module detect#( parameter DETECT_WIDTH = 5, parameter reg [DETECT_WIDTH-1:0] PATTERN = 5'b10110 )( input clk_i, input rst_n_i, input d_in, output detected_o ); reg [DETECT_WIDTH-1:0] SISO_DATA; reg [DETECT_WIDTH-1:0] SISO_FLAG; always@( posedge clk_i or negedge rst_n_i ) begin if( !rst_n_i ) begin SISO_DATA <= 0; SISO_FLAG <= 0; end else begin SISO_DATA <= { d_in, SISO_DATA[DETECT_WIDTH-1:1] }; SISO_FLAG <= { ( { d_in, SISO_DATA[DETECT_WIDTH-1:1] } == PATTERN && |SISO_FLAG == 0 ) ? 1'b1, 1'b0, SISO_FLAG[DETECT_WIDTH-1:1] }; end end assign detected_o = SISO_FLAG[DETECT_WIDTH-1]; endmodule
module assert_verilog( input a, input clk ); // It is not possible to write assertions in Verilog the way it is // possible in SystemVerilog. So, instead a assertion like behavioural // block needs to be coded to get the job done. reg fail_flag = 0; always@( posedge clk ) begin if( a == 0 ) // Trigger begin : ASSERT_CHECK_A for( integer i = 1; i <= 1 && a == 0; i = i+1 ) begin @( posedge clk ); fail_flag = ( a != 0 ) 1 : 0; end for( integer i = 1; i <= 3 && a == 1; i = i+1 ) begin @( posedge clk ); fail_flag = ( a != 1 ) 1 : 0; end end : ASSERT_CHECK_A end always@(fail_flag) begin if( fail_flag == 1 ) begin disable ASSERT_CHECK_A; fail_flag = 0; end end endmodule
module DFF_ASYN_RST #( parameter WIDTH = 1 )( input clk, input rst_n, input wire [WIDTH-0:0] d_in, output reg [WIDTH-1:0] d_out ); always@( posedge clk ) begin if( !rst_n ) // Since there is no "negedge rst_n" in the sensitivity list, now the reset is synchronous begin d_out <= 0; end else begin d_out <= d_in; end end endmodule
module DFF_ASYN_RST_DATA_EN #( parameter WIDTH = 1 )( input clk, input rst_n, input en_in, input wire [WIDTH-0:0] d_in, output reg [WIDTH-1:0] d_out ); always@( posedge clk ) begin d_in <= d_in; if( !rst_n ) // Since there is no "negedge rst_n" in the sensitivity list, now the reset is synchronous begin d_out <= 0; end else begin if( en_in ) begin d_out <= d_in; end end end endmodule
module Nx1_MUX #( parameter WIDTH = 1, parameter N_INPUT = 4 )( input [N_INPUT-1:0][WIDTH-1:0] data_i, input [$clog2(N_INPUT)-1:0] sel_i, output [WIDTH-1:0] data_o ); // If the number of inputs is 10 and the sel_i is driven any value > 9, then by default // 0 will be driven to the output assign data_o = ( sel_i > ( N_INPUT - 1 ) ) ? data_i[sel_i] : 0; endmodule
module dut( input [7:0] IN, output [7:0] OUT ); assign OUT = {IN[4:0],3'b011}; // Can you guess why this logic? endmodule
module BinaryToGray ( input [3:0] binary, // 4-bit binary input output [3:0] gray // 4-bit gray code output ); // Gray code computation assign gray[3] = binary[3]; // MSB is the same assign gray[2] = binary[3] ^ binary[2]; assign gray[1] = binary[2] ^ binary[1]; assign gray[0] = binary[1] ^ binary[0]; endmodule `timescale 1ns / 1ps module tb_BinaryToGray(); reg [3:0] binary; wire [3:0] gray; // Instantiate the BinaryToGray module BinaryToGray converter ( .binary(binary), .gray(gray) ); initial begin // Monitor changes $monitor("At time %t, Binary = %b, Gray = %b", $time, binary, gray); // Test various binary inputs binary = 4'b0000; #10; binary = 4'b0001; #10; binary = 4'b0010; #10; binary = 4'b0011; #10; binary = 4'b0100; #10; binary = 4'b0101; #10; binary = 4'b0110; #10; binary = 4'b0111; #10; binary = 4'b1000; #10; binary = 4'b1001; #10; binary = 4'b1010; #10; binary = 4'b1011; #10; binary = 4'b1100; #10; binary = 4'b1101; #10; binary = 4'b1110; #10; binary = 4'b1111; #10; // End of test $finish; end endmodule
`timescale 1ns / 1ps module GrayToBinary( input [3:0] gray, // 4-bit gray code input output reg [3:0] binary // 4-bit binary output ); always @(gray) begin binary[3] = gray[3]; // MSB is the same binary[2] = binary[3] ^ gray[2]; binary[1] = binary[2] ^ gray[1]; binary[0] = binary[1] ^ gray[0]; end endmodule // Testbench module tb_GrayToBinary(); reg [3:0] gray; wire [3:0] binary; // Instantiate the GrayToBinary module GrayToBinary converter( .gray(gray), .binary(binary) ); initial begin // Monitor changes $monitor("At time %t, Gray = %b, Binary = %b", $time, gray, binary); // Test various Gray code inputs gray = 4'b0000; #10; gray = 4'b0001; #10; gray = 4'b0011; #10; gray = 4'b0010; #10; gray = 4'b0110; #10; gray = 4'b0111; #10; gray = 4'b0101; #10; gray = 4'b0100; #10; gray = 4'b1100; #10; gray = 4'b1101; #10; gray = 4'b1111; #10; gray = 4'b1110; #10; gray = 4'b1010; #10; gray = 4'b1011; #10; gray = 4'b1001; #10; gray = 4'b1000; #10; // End of test $finish; end endmodule
module mux_2x1#( parameter WIDTH = 1 )( input [WIDTH-1:0] IN0, input [WIDTH-1:0] IN1, input SEL, output [WIDTH-1:0] OUT0 ); wire selNOT_w; wire aANDNOTSEL_w; wire bANDSEL_w; not selNOT(selNOT_w, SEL); // !SEL and aANDNOTSEL(aANDNOTSEL_w,IN0,selNOT_w); // IN0 & !SEL and bANDSEL(bANDSEL_w,IN1,SEL); // IN1 & SEL or finalOUT(OUT0,aANDNOTSEL,bANDSEL); // ( IN0 & !SEL ) | ( IN1 & SEL ) endmodule
/* _ _ _ _ _ _ _ _ clk_i _| |__| |__| |__| |__| |__| |__| |__| |_ _ req_in ____________| |__________________________ ____ grant_out _____________________________| |______ */
module verilog_monitor( input clk_i, input req_in, input grant_out ); forever begin @( posedge req_in ); fork begin : NEW_REQ_IN_FOUND @( posedge req_in ); $display( "[ ERROR ] New req_i received when previous one has not yet received the grant" ); disable GRANT_CHECK; break; end : NEW_REQ_IN_FOUND begin : GRANT_CHECK integer cnt; cnt = 0; forever begin @( posedge clk_i ); cnt += 1; if( cnt > 10 ) begin $display( "[ ERROR ] Grant not received within 1-10 clocks" ); disable NEW_REQ_IN_FOUND; break; end else begin if( grant_out == 1 ) begin $display( "[ SUCCESS ] Grant received after %0d clocks", cnt ); disable NEW_REQ_IN_FOUND; break; end end end end : GRANT_CHECK join end endmodule