Verilog is a hardware description language (HDL) that was standardized as IEEE Std 1364-1995 and first revised as IEEE Std 1364-2001.
What is HDL?
HDL describes the structure and behavior of the electronic circuit. I hope you are familiar with logic gates which are the building blocks of all the digital electronic circuits. Whatever the design that we make, will be converted to logic gates(this process is known as synthesis) and inturn these logic gates are finally converted into transistors which will be embedded on the IC(Integrated Circuit). Let us try to understand this in more detail with an example:
Let us say you are using a RAM. RAM is nothing but a memory IC(volatile – which loses content stored in it when it is powered off). To store memory what we require is registers. Each register is nothing but a flip-flop. Each flip-flop can store 1 bit of information. So we need ‘n’ number of flip-flops i.e. ‘n’ number of registers to make n-bit memory. These flip-flops are again made up of logic gates. Logic gates are made up of transistors. So finally when we go to the bottom level of a chip design we see transistors. This HDL will support us(designers) to code the memory design(example which we considered here) in different abstraction levels like(gate level, behavioral level, transistor level). which will be discussed in further lessons. You can see the below picture depicting how the abstraction is done.
So HDL in short will enable us to interpret the circuit in code language.
We use two types of HDL: 1) Verilog 2)VHDL
|Its syntax is almost similar to C (developed based on C)||Its syntax is not almost similar to C (developed based on ADA)|
|Syntax is of low verbosity||Syntax is of high verbosity|
|Easily understandable by majority||Not easily understandable by majority|
|It has an advanced version called “System Verilog”||It doesn’t have advanced version|
|It is case sensitive language||It is case insensitive language|
|User defined data types are not supported||User defined data types are supported|
|No concept of library and package||Concept of library and package|
|Mostly used in ASIC design (also used for FPGA but to less extent)||Mostly used in FPGA designs (also used in ASIC but to less extent)|
We also require to check the functionality of the design that is developed. This behavior check or functionality check of design is called verification. To verify the RTL design that is developed, we need to create a environment called testbench. Testbench can be simple or complex based on the complexity of the RTL Design. A normal counter/flip-flop/mux/gates etc. can be verified with simple test bench developed in Verilog. We have advanced versions of language/methodology with more features to verify complex designs. They are System Verilog and UVM(Universal Verification Methodology). Below diagram depicts how the testbench and RTL design are connected and how RTL is verified via testbench.
This clearly represents that DUT(Design Under Test) is instantiated/declared within the testbench(TB) and the ports(both I/P and O/P) of testbench and DUT are connected. Input stimulus is passed through the TB input ports and and the output data is collected through TB output ports. We will see in detailed explanation about this each component in upcoming lessons. The testbench that we will develop for this entire course(Verilog) will have this same structure.
Now let us understand this with one example which clearly describes how the RTL and Testbench looks like.
//RTL DESIGN module two_input_and_gate(input a1,a2, output y); wire a1,a2; reg y; //if any internal signals are used in design declare them here //anyone of the two below statements can be used to get the and gate functionality assign y = a1 & a2; //and(y,a1,a2); //verilog provides us with built in gates used via keywords endmodule
//TESTBENCH module two_input_and_gate_tb; reg a1,a2; wire y; //anyone of the two below statements can be used to establish the connection between dut and tb ports two_input_and_gate dut(.a1(a1),.a2(a2),.y(y)); //two_input_and_gate dut(a1,a2,y); //input stimulus initial begin a1 = 1'b0; a2 = 1'b0; #2 a1 = 1'b0; a2 = 1'b1; #2 a1 = 1'b1; a2 = 1'b0; #2 a1 = 1'b1; a2 = 1'b1; #2 $finish; end //this is used only in edaplayground to dump the output in waveform initial begin $dumpfile("and_gate_tb.vcd"); $dumpvars(); end endmodule
RTL design structure consists of:
a) module defining with ports declared inside it. You can also declare the type of ports i.e. whether input or output inside it. You can also specify the data type of the port i.e. reg/wire inside it. But generally most followed coding style is you declare only ports and its i/p or o/p type inside module definition.
b) As we have not declared the data type of the port inside module definition, we have declared it below the module definition.
c) If any internal signals are used in the design, you can declare them below the b part.
d) behavioral/structural/gate level/transistor level statements are declared under this c part.
e) the design coding is ended by declaring the ‘endmodule’ as the last statement.
Testbench structure consists of:
a) module definition with no ports declared inside it.
b) testbench ports are declared here with its data type(If any of the design ports are declared as ‘wire’ in design, they should be declared as ‘reg’ in testbench and vice versa). This is because the input stimulus which we pass through the testbench should store the stimulus values and pass them to the DUT I/P ports.
c) DUT and TB connection is declared here. There are two types of connection methods. One is connection by position/order. Other is connection by reference.
Connection by position/order:
Here the syntax is like declare the design module name first then declare the instantiation for the design in TB and pass the ports of TB as arguments in the instantiated design with same order in which how we declared the ports in the original design file. So by declaring like this the DUT assumes that connection of ports in the order of the ports declared in TB and DUT.
Connection by reference:
Here the syntax is like declare the design module name first then declare the instantiation for the design in TB and in the arguments pass the design ports first and connect its associated tb port(declared inside curly braces) with the design port. This doesn’t need any specific order like how you connect the ports. This is the best method to use and avoids confusion.
d) input stimulus is passed from the tb input ports which were declared as reg inside the initial block. We will discuss what is this initial block in further lessons. ‘#’ symbol indicated delay. so #2 represent 2ns delay(it may be ns/ps/us depending on the timescale declared). For now you assume it as 2ns delay. $finish will end the simulation after that particular time depending on how much time after it is declared.
e) This section is not needed in real/original simulator. It is used especially in edaplayground code editor to dump the output into a waveform so that we can view waveform directly and understand what is the input stimulus we are passing and how is the output coming pictorially.
f) The coding is ended with declaring ‘endmodule’
You can execute the above code by clicking this link ‘execute code‘
I hope now you got an idea about what is HDL, why it is used, how RTL designs are developed in HDL and how we verify the RTL designs.
Check out my next topic on basic concepts in Verilog.
Thank you and Happy learning!!!