Вы находитесь на странице: 1из 5

EE413 Tutorials Sample Verilog HDL Codes

Sample Verilog HDL Codes


The HDL (Hardware Description Language) is used for describing the circuit by codes instead of circuit
elements. More specifically, the HDL codes take place of “schematics” in the cadence libraries. For
instance, in order to describe a DFF, one should insert the sub-elements like inverters, NAND gates,
etc. in the schematics. By using HDL, it is possible to describe the same circuit by typing a number of
lines of HDL code.
There are mainly 2 hardware description language generations: HDL, and Verilog-HDL. Although both
of them are used heavily, we will work on Verilog-HDL, since it is easier, and it is closer to engineering
concepts. The Verilog-HDL version embedded in the cadence design environment is called as Verilog-
XL.
There are 2 ways of writing Verilog-XL codes, one is gate-level, and the other is behavioral.

A master-slave D-type Flip Flop


This will be a sample for gate-level Verilog-XL code. Gate-level Verilog-XL code is not much different
than drawing schematics. The following figure shows the schematics of the DFF, and the Verilog-XL
code below that describes this circuit.

1. // A master-slave type D-Flip Flop


2. module flop (data, clock, clear, q, qb);
3. input data, clock, clear;
4. output q, qb;
5. // primitive #delay instance-name (output, input1, input2, .....),
6. nand #10 nd1 (a, data, clock, clear),
7. nd2 (b, ndata, clock),
8. nd4 (d, c, b, clear),
9. nd5 (e, c, nclock),
10. nd6 (f, d, nclock),
11. nd8 (qb, q, f, clear);
12. nand #9 nd3 (c, a, d),
13. nd7 (q, e, qb);
14. not #10 inv1 (ndata, data),
15. inv2 (nclock, clock);
16. endmodule

Note that, each node and each component in the schematics have a unique name. The inputs and
output of the components are important. For instance the inputs of “nd3” are a and d, and the output
is c.
Now let's see the code in detail.
1. The first line is the comment line.
2. This line describes the name of the circuit. The format is as below:
module <circuit_name> ( <pin1>,<pin2>,...,<pin n>);
module is the keyword. The name of the circuit here is flop, and there are 5 pins with

METU MEMS-VLSI Research Group – 2003 1 Last updated on 12/12/2003


EE413 Tutorials Sample Verilog HDL Codes

corresponding names. Note that the direction of the pins (either input or output) are not
described yet.
3. This line describes the input pins, and its format is as below:
input <pin 1>, <pin 2>,..., <pin k>;
According to the format above, data, clock, and clear pins are input pins.
4. Similar to line 3, this line describes the output pins. So q and qb are the output pins.
6. Now the description of the circuit starts. For the lines from 6 to 15, the following format is valid:
<primitive_gate> <delay_time> <name> (<out>, <in1>,<in2>...);
This line inserts a component with type of primitive_gate having a transition time of delay_time.
The name of the component is name, and the output and inputs are out and in1, in2,... Writing this
line is same as inserting the component in the schematics, because this line says that there is a gate of
type primitive_gate, and its preferences are like this. For instance see the line 6. It says that there is
a nand gate with 10ns transition time. Its name is nd1, its output is a, and its inputs are data, clock,
and clear. Note that this is exactly one of the nand gates in the schematics (check it!). Each line
between 6 and 15 describe one component. So as you can see, gate-level Verilog-XL code is not very
much different than drawing schematics. Actually I usually prefer drawing schematics instead of this
method :)
One point here is important. Lines 7 to 11 have a slightly different format. It has only the
name and input/output pins of the component. This is a shortcut for describing many components in a
shorter form. This means that nd2, nd4, nd5, nd6, and nd8 have the same transition time of 10ns. Be
careful about the punctuations at the ends of the lines. Line 6 has “,”, and line 11 has “;” as the last
character.
16.States the end of the circuits code with endmodule keyword.
Gate-level HDL representation of the circuit is not much different than drawing the schematics.
Furthermore, you need the schematics of the circuit before typing gate-level code. So, this
method is not preferred much. However, it is a good starting point to learn Verilog. The next
example will be behavioral and it is much more important.

METU MEMS-VLSI Research Group – 2003 2 Last updated on 12/12/2003


EE413 Tutorials Sample Verilog HDL Codes

A 1-bit synchronous counter with parallel load and freeze modes, and
with asynchronous reset option
In this part, Verilog-XL code of a 1-bit synchronous counter with parallel load and freeze modes, and
with asynchronous reset option will be described. The following code is the final code, and it will be
described in detail.

// Verilog HDL for "EE413", "CNT1" "functional"


// Verilog HDL model of a 1-bit parallel loadable synchronous counter with
// asynchronous reset and freeze features
module CNT1(D, L, Ti, RB, CLK, Q, Qb, Tout);
input D, L, Ti, RB, CLK;
output Q, Qb, Tout;
reg q, tout;

// Define a 4-to-1 multiplexer function


function mux;
input [3:0] in;
input [1:0] s;
case (s)
2'b00: mux = in[0];
2'b01: mux = in[1];
2'b10: mux = in[2];
2'b11: mux = in[3];
endcase
endfunction

// Model the async reset


always @(RB) begin
if (!RB)
assign q = 1'b0;
else
deassign q;
end

// Model the pos edge behaviour


always @(posedge CLK) q = mux({D, D, ~q, q}, {L, Ti});
// Model the Tout
always @(Ti or q) tout = Ti & q;
// Final output pin assignments

assign Tout = tout;


assign Q = q;
assign Qb = ~q;
endmodule

To start with, // indicates a single comment line (as in the C++). The CNT module is defined at the
very beginning by keyword module.
module CNT1(D, L, Ti, RB, CLK, Q, Qb, Tout);
Note that, at this point, we do not know which pins are input and which are output. To define these we
should write:
input D, L, Ti, RB, CLK;
output Q, Qb, Tout;
With the above 2 lines, we described the input/output pins of the circuit.

METU MEMS-VLSI Research Group – 2003 3 Last updated on 12/12/2003


EE413 Tutorials Sample Verilog HDL Codes

In addition to this, we should also define internal variables, to store results before assigning them to
the output pins. In other words, the output pins cannot be changed directly in the code. Instead, an
internal variable will be used and it will be assigned (or let's say attached) to the output pin. When
this internal variable changes, the output pin which is assigned to it will change also.
In this example, there are 3 outputs. However, since Qb is logical inverse of Q, we need only 2 internal
variables. q and tout are the internal variables (registers) in our example. At the end of the code, tout
is assigned to Tout, q is assigned to Q, and ~q (logical inverse of q) is assigned to Qb. The following
line defines the registers to be used in the code.
reg q, tout;
The next lines define a function. Such functions make codes much simpler and shorter. Frequently used
architectures can be defined as a function, and then they can be invoked from the main block as many
times as desired. As you all know, we need a 4-to-1 multiplexer to perform, both load, toggle, and
freeze operations. For this purpose we have to define a 4-to-1 multiplexer function, which can be done
as follows: (We have a 4-bit input [3:0] in, and a two bit selection bits [1:0] s).
function mux;
input [3:0] in;
input [1:0] s;
case (s)
2'b00: mux = in[0];
2'b01: mux = in[1];
2'b10: mux = in[2];
2'b11: mux = in[3];
endcase
endfunction
The definition of a function is made between function and endfunction keywords. The multiplexing
definition is best described using case. You should refer to the Verilog Tutorial for further information, if
required.
Here note that, 2'b00 represents a 2-bit number of 00. The definition “input [3:0] in;” states that the
input in is a 4-bit number. in[0] corresponds to the 0th bit, and so on.
Is it possible to write this code without using function?
Now, we will define how the registers (and so outputs) will change according to the inputs. For this,
always statement will be used. There are a number of ways to use it.
always @(posedge CLK) q = mux({D, D, ~q, q}, {L, Ti});
The line above describes the synchronous operation of the circuit. Note that, the definitions starting
with always indicates the function dependency of certain signals. Here, the statement in the always
block will be done when positive edge of CLK is sensed (Note that @ and posedge are also keywords).
The statement in the always block is changing the value of q register. Note the use of function mux.
{D,D,~q,q} is the 4-bit input with q is the least significant bit. So in[0] corresponds to q, and so on.
{L, Ti} is the 2-bit output of the function. So, when a positive edge (low-to-high) transition is sensed,
the register q will be changed by the results of mux function.
always @(RB) begin
if (!RB)
assign q = 1'b0;
else
deassign q;
end
This always statement models the asynchronous reset operation. Here, we define that q variable
should be changed whenever there is a change in RB. Inside the always block (begin-end is required
for multi commands), we check the value of RB. If its zero (0), then we assign 0 to q, if not we
deassign q.
Now, one important point should be clear. Two always statements described above changes the value
of q. However, we want to fix the value of q to 0 when RB is low (why?). This is done by using assign-
deassign statement pair. This statement pair is used to fix the value of a register until it is released by

METU MEMS-VLSI Research Group – 2003 4 Last updated on 12/12/2003


EE413 Tutorials Sample Verilog HDL Codes

deassign. So, when the value of q is fixed when Rb is low, the other always statements affecting the
value of q are ignored. When Rb becomes high again, q register is released by deassign statement.
You may understand this better by simulating the circuit without deassign statement.
always @(Ti or q) tout = Ti & q;
The last always statement is generating the Tout signal. This time, the module or the lines inside that
block should be executed whenever there is a change in Ti or q. Therefore @(Ti or q) is written after
the always block. Since it is again a single assignment no begin-end are used. Note that & is used for
logical and operation.
So, we used 3 always statements. This is obvious actually, because we should model the synchronous
operation of the circuit, asynchronous reset operation, and the toggle output.
This is it. I am sure that you will be a Verilog expert after a few trials.

A Possible MUX4 Verilog-XL Code


module MUX4 (Q, I, S);
input [3:0] I;
input [1:0] S;
output Q;
wire #(5, 10) q;
function mux;
input [3:0] in;
input [1:0] s;
case (s)
2'b00: mux = in[0];
2'b01: mux = in[1];
2'b10: mux = in[2];
2'b11: mux = in[3];
endcase
endfunction
always @(I or S) q = mux(I, S);
assign Q = q;
endmodule

The above code is supplied without any warranty. That is it may function or not. It is given just to give
an idea. But verfication is left to you.

How to Realize the Circuits Described by Verilog?


There are software tools called synthesis tools, that synthesizes the described circuit from a set of user
defined blocks. The library which includes these blocks are called synthesis library. Most of the digital
ASIC chips are designed using this methodology. That is, the digital ASIC designer first describes the
circuit using behavioral Verilog HDL. Then he/she uses sysnthesis tools (usually SYNOPSYS) to
generate the netlist of the required circuit. The generated netlist contains reguired blocks, and their
connectivity information. A synthesis operation can be optimized with respect to timing, area, or with
some other cost parameters defined by the designer. After obtaining the required netlist, the netlist is
fed into PLACE and ROUTE (PR) tools. They basically take the synthesized netlist, and according to the
user supplied specifications (number of cell rows, routing channel spacings, pin locations, signal
priorities, etc), it first places the cells instanced in the synthesized netlist and performs routing of the
signals. Usually, routing is also performed in more than one step. For example power, clock, and
ordinary signal routing is performed in different steps. Especially the first two steps are given highest
priority. That is, the computer consumes more CPU power, or performs more detailed analysis while
connecting power rails and clock lines.
Today Verilog is used extensively in digital ASIC or FPGA designs. For example, complex FPGA designs
also start with the Verilog codes (sometimes referred as synthesizeable codes). Depending on the final
product, the synthesis library can be either a VLSI standard cell synthesis library or a certain type of
FPGA family.

METU MEMS-VLSI Research Group – 2003 5 Last updated on 12/12/2003

Вам также может понравиться