Selective Notes for a Digital Design Course using VHDL By: Ihab Adly Introduction Traditionally, digital design wasa manual process of designing and capturing circuits using schematic entry tools. This process has many disadvantages and is rapidly being replaced by new methods. System designers are always competing to build cost-effective products as fast as possible in a highly competitive environment. In order to achieve this, they are turning to using top-down design methodologies that include using hardware description language and synthesis, in addition to just the more traditional process of simulation. A product in this instance is any electronic equipment containing Application Specific Integrated Circuits (ASICs), or Field Programmable Gate Arrays (FPGAs). In recent years, designers have increasingly adopted top-own design methodologies even though it takes them away from logic and transistor level design to abstract programming. The introduction of industry hardware description languages and commercially available synthesis tools have helped establish this revolutionary design methodology. The advantages are clear and engineers’ design methods must change. Some of the advantages are: • • • • • • • • increased productivity yields shorter development cycles with more product features and reduced time to market, reduced Non-Recurring Engineering (NRE) costs, design reuse is enabled, increased flexibility to design changes, faster exploration of alternative architectures, faster exploration of alternative technology libraries, enable use of synthesis to rapidly sweep the design space of area and timing, and to automatically generate testable circuits, better and easier design auditing and verification. ASIC and FPGA devices Standard “off-the-shelf” integrated circuits have a fixed functional operation defined by the chip manufacturer. Contrary to this, both ASIC and FPGAs are types of integrated circuit whose function is not fixed by the manufacturer. The function is defined by the designer for a particular application. An ASIC requires a final manufacturing process to customize its operation while an FPGA does not. ASICs An Application Specific Integrated Circuit is a device that partially manufactured by an ASIC vendor in generic form. This initial manufacturing process is the most complex, time consuming, and expensive part of the total manufacturing process. The result is silicon chips with an array of unconnected transistors. Another shape of ASICs is based on standard cells in which there are no components prefabricated on the silicon chip. The manufacturer creates custom masks for every stage of the device’s process and means silicon is utilized more efficiently. 1 FPGAs The Field Programmable Gate Array is a device that is completely manufactured, but that remains design independent. Each FPGA vendor manufactures devices to a proprietary architecture. However, the architecture will include a number of programmable logic blocks that are connected to programmable switching matrices. To configure a device for a particular functional operation these matrices are programmed to route signals between the individual logic blocks. Of the most famous manufacturer of FPGAs are: Actel, Altera, Atmel, and Xilinx. Top-Down Design Methodology In an ideal world, a true top-down system level design methodology would mean describing a complete system at an abstract level using a Hardware Description Language (HDL) and the use of automated tools, for example, partitioners and synthesizers. This would drive the abstract level description to implementation on PCMs or MCMs (Multichip Modules), which contain: standard ICs, ASICs, FPGA, PLDs, and full-custom ICs. This ideal is not fulfilled, however, EDA tools are constantly being improved in the strive towards this vision. This means designers must constantly take on new rolls and learn new skills. More time is now spent designing HDL models, considering different architectures and considering system test and testability issues. Practically no time is spent designing at the gate level. Technology advancement over the last six years or so has seen a tenfold increase in the number of gates that an ASIC can contain: 100K gates are now common. This has increased the complexity of standard ICs and ASICs and resulted in the concept, “system on a chip”. A top-down design methodology is the only practical option to design such chips. Any ASIC or FPGA designs in a hardware development project are usually on the critical path of the development schedule. Traditionally, such designs have been produced by entering them as circuit diagrams using a schematic entry tool. In rare cases for reasons of cost, this may still be a viable design method for small devices such as PLDs. Provided the budget is available for simulation and synthesis tools, a top-down design approach using a Hardware Description Language (HDL), is by far the best design philosophy to adopt. Imagine using schematic to design a 100K gate ASIC; a small design change could result in major time consuming changes to the schematics. The philosophy of using a hardware description language to develop electronic hardware is similar to that of a software development project using a high-level programming language such as C. The levels of hierarchical refinement of electronic hardware in a top-down design process, is shown in Figure 1.1. It indicates how synthesis is the key link in this process. 2 PCB1 PCB2 PCB3 µP ASIC1 ROM ASIC2 RAM FPGA A RTL code B RTL code C RTL code ASIC RTL synthesis RTL synthesis RTL synthesis ASIC Layout synthesis Figure 1.1 Hierarchical refinement of electronic hardware in a top down design environment 3 A top-down design methodology takes the HDL model of hardware, written at a high level of abstraction (system or algorithmic), down through intermediate levels, to a low (gate or transistor) level; Figure 1.2. The term behavior represents the behavior of intended hardware and is independent of the level of abstraction by which it is modeled. A design represented at the gate level still represents the behavior of hardware intent. As hardware models are translated to progressively lower levels they become more complex and contain more structural detail. The benefit of modeling hardware at higher levels of behavioral abstraction is that designers are not overwhelmed with large amounts of unnecessary detail and the complexity of the design task is reduced. System concept Increasing behavioral abstraction Algorithm Architecture RTL Gate Transistor Figure 1.2 Behavioral level of abstraction pyramid A typical ASIC design flow using simulation and RTL level synthesis is shown in Figure 1.3. The same test vectors are used to verify the RTL and synthesis netlist level models. The netlist level corresponds to the gate level, but may also include larger macro cells, or even bigger mega cells. By comparing the simulation results at each level testing, netlist level testing can be automated. Increasing detailed realization & complexity 4 3 Typical ASIC design flow using simulation and RTL level synthesis 5 .High level HDL specification RTL code design-for-test Simulation vectors Simulate RTL code Simulation passed no yes RTL & test synthesis Simulate netlist Results compare no yes Vendor audits and sign off design for ASIC manufacture Figure 1. 4 (VITAL). Just as high-level programming languages allow complex design concepts to be expressed as computer programs. VHDL allows the behavior of complex electronic circuits to be captured into a design system for automatic circuit synthesis or for system simulation. C and C++. Verilog Verilog was introduced first before VHDL. Another part of the standard. Unlike these other programming languages. IEEE 1076. specifically it is 1076. IEEE 1076-1987. thus established itself as the de facto standard language for ASIC simulation libraries. Verilog has some advantage in 6 . VHDL provides features allowing concurrent events to be described. VHDL VHDL which stands for (Very high speed integrated circuit Hardware Description Language) is a programming language that has been designed and optimized for describing the behavior of digital systems.Hardware Description Language: (HDLs): A Hardware Description Language (HDL) is a software programming language used to model the intended operation of a piece of hardware. The resulting standard. 1983: The development of VHDL began with a joint effort by IBM. This made life considerably easier for ASIC. History of VHDL 1980: The USA department of defense (DOD) wanted to make circuit design self documenting. 1987: The institute of Electrical and Electronics Engineers (IEEE) was presented with a proposal to standardize the language. VHDL includes features useful for structured design techniques. is the basis for virtually every simulation and synthesis product sold today. Texas Instruments and Intermetrics. This greatly improved the portability of designs between different synthesis vendor tools. FPGA and EDA tools vendors. has been completed and sets a new standard for modeling ASIC and FPGA libraries in VHDL. This is important because the hardware described using VHDL is inherently concurrent in its operation. and offers a rich set of control and data representation features. Like Pascal. 1993: The VHDL language was revised to IEEE 1076-1993 1996: A VHDL package for use with synthesis tools become part of the IEEE 1076 standard.3. Synopsys. 1987: Verilog-XL was becoming very popular and has been used by many ASIC vendors. 7 . or to create functions (using the C language) that would be difficult or inefficient to implement directly in Verilog. 1995: The Verilog language was reviewed and adopted by IEEE as IEEE standard 1364.availability of simulation models. The PLI makes it possible for simluation model writers to go outside of Verilog when necessary to create faster simulation models. began to use the proprietary Verilog behavioral language as an input to their synthesis product. 1983: Gateway released the Verilog hardware description language known as “Verilog HDL” together with a Verilog simulator. 1989: Cadence bought Gateway. History of Verilog 1981: A CAE (Computer Aided Engineering) software company called Gateway Design Automation was founded by Prabhu Goel. the new version of the simulator was called “Verilog-XL”. Another important feature that is defined in Verilog is a programming language interface PLI. Another start-up company. 1985: The language and simulator has enhanced. end entity or_gate. Our first example is a simple OR gate. and configuration. These are: entity. y: out bit).First VHDL example: As we previously declared that VHDL is a language that describes a hardware. There are five kinds of design units in VHDL. The functionality of the block was specified using the “architecture” structure which inside it we wrote the line “y <= a or b” to describe how the inputs and outputs are related. we also declared the type pf these ports as “bit’ which specifies a type that can only handle two values “0” or “1”. A typical entity description of the OR gate will be like that: entity or_gate is port (a. The five kind of design unit are further classified as primary or secondary units. y” as the name of the ports of this block. it is not possible to analyze a secondary unit before its primary unit is analyzed. we specified “a. package body. architecture. b. we began by giving the entity a unique name and then continue to describe its inputs and outputs. In other words. The entity and architecture are called design units in VHDL. Its corresponding secondary unit is the architecture that defines the 8 . so let us examine a very simple description of a schematic using VHDL. The entity is a primary design unit that defines the interface to a circuit as we already declared. In this simple description we defined a block and then give it a name which is “or_gate” and then we described its interface. After that we need to write a description that specifies the function of this block or entity. that can be expressed as: architecture behavior of or_gate is begin y <= a or b. end architecture behavior. In VHDL we start our implementation of the hardware by describing its interface and this piece of information will be located under a section called the entity. b: in bit. and then classify these ports with “in” and “out” into inputs and outputs. A primary design unit can exist on its own. package. A secondary design unit cannot exist without its corresponding primary unit. Architecture names do not need to be unique. sum2. As with the entity. However. An architecture defines the contents of the circuit itself. or gate-level (architecture netlist). There can be much architecture associated with a particular entity. Common alternatives to architecture behavior are architecture RTL or architecture synthesis. c1. c2: bit. begin sum1 <= a xor b. The package body is the corresponding secondary design unit which contains the implementations of subprograms and operations declared in its package. but it is recommended that a consistent naming convention is adhered to. It is used to define the way in which a hierarchical design is to be built from a range of subcomponents. but this feature is rarely used The package is also a primary design unit. An example of an entity is: entity full_adder is port (a. components and other objects which can then be used in the description of the circuit. sum. c1 <= a and b. operations. It is common practice to use the architecture name behavior for synthesizable architecture. Note that the repeat of the circuit name full_adder after the end is optional. The configuration declaration is a primary design unit with no corresponding secondary. subprograms. but such examples are generally trivial and of no real use. end architecture behavior. A package declares. b. It does not matter what naming convention is used for architecture. The structure of architecture is given by the following example: architecture behavior of full_adder is signal sum1. Entities and architecture therefore exist in pairs. sum <= c1 or c2. It is possible to have an entity without an architecture. In this case the circuit full_adder has five ports: three input ports and two output ports. RTL (architecture behavior). sum2 <= sum1 xor c. c2 <= sum1 and c. the repeat of the architecture name after the end is optional. end entity full_adder. 9 . the use of the same architecture name throughout a VHDL design makes it easy to tell at a glance whether a VHDL description is system-level (architecture system). The architecture has the name behavior and belongs to the entity full_adder. it is not used for logic synthesis and will not be covered in this course. The architecture has two parts: the declarative part and the statement part. More on entities and architecture An entity defines the interface to a circuit and the name of the circuit. a complete circuit will generally have both an entity and an architecture. types. indeed.contents of the circuit. count: out bit). It is not possible to have an architecture without an entity. c: in bit. c2 <= sum1 and c. begin count <= c1 or c2. c1. c2: bit. sum2. The assignment itself has the symbol “<=” which is usually read “gets”. The source expression can be as complex as you like. sum1 <= a xor b. count <= (a and b) or (a and c) or (b and c). on the left-hand side). This declares a signal called sum1. sum2 <= sum1 xor b.The declarative part is the part before the keyword begins. However. c1 <= a andb. The right-hand side of the assignment is known as the source of the assignment. 10 . The statement part is the part after the begin. additional internal signals have been declared here signals are similar to ports but are internal to the circuit. as in “signal sum1 gets a xor b”. the following architecture is functionally equivalent to the previous version: architecture behavior of full_adder is signal sum1. this is done readability only. A signal declaration looks like: signal sum1 : bit. Types will be dealt with in later but for now it is sufficient to say that bit is a logical type which can be used for Boolean equation. the circuit of the full_adder example could have been written using just two signals assignment: sum <= a xor b xor c. For example. This is because each statement simply defines a relationship between its inputs (the source. end architecture behavior. which has a type. The simple signal assignment looks like: sum1 <= a xor b. the ordering of the statements is irrelevant. in this example the statement part only contains signal assignments describing the full adder as two half adders described by Boolean equations. In this example. on the right-hand side of the assignment) and its output (the target. called bit. For example. The left-hand side of the assignment is known as the target of the assignment (in this case sum1). sum <= sum2. In this example the statements have been written in sequence so that the dataflow is from up to bottom. This is the description of the circuit itself. b and c. There can be many signal declaration in an architecture. b. a. the second part. begin … The first part is a list of signal names. The first part is a list of port names: in this case a. Ports are the same as signals but also provide an interface through the entity so that the entity can be used as a subcircuit in a hierarchical design. A port is declared within the port specification. unlike the signal declarations which are each terminated by semicolon. in this case there are three signals. after the colon. so there is no semi-colon after the last declaration before the closing parenthesis. c : in bit). in this case the type is bit. port declarations are separated (not terminated) by semi-colons. The full_adder entity example is reproduced here to show how multiple port declarations are listed: entity full_adder is 11 . begin … Port declarations are enclosed by a port specification in the entity. c: bit. the third part is the type as in the signal declaration. in this case the mode is in. signal c: bit. each terminated by a semicolon. A port declaration has three parts: entity adder is port (a. Each port declaration within the specification is separated by semi-colons from the others. Note that. b. end entity adder. The port specification has the following structure: entity adder is port (port specification).Signals and ports Signals are the carriers of data values around an architecture. is the type of the signals: in this case bit. Note that the port specification is always terminated by a semi-colon which is outside the parentheses. The above declaration could be rewritten as three separate declarations: architecture behavior of adder is signal a: bit. b. A signal is declared in the declarative part of an architecture (between the keywords is and begin) and the declaration has two parts: architecture behavior of adder is signal a. signal b: bit. end entity adder. the second part is the mode of the port. and c. The full behavior of a buffer port is a restricted form of mode input. end architecture behavior. The mode of the port determines the direction of data-flow through the port. That is to say. The full rules also prevent mode buffer and mode out from being mixed in a hierarchical design. buffer. The meaning of the modes as they are used for logic synthesis are: in input port – cannot be assigned to in the circuit.port (a. buffer output port – like mode out but can also be read. Mode buffer is an anachronism and it is an understatement to say that the reason for its existence in the language is obscure. There is often confusion between mode out and mode buffer. sum. There are five port modes: in. and linkage. inout mode is omitted because it is specific to tristates which are dealt with in chapter 12. out2: out bit). out output port – must be assigned to in the circuit. can be read. out. inout. cannot be assigned to and so can only appear on the righthand side of a signal assignment. the rules for buffer ports are constrained so that they act like mode out ports with the added convenience that it is possible to read from the port within the architecture. 12 . it is not possible to connect a buffer mode port of a subcomponent to an out mode port of a higher level component. linkage not used by synthesis. It has been named out1 in this example because it is acting as an output. Unfortunately. being mode out. c: in bit. being mode in. Port out2. cannot be read. If a mode is not given. It is therefore recommended that only one of the output modes is ever used. architecture behavior of modes is begin out1 <= input. Port inout. however. at the very least. However. This restriction on the mixing of modes can cause inconvenience. end entity modes. then mode in will be assumed. The behavior of the modes is illustrated by the following example. b. end entity full_adder. Port out1. can only be assigned to and so can only appear on the left-hand side of a signal assignment. being mode buffer. inout bidirectional port – can only be used for tristate buses. to make the mode usable for synthesis. the rules for mode buffer are more complex than this. can be assigned to and read and so can appear on either side of an assignment. entity modes is port (input: in bit. count: out bit). out2 <= out1. out1: buffer bit. this interpretation of mode buffer is a simplification to make the mode useful for synthesis and is common to most synthesizers. z. The simple signal assignment looks like this: x <= a xor b. owing to the anachronistic nature of mode buffer. end architecture behavior. the pitfall of trying to read an out port is always avoided. end architecture illegal. The intermediate signal can then be assigned to the out mode ports. zbar: out bit). Simple signal assignment The simple signal assignment statement has already been used in the full_adder example. The corrected example is: entity and_nand is port (a. By doing this consistently. b: in bit. zbar <= not z. because the out port z is read: entity and_nand is port (a. The solution is to use an intermediate internal signal and read from that. architecture behavior of and_nand is signal result: bit. architecture illegal of and_nand is begin z <= a and b. z. The right-hand side of the assignment is known as the source expression of the assignment (in this case a xor b). b: in bit. z <= result. 13 . The first version shows an illegal description. it is recommended that only out mode is used. zbar <= not result. The problem of needing to read from an out mode port is illustrated by the following example of an and gate with true and inverted output. The section examines the signal assignment statement in more detail.Furthermore. begin result <= a and b. end entity and_nand. end entity and_nand. zbar: out bit). The left-hand side of the assignment is known as the target of the assignment (in this case x). It is good practice always to use intermediate signals for outputs and to assign them to the out ports at the end of the architecture. 14 . There must be no space between the two characters in the symbol. the source and target are of the same type. The rules of VHDL insist that the source of an assignment is the same type as the target. The xor of two signals of type bit gives a result which is also a bit. Nevertheless. Therefore. which is formed by combining the less-than and the equals symbols to form an arrow. it takes some getting used to. This example uses type bit. The source expression can be as complex as desired.The assignment itself is the symbol <=. there is no real chance of confusion because there are no situations where both meanings would be allowed by the language. the circuit of the full_adder example could have been written using just two signal assignments: sum <= a xor b xor c. count <= (a and b) or (a and c) or (b and c). For example. Fortunately. Beware of confusion with the less-than-or-equal operator <= which looks exactly the same. use ieee.std_logic_1164. The select inputs are normally binary encoded such that n select inputs can select from one of up to 2n inputs. of two or more iput signals.all. S A Y B Figure 1.std_logic_arith.4.4 circuit symbol of 2-1 multiplexer S 0 0 1 1 A 0 1 B 0 1 Y 0 1 0 1 Table 1. to the output.5 logic implementation of 2-1 multiplexer Example 1.all. One or more control signals control which input signal’s value is passed to the output. Each input signal. use ieee.1 Modeling of a 2-1 multiplexer The model of the 2-1 multiplexer described above is shown modeled by two different methods: first. 15 . using a concurrent selected signal assignment. second using the if statement in its simplest form. may represent single bit or multiple bits busses.1 Truth table of 2-1 multiplexer S A Y B Figure 1. library ieee.Combinational logic blocks Multiplexers A multiplexer selectively passes the value of one. see figure 1. and the output signal. They are: • • • • Using a conditional signal assignment (concurrent) Using a selected signal assignment (concurrent) One if statement with multiple elsif/ else clauses Using a case statement There is no incorrect modeling method. library ieee. end if. end entity mux4_1. end process. however using the case statement requires less code and is easier to read when compared with the if statement. This means they are always active and so will usually take longer to simulate. architecture second of mux_2_1 is begin process (s. a.2 Modeling of a 4-1 multiplexer Four ways of modeling a 4-1 mutliplexer are indicated. use ieee. b) begin if (s = ‘1’) then y <= a. architecture first of mux_2_1 is begin y <= a when s = ‘1’ else b.all. use ieee. y: out std_logic). b: in std_logic. else y <= b. architecture first of mux4_1 is begin 16 . b. This becomes more distinct with increasing inputs per output. y: out std_logic) . The first and second models use concurrent signal assignments so reside outside a process. a.std_logic_arith. end entity mux_2_1.entity mux_2_1 is port (s. d: in std_logic. Example 1.all. c. entity mux4_1 is port (sel: in std_logic_vector (1 downto 0).std_logic_1164. a. end architecture first. end architecture second. end process. a. end architecture third. b.3 Modeling of a four-bit wide 8-1 multiplexer A four-bit wide 8-1 multiplexer is modeled using selected signal assignment and case statement. The use of case statement instead of the if will make the codes easier to 17 . when “10” => y <= c. architecture second of mux4_1 is begin with sel select y <= a when “00”. end process. a when others. elsif (sel = “10”) then y <= c. Example 1. end architecture second. d when “11”. elsif (sel = “01”) then y <= b. when others => y <= a. end architecture fourth. --when sel = “11” end architecture first. when “01” => y <= b. when “11” => y <= d. c when “10”. b. end case. else y <= d. d) begin case sel is when “00” => y <= a. architecture third of mux4_1 is begin process (sel.y <= a when sel = “00” else b when sel = “01” else c when sel = “10” else d. c. end if. d) begin if (sel = “00”) then y <= a. b when “01”. c. a. architecture fourth of mux4_1 is begin process (sel. entity mux8_1 is port (sel: in std_logic_vector(2 downto 0). end entity mux8_1. when “100” => y <= a4. use ieee. library ieee. a6 when “110”. y: out std_logic_vector(3 downto 0)).a6.a4. a0. end architecture first. a5 when “101”. end architecture second. end process.all. when “001” => y <= a1. a6.a2. end case. when “110” => y <= a6. when “101” => y <= a5. when “010” => y <= a2.read.std_logic_1164.a1. architecture first of mux8_1 is begin with sel select y <= a0 when “000”.a5. a1 when “001”. when “011” => y <= a3. a2. a2 when “010”. a0. a3. a3 when “011”. use ieee. 18 . a5. a4 when “100”. architecture second of mux8_1 is begin process (sel.a7: in std_logic_vector(3 downto 0). It is different from the previous example in that an integer data type is used for the select input sel which eliminates the need of the others clause as a default action. a7 when “111”. when others => y <= a0. a7) begin case sel is when “000” => y <= a0.all. a1. a4. when “111” => y <= a7.std_logic_arith. a0 when others.a3. 2 Truth table of a 8-3 binary encoder All models of such a circuit must use a default “don’t care” value to minimize the synthesized circuit as only 8 of 256 (28) input conditions need to be specified. use ieee.2. more logic would be synthesized than is necessary.Encoders Discrete quantities of digital information. data are often represented in a coded form. The default assignment is a “don’t care” value to minimize synthesized logic. 19 . It is assumed that only one input has a value of 1 at any given time. selected signal assignment. Encoders are used to encode data into a coded form and decoders are used to convert it back into its original uncoded form. Example 1. If all 248 input conditions that are not explicitly defined are made like that they default to other value than “don’t care” (for example binary 000). The truth table for an 8-3 binary encoder (8 inputs and 3 outputs) is shown in Table 1. An encoder that has 2n (or less) input lines encodes input data to provide n encoded output lines.std_logic_1164.all. library ieee. binary being the most popular.6 Encoder inputs A6 A5 A4 A3 A2 A1 A0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 outputs Y2 Y1 Y0 0 0 0 0 0 1 0 1 0 0 1 1 1 0 0 1 0 1 1 1 0 1 1 1 A7 0 0 0 0 0 0 0 1 Table 1. The synthesis tool. 2n Encoder n Figure 1. otherwise the output has some undefined value and the circuit is meaningless. if capable. replaces “don’t care” values with logic 0 or logic 1 values as necessary in oreder to minimize the circuit’s logic.4 Modeling of a 8-3 binary encoder An 8-3 encoder is modeled according to the truth table of Table 1. if and case statement All models use a default assigned output value to avoid having to explicitly define all 28 – 8 = 248 input conditions that should not occur under normal operating conditions.2 using conditional signal assignment. “111” when “10000000”. end process. else y <= “---”. y: out std_logic_vector(2 downto 0)). “010” when “00000100”. “110” when “01000000”. architecture third of encoder8_3 is begin process (a) begin if (a = “00000001”) then y <= “000”. end if. “011” when “00001000”. “101” when “00100000”. “100” when “00010000”. elsif (a = “00010000”) then y <= “100”. elsif (a = “01000000”) then y <= “110”. architecture second of encoder8_3 is begin with a select y <= “000” when “00000001”. end architecture third. elsif (a = “00000010”) then y <= “001”. end architecture second. elsif (a = “00001000”) then y <= “011”. elsif (a = “00000100”) then y <= “010”. end architecture first. end entity encoder8_3. “001” when “00000010”. entity encoder8_3 is port (a: in std_logic_vector(7 downto 0). 20 . architecture first of encoder8_3 is begin y <= “000” when a = “00000001” else “001” when a = “00000010” else “010” when a = “00000100” else “011” when a = “00001000” else “100” when a = “00010000” else “101” when a = “00100000” else “110” when a = “01000000” else “111” when a = “10000000” else “---”. “---” when others. elsif (a = “00100000”) then y <= “101”.use ieee.std_logic_arith.all. elsif (a = “10000000”) then y <= “111”. when “00100000” => y <= “101”. end case. end architecture fourth. when “10000000” => y <= “111”. when “00000100” => y <= “010”. when “01000000” => y <= “110”. when others => y <= “---”. end process. when “00000010” => y <= “001”. 21 . when “00010000” => y <= “100”. when “00001000” => y <= “011”.architecture fourth of encoder8_3 is begin process (a) begin case a is when “00000001” => y <= “000”. selected signal assignments along with typical if.3. y: out std_logic_vector(7 downto 0)). type of coded format. or possibly other. there is no write or wrong modeling technique. so a decoder with n inputs can decode up to 2n outputs.7 Decoder inputs outputs A2 A1 A0 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 0 1 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 Table 1.3 Truth table of a 3-8 binary decoder Example 1.all.Decoders Decoders are used to decode data that has been previously encoded using a binary. library ieee. Again. An n-bit code can represent up to 2n distinct bits of coded information.std_logic_1164. architecture first of decoder3_8 is begin y <= “00000001” when a = “000” else “00000010” when a = “001” else 22 . entity decoder3_8 is port (a: in std_logic_vector(2 downto 0). use ieee. and case statements. The case statement is commonly used because of its clarity. Various models of a 3-6 binary decoder are included in example 1.5.5 Modeling of a 3-8 binary decoder The models of the 3-8 binary decoders in this example conform to the truth table in Table 1.all. Different model versions using conditional. end entity decoder3_8. use ieee. and the fact it is not a continuous assignment and so may simulate faster.std_logic_arith. n Decoder 2n Figure 1. elsif (a = “001”) then y <= “00000010”. “01000000” when “110”. end architecture second. “00000010” when “001”. “10000000” when “111”. “00001000”. a a a a a a = = = = = = “010” “011” “100” “101” “110” “111” else else else else else else architecture second of decoder3_8 is begin with a select y <= “00000001” when “000”.“00000100” when “00001000” when “00010000” when “00100000” when “01000000” when “10000000” when “00000001”. “00100000” when “101”. “00100000”. “00010000” when “100”. elsif (a = “100”) then y <= “00010000”. “00000010”. elsif (a = “101”) then y <= “00100000”. architecture third of decoder3_8 is begin process (a) begin if (a = “000”) then y <= “00000001”. elsif (a = “011”) then y <= “00001000”. “00000100” when “010”. end architecture first. elsif (a = “010”) then y <= “00000100”. elsif (a = “110”) then y <= “01000000”. end architecture third. “00001000” when “011”. “00010000”. architecture fourth begin process (a) begin case a is when “000” => when “001” => when “010” => when “011” => when “100” => when “101” => of decoder3_8 is y y y y y y <= <= <= <= <= <= “00000001”. end if. 23 . end process. “00000100”. “00000001” when others. elsif (a = “111”) then y <= “10000000”. else y <= “00000001”. or A has an unused value.std_logic_arith.all. end case. end entity decoder3_6. en) begin if (en = ‘0’) then y <= “000000”.4. end architecture fourth. when “111” => y <= “10000000”. entity decoder3_6 is port (en: in std_logic. end process. 24 . y: out std_logic_vector(5 downto 0)). When the enable is inactive (En = 0). This example is different from the previous one because it has a separate input enable signal and there are two unused binary values for the 3-bit input A. when others => y <= “00000001”. a: in std_logic_vector(2 downto 0). separately from the enclosed case statement. The model below uses an if statement to check the enable input En.all.when “110” => y <= “01000000”. use ieee. the 6-bit output must be at logic 0. architecture first of decoder3_6 is begin process (a. use ieee.6 Modeling of a 3-6 binary decoder with enable En 0 1 1 1 1 1 1 1 1 Inputs A2 A1 A0 − − − 0 0 0 0 0 1 0 1 0 0 1 1 1 0 0 1 0 1 1 1 0 1 1 1 Y5 0 0 0 0 0 0 1 0 0 outputs Y4 Y3 Y2 Y1 Y0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 − =don’t care Table 1.4 Truth table of a 3-6 binary decoder with enable The model version of the 3-6 binary decoder conforms to the truth table Table 1. library ieee. Example 1. else case a is when “000” => y <= “000001”.std_logic_1164. when others => y <= “000000”. end architecture first. 25 . when “010” => y <= “000100”.when “001” => y <= “000010”. when “011” => y <= “001000”. end case. end if. when “101” => y <= “100000”. when “100” => y <= “010000”. end process. for example.Comparators A comparator compares two or more inputs using one.std_logic_arith. use ieee. so it should not be used in comparison. “if ((a = b) and (a = c))”. b: in unsigned(5 downto 0).7 6-bit two input equality comparator: 6 a Comparator 6 b y Figure 1. as comparison must be preformed between signals or variables that have a defined values and since std_logic_vector does not indicate a value of the bus. otherwise it is at logic ‘0’. When the given relationship(s) is true. These equality. 26 . an output signal is given (logic 0 or logic1). that is. Note that the inputs buses to be compared can’t be of type std_logic_vector. logical operators can be used to logically test the result of multiple comparisons. Comparators are only modeled using the if statement with an else clause and no else-if clauses. entity simple_comparator is port (a.8 6-bit two input equality comparator Typical comparator is shown in figure 1. However. use ieee. Any two data objects are compared using equality and relational operators in the expression part of the if statement.5 Equality. y: out std_logic).std_logic_1164. they can be whether unsigned or signed types. statements like “if (a = b = c)” cannot be used. relational and logical operators Example 1.5. Only two data objects can be compared at once. library ieee. Operators Equality & Relational VHDL = /= < <= > >= not and or Logical Table 1.all. The single bit output is at logic ‘1’ when the two 6-bit input buses are the same.all. or a number of different comparisons.8. relational and logical operators are listed in Table 1. f) begin if (a = b and (c /= d or e >=f)) then y <= ‘1’. use ieee. else y <= ‘0’.std_logic_1164.8 Multiple Comparison Comparator: Extra parentheses enclosing “c /= d or e >= f” means that either one of these conditions and “a = b” must be true for the output to be at logic 1. use ieee.all. f: in unsigned(2 downto 0). 27 . end process. end architecture rtl. d. e. end process.end entity simple_comparator. c. end if. architecture rtl of simple_comparator is begin process (a. c. Example 1. b) begin if (a = b) then y <= ‘1’. d. library ieee. end entity multiple_comparator. architecture rtl of multiple_comparator is begin process (a. end architecture rtl. y: out std_logic). b. else y <= ‘0’.std_logic_arith. b.all. entity multiple_comparator is port (a. e. end if. 28 . use ieee.std_logic_arith.9 Modeling of a D-type transparent latch The if statement without else clause is the simplest implementation of D-type transparent latch. use ieee.6 Characteristic table of a D-type transparent latch Q output held at logic ‘1’ when enable goes inactive (logic ‘0’) EN D Q Q Figure 1. entity d_latch is port (d. library ieee.9 The level sensitive D-type transparent latch inputs D EN 0 − 0 1 1 1 outputs Q+ Q+ QQ0 1 1 0 − =don’t care Table 1.10 Simulation of the level sensitive D-type transparent latch Example 1.std_logic_1164. see Figure 1. D Latch EN Q Q Figure 1.Latches A latch is a level sensitive memory cell that is transparent to signals passing from the D input to Q output when enabled.9.all. en: in std_logic.all. The Q-bar output signal is always the inverse of the Q output signal. and holds the value of D on Q at the time when it becomes disabled. 29 . end architecture rtl.all. end if. end process.q: out std_logic). end architecture rtl. Example 1. end entity d_latch. en. end if. architecture rtl of d_latch is begin process (d.10 Modeling latches with clear input Latches with clear will set the output to ‘0’ whenever the clear signal goes to ‘1’. use ieee. entity d_latch is port (d. clear: in std_logic. The example code above models a latch with a clear input library ieee. elsif (en = ‘1’) then q <= d. en) begin if (en = ‘1’) then q <= d. end entity d_latch. Latches with preset will preset the output to ‘1’ instead to ‘0’.all. en. Clear and preset inputs to a latch are always asynchronous with the enable. end process. use ieee.std_logic_1164. q: out std_logic). architecture rtl of d_latch is begin process (d. clear) begin if (clear = ‘1’) then q <= ‘0’.std_logic_arith. all. see Figure 1. library ieee.std_logic_1164. D Q Flip-flop Q CLK Figure 1.7 Characteristic table of a D-type flip-flop Q output is only due to change at clock +ve edges CLK D Q Q Figure 1.11 Modeling of a D-type flip-flop Different models of flip-flops with +ve and –ve edge triggered are shown in architectures below.10. The first and the second architectures use a VHDL attributes to detect the clk signal edge.10 The level sensitive D-type flip-flop inputs D CLK 0 ↑ 1 ↑ 0 − 1 − outputs Q+ Q+ QQQQQQ- Table 1. The Q-bar output signal is always the inverse of the Q output signal. The output value is held until the next active clock edge.11 Simulation of a +ve edge sensitive D-type flip-flop Example 1. when an active edge transition occurs on its clock input.std_logic_arith. use ieee. use ieee.D-Type Flip-Flop The D-type flip-flop is an edge triggered memory device that transfers a signal’s value on its D input. while the third and fourth architectures use a function call for the same purpose.all. to its Q output. 30 . architecture third of d_flip_flop is begin process (clk) begin if (rising_edge(clk)) then q <= d.entity d_flip_flop is port (d. end process.12 Modeling flip-flops with reset Different flip-flops with asynchronous and synchronous resets are modeled. while the second architecture models D-type flip31 . end process. architecture second of d_flip_flop is begin process (clk) begin if (clk’event and clk = ‘0’) then q <= d. end entity d_flip_flop. end architecture second. architecture fourth of d_flip_flop is begin process (clk) begin if (falling_edge(clk)) then q <= d. end if. q: out std_logic). end process. clk: in std_logic. this is the commonly used D-type flip-flop. end architecture fourth. end architecture first. architecture first of d_flip_flop is begin process (clk) begin if (clk’event and clk = ‘1’) then q <= d. end architecture third. end if. end if. end if. The first architecture models a D-type flip-flop with an asynchronous reset input. Example 1. end process. rst: in std_logic. clk. 32 .all. else q <= d. end process.std_logic_1164.flop with a synchronous reset as appears from the process sensitivity list and the if statements sequence. end if. architecture second of d_flip_flop is begin process (clk) begin if (rising_edge(clk)) then if (rst = ‘1’) then q <= ‘0’. clk) begin if (rst = ‘1’) then q <= ‘0’. end entity d_flip_flop. elsif (rising_edge(clk)) then q <= d. use ieee. library ieee. end architecture second. end if.std_logic_arith. end architecture first. q: out std_logic). end process. architecture first of d_flip_flop is begin process (rst. use ieee. entity d_flip_flop is port (d. end if.all. architecture rtl of d_flip_flop is begin process (rst. 33 . elsif (rising_edge(clk)) then if (en = ‘1’) then q <= d.std_logic_arith. end if. clk.13 Modeling flip-flop with enable and asynchronous reset Flip-flop with enable input and asynchronous reset is modeled to illustrate the addition of the enable signal control. entity d_flip_flop is port (d.std_logic_1164. end architecture rtl.all. end process. end if. rst. which is synchronous. clk) begin if (rst = ‘1’) then q <= ‘0’. use ieee. en: in std_logic.all. use ieee. accordingly with the asynchronous reset. end entity d_flip_flop.Example 1. q: out std_logic). library ieee. 14 Modeling of a parallel 8 bits register A typical example for a parallel 8 bits register is modeled. rst: in std_logic. library ieee. architecture rtl of reg_par is begin process (rst. reg_in: in std_logic_vector(7 downto 0). an others statement in the reset action line is added to fill registers with any size with zeros. clk) begin if (rst = ‘1’) then reg_out <= “00000000”. otherwise remaining the contents unchanged. based on the flip-flop model shown previously but with inputs and outputs are extended as buses. use ieee. Example 1. reg_out: out std_logic_vector(7 downto 0)). 34 . see Figure 1. end entity reg_par. so that the register only register the value at its inputs when enable is active.std_logic_arith. end architecture rtl. its implementation has the same structure as for one flip-flop but with extended inputs and outputs. end if. Also.15 Modeling of a parallel 8 bits register with enable The same as the previous example but with an added enable signal to provide control over the register. n input bus Register Register clk rst n output bus Figure 1. use ieee.all. entity reg_par is port (clk.13.12.std_logic_1164.all. This model is also based on the flip-flop model shown in example 1. end process.12 Register with n inputs and n outputs Example 1. elsif (rising_edge(clk)) then reg_out <= reg_in.Registers A parallel register is simply a bank of D-type flip-flops. end if. end process. end architecture rtl. end if.std_logic_arith. reg_out: out std_logic_vector(7 downto 0)). 35 .all. clk) begin if (rst = ‘1’) then reg_out <= (others => ‘0’). rst.std_logic_1164.library ieee. use ieee.all. en: in std_logic. elsif (rising_edge(clk)) then if (en = ‘1’) then reg_out <= reg_in. end entity reg_par. entity reg_par is port (clk. architecture rtl of reg_par is begin process (rst. use ieee. reg_in: in std_logic_vector(7 downto 0). and shift_right signals are combined together into one bus to facilitate the use of case statement afterwards. and shift_right n-1 1 n-1 0 n-1 or ‘1’ 0 n-1 0 0 1 0 0 1 1 0 1 0 0 1 1 0 0 1 1 0 1 0 0 1 0 original register contents 1 0 register contents after 0 or ‘1’ one shift left action 0 1 0 0 Barrel shifter operation after one shift left action register contents after one shift right action Figure 1. Depending on the usage of the register. signals shift_left and shift_right see Figure 1.16 Modeling of a parallel 8 bits shift register A typical example for a parallel 8 bits shift register is modeled. see Example 1. (we cannot do something like that: reg_out <= reg_out because reg_out is defined as output). or ‘1’.13. added controls shift_left. and shift_right actions Example 1.13 Parallel shift register with added control shift_left.14. its implementation has the same structure as for one flip-flop but with extended inputs and outputs. see Figure 1.16. the empty place appears after shifting is filled whether with ‘0’. A typical parallel shift register that has added controls to achieve these features. These signals control whether the register is to shift its contents to left or right. n input bus shift_right shift left Shift Register clk Register rst n output bus Figure 1. or the shifted bit from the other side of the register (barrel shifters). An intermediate signal definition is made to define a new bus (reg_temp) to hold the register contents which is necessary because we cannot assign value to output and read it in the same time. Signals are simply a bank of D-type flip-flops.Shift Registers Shift registers are registers with added features that enable them to shift their contents in either directions.14 Parallel shift register operation due to shift_left. so we cannot read 36 . begin shift_control <= shift_left & shift_right.std_logic_arith. end process. reg_out <= reg_temp. entity reg_par_shift is port (clk.std_logic_1164. reg_out: out std_logic_vector(7 downto 0)). when “10” => reg_temp <= reg_temp(6 downto 0) & ‘0’.all. end if. shift_right. when “01” => reg_temp <= ‘0’ & reg_temp(7 downto 1). reg_in: in std_logic_vector(7 downto 0). end architecture rtl. --can be omitted end case. rst: in std_logic. clk) begin if (rst = ‘1’) then reg_temp <= (others => ‘0’). use ieee. process (rst. use ieee. when others => reg_temp <= reg_temp.it inside (can not appear on the right hand side of any assignment). 37 . elsif (rising_edge(clk)) then case shift_control is when “00” => reg_temp <= reg_in. shift_left: in std_logic. Before the end of the architecture the value of the intermediate bus is then passed to the output bus.all. library ieee. architecture rtl of reg_par_shift is signal shift_control: std_logic_vector(1 downto 0). end entity reg_par_shift. signal reg_temp: std_logic_vector(7 downto 0). 17 Modeling of a 4 bits binary counter The simplest and most common way of modeling a binary counter that can increment or decrement is by adding or subtracting a constant 1 using the “+” or “−” arithmetic operators in assignments residing in a section of code inferring synchronous logic. is called a counter. rst: in std_logic. use ieee. Counters count the number of occurrences of an event. that is.std_logic_arith. An intermediate signal definition is made to define a new bus (count_temp) to hold the counter state which is necessary because we cannot assign value to output and read it in the same time. architecture rtl of binary_count is signal count_temp: unsigned(3 downto 0). (we cannot do something like that: count_out <= count_out + 1 because count_out is defined as output). extra control signals can be added n Counter Register clk rst output bus Figure 1. upon the application of input pulses on one or more inputs. Before the end of the architecture the value of the intermediate bus is then passed to the output bus after doing a type conversion to convert the type unsigned to std_logic_vector type used in the output bus definition in the entity declaration. end entity binary_count. use ieee. also the “+ 1” operation cannot by applied over std_logic_vector types as they do not implicitly have an equivalent value.all.15 Counter with n outputs cycles over 2n states Example 1. so we cannot read it inside (can not appear on the right hand side of any assignment). Apart from general purpose counting.std_logic_1164.all. entity binary_count is port (clk. An example for this implementation is shown for a 4 bits binary counter. counters can be used as clock dividers and for generating timing control signals. count_out: out std_logic_vector(3 downto 0)). begin 38 . input pulses that occur either randomly or at uniform intervals of time. instead an unsigned or signed types has to be used. Counters are used extensively in digital design for all kinds of applications.Counters A register that goes through a predetermined sequence of binary values (states). library ieee. all. count_out <= std_logic_vector(count_temp). end process.std_logic_1164. count_out: out std_logic_vector(3 downto 0)). so this counter only counts when the enable signal is active. end architecture rtl. else count_temp <= count_temp. entity binary_count is port (clk. elsif (rising_edge(clk)) then count_temp <= count_temp + 1.process (rst. clk) begin if (rst = ‘1’) then count_temp <= (others => ‘0’). elsif (rising_edge(clk)) then if (enable = ‘1’) then count_temp <= count_temp + 1. count_out <= std_logic_vector(count_temp). use ieee. enable: in std_logic. architecture rtl of binary_count is signal count_temp: unsigned(3 downto 0).std_logic_arith. clk) begin if (rst = ‘1’) then count_temp <= (others => ‘0’). Example 1. 39 . rst. end if.18 Modeling of a 4 bits binary counter with enable The same counter implemented before is used but with adding extra control over the counting event. end entity binary_count. end architecture rtl. end if.all. library ieee. --can be omitted end if. begin process (rst. end process. otherwise the counter holds its state. use ieee. use ieee. end entity binary_count. elsif (rising_edge(clk)) then case count_control is when “00” => count_temp <= count_temp.std_logic_1164. signal count_control: std_logic_vector(1 downto 0). entity binary_count is port (clk. use ieee. when “01” => count_temp <= count_temp – 1. count_up.19 Modeling of a counter that counts up by two and down by one An example for a 4 bits binary counter with added control to make the counter counts up by two or down by one.all.std_logic_arith. begin count_control <= count_up & count_down.all. rst: in std_logic. architecture rtl of binary_count is signal count_temp: unsigned(3 downto 0). 40 . end process. library ieee. process (rst. when others => count_temp <= count_temp. when “10” => count_temp <= count_temp + 2. end architecture rtl. count_out <= std_logic_vector(count_temp).Example 1. count_out: out std_logic_vector(3 downto 0)). and count_down are combined together into one bus to facilitate the use of case statement afterwards. The control signals count_up. end if. count_down: in std_logic. end case. clk) begin if (rst = ‘1’) then count_temp <= (others => ‘0’).