Open navigation menu
Close suggestions
Search
Search
en
Change Language
Upload
Sign in
Sign in
Download free for days
0 ratings
0% found this document useful (0 votes)
538 views
424 pages
VHDL Made Easy
This introduces the beginner to the world of VHDL programming.
Uploaded by
dario_santoro-1
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content,
claim it here
.
Available Formats
Download as PDF or read online on Scribd
Download
Save
Save VHDL Made Easy For Later
Share
0%
0% found this document useful, undefined
0%
, undefined
Print
Embed
Report
0 ratings
0% found this document useful (0 votes)
538 views
424 pages
VHDL Made Easy
This introduces the beginner to the world of VHDL programming.
Uploaded by
dario_santoro-1
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content,
claim it here
.
Available Formats
Download as PDF or read online on Scribd
Go to previous items
Go to next items
Download
Save
Save VHDL Made Easy For Later
Share
0%
0% found this document useful, undefined
0%
, undefined
Print
Embed
Report
Download
Save VHDL Made Easy For Later
You are on page 1
/ 424
Search
Fullscreen
ANY VHDL Made
current_state <= RDY; when RDY => rdy_in strobe if strobe = “1” then current_state <= SEND; end if, when SEND => current_state <= POLL; when POLL => if rdy_in = 1’ then current_state <= RDY; end if; end case; end if; ‘end process; tdy_in In a behavioral description, the concept of time may be ex- pressed precisely, with actual delays between related events (such as the propagation delays within gates and on wires), or it may simply be an ordering of operations that are expressed sequentially (such as in a functional description of a flip-flop). When you are writing VHDL for input to synthesis tools, you may use behavioral statements in VHDL to imply that there are registers in your circuit. It is unlikely, however, that your synthesis tool will be capable of creating precisely the same behavior in actual circuitry as you have defined in the lan- guage. (Synthesis tools today ignore detailed timing specifica- tions, leaving the actual timing results at the mercy of the target device technology.) It is also unlikely that your synthe- sis tool will be capable of accepting and processing a very wide range of behavioral description styles. 352. A First Look At VHDL Writing behavior-level VHDL is very much like writing one or more small software programs. Dataflow In the dataflow level of abstraction you describe how informa- tion is passed between registers in your circuit. Figure 2-7: At the dataflow level of abstraction, a large counter is described in terms of registers and combinational logic. 36 If you are familiar with software programming, writing behavior-level VHDL will not seem like anything new. Just like a programming language, you will be writing one or more small programs that operate sequentially and communicate with one another through their interfaces. The only difference between behavior-level VHDL and a software programming language is the underlying execution platform: in the case of software, it is some operating system running on a CPU; in the case of VHDL, it is the simulator and/or the synthesized hardware. In the dataflow level of abstraction, you describe your circuit in terms of how data moves through the system. At the heart of most digital systems today are registers, so in the dataflow level of abstraction you describe how information is passed between registers in the circuit. You will probably describe the combinational logic portion of your circuit at a relatively high level (and let a synthesis tool figure out the detailed imple- mentation in logic gates), but you will likely be quite specific about the placement and operation of registers in the com- plete circuit. An example of the dataflow level of abstraction is shown in Figure 2-7. This circuit (a 20-bit loadable counter) would be very tedious to describe using structural techniques. Data Load Q[19:0) 20-Bit Register ClkThe dataflow level of abstraction allows the drudgery of combina- tional logic to be simplified... Structure A structure-level description defines the circuit in terms of a collection of components. Levels of Abstraction (Styles) The dataflow level of abstraction is often called register transfer logic, or RTL. This level of abstraction is an intermediate level that allows the drudgery of combinational logic to be simpli- fied (and, presumably, taken care of by logic synthesis tools) while the more important parts of the circuit, the registers, are more completely specified. There are some drawbacks to using a dataflow method of design in VHDL. First, there are no built-in registers in VHDL; the language was designed to be general-purpose, and the emphasis was placed by VHDL's designers on its behavioral aspects. If you are going to write VHDL at the dataflow level of abstraction, you must first create (or obtain) behavioral descriptions of the register elements you will be using in your design. These elements must be provided in the form of components (using VHDL's hierarchy features) or in the form of subprograms (functions or procedures). But for hardware designers, it can be difficult to relate the sequential descriptions and operation of behavioral VHDL with the hardware being described (or modeled). For this reason, many VHDL users, particularly those who are using VHDL as an input to synthesis, prefer to stick with levels of abstraction that are easier to relate’to actual hardware devices (such as logic gates and flip-flops). These users are often more comfortable using the dataflow level of abstraction. The third level of abstraction, structure, is used to describe a circuit in terms of its components. Structure can be used to create a very low-level description of a circuit (such as a transistor-level description) or a very high-level description (such as a block diagram). Ina gate-level description of a circuit, for example, compo- nents such as basic logic gates and flip-flops might be con- nected in some logical structure to create the circuit. This is what is often called a neflist. For a higher-level circuit—one in 372. A First Look At VHDL Structure-level VHDL features are very useful for managing complexity. Figure 2-8: At the structure level of abstraction, you connect together lower-level compo- nents, such as gates and flip-flops, to create a larger system. which the components being connected are larger functional blocks—structure might simply be used to segment the design description into manageable parts. Structure-level VHDL features, such as components and configurations, are very useful for managing complexity. The use of components can dramatically improve your ability to re-use elements of your designs, and they can make it pos- sible to work using a top-down design approach. To give an example of how a structural description of a circuit relates to higher levels of abstraction, consider the design of a simple 5-bit counter. To describe such a counter using tradi- tional design methods, we might immediately draw a picture of five T flip-flops with some simple decode logic as shown in Figure 2-8: vec RstLevels of Abstraction (Styles) The following VHDL design description represents the pre- ceding schematic in the form of a netlist of connected compo- nents: entity andgate is port(A,B,C,D: in bit := ‘1’; Y: out bit); end andgate; architecture gate of andgate is begin Y <=Aand B and C and D; end gate; entity tff is port(Rst,Clk,T: in bit; Q: out bit); end tff; architecture behavior of tff is begin process(Rst,Clk) variable Qtmp: bit; begin if (Rst = ‘1’) then Qtmp := ‘0’; elsif Clk = ‘1’ and Cik’event then T= ‘1’ then Qtmp := not Qtmp; end if; end if; Q <= Qtmp; end process; end behavior; entity TCOUNT is port (Rst,Clk: in bit; Count: out bit_vector(4 downto 0)); end TCOUNT; architecture STRUCTURE of TCOUNT is component tff port(Rst,Cik,T: in bit; Q: out bit); end component; component andgate port(A,B,C,D: in bit := ‘1’; Y: out bit); end component; 392. A First Look At VHDL constant VCC: bit := ‘1’; signal T,Q: bit_vector(4 downto 0); begin T(0) <= VCC; TO: tif port map (Rst=>Rst, Clk=>Clk, T=>T(0), Q=>Q(0)); T(1) <= Q(0); T1: tif port map (Rst=>Rst, Clk=>Clk, T=>T(1), Q=>Q(1)); A1: andgate port map(A=>Q(0), B=>Q(1), Y=>T(2)); T2: tf port map (Rst=>Rst, Clk=>Clk, T=>T(2), Q=>Q(2)); A2: andgate port map(A=>Q(0), B=>Q(1), C=>Q(2), Y=>T(3)); 13: tff port map (Rst=>Rst, Clk=>Clk, T=>T(3), Q=>Q(3)); A3: andgate port map(A=>Q(0), B=>Q(1), C=>Q(2), D=>Q(3), Y=>T(4)); T4: tff port map (Rst=>Rst, Cik=>Clk, T=>T(4), Q=>Q(4)); Count <= Q; end STRUCTURE; This structural representation seems a straightforward way to describe a 5-bit counter, and it is certainly easy to relate to hardware since just about any imaginable implementation technology will have the features necessary to implement the circuit. For larger circuits, however, such descriptions quickly become impractical. Sample Circuit eee Ee To help demonstrate some of the important concepts we have covered in the first half of this chapter, we will present a very simple circuit and show how the function of this circuit can be described in VHDL. The design descriptions we will show are intended for synthesis and therefore do not include timing specifications or other information not directly applicable to today’s synthesis tools. We will present a This sample circuit combines the comparator circuit presented simple circuit that earlier with a simple 8-bit loadable shift register. The shift includes both combi- . . fot * . national and regis- register will allow us to examine in detail how higher-level tered logic elements. VHDL descriptions can be written for synthesis of both combi- national and registered logic. 40Figure 2-9: Our sample circuit will combine behavior, dataflow, and struc- ture levels of abstrac- tion. Many of the concepts of VHDL are familiar to users of schematic hierarchy. Sample Circuit The two subcircuits (the shifter and comparator) will be connected using VHDL's hierarchy features and will demon- strate the third level of abstraction: structure. The complete circuit is shown in Figure 2-9. Init[8) This diagram has been intentionally drawn to look like a hierarchical schematic with each of the lower-level circuits represented as blocks. In fact, many of the concepts we will cover during the development of this circuit are the same concepts familiar to users of schematic hierarchy. These concepts include the ideas of component instantiation, map- ping of ports, and design partitioning. In a more structured project environment, you would prob- ably enter a circuit such as this by first defining the interface requirements of each block, then describing the overall design of the circuit as a collection of blocks connected together through hierarchy at the top level. Later, after the system interfaces had been designed, you would proceed down the hierarchy (using a top-down approach to design) and fill in the details of each subcircuit. In this example, however, we will begin by describing each of the lower-level blocks first and then connect them to form the complete circuit. 42. A First Look At VHDL Comparator Using standard logic data types allows circuit elements from different sources to be easily combined and re-used, and gives you more detailed and precise simulation. 42 The comparator portion of the design will be identical to the simple 8-bit comparator we have already seen. The only difference is that we will use the IEEE 1164 standard logic data types (std_logic and std_logic_vector) rather than the bit and bit_vector data types used previously. Using standard logic data types for all system interfaces is highly recommended, as it allows circuit elements from different sources to be easily combined. It also provides you the opportunity to perform more detailed and precise simulation than would otherwise be possible. The updated comparator design description, using the IEEE 1164 standard logic data types, is shown below: ight-bit comparator library ieee; use ieee.std_logic_1164.all; entity com} is port (A, B: in std_logic_vector(0 to 7); EQ: out std_logic); end compare; architecture compare1 of compare is begin EQ <= ‘1’ when (A= B) else ‘0’; end compare1; Let’s take a closer look at this simple VHDL design descrip- tion. Reading from the top of the source file, we see: * acomment field, indicated by the leading double-dash symbol (“--”). VHDL allows comments to be embed- ' ded anywhere in your source file, provided they are prefaced by the two hyphen characters as shown. Comments in VHDL extend from the double-dash symbol to the end of the current line. There is no block comment facility in VHDL.Comparator * a library statement that causes the named library IEEE to be loaded into the current compile session. When you use VHDL libraries, it is recommended that you include your library statements once at the beginning of the source file, before any use clauses or other VHDL statements. * ause clause, specifying which items from the IEEE library are to be made available for the subsequent design unit (the entity and its corresponding architec- ture). The general form of a use statement includes three fields delimited by a period: the library name (in this case ieee), a design unit within the library (nor- mally a package, in this case named std_logic_1164), and the specific item within that design unit (or, as in this case, the special keyword all, which means every- thing) to be made visible. * an entity declaration describing the interface to the comparator. Note that we have now specified std_logic and std_logic_vector, which are standard data types provided in the IEEE 1164 standard and in the associ- ated IEEE library. * an architecture declaration describing the actual func- tion of the comparator circuit. Conditional Signal Assignment The function of the comparator is defined using a simple concurrent assignment to port EQ. The type of statement used in the assignment to EQ is called a conditional signal assign- ment. Conditional signal Conditional signal assignments make use of the when-else assignments allow language feature and allow complex conditional logic to be complex combina- described. The following VHDL description of a multiplexer tional logic to be (diagrammed in Figure 2-10) makes the use of the conditional described. . * signal assignment more clear:2. A First Look At VHDL Figure 2-10. A conditional signal assignment describes two or more alternate conditions, as in this _ 4-input multiplexer. Sel 9On> architecture mux1 of mux is begin Y <= Awhen (Sel = “00”) else B when (Sel = 01”) else C when (Sel = “10”) else D when (Sel = “11”); end mux1; Selected Signal Assignment The selected signal assignment is similar to the conditional signal assignment, but it does not imply a priority for the conditions. 44 Another form of signal assignment can be used as an alterna- tive to the conditional signal assignment. The selected signal assignment has the following general form (again, using a multiplexer as an example): architecture mux2 of mux is begin with Sel select Y <= Awhen “00”, B when “01”, C when “10”, D when “11”; end mux2; Choosing between a conditional or selected signal assignment for circuits such as this is largely a matter of taste. For most designs, there is no difference in the results obtained with either type of assignment statement. For some circuits, however, the conditional signal assignment can imply priori- ties that result in additional logic being required. This differ- ence is discussed in detail in Chapter 5, Understanding Concur- rent Statements.Shifter (Entity) Shifter (Entity) Note: In the 1993 version of the VHDL language standard, there is one important difference between the conditional signal assignment and a selected signal assignment that may cause some confusion. In Standard 1076-1993, a conditional assignment statement does not have to include a final, terminat- ing else clause, and the conditions specified do not have to be all-inclusive. When one or more possible input conditions are missing from a conditional assignment, the default behavior under those conditions is for the target signal to hold its value. This means that the conditional assignment state- ment can be used to effectively create a latch. Some synthesis tools support this use of a conditional signal assignment, while others do not. The best advice: do not write incomplete conditional signal assignments. Figure 2-11: The 8-bit shifter accepts an 8- bit value (Data) when the Load input is asserted. Otherwise, it rotates the contents of its registers by one bit. The shifter also includes an asynchro- nous reset. The second and most complex part of this design is the 8-bit shifter. This circuit (diagrammed below in Figure 2-11) accepts 8-bit input data, loads this data into a register and, when the load input signal is low, rotates this data by one bit with each rising edge clock signal. The shift register is provided with an asynchronous reset, and the data stored in the register are accessible via the output signal Q. They are many ways to describe a shifter such as this in VHDL. If you are going to use synthesis tools to process the design description into an actual device technology, however, you must restrict yourself to well established synthesis con- ventions when entering the design description. We will exam- ine two of these conventions when entering this design. 452. A First Look At VHDL Using a Process The first design description that we will write for this shifter is used to describe the a description that uses a VHDL process statement to describe behavior of a circuit the behavior of the entire circuit over time. The process is a over time. behavioral language feature, but its use for synthesis is quite constrained, as we will see in this and later chapters. A process can be The VHDL source code for the shifter is shown below: Eight-bit shifter library ieee; use ieee.std_logic_1164.all; entity rotate is port( Clk, Rst, Load: in std_logic; Data: in std_logic_vector(0 to 7); Q: out std_logic_vector(0 to 7)); end rotate; architecture rotate1 of rotate is signal‘Qreg: std_logic_vector(0 to 7); begin reg: process(Rst,Clk) begin if Rst = ‘1’ then -- Async reset Qreg <= “00000000”; elsif (Clk = ‘1’ and Clk’event) then if (Load = ‘1’) then Qreg <= Data; else Qreg <= Qreg(1 to 7) & Qreg(0); end if; end if; end process; Q <= Qreg; end rotate1; Let’s look closely at this source file. Reading from the top, we see: / 46Shifter (Entity) * acomment field, as described previously. ¢ library and use statements, allowing us to use the IEEE 1164 standard logic data types. * anentity declaration defining the interface to the circuit. Note that the direction (mode) of Q is written as out, indicating that we will not attempt to read its value within this design unit. (If Q was to be used directly as the register, rather than introducing an intermediate signal Qreg, it would need to be of mode inout or buffer.) ¢ an architecture declaration, consisting of a single process statement that defines the operation of the shifter over time in response to events appearing on the clock (Clk) and asynchronous reset (Rst). Process Statement A process statement allows sequential statements to be described, which can imply operation over time. The process statement in VHDL is the primary means by which sequential operations (such as registered circuits) can be described. For use in describing registered circuits, the most common form of a process statement is: architecture arch_name of ent_name is begin process_name: process(sensitivity_list) local_declaration; Jocal_declaration; begin sequential statement; sequential statement; sequential statement; end process; end arch_name; A process statement consists of the following items: 472. A First Look At VHDL A process describes the sequential execution of state- ments that depend on one or more events occurring. 48 * An optional process name (an identifier followed by a colon character). © The process keyword. * An optional sensitivity list, indicating which signals result in the process being executed when there is some event detected. (The sensitivity list is required if the process does not include one or more wait state- ments to suspend its execution at certain points. We will look at examples that do not use a sensitivity list later on in this chapter). ¢ Anoptional declarations section, allowing local objects and subprograms to be defined. ¢ A begin keyword. * A sequence of statements to be executed when the process runs. * anend process statement. The easiest way to think of a VHDL process such as this is to relate it to a small software program that executes (in simula- tion) any time there is an event on one of the process inputs, as specified in the sensitivity list. A process describes the sequential execution of statements that are dependent on one or more events occurring. A flip-flop is a perfect example of such a situation; it remains idle, not changing state, until there is a significant event (either a rising edge on the clock input or an asynchronous reset event) that causes it to operate and potentially change its state. Although there is a definite order of operations within a process (from top to bottom), you can think of a process as executing in zero time. This means that (a) a process can be used to describe circuits functionally, without regard to their actual timing, and (b) multiple processes can be “execut “in parallel with little or no concern for which processes completeIn the absence of an event on one or more of the signals in the sensitivity list, the process remains Suspended and the signals assigned within the process hold their values. Shifter (Entity) their operations first. (There are certain caveats to this behav- ior of VHDL processes. These caveats will be described in detail in Chapter 6, Understanding Sequential Statements.) Let’s see how the process for our shifter operates. For your reference, the process is shown below: reg: process(Rst,Clk) begin if Rst =‘1’then -- Async reset Qreg <= “00000000”; elsif (Clik = ‘1’ and Clk’event) then if (Load = ‘1’) then Qreg <= Data; else Qreg <= Qreg(1 to 7) & Qreg(0); end if; end if; end process; As written, the process is dependent on (or sensitive to) the asynchronous inputs Rst and Clk. These are the only signals that can have events directly affecting the operation of the circuit; in the absence of any event on either of these signals, the circuit described by the process will simply hold its cur- rent value (that is, the process will remain suspended). Now let’s examine what happens when an event occurs on either one of these asynchronous inputs. First, consider what happens when the input Rst has an event in which it transi- tions to a high state (represented by the std_ulogic value of ‘1’). In this case, the process will begin execution and the first if statement will be evaluated. Because the event was a transi- tion to ‘1’, the simulator will see that the specified condition (Rst = ‘1’) is true and the assignment of signal Qreg to the reset value of “00000000” will be performed. The remaining statements of the if-then-elsif expression (those that are dependent on the elsif condition) will be ignored. (The assign- ment statement immediately following the process, the assign- ment of output signal Q to the value of Qreg, is not subject to the if-then-elsif expression of the process or its sensitivity list, 492. A First Look At VHDL A process can be somewhat confusing, but it is important to understand how signals within the process are updated over time. 50 and is therefore valid at all times.) Finally, the process sus- pends, all signals that were assigned values in the process (in this case Qreg) are updated, and the process waits for another event on Clk or Rst. What about the case in which there is an event on Clk? In this case, the process will again execute, and the if-then-elsif expressions will be evaluated, in turn, until a valid condition is encountered. If the Rst input continues to have a high value (a value of ‘1’), then the simulator will evaluate the first if test as true, and the reset condition will take priority. If, however, the Rst input is not a value of ‘1’, then the next expression (Clk = 1’ and Clk’event) will be evaluated. This expression is the most commonly-used convention for detecting clock edges in VHDL. To detect a rising edge clock, we write the expres- sion Clk = ‘1’ in the conditional expression, just as we did when detecting a reset condition. For this circuit, however, the expression Clk = ‘1’ would not be specific enough, since the process may have begun execution as the result of an event on Rst that did not result in Rst transitioning to a ‘1’. To ensure that the event we are responding to is actually an event on Clk, we use the built-in VHDL attribute ‘event to check if Clk was that signal triggering the process execution. If the event that triggered the process execution was actually a rising edge on Clk, then the simulator will go on to check the remaining if-then logic to determine which assignment statement is to be executed. If Load is determined to be ‘1’, then the first assignment statement is executed and the data is loaded from input Data to the registers. If Load is not ‘1’, then the data in the registers is shifted, as specified, using the bit slice and concatenation operations available in the language. Confusing? Perhaps; but if you simply use the style just presented as a template for describing registered logic and don’t worry too much about the details of how it is executed during simulation, you should be in pretty good shape. Just keep in mind that every assignment to a signal you make that is dependent on a Clk = ‘1’ and Clk’event expression willShifter (Entity) result in at least one register when synthesized. (More detailed discussions of how flip-flops and latches are generated from synthesis tools can be found in Chapter 6, Understanding Sequential Statements.) Process Statements Without Sensitivity Lists A process must include either a sensitivity list, or one or more wait state- ments. VHDL process statements have two primary forms. The first form uses the sensitivity list described in the previous section and executes during simulation whenever there is an event on any signal in the sensitivity list. This first form of a process statement is the most common (and recommended) method for describing registered sequential logic for the purposes of synthesis. There is another form of process statement that is useful for other applications, however. This form does not include a sensitivity list. Instead, it includes one or more statements that suspend the execution of the process until some condition has been met. The best example of such a process is a test bench, in which a sequence of test inputs are applied over time, with a predefined time value (or external triggering event) defined as the condition for re-activation of the process. The general form of such a process is: architecture arch_name of ent_name is begin process_name: process local_declaration; local_declaration; begin sequential statement; sequential statement; \ wait until (condition); . sequential statement; wait for (time); end process; end arch; 512. A First Look At VHDL Examples of this form of process will be examined later in this chapter and in Chapter 9, Writing Test Benches. VHDL requires that all processes include either a sensitivity list, or one or more wait statements to suspend the process. (It is not legal to have both a sensitivity list and a wait state- ment.) Concurrent and Sequential VHDL Figure 2-12: VHDL allows both concur- rent and sequential statements to be entered. All statements in the concurrent area are executed at the same time, and there is no significance to the order in which concurrent statements are entered. 52 Understanding the fundamental difference between concur- rent and sequential statements in VHDL is important to making effective use of the language. The diagrams of Figure 2-12 illustrate the basic difference between these two types of statements: BEGIN _¥ Statement + Statement Sl Statement ¥ End Statement I Statement Statement The left-most diagram illustrates how concurrent statements are executed in VHDL. Concurrent statements are those statements that appear between the begin and end statements of a VHDL architecture. This area of your VHDL architecture is what is known as the concurrent area. In VHDL, all state- ments in the concurrent area are executed at the same time, and there is no significance to the order in which the state- ments are entered.You can think of the process as one large concurrent statement that itself contains a series of sequential statements. Concurrent and Sequential VHDL The right-most diagram shows how sequential VHDL state- ments are executed. Sequential statements are executed one after the other in the order that they appear between the begin and end statements of a VHDL architecture. The interaction of concurrent and sequential statements is illustrated in the example below. While the if-elsif-end-if statements in the body of the process are executed sequen- tially (e., one after the other), the body of the process is treated by VHDL as a single concurrent statement and is executed at the same time as all other concurrent statements in the simulation. architecture rotate2 of rotate is signal Qreg: std_logic_vector(0 to 7); begin reg: process(Rst,Clk) begin if Rst = ‘1’ then -- Async reset Qreg <= “00000000”; elsif (Clk = ‘1’ and Clk’event) then if (Load = ‘1’) then Qreg <= Data; else Qreg <= Qreg(1 to 7) & Qreg(0); _ end if; end if; end process; Concurrent Sequential Q <= Qreg; end rotate2; Note: Writing a description of a circuit using the sequential programming features of VHDL (statements entered within processes and subprograms) does not necessarily mean that the circuit being described is sequential in its operation. Sequential circuits require some sort of internal memory (such as one or more flip-flops or latches) to operate, and a VHDL process or subprogram may or may not imply such memory elements. As we will see2. A First Look At VHDL. Signals and Vai It is useful to think of signals as wires, as in a schematic, and variables as being more similar to variables found in software programming languages. in later chapters, it is actually quite common to describe strictly combina- tional circuits—circuits having no memory and, hence, no sequential behavior—using sequential statements within processes and subprograms. riables There are two fundamental types of objects used to carry data from place to place in a VHDL design description: signals and variables. You can use variables to simplify sequential state- ments (within processes, procedures and functions), but you must always use signals to carry information between concur- rent elements of your design (such as between two indepen- dent processes). Signals and variables are described in more detail in a later chapter. For now, it is useful to think of signals as wires (as in a schematic) and variables as temporary storage areas similar to variables in a traditional software programming language. In many cases, you can choose whether to use signals or variables to perform the same task. For your first design efforts you should probably stick to using signals, unless you fully understand the consequences of using variables for your particular application. Using a Procedure to Describe Registers 54 ' As we have seen from the first version of the 8-bit shifter, describing registered logic using processes requires you to follow some established conventions (if you intend to synthe- size the design) and to consider the behavior of the entire circuit. In the shifter design description previously shown, the registers were implied by the placement and use of statements such as if Clk = ‘1’ and Clk’event. Assignment statements subject to that clause resulted in D-type flip-flops being im- plied for the signals.Many VHDL users find it easier to write concurrent, dataflow- level statements for registered logic rather than use processes. Using a Procedure to Describe Registers For smaller circuits, this mixing of combinational logic func- tions and registers is fine and not difficult to understand. For larger circuits, however, the complexity of the system being described can make such descriptions hard to manage, and the results of synthesis can often be confusing. For these circuits, you might choose to retreat to more of a dataflow level of abstraction and to clearly define the boundaries between registered and combinational logic. One way to do this is to remove the process from your design and replace it with a series of concurrent statements represent- ing the combinational and registered portions of the circuit. You can do this using either procedures or lower-level compo- nents to represent the registers. The following VHDL design description uses a register procedure to describe the same shifter circuit previously described: architecture shift3 of shift is signal D,Qreg: std_logic_vector(0 to 7); begin D <= Data when (Load = ‘1’) else Qreg(1 to 7) & Qreg(0); dff(Rst, Clk, D, Qreg); Q <= Qreg; end rotate3; In the shift3 version of the design description above, the behavior of the D-type flip-flop has been placed in an external procedure, dff(), and intermediate signals have been intro- duced to more clearly describe the separation between the combinational and registered parts of the circuit. Figure 2-13 helps to illustrate this separation. In this example, the combinational logic of the counter has been written in the form of a single concurrent signal assign- ment, while the registered operation of the counter’s output has been described using a call to a procedure named dff. 552. A First Look At VHDL Inputs Logic Registers Outputs Figure 2-13: When using a dataflow level of abstraction, you clearly distinguish the registered and combinational parts of your design. What does the dff procedure look like? The following is one possible procedure for a D-type flip-flop: procedure dff (signal Rst, Clk: in std_logic; signal D: in std_logic_vector(0 to 7); signal Q: out std_logic_vector(0 to 7)) is begin if Rst = ‘1’ then Q <= “00000000”; elsif Clk = ‘1’ and Clk’event then Warning: Bad Code! The above procedure is actually rather poorly written, as it assumes a specific width (eight bits) for the D and Q parameters. A more flexible and reusable procedure could be written that makes use of attributes (such as ‘length) to determine the actual number of bits of the signals within the procedure. A procedure can look Notice that this procedure has a striking resemblance to the very much like a process statement presented earlier. The same if-then-elsif process... structure used in the process is used to describe the behavior of the registers. Instead of a sensitivity list, however, the procedure has a parameter list describing the inputs and outputs of the procedure. 56Using a Component to Describe Registers The parameters defined within a procedure or function defini- tion are called its formal parameters. When the procedure or function is executed in simulation, the formal parameters are replaced by the values of the actual parameters specified when the procedure or function is used. If the actual parameters being passed into the procedure or function are signal objects, then the signal keyword can be used (as shown above) to ensure that all information about the signal object, including its value and all of its attributes, is passed into the procedure or function. Using a Component to Describe Registers Another common approach to dataflow- level design is to make use of compo- nents for the regis- tered elements of) the circuit. “ It is important to note that if you wish to use procedures to describe your registers, you will need to make sure the synthe- sis tool you are using allows this. While most VHDL synthesis tools support the use of procedures for registers, some do not, while others have severe restrictions on the use of procedures. If you are not sure, or if you want to have the most portable design descriptions possible, you should replace procedures such as this with components, as in the following example: architecture shift4 of shift is component dff port(Rst, Clk: std_logic; D: in std_logic_vector(0 to 7); Q: out std_logic_vector(0 to 7)); end component; signal D, Qreg: std_logic_vector(0 to 7); begin D <= Data when (Load = ‘1’) else Qreg(1 to 7) & Qreg(0); REG1: dff port map(Rst, Clk, D, Qreg); Q <= Qreg; end shift4; 572. A First Look At VHDL An entity and architecture pair describing exactly the same behavior as the dff procedure is shown below: library ieee; use ieee.std_logic_1164.all; entity dff is port (Rst, Clk: in std_logic; D: in std_logic_vector(0 to 7); Q: out std_logic_vector(0 to 7)); end df; architecture behavior of dff is begin process (Rst, Clk) begin if Rst = ‘1’ then Q <= “00000000”; elsif Clk = ‘1’ and Clk’event then Q<=D; end if; } end process; “ end behavior; Structural VHDL Structure-level design The structure level of abstraction is used to combine multiple methods can be | components to forma larger circuit or system. As such, useful for managing structure can be used to help manage a large and complex fone design Jos crp- design, and structure can make it possible to reuse compo- tion. nents of a system in other design projects. Because structure only defines the interconnections between components, it cannot be used to completely describe the function of a circuit; at the lowest level, all components of your system must be described using behavioral and/or dataflow levels of abstraction.Figure 2-14: Our sample design has now grown to include both the comparator and shifter. Design Hierarchy Structural VHDL descriptions are quite similar in format to schematic netlists. Structural VHDL To demonstrate how the structure level of abstraction can be used to connect lower-level circuit elements into a larger circuit, we will connect the comparator and shift register circuits into a larger circuit as shown in Figure 2-14. Init[8} Notice that we have drawn this diagram in much the same way you might enter it into a schematic capture system. Structural VHDL has many similarities with schematic-based design, as we will see. When you write structural VHDL, you are in essence writing a textual description of a schematic netlist (a description of how the components on the schematic are connected by wires, or nets). In the world of schematic entry tools, such netlists are usually created for you automatically by the schematic editor. When writing VHDL, you enter the same sort of information by hand. (Note: many schematic capture tools in existence today are capable of writing netlist information in the form of a VHDL source file. This can save you a lot of time if you are used to drawing block diagrams in a schematic editor.) 592. A First Look At VHDL Figure 2-15: The hierarchy of a design can be represented as a tree of con- nected components. Larger circuits can be constructed from smaller building blocks... When you use components and wires (signals, in VHDL) to connect multiple circuit elements together, it is useful to think of your new, larger circuit in terms of a hierarchy of compo- nents. In this view, the top-level drawing (or top-level VHDL entity and architecture) can be seen as the highest level in a hierarchy tree, as shown in Figure 2-15. SHIFTCOMP COMPARE In this example, we have introduced a new top-level compo- nent (called shiftcomp) that references the two lower-level components shift and compare. Because the new shiftcomp design entity can itself be viewed as a component, and consid- ering the fact that any component can be referenced more than once, we quickly see how very large circuits can be constructed from smaller building blocks. The following VHDL source file describes our complete circuit using structural VHDL statements (component declarations and component instantiations) to connect together the com- pare and shift portions of the circuit: library ieee; use ieee.std_logic_1164.all; entity shiftcomp is port(Cik, Rst, Load: in std_ulogic; Init: in std_ulogic_vector(0 to 7); Test: in std_ulogic_vector(0 to 7); Limit: out std_ulogic); end shiftcomp; architecture structure of shiftcomp isTest Benches component compare Port(A, B: in std_ulogic_vector(0 to 7); EQ: out std_ulogic); end component; component shift Port(Cik, Rst, Load: in std_ulogic; Data: in std_ulogic_vector(0 to 7); Q: out std_ulogic_vector(0 to 7)); end component; signal Q: std_ulogic_vector(0 to 7); begin COMP1: compare port map (A=>Q, B=>Test, EQ=>Limit); SHIFT1: shift port map (Clk=>Clk, Rst=>Rst, Load=>Load, Data=>Init, Q=>Q); end structure; Note: In the above context, the VHDL symbol => is used to associate the signals within an architecture to ports defined within the lower-level component. See Chapter 8, Partitioning Your Design. VHDL provides many There are many ways to express the interconnection of compo- ways to describe nents and to improve the portability and reusability of those component intercon- + : nections. components. We will examine these more advanced uses of components in a later chapter. Test Benches At this point, our sample circuit is complete and ready to be processed by a synthesis tool. Before processing the design, however, we should take the time to verify that it actually does what it is intended to do, by running a simulation. 612. A First Look At VHDL You can think of a test bench as a virtual circuit tester... Figure 2-16: A test bench is a top-level VHDL description of a sequence of tests to be applied to your design. 62 Simulating a circuit such as this one requires that we provide more than just the design description itself. To verify the proper operation of the circuit over time in response to input stimulus, we will need to write a test bench. The easiest way to understand the concept of a test bench is to think of it as a virtual circuit tester. This tester, which you will describe in VHDL, applies stimulus to your design descrip- tion and (optionally) verifies that the simulated circuit does what it is intended to do. Figure 2-16 graphically illustrates the relationship between the test bench and your design description, which is called the unit under test, or UUT. Check Stimulus : Results Unit Under Test Test Bench To apply stimulus to your design, your test bench will prob- ably be written using one or more sequential processes, and it will use a series of signal assignments and wait statements to describe the actual stimulus. You will probably use VHDL's looping features to simplify the description of repetitiveDeveloping a compre- hensive test bench can be a large-scale project in itself... Figure 2-17; During simulation, the test bench becomes the top level of your design. Test Benches stimulus (such as the system clock), and you may also use VHDU's file and record features to apply stimulus in the form of test vectors. To check the results of simulation, you will probably make use of VHDL’s assert feature, and you may also use the text I/O features to write the simulation results to a disk file for later analysis. For complex design descriptions, developing a comprehensive test bench can be a large-scale project in itself. In fact, it is not unusual for the test bench to be larger and more complex than the underlying design description. For this reason, you should plan your project so that you have the time required to develop the test bench in addition to developing the circuit being tested. You should also plan to create test benches that are re-usable, perhaps by developing a master test bench that reads test data from a file. When you create a test bench for your design, you use the structural level of abstraction to connect your lower-level (previously top-level) design description to the other parts of the test bench, as shown in Figure 2-17. TEST BENCH SHIFTCOMP COMPARE 632. A First Look At VHDL Sample Test Bench Even a simple test bench can require more lines of VHDL statements than the underlying design description... The following VHDL source statements, with explanatory comments, describe a simple test bench for our sample circuit: library ieee; use ieee.std_logic_1164.all; entity testbnch is end testbnch; -- No ports needed ina -- testbench use work.shiftcomp; architecture behavior of testbnch is component shiftcomp is -- Declares the lower-level port(Clk, Rst, Load: in std_logic; -- component and its ports Init: in std_logic_vector(0 to 7); Test: in std_logic_vector(0 to 7); Limit: out std_logic); end component; signal Cik, Rst, Load: std_logic; signal Init: std_logic_vector(0 to 7); signal Test: std_logic_vector(0 to 7); signal Limit: std_logic; begin DUT: shiftcomp port map -- Introduces top-level signals -- to use when testing the -- lower-level circuit -- Creates an instance of the (Clk, Rst, Load, Init, Test, Limit);-- lower-level circuit (the clock: process variable ciktmp: std_logic := ‘0’; begin clktmp := not clktmp; Clk <= clktmp; wait for 50 ns; end process; stimulus: process begin Rst <= '0'; Load ‘ Init <= “00001111”; Test <= “11110000”; wait for 100 ns; Load <= 0"; wait for 600 ns; end process; end behavior; -- unit under test) -- This process sets up a -- background clock of 100 ns -- period. -- This process applies -- stimulus to the design -- inputs, then waits for some -- amount of time so we can -- observe the results during -- simulation.What We've Learned So Far More advanced applications of test benches can be found in Chapter 9: Writing Test Benches. What We’ve Learned So Far Wow! We've covered a lot of ground. So far, we’ve learned about VHDL design elements, different levels of abstraction, and concurrent and sequential VHDL. In addition, we’ve seen examples of hierarchy, a test bench, and we've talked about synthesizable VHDL. If you have questions, don’t worry. All of these topics will be covered in more detail in later chapters. For now, pour yourself a cup of your favorite hot drink and let’s continue our adventure together by... 653. Exploring Objects and Data Types VHDL includes a number of language elements that can be used to represent and store data... VHDL includes a number of language elements, collectively called objects, that can be used to represent and store data in the system being described. The three basic types of objects that you will use when entering a design description for synthesis or creating functional tests (in the form of a test bench) are signals, variables and constants. Each object that you declare has a specific data type (such as bit or integer) and a unique set of possible values. The values that an object can take will depend on the defini- tion of the type used for that object. For example, an object of type bit has only two possible values, '0' and '1', while an object of type real has many possible values (floating point numbers within a precision and range defined by the VHDL standard and by the specific simulator you are using). When an explicit value is specified (such as when you are assigning a value to a signal or variable, or when you are passing a value as a parameter to a subprogram), that value is represented in the form of a literal. 673. Exploring Objects and Data Types Signals Signals are similar to wires on a schematic, and can be used to interconnect concur- rent elements of the design. 68 Signals are objects that are used to connect concurrent ele- ments (such as components, processes and concurrent assign- ments), similar to the way that wires are used to connect components on a circuit board or in a schematic. Signals can be declared globally in an external package or locally within an architecture, block or other declarative region. To declare a signal, you write a signal statement such as the following: architecture arch1 of my_design is signal Q: std_logic; begin end arch; In this simple example, the signal Q is declared within the declaration section of the arch1 architecture. At a minimum, a signal declaration must include the name of the signal (in this case Q) and its type (in this case the standard type std_logic). If more than one signal of the same type is required, multiple signal names can be specified in a single declaration: architecture arch2 of my_design is signal Bus1, Bus2: std_logic_vector(7 downto 0); begin end declare; In the first example above, the declaration of Q was entered in the declaration area of architecture arch1. Thus, the signal Q will be visible anywhere within the arch1 design unit, but it will not be visible within other design units. To make the signal Q visible to the entire design (a global signal), you would have to move the declaration into an external package, as shown below: package my_package is signal Q: std_logic; -- Global signal end my_package;Signals use work.my_package.Q; -- Make Q visible to the architecture architecture arch1 of my_design is begin end arch ; In this example, the declaration for Q has been moved to an external package, and a use statement has been specified, making the contents of that package visible to the subsequent architecture. (For more information about packages and use statements, refer to Chapter 8, Partitioning Your Design). Signal Initialization Signals can be initialized to a specific value. Using Signals In addition to creating one or more signals and assigning them a type, the signal declaration can also be used to assign an initial value to the signal, as shown below: signal BusA: std_logic_vector(15 downto 0) := (others => 'Z'); This particular initialization uses a special kind of assignment, called an aggregate assignment, to assign all signals of the array BusA to an initial value of 'Z’. (The 'Z’' value is defined in the IEEE 1164 standard as a high-impedence state.) Initialization values are useful for simulation modeling, but they are not recommended for design descriptions that will be processed by synthesis tools. Synthesis tools typically ignore initialization values because they cannot assume that the target hardware will power up in a known state. You will use signals in VHDL in two primary ways. First, if you want signals to carry information between different functional parts of your design, such as between two compo- nents, you will probably use them in a way similar to the following: library ieee; use ieee.std_logic_1164.all; entity shiftcomp is port(Clk, Rst, Load: in std_logic; Init: in std_logic_vector(0 to 7); 693. Exploring Objects and Data Types Signals can also be used to describe complex logical expressions. 70 Test: in std_logic_vector(0 to 7); Limit: out std_logic); end shiftcomp; architecture structure of shiftcomp is component compare port(A, B: in std_logic_vector(0 to 7); EQ: out bit); end component; component shift port(Clk, Rst, Load: in std_logic; Data: in std_logic_vector(0 to 7); Q: out std_logic_vector(0 to 7)); end component; signal Q: std_logic_vector(0 to 7); begin COMP1: compare port map (Q, Test, Limit); SHIFT1: shift port map (Clk, Rst, Load, Init, Q); end structure; This example (described in Chapter 2, A First Look At VHDL) declares the signal Q within the architecture, then uses Q to connect the two components COMP! and SHIFT1 together. A second way of using signals is demonstrated by the follow- ing example in which signals are used within logic expres- sions and are assigned values directly (in this case within a process): library ieee; use ieee.std_logic_1164.all; entity synch is port (Rst, Clk, Grant, nSelect: in std_logic; Request: out std_logic); end synch; architecture dataflow of synch is signal Q1, Q2, Q3, D3: std_logic; beginVariables Variables can be used only within processes, functions and proce- dures. Variables dff: process (Rst, Clk) begin if Rst = ‘1’ then Q1 <='05 Q2 <='0'; Q3 <= '0'; elsif Clk = ‘1’ and Clk’event then Q1 <= Grant; Q2 <= Select; Q3 <= D3; end if; end process; 03 <= Q1 and Q3 or Q2; Request <= Q3; end dataflow; This example (which is a simplified synchronizer circuit) uses three signals, Q1, Q2 and Q3, to represent register elements, with the signal D3 being used as an intermediate signal representing a combinational logic function connecting the outputs of registers Q1, Q2 and Q3 to the input of Q3. The final assignment assigns the Q3 register output to the Request output port. The register behavior is encapsulated into a process, dff, simplifying the concurrent statements that follow. It is important to note that there is no significance to the order in which these concurrent statements occur. Like wires drawn between symbols on a schematic, signals assigned and used within a VHDL architecture are independent of each other and are not position dependent. Variables are objects used to store intermediate values be- tween sequential VHDL statements. Variables are only al- lowed in processes, procedures and functions, and they are always local to those functions. 713. Exploring Objects and Data Types Variables can repre- sent intermediate storage elements which may or may not imply registers. 72 Note: The 1076-1993 language standard adds a new type of global variable that has visibility between different processes and subprograms. Global vari- ables are not generally supported in synthesis tools and are not discussed in this book. Variables in VHDL are much like variables in a conventional software programming language. They immediately take on and store the value assigned to them (this is not true of sig- nals, as described in Chapter 6, Understanding Sequential Statements), and they can be used to simplify a complex calcu- lation or sequence of logical operations. The following example is a modified version of the synchro- nizer circuit presented in the previous section: library ieee; use ieee.std_logic_1164.all; entity synch is port (Rst, Clk, Grant, nSelect: std_ulogic; Request: std_ulogic); end synch; architecture behavior of synch is begin process(Rst, Clk) variable Q1, Q2, Q3: std_ulogic; begin if Rst =‘1’then -- Async reset Qt: Q2 3 Q3 := 0; elsif (Clk = ‘1’ and Clk’event) then Q2 := Select; Q3 := Q1 and Q3 or Q2; end if; Request <= Q3; end process; end behavior; In this version of the synchronizer, a single process is again used to describe the behavior of the three commonly-clocked register elements. But in this case, the connections between the three registers are represented by variables that are local to the process, and the result (the output of register Q3) is thenConstants Constants assigned to the output port Request. This version of the design will probably not work as intended, because the regis- tered behavior of Q1 and Q2 will be “short circuited” by the fact that variables were used. Because variables do not always result in registers being generated within otherwise clocked processes, you must be very careful when using them. The important distinctions between signals and variables are covered in more detail in a Jater chapter. Constants are useful for representing commonly-used values of specific types. Constants are objects that are assigned a value once, when declared, and do not change their value during simulation. Constants are useful for creating more readable design de- scriptions, and they make it easier to change the design at a later time. The following code fragment provides a few ex- amples of constant declarations: architecture sample1 of consts is constant SRAM: bit_vector(15 downto 0) := X"FOFO”; constant P: 'RT; string := “This is a string”; constant er:or_flag: boolean := True; begin process(...) constant CountLimit: integer := 205; begin end process; end arch1; Constant declarations can be located in any declaration area in your design description. If you want to create constants that are global to your design description, then you will place the constant declarations into external packages (see Chapter 8, Partitioning Your Design). If a constant will be used only within 733. Exploring Objects and Data Types Literals one segment of your design, you can place the constant decla- ration within the architecture, block, process or subprogram that requires it. Literals do not always have an explicit data type... Character Literals String Literals Bit String Literals 74 Explicit data values that are assigned to objects or used within expressions are called literals. Literals represent specific val- ues, but they do not always have an explicit type. (For ex- ample, the literal '1' could represent either a bit data type or a character.) Literals do, however, fall into a few general catego- ries. Character literals are 1-character ASCII values that are enclosed in single-quotes, such as the values '1', 'Z', '$' and ':'. The data type of the object being assigned one of these values (or the type implied by the expression in which the value is being used) will dictate whether a given character literal is valid. The literal value '$', for example, is a valid literal when as- signed to a character type object, but it is not valid when assigned to a std_logic or bit data type. String literals are collections of one or more ASCII characters enclosed in double-quote characters. String literals may contain any combination of ASCII characters, and they may be assigned to appropriately sized arrays of single-character data types (such as bit_vector or std_logic_vector) or to objects of the built-in type string. Bit string literals are special forms of string literals that are used to represent binary, octal, or hexadecimal numeric data values.Bit string literals can be represented using non-binary formats... Numeric Literals Literals When representing a binary number, a bit string literal must be preceded by the special character 'B', and it may contain only the characters '0' and '1'. For example, to represent a decimal value of 36 using a binary format bit string literal, you would write B"100100". When representing an octal number, the bit string literal must include only the characters '0' through '7', and it must be preceded by the special character 'O', as in O"446". When representing a hexadecimal value, the bit string literal must be preceded by the special character 'X', and it may include only the characters '0' through '9' and the characters ‘A’ through 'F’, as in X"B295". (Lower-case characters are also allowed, so 'a' through 'f' are also valid.) The underscore character '_' may also be used in bit string literals as needed to improve readability. The following are some examples of bit string literals representing a variety of numeric values: B"0111_1101" (decimal value 253) O0"654" (decimal value 428) O0"146_231" (decimal value 52,377) X"C300" (decimal value 49,920) Note: In VHDL standard 1076-1987, bit string literals are only valid for the built-in type bit_vector. In 1076-193, bit string literals can be applied to any string type, including std_logic_vector. There are two basic forms of numeric literals in VHDL, integer literals and real literals. Integer literals are entered as you would expect, as decimal numbers preceded by an optional negation character ('-'). The range of integers supported is dependent on your particular 753. Exploring Objects and Data Types The actual range of a real number literal is defined as a minimum range in the VHDL specification. Based Literals 76 simulator or synthesis tool, but the VHDL standard does specify a minimum range of -2,147,483,647 to +2,147,483,647 (32 bits of precision, including the sign bit). Real literals are entered using an extended form that requires a decimal point. For large numbers, scientific notation is also allowed using the character 'E', where the number to the left of the 'E' represents the mantissa of the real number, while the number to the right of the 'E' represents the exponent. The following are some examples of real literals: 5.0 -12.9 1.6E10 1.2E-20 The minimum and maximum values of real numbers are defined by the simulation tool vendor, but they must be at least in the range of -1.0E38 to +1.0E38 (as defined by the standard). Numeric literals may not include commas, but they may include underscore characters (“_”) to improve readabil- ity, as in: 1_276_801 -- integer value 1,276,801 Type checking is strict in VHDL, and this includes the use of numeric literals. It is not possible, for example, to assign an integer literal of 9 to an object of type real. (You must instead enter the value as 9.0.) Based literals are another form of integer or real values, but they are written in non-decimal form. To specify a based literal, you precede the literal with a base specification (such as 2, 8, or 16) and enclose the non-decimal value with a pair of '#' characters as shown in the examples below: 2#10010001# (integer value 145)Physical Literals Types and Subtypes 16#FFCC# (integer value 65,484) 2#101.0#E10 (real value 5,120.0) Physical literals are special types of literals used to represent physical quantities such as time, voltage, current, distance, etc. Physical literals include both a numeric part (expressed as an integer) and a unit specification. Physical types will be described in more detail later in this chapter. The following examples show how physical literals can be expressed: 300 ns (300 nanoseconds) 900 ps (900 picoseconds) 40ma_ (40 milliamps) Types and Subtypes VHDL's data types fall into four general catagories... The VHDL 1076 specification describes four classes of data types: * Scalar types represent a single numeric value or, in the case of enumerated types, an enumeration value. The standard types that fall into this class are integer, real (floating point), physical, and enumerated types. All of these basic types can be thought of as numeric values. ¢ Composite types represent a collection of values. There are two classes of composite types: arrays con- taining elements of the same type, and records contain- ing elements of different types. ¢ Access types provide references to objects in much the same way that pointer types are used to reference data in software programming languages. ¢ File types reference objects (typically disk files) that contain a sequence of values. 773. Exploring Objects and Data Types. Each data type has a uniquely-defined set of possible values. Subtypes can be used to constrain an existing type to a subset of its values. Scalar Types Each type in VHDL has a defined set of values. For example, the value of an integer data type has a defined range of at least -2147483647 to +2147483647. In most cases you will only be interested in a subset of the possible values for a type, so VHDL provides the ability to specify a constraint whenever an object of a given type is declared. The following declaration creates an object of type integer that is constrained to the positive values of 0 to 255: signal Shortint: integer range 0 to 255; VHDL also provides a feature called a subtype, allowing you to declare an alternate data type that is a constrained version of an existing type. For example, the declaration subtype SHORT integer range 0 to 255; creates an alternate scalar type with a constrained range. Because SHORT is a subtype of integer, it carries with it all operations available for the integer base type. The four classes of data types are discussed in more detail below. =—eee 78 Scalar types are those types that represent a single value, and are ordered in some way so that relational operations (such as greater than, less than, etc.) can be applied to them. These types include the obvious numeric types (integer and real) as well as less obvious enumerated types such as Boolean and Character. The table of Figure 3-1 lists the built-in scalar types defined in VHDL Standard 1076.Figure 3-1. Scalar types have an implied order that allows relational operators to be applied to them. Bit Type Scalar Types Typical Values Bit '1','0 Defined as an enumerated type. Boolean True, False The result of any compari- son operation. Also an enumerated type. Integer 0, 1, 2, -32,129, etc. Minimum range of -2147483647 to +2147483647, inclusive. Character ‘a’, 'b’, '0','1', '2', '$', ISO 8859-1 character set. '@', etc. Real Floating point number | Minimum range of -1.0E38 to_+1.0E38. Severity_level | NOTE, ERROR Enumerated type used in severity clause of report. Time 100 ns Aphysical type. The bit data type is the most fundamental representation of a wire in VHDL. The bit type has only two possible values, ‘0’ and ‘1’, that can be used to represent logical 0 and 1 values (respectively) in a digital system. The following example uses bit data types to describe the operation of a full adder: entity fulladder is port (X: in bit; Y: in bit; Cin: in bit; Cout: out bit; Sum: out bit); end fulladder; architecture concurrent of fulladder is begin Sum <= X xor Y xor Cin; 793. Exploring Objects and Data Types Boolean Type Integer Type An alternative to VHDL's built-in integer type is provided in Standard 1076.3. 80 Cout <= (X and Y) or (X and Cin) or (Y and Cin); end concurrent; The bit data type supports the following operations: and, or, nand, nor, xor, xnor, not, =, /=, <, <=, >, and >=. Note: The IEEE 1164 specification describes an alternative to bit called std_ulogic. Std_ulogic has nine possible values, allowing the values and states of wires (such as high-impedence, unknown, etc.) to be more accu- rately described. (See Chapter 4, Using Standard Logic.) The Boolean type has two possible values, True and False. Like the bit data type, the Boolean type is defined as an enumerated type. The Boolean type does not have any implied width; it is simply the result of a logical test (such as a comparison opera- tion or an if statement) or the expression of some logical state (such as in the assignment, ErrorFlag <= True;). An integer type includes integer values in a specified range. The only predefined integer type is integer. Integer types have a minimum default range of -2147483647 to +2147483647, inclusive. However, you can restrict that value with a range constraint and/or declare a new integer subtype with a range constrained range, as in the following example: ‘subtype byteint integer range 0 to 255; The predefined subtype natural restricts integers to the range of 0 to the specified (or default) upper range limit. The predefined subtype positive restricts integers to the range of 1 to the specified (or default) upper range limit. An alternative to the integer data type is provided with IEEE Standard 1076.3. This standard defines the standard data types signed and unsigned, which are array types (based on theScalar Types IEEE 1164 9-valued data types) that have properties of both array (composite) and numeric (scalar) data types. Like an array, you can perform shifting and masking operations on them and, like integers, you can perform arithmetic operations on them. More information about the IEEE 1076.3 data types can be found in Chapter 4, Using Standard Logic. Real (Floating Point) Types Character Type Floating point types are used to approximate real number values. The predefined floating point type provided in VHDL is called real. It has possible values in the range of at least - 1.0E38 to +1.0E38. The following declaration decribes a signal of type real that has been initialized to a real value of 4589.3: signal FO: real := 4589.3; The real data type supports the following operations: =, /=, <, <=, >, >=, +, -, abs, +, -,*, and /. Note: Floating point types have little use in synthesizable designs, as no synthesis tool available today will accept them. VHDU's character data type is similar to the character types you might be familiar with from software languages. Charac- ters can be used to represent string data (such as you might use in a test bench), to display messages during simulation, or to represent actual data values in your design description. Unlike many software languages, character values in VHDL have no explicit value. This means that they cannot be simply mapped onto numeric data types or assigned directly to arrays of bits. The character values defined in the 1076-1987 standard pack- age are defined in Figure 3-2. 813. Exploring Objects and Data Types Figure 3-3.The character literals supported in VHDL are defined as enumerated types, and therefore have no explicit numeric value. VHDL Standard 1076- 1993 extends the character data type fo the 256-character ISO 8859 character set. 82 ETX, VI, DC3, ESC, EOT, FE, DC4, FPS, $), or um ", <, vy, T, NY, ACK, BEL, SO, SYN, RSP, ‘&, The IEEE 1076-1993 specification extends this character set to the 256-character ISO 8859 standard. Once again, there is no specific numeric value associated with a given character literal in VHDL. (You cannot, for example, assign a character literal to an 8-bit array without providing a type conversion function that assigns unique array values— such as ASCII values—to the target array for each character value.) The character data type is an enumerated type. However, there is an implied ordering (as listed above).Scalar Types Severity_Level Type Type severity level is only used in VHDL’s assert statement. Severity_level is a special data type used in the report section of an assert statement. There are four possible values for an object of type severity_level: note, warning, error and failure. You might use these severity levels in your test bench, for example, to instruct your simulator to stop processing when an error (such as a test vector failure) is encountered during a simulation run. The following assert statement makes use of the FAILURE severity level to indicate that the simulator should halt processing if the specified condition evaluates false: assert (error_flag = ‘1’) report "There was an error; simulation has halted." severity FAILURE; Time and Other Physical Types Physical types such as time define Specific units that are are multiples of a base unit. Subtypes can be used to constrain an existing type to a subset of its values. Time is a standard data type that falls into the catagory of physical types in VHDL. Physical types are those types that are used for measurement. They are distinquished by the fact that they have units of measure, such as (in the case of time) sec- onds, nanoseconds, etc. Each unit in the physical type (with the exception of the base unit) is based on some multiple of the preceding unit. The definition for type time, for example, might have been written as follows (the actual definition is implemen- tation-dependent): type time is range -2147483647 to 2147483647 units fs; ps = 1000 fs; ns = 1000 ps; us = 1000 ns; ms = 1000 us; sec = 1000 ms; min = 60 sec; hr = 60 min; end units; 833. Exploring Objects and Data Types Enumerated Types Enumerated types can be used to describe high-level design concepts using symbolic values. 84 As we have seen, enumerated types are used to describe (internally) many of the standard VHDL data types. You can also use enumerated types to describe your own unique data types. For example, if you are describing a state machine, you might want to make use of an enumerated type to represent the various states of the machine, as in the following example: architecture FSM of VCONTROL is type states is (StateLive,StateWait,StateSample,StateDisplay); signal current_state, next_state: states; begin -- State transitions: STTRANS: process(current_state, Mode, VS,ENDFR) begin case current_state is when StateLive => -- Display live video on the output when StateWait => -- Wait for vertical sync when StateSample => -- Sample one frame of video when StateDisplay => -- Display the stored frame end case; end process; end FSM; In this example (the control logic for a video frame grabber, described in detail in Chapter 6, Understanding Sequential Statements), an enumerated type (states) is defined in the architecture, and two signals (current_state and next_state) are declared for use in the subsequent state machine description. Using enumerated types in this way has two primary advan- tages: first, it is very easy to debug a design that uses enumer- ated types, because you can observe the symbolic type names during simulation; second, and perhaps more importantly for this state machine description, you can defer the actual encod- ing of the symbolic values until the time that you implement the design in hardware.Composite Types Synthesis tools generally recognize the use of enumerated types in this way and can perform special optimizations, assigning actual binary values to each symbolic name during synthesis. Synthesis tools generally also allow you to override the encod- ing of enumerated data types, so you have control over the encoding process. Composite Types Composite types include arrays (such as bit-vector and string) and records. Array Types Arrays can be indexed using to or downto index ranges. bit_vector | "00100101", "10", etc. Array of bit string “Simulation failed!", etc. | Array of characters records Any collection of values | User defined composite data type. Composite types are collections of one or more types of values. An array is a composite data type that contains items of the same type, either in a single dimension (such as a list of num- bers or characters) or in multiple dimensions (such as a table of values). Records, on the other hand, define collections of possi- bly unrelated data types. Records are useful when you need to represent complex data values that require multiple fields. An array is a collection of one or more values or objects of the same type. Arrays are indexed by a number that falls into the declared range of the array. The following is an example of an array type declaration: type MyArray is array (15 downto 0) of std_ulogic; This array type declaration specifies that the new type MyArray contains 16 elements, numbered downward from 15 to 0. Arrays can be given ranges that decrement from left to right (as shown) or increment (using the to keyword instead of downto). Index ranges do not have to begin or end at zero. 853. Exploring Objects and Data Types Arrays can be declared with no specific range, creating an un- bounded array. VHDL also supports the use of multidimen- sional arrays. 86 The index range (in this case 15 downto 0) is what is known as the index constraint. It specifies the legal bounds of the array. Any attempt to assign values to, or read values from, an ele- ment outside the range of the array will result in an error during analysis or execution of the VHDL design description. The index constraint for an array can specify an unbounded array using the following array range syntax: type UnboundedArray is array (natural range <>) of std_ulogic; This array type declaration specifies that the array UnboundedArray will have a index constraint matching the range of integer subtype natural, which is defined as 0 to the highest possible integer value (at least 2,147,483,647). An array type is uniquely identified by the types (and con- straints) of its elements, the number of elements (its range), and the direction and order of its indices. Arrays can have multiple indices, as in the following example: type multi is array(7 downto 0, 255 downto 0) of bit; Note: Multidimensional arrays are not generally supported in synthesis tools. They can, however, be useful for describing test stimulus, memory ele- ments, or other data that require a tabular form. The following example (a parity generator) demonstrates how array elements can be accessed, in this case within a loop: entity parity10 is port(D: in array(0 to 9) of bit; ODD: out bit); constant WIDTH: integer := 10; end parity10; architecture behavior of parity10 Is begin process(D) variable otmp: Boolean; beginIt is important to consider the direction of an array before assigning values... Composite Types otmp := false; for i in 0 to D'length - 1 loop if D(i) = ‘1’ then otmp end i end process; end behavior; The direction of an array range has an impact on the index values for each element. For example, the following declara- tions: signal A: bit_vector(0 to 3); signal B: bit_vector(3 downto 0); create two objects, A and B, that have the same width but different directions. The aggregate assignments: Ac (1'0''11/0); B<=(‘0'/'1''0' are exactly identical to the assignments: A(0) <= ‘1’: A(1) ‘0’; A(2) v5 A(3) <= ‘07; B(3) <= B(2) <= ‘1’; B(1) <= 0; BO) <= ‘1’; ‘0; In this case, the arrays have the same contents when viewed in terms of their array indices. Assigning the value of B to A, as in: A<=B; 873. Exploring Objects and Data Types Record Types Record data types can be used to describe a collection of unrelated types. 88 which would be exactly equivalent to the assignments: A(0) <= B(3); A(1) <= B(2); A(2) <= B(1); A(3) <= B(O); The leftmost element of array A has an index of 0, while the leftmost value of array B has an index value of 1. Arecord is a composite type that has a value corresponding to the composite value of its elements. The elements of a record may be of unrelated types. They may even be other composite types, including other records. You can access data in a record either by referring to the entire record (as when copying the contents of one record object to another record object), or individually by referring to a field name. The following ex- ample demonstrates how you might declare a record data type consisting of four elements: type data_in_type is record ClkEnable: std_logic; Din: std_logic_vector(15 downto 0); Adar: integer range 0 to 255; CS: std_logic; end record; The four names, ClkEnable, Din, Addr and CS are all field names of the record, representing data of specific types that can be stored as a part of the record. For example, an object of type data_in_type could be created and initialized with the following signal declaration: signal test_record: data_in_type := (‘0', “1001011011110011”, 165, ‘1’); This initialization would be identical to the assignments: test_record.ClkEnable <= ‘0’; test_record.Din <= “1001011011110011”; test_record.Addr <= 165; test_record.CS <= ‘1’;Composite Types Records types are not generally synthesizable; however, they can be very useful when describing test stimulus. Examples shown in Chapter 9, Writing Test Benches, show how records can be used in combination with arrays to organize test stimulus. Access and Incomplete Types Access types are similar to pointers ina high-level software programming lan- guage. File Types File types are very useful for writing test benches. Access types and incomplete types are used to create data indirection in VHDL. You can think of access types as being analogous to pointers in software programming languages such as C or Pascal. Incomplete types are required to create recursive types such as linked lists, trees and stacks. Access and incomplete types can be useful for creating dynamic representations of data (such as stacks), but they are not supported in today’s synthesis tools. Refer to the IEEE VHDL Language Reference Manual for more information about these language features. File types are very useful for writing test benches. File types differ in the VHDL 1076-1987 and 1076-1993 specifications. Discussions and examples of each are presented below. VHDL 1076-1987 File Types A file type is a special type of variable that contains sequential data. In the 1987 VHDL standard language, files are implicitly opened when they are declared, and it is not possible to explicitly close them. Objects of type file can be read from and written to using functions and procedures (read, write, and endfile) that are provided in the standard library. Additional functions and procedures for formating of data read from files is provided in the Text I/O library, which is also part of the 1076 standard. The built-in functions available for reading and writing files in VHDL (the 1987 specification) are: 893. Exploring Objects and Data Types Read(f, object)—Given a declared file and an object, read one field of data from the file into that object. When the read procedure is invoked, data is read from the file and the file is advanced to the start of the next data field in the file. Write(£, object)—Given a declared file and an object, write the data contained in the object to the file. Endfile(f)—Given a declared file, return a boolean true value if the current file marker is at the end of the file. VHDL does not Files in VHDL are sequential; there is no provision for open- support fandom. ing a file and reading from a random location in that file, or : for writing specific locations in a file. To use an object of type file, you must first declare the type of its contents, as shown below: type file_of_characters is file of character; This declaration creates a new type, called file_of_characters, that consists of a sequence of character values. To use this file type, you would then create an object of type file_of_characters, as shown below: file testfile: file_of_characters is in “TESTFILE.ASC”; This statement creates the object testfile and opens the indi- cated disk file. You can now use the built-in read procedure to access data in the file. A complete architecture that loops through a file and reads each character is shown below: architecture sample87 of readfile is begin Read_input: process type character_file is file of character; file cfile: character_file is in “TESTFILE.ASC”; variable C: character; variable char_cnt: integer := 0; begin while not endfile(cfile) loop tread (cfile, C) ; -- Get a character from cfile into CVHDL 1076-1993 allows files to be opened and closed as needed during simulation. Composite Types char_cnt=char_cnt+1; -- Keep track of the number of -- characters end loop; end process; end sample87; VHDL 1076-1993 File Types In VHDL '93, file types and associated functions and proce- dures were modified to allow files to be opened and closed as needed. In the 1987 specification, there is no provision for closing a file, and problems can arise when it is necessary for two parts of the same design description to open the same file at different points, or when existing files must be both read from and written to (as when appending data). The built-in functions available for file operations in VHDL ’93 are: File_open(f, fname, fmode)—Given a declared file object, file name (a string value) and a mode (either READ- MODE, WRITE_MODE, or APPEND_MODE), open the indicated file. File_open(status, f, fname, fmode)—Same as above, but return the status of the file open request in the first parameter, which is of type file_open_status. The status returned is either OPEN_OK (meaning the file was successfully opened), STATUS_ERROR (meaning the file was not opened because there was already an open file associated with the file object), NAME_ERROR (meaning there was a system error related to the file name specified) or MODE_ERROR (meaning that the specified mode is not valid for the specified file). File_close(f)—Close the specified file. 913. Exploring Objects and Data Types Read(f, object)—Given a declared file and an object, read one field of data from the file into that object. When the read procedure is invoked, data is read from the file and the file is advanced to the start of the next data field in the file. Write(£, object)—Given a declared file and an object, write the data contained in the object to the file. Endfile(f)—Given a declared file, return a boolean true value if the current file marker is at the end of the file. A complete architecture that opens a file and loops through it, reading each character in the file, is shown below: architecture sample93 of readfile is begin Read_input: process type character_file is file of character; file cfile: character_file; variable C: character; variable char_cnt: integer := 0; begin file_open(cfile, “TESTFILE.ASC”, READ_MODE); while not endfile(cfile) loop read (cfile, C) ; -- Get a character from cfile into C char_cnt=char_cnt+1; -- Keep track of the number of -- characters end loop; file_close(cfile); end process; end sample93; Operators VHDL is a rich The following charts summarize the operators available in language that VHDL. As indicated, not all operators can be used for all data inaudes many - types, and the data type that results from an operation may operators. differ from the type of the object on which the operation is performed. 92Note: Operations defined for types Bit are also valid for type std_ulogic and std_logic. Logical Operators Operators. The logical operators and, or, nand, nor, xor and xnor are used to describe Boolean logic operations, or perform bit-wise operations, on bits or arrays of bits. Operator Description Operand Types Result Type and And Any Bit or Boolean type or Or Any Bit or Boolean type nand Not And Any Bit or Boolean type nor Not Or Any Bit or Boolean type xor Exclusive Or Any Bit or Boolean type nxor Not Exclusive Any Bit or Boolean type Or Relational Operators Same type Same type Same type Same type Same type Same type Relational operators are used to test the relative values of two scalar types. The result of a relational operation is always a Boolean true or false value. Operator Description Operand Types Result Type = Equality Any type Is Inequality Any type Boolean Boolean 933. Exploring Objects and Data Types < Ordering Any scalar type Boolean. <= or > discrete array >= type Adding Operators The adding operators can be used to describe arithmetic functions or, in the case of array types, concatenation operations. Operator Description Operand Types Result Type + Addition Any numeric type Same type - Subtraction Any numeric type Same type & Concatenation Any numeric type Same type & Concatenation Any array or element type Same array type Multiplying Operators 94 The multiplying operators can be used to describe mathematical functions on numeric types. Note: Synthesis tools vary in their support for multiplying operators. Operator Description Operand Types Result Type * Multiplication Left: Any integer or Same type floating point type Right: Same type * Multiplication Left: Any physical type Same as left Right: Integer or real typeOperators * Multiplication Left: Any integer or real Same as right type Right: Any physical type / Division Any integer or floating Same type point type / Division Left: Any physical type Same as left Right: Any integer or real type / Division Left: Any physical type Integer Right: Same type Operator Description Operand Types Result Type mod Modulus Any integer type Same type rem Remainder Any integer type Same type Sign Operators Sign operators can be used to specify the sign (either postive or negative) of a numeric object or literal. Operator Description Operand Types Result Type + Identity Any numeric type Same type - Negation Any numeric type Same type Miscellaneous Operators The exponentiation and absolute value operators can be applied to numeric types, in which case they result in the same numeric type. The logical nega- tion operator results in the same type (bit or Boolean), but with the reverse logical polarity. 953. Exploring Objects and Data Types Operator Description Operand Types Result Type “ Exponentiation Left: Any integer type Same as Left Right: Integer type “* Exponentiation Left: Any floating point Same as Left type Right: Integer type abs Absolute value Any numeric type Same numeric type not Logical Any Bit or Boolean Same type negation type Shift Operators (1076-1993 only) The shift operators (defined in 1076-1993) provide bit-wise shift and rotate operatons for arrays of type bit or Boolean. Operator Description Operand Types Result Type sll Shift left logical Left: Any one-dimensinal Same as left array type whose element _ operand type type is Bit or Boolean Right: Integer type srl Shift right (same as above) (same as above) logical sla Shift left (same as above) (same as above) arithmetic sra Shift right (same as above) (same as above) arithmetic rol Rotate left (same as above) (same as above) logical ror Rotate right (same as above) (same as above) logical 96Attributes Attributes Attributes provide additional information about various types of VHDL objects. Attributes are a feature of VHDL that allow you to extract additional information about an object (such as a signal, vari- able or type) that may not be directly related to the value that the object carries. Attributes also allow you to assign additional information (such as data related to synthesis) to objects in your design description. There are two classes of attributes: those that are predefined as a part of the 1076 standard, and those that have been intro- duced outside of the standard, either by you or by your design tool supplier. Predefined Attributes Predefined attributes are always applied to a prefix... The VHDL specification describes five fundamental kinds of attributes. These five kinds of attributes are categorized by the results that are returned when they are used. The possible results returned from these attributes are: a value, a function, a signal, a type or a range. Predefined attributes are always applied to a prefix (such as a signal or variable name, or a type or subtype name), as in the statement: wait until Cik = ‘1’ and Clk’event and Clk’last_value = ‘0’; In this statement, the attributes ‘event and ‘last_value have been applied to the prefix Clk, which is a signal. Some attributes also include parameters, so they are written in much the same way you would write a call to a function: variable V: state_type := state_type’val(2); -- V has the value of -- Strobe In this case, the attribute ‘val has been applied to the prefix state_type (which is a type name) and has been given an attribute parameter, the integer value 2. 973. Exploring Objects and Data Types Value Kind Attributes: ‘Left, ‘Right, ‘High, ‘Low, ‘Length, ‘Ascending The value kind attributes that return an explicit value and are applied to a type or subtype include the following: ‘Left—This attribute returns the left-most element index (the bound) of a given type or subtype. Example: type bit_array is array (1 to 5) of bit; variable L: integer := bit_array’left; -- Lhas a value of 1 ‘Right—Returns the right-most bound of a given type or subtype. Example: type bit_array is array (1 to 5) of bit; variable R: integer := bit_array’right; -- Rhas a value of 5 ‘High—returns the upper bound of a given scalar type or subtype. Example: type bit_array is array(-15 to +15) of bit; variable H: integer := bit_array’high; -- Hhas a value of 15 “Low—returns the upper bound of a given scalar type or subtype. Example: type bit_array is array(15 downto 0) of bit; variable L: integer := bit_array'low; -- Lhas a value of 0 “Length—returns the length (number of elements) of an array. Example: type bit_array is array (0 to 31) of bit; variable LEN: integer := bit_array’length -- LEN has a value of 32 “Ascending—(VHDL ’93 attribute) returns a boolean true value of the type or subtype is declared with an as- cending range. 98Attributes Example: type asc_array is array (0 to 31) of bit; type desc_array is array (36 downto 4) of bit; variable A1: boolean := asc_array’ascending; -- Al has a value of true variable A2: boolean := desc_array’ascending; -- A2 has a value of false As you can see from the examples, value kind attributes (and all other predefined attributes) are identified by the ‘ (single quote) character (which is also called a tick). They are applied to type names, signals names and other identifiers, depending on the nature of the attribute. The value type attributes are used to determine the upper and lower (or left and right) bounds of a given type. The following sample architecture uses the ‘right and ‘left attibutes to determine the left- and right-most element indices of an array in order to describe a width-independent shift operation: architecture behavior of shifter is begin reg: process(Rst,Cik) begin if Rst=‘1’ then -- Async reset Qreg := (others => ‘0’); elsif rising_edge(Clk) then Qreg := Data(Data’left+1 to Data’ right) & Data(Data' lett); end if; end process; end behavior; The ‘right, ‘left, ‘high and ‘low attributes can be used to return non-numeric values. The following example demon- strates how you can use the ‘left and ‘right attributes to identify the first and last items in an enumerated type: architecture example of enums is type state_type is (Init, Hold, Strobe, Read, Idle); signal L, R: state_type; begin L<=state_type’left; —-- L has the value of Init R <= state_type’right; -- R has the value of Idle end example; 993. Exploring Objects and Data Types 100 Value Kind Attributes: ‘Structure, ‘Behavior There are two additional value kind attributes that can be used to determine information about blocks or attributes in a design. These attributes, ‘structure and ‘behavior, return true or false values depending on whether the block or architec- ture being referenced includes references to lower-level com- ponents. The ‘structure attribute returns true if there are references to lower-level components, and false if there are no references to lower-level components. The ‘behavior attribute returns false if there are references to lower-level components, and true if there are no references to lower-level components. ‘Structure—returns a true value if the prefix (which must be an architecture name) includes references to lower- level components. ‘Behavior—returns a true value if the prefix (which must be an architecture name) does not include references to lower-level components. Value Kind Attributes: ‘Simple_name, ‘Instance_name, ‘Path_name VHDL ’93 adds three attributes that can be used to determine the precise configuration of entities in a design description. These attributes return information about named entities, which are various items that become associated with identifi- ers, character literals or operator symbols as the result of a declaration. For more information about these attributes, refer to the IEEE VHDL Language Reference Manual. ‘Simple_name—(VHDL ’93 attribute) returns a string value corresponding to the prefix, which must be a named entity.Attributes ‘Instance_name—(VHDL '93 attribute) returns a string value corresponding to the complete path (from the design hierarchy root) to the named entity specified in the prefix, including the names of all instantiated design entities. The string returned by this attribute has a fixed format that is defined in the IEEE VHDL Language Reference Manual. ‘Path_name—(VHDL ’93 attribute) returns a string value corresponding to the complete path (from the design hierarchy root) to the named entity specified in the prefix. The string returned by this attribute has a fixed format that is defined in the IEEE VHDL Language Reference Manual. Function Kind Attributes: ‘Pos, ‘Val, ‘Succ, ‘Pred, ‘Leftof, ‘Rightof Attributes that return information about a given type, signal, or array value are called function kind attributes. VHDL de- fines the following function kind attributes that can be applied to types: ‘Pos(value)—returns the position number of a type value. Example: _ type state_type is (Init, Hold, Strobe, Read, Idle); variable P: integer := state_type’pos(Read); -- Phas the value of 3 “Val(value)—returns the value corresponding to a position number of a type value. Example: type state_type is (Init, Hold, Strobe, Read, Idle); variable V: state_type := state_type’val(2); ~- Vhas the value of Strobe ‘Succ(value)—returns the value corresponding to position number after a given type value. Example: _ type state_type is (Init, Hold, Strobe, Read, Idle); variable V: state_type := state. type’suce( Init); ~- V has the value of Hold 1013. Exploring Objects and Data Types ‘Pred(value)—returns the value corresponding to position number preceding a given type value. Example: __ type state_type is (Init, Hold, Strobe, Read, Idle); variable V: state_type := state_type’pred(Hold); ~- V has the value of Init ‘Leftof(value)—returns the value corresponding to posi- tion number to the left of a given type value. Example: type state_type is (Init, Hold, Strobe, Read, Idle); variable V: state_type := state_type'leftof({dle); ~ V has the value of Read ‘Rightof(value)—returns the value corresponding to position number to the right of a given type value. type is (Init, Hold, Strobe, Read, Idle); tate_type := state_type’rightof(Read); ~ V has the value of Idle Example: _type stat variable From the above descriptions, it might appear that the ‘val and ‘succ attributes are equivalent to the attributes ‘leftof and “rightof. One case where they would be different is the case where a subtype is defined that changes the ordering of the base type: type state_type is (Init, Hold, Strobe, Read, Idle); subtype reverse_state_type is state_type range Idle downto Init; variable V1: reverse_state_type := reverse_state_type’leftof(Hold); V1 has the value of Strobe variable V2: reverse_state_type := reverse_state_type’pred(Hold); -- V2 has the value of Init Function Kind Array Attributes: ‘Left, ‘Right, ‘High, ‘Low The function kind attributes that can be applied to array objects include: “Left(value)—returns the index value corresponding to the left bound of a given array range. 102Attributes Example: type bit_array is array (15 downto 0) of bit; variable |: integer := bit_array’left(bit_array’range); ~- Thas the value of 15 ‘Right(value)—returns the index value corresponding to the right bound of a given array range. Example: type bit_array is array (15 downto 0) of bit; variable |: integer := bit_array'right(bit_array’range); ~ Thas the value of 0 ‘High(value)—returns the index value corresponding to the upper-most bound of a given array range. Example: type bit_array is array (15 downto 0) of bit; variable |: integer := bit_array’high(bit_array’range); ~- [has the value of 15 “Low(value)—returns the index value corresponding to the lower bound of a given array range. Example: type bit_array is array (15 downto 0) of bit; variable |: integer : bit_array'low(bit_array’rang ~- Thas the value of 0 Function Kind Attributes: ‘Event, ‘Active, ‘Last_event, ‘Last_value, ‘Last_active Function kind attributes that return information about signals (such as whether that signal has changed its value or its previous value) include: ‘Event—returns a true value of the signal had an event (changed its value) in the current simulation delta cycle. Example: process(Rst,Cik) begin if Rst = ‘1’ then Q<=05 1033. Exploring Objects and Data Types elsif Clk = ‘1’ and Cik’event then -- Look for clock edge Q end if; end process; “Active—returns true if any transaction (scheduled event) occurred on this signal in the current simulation delta cycle. Example: process variable A\E: boolean; begin Q <= Dafter 10 ns; Q’active; — A gets a value of True i= Qlevent; - E gets a value of False end proces: “Last_event—returns the time elapsed since the previous event occurring on this signal. Example: process varlable T: time; begin Q <= Datter 5 ns; wait 10 ns; Q'last event; —-T gets a value of 5 ns end proce: “Last_value—returns the value of the signal prior to the last event. Example: process variable V: bit; begin Q<=1; wait 10 ns; Qc 0! wait 10 ns; V:=Q'last_value; -- V gets a value of ‘1’ end process; 104Attributes ‘Last_active—returns the time elapsed since the last transaction (scheduled event) of the signal. Example: process variable T: time; begin Q <= D after 30 ns; wait 10 ns; T:=Q'last_active; ~T gets a value of 10 ns end process; Note: The ‘active, ‘last_event, ‘last_value and ‘last_active attributes are not generally supported in synthesis tools. Of the preceding five attributes, only ‘event should be used when describing synthesizable registered circuits. The ‘active, ‘last_event, ‘last_value and ‘last_active at- tributes should only be used to describe circuits for test purposes (such as {for setup and hold checking). If they are encountered by a synthesis pro- gram, they will either be ignored, or the program will return an error and halt operation. Function Kind Attributes: ‘Image, ‘Value The ‘image and ‘value attributes were added in the 1993 specification to simplify the reporting of information through Text I/O. These attributes both return string results corre- sponding to their parameter values. ‘Image(expression)—(VHDL '93 attribute) returns a string representation of the expression parameter, which must be of a type corresponding to the attribute prefix. Example: assert (Data.Q =‘1') report “Test failed on vector “ & integer'image(vector_idx) severity WARNING; ‘Value(string)\—(VHDL ‘93 attribute) returns a value, of a type specified by the prefix, corresponding to the parameter string. 1053. Exploring Objects and Data Types Example: write(a_outbuf,string’(“Enter desirad state (example: $1)")); writeline(OUTPUT,a_outbuf); readline(INPUT,a_inbut); read(a_inbuf.instate); -- instate is a string type next_state <= state_type’value(instat ~ convert string to type state_type write(a_outbuf,string’(“Enter duration (example: 15)")); writeline(OUTPUT,a_outbuf); readline(INPUT,a_inbuf); read(a_inbufinduration); — -- induration is a string type duration <= integer'value (induration); -- convert string to type integer Sig.1al Kind Attributes: ‘Delayed, ‘Stable, ‘Quiet, ‘Transaction The signal kind attributes are attributes that, when invoked, create special signals that have values and types based on other signals. These special signals can then be used any- where in the design description that a normally declared signal could be used. One example of where you might use such an attribute is to create a series of delayed clock signals that are all based on the waveform of a base clock signal. Signal kind attributes include the following: “Delayed(time)—creates a delayed signal that is identical in waveform to the signal the attribute is applied to. (The time parameter is optional, and may be omitted.) Example: process(Cik'delayed(hold)) ~- Hold time check for input Data begin if Clk = ‘1’ and Cik’stable(hold) then assert(Data’stable(hold)) report “Data input failed hold time check!” severity waming; 106Attributes end if; end process; ‘Stable (time)—creates a signal of type boolean that becomes true when the signal is stable (has no event) for some given period of time. Example: process variable A: Boolean; begin wait for 30 ns; Q <= Datter 30 ns; wait 10 ns; A:= C'stable(20 ns); ~- Agets a value of true (event has not ~ yet occurred) wait 30 ns; A:= Q’stable(20 ns); ~ A gets a value of false (only 10 ns ~ since event) end process; ‘Quiet (time)—creates a signal of type boolean that be- comes true when the signal has no transactions (sched- uled events) or actual events for some given period of time. Example: process variable A: Boolean; begin wait for 30 ns; Q <= Datter 30 ns; wait 10 ns; A:= Q’quiet(20 ns); - A gets a value of false (10 ns since -- transaction) wait 40 n: A:= Q’quiet(20 ns); - Afinally gets a value of true (20 ns -- since event) end process; 1073. Exploring Objects and Data Types “Transaction—creates a signal of type bit that toggles its value whenever a transaction or actual event occurs on the signal the attribute is applied to. Type Kind Attribute: ‘Base “Base—returns the base type for a given type or subtype. Example: type miv7is (0.'1'X''Z'/H'L'W); subtype miv4 is miv7 range ‘0' to 'Z’; variable V1: miv4 := miv4’right; -- V1 has the value of ‘2’ variable V2: miv7 := miv4’base'right; V2 has the value of ‘W" variable I1: integer := miv4’width; has the value of 4 variable I2: integer := miv4’base'width; -- 2 has the value of 7 Range Kind Attributes: ‘Range, ‘Reverse_range The range kind attributes return a special value that is a range, such as you might use in a declaration or looping scheme. “Range—returns the range value for a constrained array. Example: function parity(D: std_logic_vector) return std_logic is result: std_logic varial begin for i in D'range loop end parity; ‘Reverse_range—returns the reverse of ihe range value for a constrained array. Example: STRIPX: for i in D’reverse_range loop 108Attributes. else exit; -- only strip the terminating Xs end if; end loop; Custom Attributes Custom attributes are those attributes that are not defined in the Custom attributes can IEEE specifications, but that you (or your simulation or synthe- be used to attach sis tool vendor) define for your own use. A good example is the information to (or attribute enum_encoding, which is provided by a number of decorate) a VHDL synthesis tool vendors (most notably Synopsys) to allow spe- object. cific binary encodings to be attached to objects of enumerated types. An attribute such as enum_encoding is declared (again, either by you or by your design tool vendor) using the following method: attribute enum_encoding: string; This attribute could be written directly in your VHDL design description, or it could have been provided to you by the tool vendor in the form of a package. Once the attribute has been declared and given a name, it can be referenced as needed in the design description: type statevalue is (INIT, IDLE, READ, WRITE, ERROR); attribute enum_encoding of statevalue: type is "000 001 011 010 110"; When these declarations are processed by a synthesis tool that supports the enum_encoding attribute, information about the encoding of the type statevalue will be used by that tool. When the design is processed by design tools (such as simulators) that do not recongnize the enum_encoding attribute, it will simply be ignored. 1093. Exploring Objects and Data Types Custom attributes are a convenient "back door" feature of VHDL, and design tool vendors have created many such attributes to give you more control over the synthesis and simulation process. For detailed information about custom attributes, refer to your design tool documentation. Type Conversions and Type Marks VHDL is a strongly typed language... VHDLis a strongly typed language, meaning that you cannot simply assign a literal value or object of one type to an object of another type. To allow the transfer of data between objects of different types, VHDL includes type conversion features for types that are closely related. VHDL also allows type conver- sion functions to be written for types that are not closely re- lated. In addition, VHDL includes type mark features to help specify (or qualify) the type of a literal value when the context or format of the literal makes its type ambiguous. Explicit Type Conversions Explicit type conver- sions are allowed between closely- related types. 110 The simplest type conversions are explicit type conversions, which are only allowed between closely related types. Two types are said to be closely related when they are either abstract numeric types (integers or floating points), or if they are array types of the same dimensions and share the same types (or the element types themselves are closely related) for all elements in the array. In the case of two arrays, it is not necessary for the arrays to have the same direction. If two subtypes share the same base type, then no explicit type conversion is required. The following example demonstrates implicit and explicit type conversions: architecture example of typecony is. type array! is array(0 to 7) of std_logic; type array2 is array(7 downto 0) of std_logic; subtype array3 is std_logic_vector(0 to 7); subtype array4 is std_logic_vector(7 downto 0); signal at: array1; signal a2: array2;Type Conversions and Type Marks signal a3: array signal a4: array4; begin a2 <= array2(a1);~- explicit type conversion ad <= a3; ~- no explicit type conversion needed end example; Type Conversion Functions Type conversion functions can be used to assign a value of one type to an object ofa different type. To convert data from one type to an unrelated type (such as from an integer type to an array type), you must make use of a type conversion function. Type conversion functions may be obtained from standard libraries (such as the IEEE 1164 library), from vendor-specific libraries (such as those supplied by synthesis tool vendors), or you can write you own type conver- sion functions. A type conversion function is a function that accepts one argu- ment of a specified type and returns the equivalent value in another type. The following two functions are examples of type conversion functions that convert between integer and array (std_ulogic_vector) data types: ~ Convert a std_ulogic_vector to an unsigned integer function to_uint (a: std_ulogic_vector) return integer is 8 av: Std_ulogic_vector (1 to a'length) is a; variable val: integer := 0; for iin a'length downto 1 loop if (av() =") then ~if LSBis ‘1’, ~- add value for current bit position return val; end to_uint; 111
You might also like
VHDL
PDF
No ratings yet
VHDL
33 pages
VHDL Made Easy
PDF
No ratings yet
VHDL Made Easy
424 pages
VHDL Sim Syn Soc
PDF
No ratings yet
VHDL Sim Syn Soc
37 pages
VHDL Assign 2.0
PDF
No ratings yet
VHDL Assign 2.0
5 pages
Main Topics:: Circuit Design Based On VHDL VHDL Basics Advanced VHDL Language Structures Circuit Examples
PDF
No ratings yet
Main Topics:: Circuit Design Based On VHDL VHDL Basics Advanced VHDL Language Structures Circuit Examples
33 pages
FR
PDF
No ratings yet
FR
32 pages
CH-05 A Introduction To HDL.
PDF
No ratings yet
CH-05 A Introduction To HDL.
63 pages
Main Topics:: Circuit Design Based On VHDL VHDL Basics Advanced VHDL Language Structures Circuit Examples
PDF
No ratings yet
Main Topics:: Circuit Design Based On VHDL VHDL Basics Advanced VHDL Language Structures Circuit Examples
33 pages
Main Topics:: Circuit Design Based On VHDL VHDL Basics Advanced VHDL Language Structures Circuit Examples
PDF
No ratings yet
Main Topics:: Circuit Design Based On VHDL VHDL Basics Advanced VHDL Language Structures Circuit Examples
33 pages
DSD Using VHDL
PDF
100% (1)
DSD Using VHDL
54 pages
16ECU19 - VLSI Design and VHDL: Introduction and Basic Concept of VHDL Session I
PDF
No ratings yet
16ECU19 - VLSI Design and VHDL: Introduction and Basic Concept of VHDL Session I
42 pages
VHDL Logic Synthesis Approach PDF
PDF
No ratings yet
VHDL Logic Synthesis Approach PDF
175 pages
Unit 1 - Hardware Description Languages
PDF
No ratings yet
Unit 1 - Hardware Description Languages
24 pages
1 Intro
PDF
No ratings yet
1 Intro
33 pages
VHDL
PDF
No ratings yet
VHDL
94 pages
Understanding HDL and VHDL Basics
PDF
No ratings yet
Understanding HDL and VHDL Basics
36 pages
Lesson 15 VHDL
PDF
No ratings yet
Lesson 15 VHDL
37 pages
Introduction To VHDL Programming
PDF
No ratings yet
Introduction To VHDL Programming
68 pages
VHDL Introduction for Digital Systems
PDF
No ratings yet
VHDL Introduction for Digital Systems
15 pages
Understanding VHDL in VLSI Design
PDF
No ratings yet
Understanding VHDL in VLSI Design
22 pages
VHDL Programming Overview
PDF
No ratings yet
VHDL Programming Overview
71 pages
Lecture 4
PDF
No ratings yet
Lecture 4
4 pages
VHDL Lectures
PDF
No ratings yet
VHDL Lectures
676 pages
VHDL Basics and Design Overview
PDF
No ratings yet
VHDL Basics and Design Overview
19 pages
VHDL 160909
PDF
No ratings yet
VHDL 160909
69 pages
VLSI System Design & Modeling Technique
PDF
No ratings yet
VLSI System Design & Modeling Technique
46 pages
CME 4456 Reconfigurable Computing: Şerife YILMAZ
PDF
No ratings yet
CME 4456 Reconfigurable Computing: Şerife YILMAZ
72 pages
Summer Training VHDL
PDF
No ratings yet
Summer Training VHDL
38 pages
Lecture 2-Intro VHDL
PDF
No ratings yet
Lecture 2-Intro VHDL
43 pages
Lesson 1.1 Introduction To HDL
PDF
No ratings yet
Lesson 1.1 Introduction To HDL
23 pages
675DF
PDF
No ratings yet
675DF
7 pages
VHDL Components and Tools Overview
PDF
No ratings yet
VHDL Components and Tools Overview
50 pages
VHDL Training Report
PDF
63% (8)
VHDL Training Report
25 pages
VHDL Information
PDF
100% (1)
VHDL Information
21 pages
Free Range VHDL 2023 1
PDF
No ratings yet
Free Range VHDL 2023 1
206 pages
Intro To VHDL
PDF
No ratings yet
Intro To VHDL
31 pages
History of VHDL Development
PDF
No ratings yet
History of VHDL Development
17 pages
1 VHDL
PDF
No ratings yet
1 VHDL
69 pages
VHDL Basics: Digital System Design Guide
PDF
No ratings yet
VHDL Basics: Digital System Design Guide
26 pages
VHDL PDF
PDF
No ratings yet
VHDL PDF
112 pages
Chapter 1
PDF
No ratings yet
Chapter 1
38 pages
Digital Design Using HDL Unit 2 Lecture 3 With Q and A
PDF
No ratings yet
Digital Design Using HDL Unit 2 Lecture 3 With Q and A
32 pages
VHDL: A Comprehensive Overview
PDF
No ratings yet
VHDL: A Comprehensive Overview
7 pages
VHDL Guide for Hardware Engineers
PDF
No ratings yet
VHDL Guide for Hardware Engineers
10 pages
VHDL Programming and Digital Design Guide
PDF
No ratings yet
VHDL Programming and Digital Design Guide
39 pages
Pedroni 2010 - Capítulo 1
PDF
No ratings yet
Pedroni 2010 - Capítulo 1
8 pages
Lecture 5 VHDL
PDF
No ratings yet
Lecture 5 VHDL
29 pages
Introduction to Hardware Description Languages
PDF
No ratings yet
Introduction to Hardware Description Languages
10 pages
Ece IV Fundamentalsofhdl10ec45 Notes 150103114952 Conversion Gate02
PDF
No ratings yet
Ece IV Fundamentalsofhdl10ec45 Notes 150103114952 Conversion Gate02
288 pages
Hardware Description Language
PDF
No ratings yet
Hardware Description Language
23 pages
64-Bit ALU Design Using VHDL
PDF
No ratings yet
64-Bit ALU Design Using VHDL
59 pages
RT-Linux Audio Player Control
PDF
No ratings yet
RT-Linux Audio Player Control
21 pages
Software Engineering by Abraham
PDF
No ratings yet
Software Engineering by Abraham
55 pages
Logic DesignCh05
PDF
100% (1)
Logic DesignCh05
92 pages
Electronics System Design Using FPGA
PDF
No ratings yet
Electronics System Design Using FPGA
15 pages
Block Diagram Reduction Techniques
PDF
No ratings yet
Block Diagram Reduction Techniques
47 pages
Comparison of VHDL Verilog and SystemVerilog
PDF
No ratings yet
Comparison of VHDL Verilog and SystemVerilog
7 pages
Energy Effi Cient Embedded Video Processing Systems: Muhammad Usman Karim Khan Muhammad Shafi Que Jörg Henkel
PDF
No ratings yet
Energy Effi Cient Embedded Video Processing Systems: Muhammad Usman Karim Khan Muhammad Shafi Que Jörg Henkel
242 pages
DSP Arithmetic for Academics
PDF
No ratings yet
DSP Arithmetic for Academics
96 pages
FSM Slides
PDF
0% (1)
FSM Slides
37 pages
Ug1137 Zynq Ultrascale Mpsoc Swdev
PDF
No ratings yet
Ug1137 Zynq Ultrascale Mpsoc Swdev
620 pages
Oslib RM
PDF
No ratings yet
Oslib RM
346 pages
t34010 User Guide
PDF
No ratings yet
t34010 User Guide
565 pages
1.02 Google HC30.Google - jasonRedgrave.V01
PDF
No ratings yet
1.02 Google HC30.Google - jasonRedgrave.V01
18 pages