VHDL tutorial - Creating a hierarchical design

Gene BrenimanMay 22, 20086 comments

Quick Links

In earlier blog entries I introduced some of the basic VHDL concepts. First, developing a function ('VHDL tutorial') and later verifying and refining it ('VHDL tutorial - part 2 - Testbench' and 'VHDL tutorial - combining clocked and sequential logic'). In this entry I will describe how to build a VHDL design made up of a collection of smaller pieces (similar to using subroutines in software development).

When developing a design in VHDL, the first impulse is to describe the entire design in a single file. Another common situation arises when a simple, existing design grows in complexity. Either way, you can end up with a design that becomes more and more difficult to read and maintain.

By adopting a more hierarchical design approach it is possible to reuse common elements, and segment a complex design into smaller pieces. Both of these techniques result in a more maintainable design. VHDL allows you to define and describe an 'entity', which can then be included into other, higher-level designs. Using entities, it is possible to both hide complexity and to manage changes more effectively (modify a single instance of a component, effecting multiple uses of the component). In this example, we will define a simple entity of a counter (or divider) which we can then replicate in the main module.

The first step in creating an entity, is to define its input(s) and output(s). In this example we will create a simple divide by ten counter. This counter will have two input signals (rst and clkin). The counter will also have a single output signal (clkout). The output signal is of the 'inout' type. This type is usable as either an input or output. This type is used to allow us to construct a simple state toggle for the 'clkout' output. The definition of our entity, for this example then looks like:

entity definition

The definition includes the name of entity (div1) and the declaration of the inputs and outputs (name and type). In this example, 'rst' is used to initialize and synchronize the counters (this can be used to insure that a full count occurs prior to an output toggle).

With the definition complete, we can begin to design the logic (or behavior) of the counter. First, we need to define the necessary variables and a process to provide the logic for our entity. A signal is needed to provide a 'counter-down' variable (clkdiv). For this example, we will use a 3-bit, unsigned integer. The number of bits needed is determined by one half the division value, as this is a symmetrical counter (count down, toggle, count down, toggle, producing a 50% duty cycle).

Number of bits (unsigned integer)
Counter Range
1 ÷ 4
2 ÷ 4 through 8
3 ÷ 4 through 16
4 ÷ 4 through 32


Here is the main body of our ÷ 10 entity.

Behavior

Line 25 shows the process declaration and the input sensitivity list. The sensitivity list defines the input(s) that can effect a change of the output(s) in the process. In this case, both rst and clkin can cause the output (clkout) to change. Lines 27-29 are the initialization part of the process. If rst is '0', the clock counter (clkdiv) is set to "100" (or 4) and clkout is set to '0'. If rst is not equal to '0', then the design will sample clkin for an event, in which the clkin input is equal to '0'. An 'event' is the detection of a change in state of a variable. Thus, Line 30, translates into: "if clkin changes from '1' to '0' then". If this is the case, Lines 31-36 are processed according to the state of the clkdiv variable. If clkdiv is equal to '000' (terminal count), the clkdiv variable is reset to "100" (line 32) and the output (clkout) is toggled (i.e. the logic state of clkout is inverted, 0->1, or 1->0, line 33). If the clkdiv value is not zero, the value is decremented by one (counted down, line 35).

This completes the definition of the entity div10. The following is the complete module for our ÷ 10 counter.

complete entity

With the entity complete, we will define another module that will use this entity as a component of the design. To demonstrate the use of the entity, I have constructed a very simple example that will create a chain of divide by ten counters, to achieve a total clock division of 1000.

The first step in constructing the upper-level module is to define its inputs and outputs. In this example we need only three I/O definitions. The first is a global reset input that can be passed down to the counter/dividers. The next input is a clock input, which is passed to the initial counter/divider. And finally, we need an output signal to pass our clock divided signal out of the device.

Device

The next step is to create variables for the outputs of each of the three divider stages. These variables will represent the input clock ÷ 10 (MC_10), the input clock ÷ 100 (MC_100) and the input clock ÷ 1000 (MC_1000).

Signals

In order to use our ÷ 10 entity (div10), created above, we need to generate a component description that matches our newly created entity.

component definition

With all the inputs, outputs, variables and components defined, we can connect the components to construct our divider chain. Each instance of our component receives the same reset signal (Reset), but have unique clock in and clock out variables. The first divider uses our master clock (MClk) to generate the ÷ 10 clock (MC_10). The second divider uses the ÷ 10 clock (MC_10) to generate the ÷ 100 clock (MC_100). The final divider uses the ÷ 100 clock (MC_100) to generate the ÷ 1000 clock (MC_1000).

logic

Putting all the pieces together, with the necessary boiler plate, gives us our completed high-level module. In line 39 of our example, the output of the third counter (MC_1000, which is actual defined as an inout pin, due to its dual usage in the divide by 10 entity) is assigned to our device output pin (ClkOut). This assignment transfers the value of the 'inout' signal to our device output pin.

complete example

The created example compiled easily into the XC2C128-7VQ100 part. The summary shows that the part is only partially full (<10%), leaving plenty of room for still future enhancements.

Summary

Hopefully this example will assist you in using a hierarchical design approach in your VHDL projects. I have found this technique to be an extremely useful tool. In one project, I used multiple instances of multiple divider components to build a large programmable divider chain. By hiding all of the divider implementation into lower-level modules, I was left with a much more readable high-level module.

Thank you for your comments and suggestions. I look forward to any further questions.

Good luck and happy designing!

Gene

(Note: Pardon my lack of recent blog entries. I have been recovering from a broken finger of my dominate (right) hand. Typing and mousing have been a challenge for a while. Rehab has been going well, and my normal hunt and peck typing skills are returning to normal)

VHDL Tutorial Part 2 is HERE


Previous post by Gene Breniman:
   VHDL tutorial - combining clocked and sequential logic
Next post by Gene Breniman:
   VHDL tutorial - A practical example - part 1 - Hardware

Comments:

[ - ]
Comment by zhou0283February 16, 2010
Isn't "div10" as defined here a divide-by-8 counter?
[ - ]
Comment by genebrenFebruary 19, 2010
RCIngham, The divider is actually a divide by 10. On 5 consectutive clocks the counter counts down 4,3,2,1,0. On zero the output is toggled, and the count reloaded.
[ - ]
Comment by leblancmenesesJune 2, 2008
thanks for the article if i ever need to write verilog again.. i'll know where to look. i'm hoping by then it'll be more c++ style and more model based engineering driven. (pretty diagrams converted to code.... using xmi and xslt transforms)
[ - ]
Comment by sadidAugust 2, 2008
Good and Thank but you can code the component more parametric form example div_m & m=8,10,20,45,... it'll have more fun!
[ - ]
Comment by phillincOctober 24, 2008
Thanks very much for your very interesting blogs, thay have been a tremendous help for myself in getting over the VHDL learning curve, aswell as the learning curve associated with the xilinx development enviroment. I am currently studying embedded systems at a university here in the UK, and am struggling with the development of VHDL packages, and would appreciate it if you could possibly send me a link to one of your previous blogs as i find your practical way of explaining the subject highly enlightening. If you have not done a previous blog would you possibly concider doing one addressing the subject. Thanking You phillinc
[ - ]
Comment by Martin ThompsonMay 14, 2009
Interesting post - I have a couple of comments (which come from having to continually re-educate students that arrive with me :): 1) Component instantiation is a bit old-hat these days - use direct instantiation, then you don't have to keep your components up-to-date! 2) *Still* perpetuating std_logic_arith! Any chance you could change your examples to numeric_std and save another generation of students growing up using non-standard libraries?

To post reply to a comment, click on the 'reply' button attached to each comment. To post a new comment (not a reply to a comment) check out the 'Write a Comment' tab at the top of the comments.

Registering will allow you to participate to the forums on ALL the related sites and give you access to all pdf downloads.

Sign up
or Sign in