Monday, June 28, 2010

VHDL samples


The sample VHDL code contained below is for tutorial purposes.
An expert may be bothered by some of the wording of the examples
because this WEB page is intended for people just starting to
learn the VHDL language. There is no intention of teaching
logic design, synthesis or designing integrated circuits.
It is hoped that people who become knowledgeable of VHDL will
be able to develop better models and more rapidly meet whatever
their objectives might be using VHDL simulations.



Click here to have all references included, BIG!


Contents




A few VHDL compilers have bugs. 'alias' may have to be eliminated.


Example of VHDL writing to standard output



The VHDL source code is hello_world.vhdl
This demonstrates the use of formatting text output to a screen.
A process is used to contain the sequential code that builds an
output line, then writes the line to standard output, the display screen.

Almost identical VHDL code hello_proc.vhdl
uses a procedure in place of the process to contain the sequential code.
note that the procedure has no arguments and the call needs no label.
Simply the statement my_proc; in the architecture is the call.


Example of VHDL reading and writing disk files



The VHDL source code is file_io.vhdl

This example is a skeleton for a VHDL simulation that needs input
from a file, simulates based on the input and produces output to
a file. The output file may be used as input to other applications.
The importance of being able to write to the display screen and to
read and write files is to maintain portability of your VHDL code.
Especially test benches, must be independent of any specific VHDL
systems Graphic User Interface, GUI. GUI differ radically and it
may be important to you to be able to develop and debug your
VHDL code independent of the host machine and independent of
the VHDL system supplier.


Simple parallel 8-bit sqrt using one component



The VHDL source code is sqrt8.vhdl
The output of the VHDL simulation is sqrt8.out
The schematic is sqrt8.jpg
The Sm component schematic is sqrtsm.jpg

This example shows how a Sm component is directly coded in VHDL as
concurrent statements. The multiplexor is coded as a single "when"
statement. "Sm" is mnemonic for subtractor-multiplexor.

The overall circuit that inputs an 8-bit integer and outputs a 4-bit
integer square root uses many copies of the Sm component. This circuit
uses the "entity" method of instantiating copies of a component. The
"port map" is the mapping of actual parameters onto the formal
parameters in the Sm entity.

The theory of operation is described in sqrt.txt
and wikipedia


Optimized parallel 8-bit sqrt using many components



The VHDL source code is sqrt8m.vhdl
The output of the VHDL simulation is sqrt8m.out
The schematic is sqrt8m.jpg

This circuit performs the same function on the input as does
sqrt8.vhdl above. The difference is that many specialized
entities were created as building block components. The specialization
eliminates circuitry that is not needed because the inputs are
logical 0 or 1. This was a step in developing the parallel 32-bit
square root circuit shown next.

The Sm component family are subsets of the schematic sqrtsm.jpg
sqrtsn.jpg
sqrts0.jpg
sqrts1.jpg
sqrtsb.jpg
sqrts0b.jpg
sqrts1b.jpg



32-bit parallel integer square root



The VHDL source code is sqrt32.vhdl
The output of the VHDL simulation is sqrt32.out
The schematic was never drawn. sqrt8m.vhdl was expanded
using "generate" statements to create sqrt32.vhdl


A group of VHDL components using generic parameters



Common building blocks for simulating digital logic are adders, registers,
multiplexors and counters. This example shows a set of generic entities
and the corresponding architectures that have the word length and delay
time as generic parameters. In addition to being useful in circuits,
the generic word length allows much smaller circuits to be debugged and
then the word length increased to the final desired value. The test
bench uses a word length of 8 while the example circuit that performs
a sequential multiplication uses a 16 bit word length.

Similar to the entity declaration "port" and the entity instantiation
"port map", with generics there is an entity declaration "generic" and
the entity instantiation "generic map."

The VHDL source code for the generic adder is add_g.vhdl
The VHDL source code for the generic register is reg_g.vhdl
The VHDL source code for the generic multiplexor is mux_g.vhdl
The VHDL source code for the generic counter is cntr_g.vhdl
The VHDL source code for the generic test bench is test_g.vhdl
The output of the VHDL simulation is test_g.out


A serial multiplier using generic components



The VHDL source code for the generic serial multiplier is mul_ser_g.vhdl
The output of the VHDL simulation is mul_ser_g.out

This simulation models a multiplier using "hi" and "lo" registers used
in the MIPS architecture and is similar to the Patterson and Hennessey
example.


Example of behavioral and circuit VHDL barrel shifter



The VHDL source code for a barrel shifter, includes both behavioral
and circuit description bshift.vhdl
The VHDL source code for testing bshift.vhdl and comparing the behavioral
model to the circuit model test_bshift.vhdl
Note the example use of a package and a function definition to convert
the 5-bit std_logic_vector shift count "shift" to an integer "shft"
The one process "test_data_generator" updates the signal "count" and
also prints the results of the behavioral and circuit model for the
three types of shifts: left logical, right logical and right arithmetic.
The output of the VHDL simulation is test_bshift.out
A partial schematic of the right logical shift is



Example of serial multiplier model



The VHDL source code for a serial multiplier, using a shortcut model
where a signal acts like a register. "hi" and "lo" are registers
clocked by the condition mulclk'event and mulclk='1'
The VHDL is mul_ser.vhdl
The output of the simulation is mul_ser.out

At the start of multiply: the multiplicand is in "md", the multiplier
is in "lo" and "hi" contains 00000000. This multiplier only works
for positive numbers. Use a Booth multiplier for twos-complement
values.

At the end of multiply: the upper product is in "hi and the
lower product is in "lo."

A partial schematic of just the multiplier data flow is


The modified Booth serial multiplier, using a shortcut model is:
The VHDL is bmul_ser.vhdl
The output of the simulation is bmul_ser.out

A partial schematic of the Booth multiplier data flow is



Example of serial divider model



The VHDL source code for a serial divider, using a shortcut model
where a signal acts like a register. "hi", "lo" and quo are registers
clocked by the condition divclk'event and divclk='1'
The VHDL is div_ser.vhdl
The output of the simulation is div_ser.out

At the start of the divide: the divisor is in "md" ,
the upper dividend is in "hi" and the lower dividend is in "lo."

At the end of the divide: "lo" contains the quotient and "hi" contains
the uncorrected remainder (may need the divisor added to remainder)

A partial schematic of just the divider data flow is



Example of parallel 32-bit multiplier model



An unsigned multiplier using a carry save adder structure.
The VHDL source code for a parallel multiplier, using 'generate'
to make the VHDL source code small is mul32c.vhdl
The test bench is mul32c_test.vhdl
The output of the simulation is mul32c_test.out

The VHDL source code for a parallel Booth multiplier, two's complement
32-bit multiplicand by 32-bit multiplier input producing 64-bit product
is bmul32.vhdl
The test bench is bmul32_test.vhdl
The output of the simulation is bmul32_test.out

Both VHDL models use a concurrent conditional statement to model
various multiplexors.




A partial schematic of the multiplier is


A partial schematic of the add32csa is



Example of parallel 4-bit divider model



An unsigned divider using non-restoring divide with uncorrected
remainder. The basic cell is a Controlled Add/Subtract, CAS.

A partial schematic of the divider is


The test bench is divcas4_test.vhdl
The output of the simulation is divcas4_test.out


Simple example of component vs entity



VHDL allows a hierarchy of entities containing components.
At each level VHDL allows multiple architectures and multiple
configurations for each entity.

The following two examples, ctest1 and ctest1a, show use of
components with a configuration and use of "entity WORK."
that does not need a configuration.

ctest1.vhdl uses two components, fadd and add32
with a configuration file to select the element-architecture pair from
a library to use for each component. There could be a behavioral
architecture, a detailed circuit architecture, a timing architecture and
possibly others. The configuration can be used to select for each
component the desired architecture(s).

ctest1a.vhdl uses the same entities without
component declarations and without a configuration. This latter case
is not recommended for large designs or team projects.


Pipeline stalling on rising and falling clocks



When designing a pipeline where all data moves to the next stage on
a common clock, it requires two different circuits to stall the pipeline,
depending on registers accepting data on rising or falling clock.

Coding techniques include:
When storage elements accept data on a rising clock
Initialize clk to 0 so that a transition does not occur at time zero
The stall clock is clk or stall

When storage elements accept data on a falling clock
Initialize clk to 1 so that a transition does not occur at time zero
The stall clock is clk or not stall

The schematics for the rising and falling clock cases are :





The corresponding VHDL source code and output for the cases are:

stall_up.vhdl and stall_up.out
stall_down.vhdl and stall_down.out


Tracing all changes in a signal



When debugging VHDL it is sometimes useful to follow every change
to some signal. This signal tracing is easily accomplished by
a small process.

The technique is to have a process that monitors the signal(s)
For each signal, say xxx, create a process in the design unit with the signal

prtxxx: process (xxx)
variable my_line : LINE;
begin
write(my_line, string'("xxx="));
write(my_line, xxx);
write(my_line, string'(", at="));
write(my_line, now);
writeline(output, my_line);
end process prtxxx;

Obviously edit the above and replace xxx with your signal name.
Now, every time your signal changes a line out output shows it's value
and the time when it changed. Of particular interest is if 'U' or 'X'
appears, meaning Uninitialized or X for "don't know" ambiguous.
Do not use hwrite, this masks the 'U' and 'X'
a specific example is shown below on sum and cout

An example circuit using this technique on a 32-bit ripple carry
adder in signal_trace.vhdl


Other Links


No comments:

Post a Comment