A digital element such as a flip-flop can be represented with combinational gates like NAND and NOR. The functionality of a flip-flop is achieved by the connection of a certain set of gates in a particular manner. How the gates have to be connected is usually figured out by solving K-map from the truth table. The truth table is nothing but a table that tells us what inputs combine together to give what values of output. Shown in the image below is an electronic circuit that represents a D-flip flop and the corresponding truth table. The output q becomes 1 only when rstn and d are both having a value of 1.

intro-verilog-hardware-schematic-to-verilog

What is a hardware schematic ?

A hardware schematic is a diagram that shows how the combinational gates should be connected to achieve a particular hardware functionality. In this case, it is the set of NAND gates connected like shown towards the left in the image above. However, if we know what values of inputs contribute to make the output have a value of 1, then we can essentially hide the internal details of the connections and encapsulate it into a black-box. This block provides us with certain inputs and outputs that is similar to the hardware schematic made up of combinational gates.

What is a Hardware Description Language ?

It will be easier if we can describe how this block should behave and then let software tools convert that behavior into actual hardware schematic. The language that describes hardware functionality is called Verilog, and is classified as a Hardware Description Language.

What is meant by design functionality ?

Some typical behavioral requirements for a D-flip-flop are :

  • clock should be an input to the flop
  • if the active-low reset is 0, then the flop should reset
  • if the active-low reset is 1, then the flop output 'q' should follow input 'd'
  • output 'q' should get a new value only at the posedge of clock

An important question comes to mind : how do we know whether the behavior described in Verilog accurately reflects the intended behavior of the design ?

What is verification ?

This is checked by different methods and is collectively called as verification. The most common and widely practiced method of verification is circuit simulation. There are software tools to understand how a hardware described in Verilog should behave and provide various input stimuli to the design model. The output of the design is then checked against expected values to see if the design is functionally correct.

All simulations are performed by EDA (Electronic Design Automation) software tools and the Verilog design RTL is placed inside an entity called as testbench. Within the testbench, various tests provide different stimuli to the design. Such a testbench is shown in the image below.

intro-verilog-testbench

Sections of Verilog code

All behavior code should be described within the keywords module and endmodule. Rest of the design code would mostly follow the given template.

Verilog sections template

  1. Module definition and port list declaration
  2. List of input and output ports
  3. Declaration of other signals using allowed Verilog data types
  4. Design may depend on other Verilog modules and hence their instances are created by module instantiations
  5. The actual Verilog design for this module that describes its behavior


module [design_name] ( [port_list] );

	[list_of_input_ports]
	[list_of_output_ports]

	[declaration_of_other_signals]

	[other_module_instantiations_if_required]

	[behavioral_code_for_this_module]
endmodule

Example

The code shown below describes the behavior of a D type flip-flop. The first few lines declare a new module called dff and define the input and output ports. The only other signal used in this design is q and is declared next. Since this is a simple design, it does not depend on any other module and hence there are no module instantiations. The always block describes how the hardware should behave during certain events and hence is behavioral code.


// "dff" is the name of this module 

module  dff  ( 	input 	d, 			// Inputs to the design should start with "input"
						rstn,
						clk,
				output	q); 		// Outputs of the design should start with "output"
				
	reg q; 							// Declare a variable to store output values
	
	always @ (posedge clk) begin 	// This block is executed at the positive edge of clk 0->1
		if (!rstn)  				// At the posedge, if rstn is 0 then q should get 0
			q <= 0;
		else 
			q <= d; 				// At the posedge, if rstn is 1 then q should get d
	end
endmodule 							// End of module

Testbench code

The testbench is the Verilog container module that allows us to drive the design with different inputs and monitor its outputs for expected behavior. In the example shown below, we have instantiated the flop design illustrated above and connected it with testbench signals denoted by tb_*. These testbench signals are then assigned certain values and are eventually driven as inputs to the design.


module tb;

	// 1. Declare input/output variables to drive to the design
	reg 	tb_clk;
	reg 	tb_d;
	reg 	tb_rstn;
	wire 	tb_q;
	
	// 2. Create an instance of the design
	// This is called design instantiation
	dff 	dff0 ( 	.clk 	(tb_clk), 		// Connect clock input with TB signal
					.d 		(tb_d), 		// Connect data input with TB signal
					.rstn 	(tb_rstn), 		// Connect reset input with TB signal
					.q 		(tb_q)); 		// Connect output q with TB signal
					
	// 3. The following is an example of a stimulus
	// Here we drive the signals tb_* with certain values
	// Since these tb_* signals are connected to the design inputs,
	// the design will be driven with the values in tb_*
	initial begin
		tb_rsnt 	<= 	1'b0;
		tb_clk 		<= 	1'b0;
		tb_d 		<=  1'b0;
	end
endmodule