ASIC Va VHDL Toan Tap
ASIC Va VHDL Toan Tap
VHDL
10
Key terms and concepts: syntax and semantics identifiers (names) entity and architecture package and library interface (ports) types sequential statements operators arithmetic concurrent statements execution configuration and specification History: U.S. Department of Defense (DoD) VHDL (VHSIC hardware description language) VHSIC (very high-speed IC) program Institute of Electrical and Electronics Engineers (IEEE) IEEE Standard 1076-1987 and 1076-1993 MIL-STD-454 Language Reference Manual (LRM)
10.1 A Counter
Key terms and concepts: VHDL keywords parallel programming language VHDL is a hardware description language analysis (the VHDL word for compiled) logic description, simulation, and synthesis
entity Counter_1 is end; -- declare a "black box" called Counter_1 library STD; use STD.TEXTIO.all; -- we need this library to print architecture Behave_1 of Counter_1 is -- describe the "black box" -- declare a signal for the clock, type BIT, initial value '0' signal Clock : BIT := '0'; -- declare a signal for the count, type INTEGER, initial value 0 signal Count : INTEGER := 0; begin process begin -- process to generate the clock wait for 10 ns; -- a delay of 10 ns is half the clock cycle Clock <= not Clock; if (now > 340 ns) then wait; end if; -- stop after 340 ns end process; -- process to do the counting, runs concurrently with other processes process begin -- wait here until the clock goes from 1 to 0 wait until (Clock = '0'); -- now handle the counting
1
SECTION 10
VHDL
if (Count = 7) then Count <= 0; else Count <= Count + 1; end if; end process; process (Count) variable L: LINE; begin -- process to print write(L, now); write(L, STRING'(" Count=")); write(L, Count); writeline(output, L); end process; end;
> vlib work > vcom Counter_1.vhd Model Technology VCOM V-System VHDL/Verilog 4.5b -- Loading package standard -- Compiling entity counter_1 -- Loading package textio -- Compiling architecture behave_1 of counter_1 > vsim -c counter_1 # Loading /../std.standard # Loading /../std.textio(body) # Loading work.counter_1(behave_1) VSIM 1> run 500 # 0 ns Count=0 # 20 ns Count=1 (...15 lines omitted...) # 340 ns Count=1 VSIM 2> quit >
Cout A(7) B(7) A(6) B(6) A(5) B(5) A(4) B(4) A(3) B(3) A(2) B(2) A(1) B(1) A(0) B(0) + + + + + + + + Cin Cout + 8 + Cin Sum Sum(7) Sum(6) Sum(5) Sum(4) Sum(3) Sum(2) Sum(1) Sum(0)
A B
8 8
SECTION 10
VHDL
D CLK
Q QN CLR
An 8-bit register
entity Register8 is port (D : in BIT_VECTOR(7 downto 0); Clk, Clr: in BIT ; Q : out BIT_VECTOR(7 downto 0)); end; architecture Structure of Register8 is component DFFClr port (Clr, Clk, D : in BIT; Q, QB : out BIT); end component; begin STAGES: for i in 7 downto 0 generate FF: DFFClr port map (Clr, Clk, D(i), Q(i), open); end generate; end;
D 8 Clk
Q 8 Clr
An 8-bit multiplexer
entity Mux8 is generic (TPD : TIME := 1 ns); port (A, B : in BIT_VECTOR (7 downto 0); Sel : in BIT := '0'; Y : out BIT_VECTOR (7 downto 0)); end; architecture Behave of Mux8 is begin Y <= A after TPD when Sel = '1' else B after TPD; end;
A 8 8 Sel Y 8
1 B0
Eight 2:1 MUXs with single select input. Timing: TPD(input to Y)=1ns
n X =0 F
SECTION 10
VHDL
n D LD SH DIR CLK
m Q
CLR
Clock Clear, active high Load, active high Shift, active high Direction, 1 = left Data in Data out
Variable-width shift register. Input width must be less than output width. Output is left-shifted or right-shifted under control of DIR. Unused MSBs are zero-padded during load. Clear is asynchronous. Loadis synchronous.
Timing: TCQ (CLR to Q) = 0.3ns TLQ (LD to Q) = 0.5ns TSQ (SH to Q) = 0. 7ns
S Shift=1
A Add=1 1
I Init=1
LSB=1 C
Start=1 LSB/Stop= 00 01 1
Reset
E Done=1 Start=0
others
SECTION 10
VHDL
Start A Init Shift '0' CLK D 4 LD SH DIR CLK ShiftN SR1 B Init Shift '1' D 4 LD SH DIR CLK ShiftN SR2 Reset Q 8 SRA 8 AllZero SRA(0) CLR Reset Z1 X F =0 F
F1 Start Stop LSB CLK Clk SM_1 Reset Shift Add Init Done Reset Shift Add Init
Mult8
Done
OFL(not used) A1 Adder8 Add R1 Cout 8 Q SRB A Register8 + 8 ADDout A Sel 8 1 Y MUXout 8 8 DQ B B + Sum 0 CLK Clk Cin Mux8 CLR Clr M1 '0' Reset REGclr = Reset or Init REGout
Result 8
entity Mult8 is port (A, B: in BIT_VECTOR(3 downto 0); Start, CLK, Reset: in BIT; Result: out BIT_VECTOR(7 downto 0); Done: out BIT); end Mult8; architecture Structure of Mult8 is use work.Mult_Components.all; signal SRA, SRB, ADDout, MUXout, REGout: BIT_VECTOR(7 downto 0); signal Zero,Init,Shift,Add,Low:BIT := '0'; signal High:BIT := '1'; signal F, OFL, REGclr: BIT; begin REGclr <= Init or Reset; Result <= REGout; SR1 : ShiftN port map (CLK=>CLK,CLR=>Reset,LD=>Init,SH=>Shift,DIR=>Low ,D=>A,Q=>SRA); SR2 : ShiftN port map (CLK=>CLK,CLR=>Reset,LD=>Init,SH=>Shift,DIR=>High,D=>B,Q=>SRB); Z1 : AllZero port map (X=>SRA,F=>Zero); A1 : Adder8 port map (A=>SRB,B=>REGout,Cin=>Low,Cout=>OFL,Sum=>ADDout); M1 : Mux8 port map (A=>ADDout,B=>REGout,Sel=>Add,Y=>MUXout); R1 : Register8 port map (D=>MUXout,Q=>REGout,Clk=>CLK,Clr=>REGclr); F1 : SM_1 port map (Start,CLK,SRA(0),Zero,Reset,Init,Shift,Add,Done); end;
10.2.7 Packages and Testbench package Mult_Components is component Mux8 port (A,B:BIT_VECTOR(7 downto 0); Sel:BIT;Y: out BIT_VECTOR(7 downto 0));end component; component AllZero port (X : BIT_VECTOR; F:out BIT );end component; component Adder8 port (A,B:BIT_VECTOR(7 downto 0);Cin:BIT; Cout:out BIT;Sum:out BIT_VECTOR(7 downto 0));end component ; component Register8 port (D:BIT_VECTOR(7 downto 0); Clk,Clr:BIT; Q: out BIT_VECTOR(7 downto 0));end component; component ShiftN port (CLK,CLR,LD,SH,DIR:BIT;D:BIT_VECTOR; Q:out BIT_VECTOR); end component; component SM_1 port (Start,CLK,LSB,Stop,Reset:BIT; Init,Shift,Add,Done: out BIT);end component; end; Utility code to help test the multiplier: package Clock_Utils is procedure Clock (signal C: out Bit; HT, LT:TIME); end Clock_Utils; package body Clock_Utils is procedure Clock (signal C: out Bit; HT, LT:TIME) is begin loop C<='1' after LT, '0' after LT + HT; wait for LT + HT; end loop; end; end Clock_Utils; Two functions for testingto convert an array of bits to a number and vice versa: package Utils is function Convert (N,L: NATURAL) return BIT_VECTOR; function Convert (B: BIT_VECTOR) return NATURAL; end Utils; package body Utils is function Convert (N,L: NATURAL) return BIT_VECTOR is variable T:BIT_VECTOR(L-1 downto 0); variable V:NATURAL:= N; begin for i in T'RIGHT to T'LEFT loop T(i) := BIT'VAL(V mod 2); V:= V/2; end loop; return T; end; function Convert (B: BIT_VECTOR) return NATURAL is variable T:BIT_VECTOR(B'LENGTH-1 downto 0) := B; --1 --2 --3 --4 --5 --6 --7 --8 --9 --10 --11 --12 --13 --14 --1 --2 --3 --4 --5 --6 --7 --8 --9 --10 --1 --2 --3 --4 --5 --6 --7 --8 --9 --10 --11 --12 --13 --14
10
SECTION 10
VHDL
variable V:NATURAL:= 0; begin for i in T'RIGHT to T'LEFT loop if T(i) = '1' then V:= V + (2**i); end if; end loop; return V; end; end Utils; The following testbench exercises the multiplier model: entity Test_Mult8_1 is end; -- runs forever, use break!! architecture Structure of Test_Mult8_1 is use Work.Utils.all; use Work.Clock_Utils. all; component Mult8 port (A, B : BIT_VECTOR(3 downto 0); Start, CLK, Reset : BIT; Result : out BIT_VECTOR(7 downto 0); Done : out BIT); end component; signal A, B : BIT_VECTOR(3 downto 0); signal Start, Done : BIT := '0'; signal CLK, Reset : BIT; signal Result : BIT_VECTOR(7 downto 0); signal DA, DB, DR : INTEGER range 0 to 255; begin C: Clock(CLK, 10 ns, 10 ns); UUT: Mult8 port map (A, B, Start, CLK, Reset, Result, Done); DR <= Convert(Result); Reset <= '1', '0' after 1 ns; process begin for i in 1 to 3 loop for j in 4 to 7 loop DA <= i; DB <= j; A<=Convert(i,A'Length);B<=Convert(j,B'Length); wait until CLK'EVENT and CLK='1'; wait for 1 ns; Start <= '1', '0' after 20 ns; wait until Done = '1'; wait until CLK'EVENT and CLK='1'; end loop; end loop; for i in 0 to 1 loop for j in 0 to 15 loop DA <= i; DB <= j; A<=Convert(i,A'Length);B<=Convert(j,B'Length); wait until CLK'EVENT and CLK='1'; wait for 1 ns; Start <= '1', '0' after 20 ns; wait until Done = '1'; wait until CLK'EVENT and CLK='1'; end loop; end loop; wait; end process; end;
--1 --2 --3 --4 --5 --6 --7 --8 --9 --10 --11 --12 --13 --14 --15 --16 --17 --18 --19 --20 --21 --22 --23 --24 --25 --26 --27 --28 --29 --30 --31 --32 --33 --34 --35
11
subject verb object. The|A noun [article] noun {, and article noun} the|a man|shark|house|food eats|paints
::= | [] {}
"can be replaced by" "or" "contents optional" "contents can be left out, used once, or repeated"
The following two sentences are correct according to the syntax rules:
A shark eats food. The house paints the shark, and the house, and a man.
Semantic rules tell us that the second sentence does not make much sense.
12
SECTION 10
VHDL
s -- A simple name. S -- A simple name, the same as s. VHDL is notcase sensitive. a_name -- Imbedded underscores are OK. -- Successive underscores are illegal in names: Ill__egal -- Names can't start with underscore: _Illegal -- Names can't end with underscore: Illegal_ Too_Good -- Names must start with a letter. -- Names can't start with a number: 2_Bad \74LS00\ -- Extended identifier to break rules (VHDL-93 only). VHDL \vhdl\ \VHDL\ -- Three different names (VHDL-93 only). s_array(0) -- A static indexed name (known at analysis time). s_array(i) -- A non-static indexed name, if i is a variable.
entity Literals_1 is end; architecture Behave of Literals_1 is begin process variable I1 : integer; variable Rl : real; variable C1 : CHARACTER; variable S16 : STRING(1 to 16); variable BV4: BIT_VECTOR(0 to 3); variable BV12 : BIT_VECTOR(0 to 11); variable BV16 : BIT_VECTOR(0 to 15); begin -- Abstract literals are decimal or based literals. -- Decimal literals are integer or real literals. -- Integer literal examples (each of these is the same): I1 := 120000; Int := 12e4; Int := 120_000; -- Based literal examples (each of these is the same): I1 := 2#1111_1111#; I1 := 16#FFFF#; -- Base must be an integer from 2 to 16: I1 := 16:FFFF:; -- you may use a : if you don't have #
13
-- Real literal examples (each of these is the same): Rl := 120000.0; Rl := 1.2e5; Rl := 12.0E4; -- Character literal must be one of the 191 graphic characters. -- 65 of the 256 ISO Latin-1 set are non-printing control characters C1 := 'A'; C1 := 'a'; -- different from each other -- String literal examples: S16 := " string" & " literal"; -- concatenate long strings S16 := """Hello,"" I said!"; -- doubled quotes S16 := % string literal%; -- can use % instead of " S16 := %Sale: 50%% off!!!%; -- doubled % -- Bit-string literal examples: BV4 := B"1100"; -- binary bit-string literal BV12 := O"7777"; -- octal bit-string literal BV16 := X"FFFF"; -- hex bit-string literal wait; end process; -- the wait prevents an endless loop end;
14
SECTION 10
VHDL
entity_declaration ::= entity identifier is [generic (formal_generic _interface_list);] [port (formal_port_interface_list);] {entity_declarative_item} [begin {[label:] [postponed] assertion ; |[label:] [postponed] passive_procedure_call ; |passive_process_statement}] end [entity] [entity_identifier] ;
entity Half_Adder is port (X, Y : in BIT := '0'; Sum, Cout : out BIT); -- formals end;
architecture_body ::= architecture identifier of entity_name is {block_declarative_item} begin {concurrent_statement} end [architecture] [architecture_identifier] ;
architecture Behave of Half_Adder is begin Sum <= X xor Y; Cout <= X and Y; end Behave;
Components:
component_declaration ::= component identifier [is] [generic (local_generic _interface_list);] [port (local_port_interface_list);] end component [component_identifier];
architecture Netlist of Half_Adder is component MyXor port (A_Xor,B_Xor : in BIT; Z_Xor : out BIT); end component; -- component with locals component MyAnd port (A_And,B_And : in BIT; Z_And : out BIT); end component; -- component with locals
15
begin Xor1: MyXor port map (X, Y, Sum); And1 : MyAnd port map (X, Y, Cout); end;
These design entities (entityarchitecture pairs) would be part of a technology library: entity AndGate is port (And_in_1, And_in_2 : in BIT; And_out : out BIT); -- formals end;
architecture Simple of AndGate is begin And_out <= And_in_1 and And_in_2; end;
entity XorGate is port (Xor_in_1, Xor_in_2 : in BIT; Xor_out : out BIT); -- formals end;
architecture Simple of XorGate is begin Xor_out <= Xor_in_1 xor Xor_in_2; end;
configuration_declaration ::= configuration identifier of entity_name is {use_clause|attribute_specificationgroup_declaration} | block_configuration end [configuration [configuration ] _identifier] ;
configuration Simplest of Half_Adder is use work.all; for Netlist for And1 : MyAnd use entity AndGate(Simple) port map -- association: formals => locals (And_in_1 => A_And, And_in_2 => B_And, And_out => Z_And); end for; for Xor1 : MyXor use entity XorGate(Simple) port map (Xor_in_1 => A_Xor, Xor_in_2 => B_Xor, Xor_out => Z_Xor);
16
SECTION 10
VHDL
And1 Xor1
A Cout A Sum
Xor1: MyXor port map (X, Y, Sum); F formal L local component A_Xor B_Xor L L MyXor port (A_Xor,B_Xor : in BIT; Z_Xor : out BIT) for Xor1:MyXor use entity XorGate(Simple) port map (Xor_in_1 => A_Xor, Xor_in_2 => B_Xor, Xor_out => Z_Xor); configuration Simplest of Half_Adder Xor_in_1 F Xor_in_2 F entity XorGate architecture Simple of XorGate F Xor_out L Z_Xor
17
package_declaration ::= package identifier is {subprogram_declaration | type_declaration | subtype_declaration | constant_declaration | signal_declaration | file_declaration | alias_declaration | component_declaration | attribute_declaration | attribute_specification | disconnection_specification | use_clause | shared_variable_declaration | group _declaration | group_template_declaration} end [package] [package_identifier] ;
package_body ::= package body package_identifier is {subprogram_declaration | subprogram_body | type_declaration | subtype_declaration | constant_declaration | file_declaration | alias_declaration | use_clause | shared_variable_declaration | group _declaration | group_template_declaration} end [package body] [package_identifier] ;
library MyLib; -- library clause use MyLib.MyPackage. all; -- use clause -- design unit (entity + architecture, etc.) follows:
10.6.1 Standard Package Key terms: STANDARD package (defined in the LRM ) TIME INTEGER REAL STRING CHARACTER I use uppercase for standard types ISO 646-1983 ASCII character set character codes graphic symbol (glyph) ISO 8859-1:1987(E) ISO Latin-1
package Part_STANDARD is type BOOLEAN is (FALSE, TRUE); type BIT is ('0', '1');
18
SECTION 10
VHDL
type SEVERITY_LEVEL is (NOTE, WARNING, ERROR, FAILURE); subtype NATURAL is INTEGER range 0 to INTEGER'HIGH; subtype POSITIVE is INTEGER range 1 to INTEGER'HIGH; type BIT_VECTOR is array (NATURAL range <>) of BIT; type STRING is array (POSITIVE range <>) of CHARACTER; -- the following declarations are VHDL-93 only: attribute FOREIGN: STRING; -- for links to other languages subtype DELAY_LENGTH is TIME range 0 fs to TIME'HIGH; type FILE_OPEN_KIND is (READ_MODE,WRITE_MODE,APPEND_MODE); type FILE_OPEN_STATUS is (OPEN_OK,STATUS_ERROR, NAME_ERROR,MODE_ERROR); end Part_STANDARD;
type TIME is range implementation_defined -- and varies with software 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;
type NUL, BS, DLE, CAN, ' ', '(', '0', '8', '@', 'H', 'P', 'X', '`', 'h', 'p', 'x',
Part_CHARACTER SOH, STX, ETX, HT, LF, VT, DC1, DC2, DC3, EM, SUB, ESC, '!', '"', '#', ')', '*', '+', '1', '2', '3', '9', ':', ';', 'A', 'B', 'C', 'I', 'J', 'K', 'Q', 'R', 'S', 'Y', 'Z', '[', 'a', 'b', 'c', 'i', 'j', 'k', 'q', 'r', 's', 'y', 'z', '{',
is ( EOT, FF, DC4, FSP, '$', ',', '4', '<', 'D', 'L', 'T', '\', 'd', 'l', 't', '|',
-- 128 ASCII characters in VHDL-87 ENQ, ACK, BEL, -- 33 control characters CR, SO, SI, -- including: NAK, SYN, ETB, -- format effectors: GSP, RSP, USP, -- horizontal tab = HT '%', '&', ''', -- line feed = LF '-', '.', '/', -- vertical tab = VT '5', '6', '7', -- form feed = FF '=', '>', '?', -- carriage return = CR 'E', 'F', 'G', -- and others: 'M', 'N', 'O', -- FSP, GSP, RSP, USP use P 'U', 'V', 'W', -- suffix to avoid conflict ']', '^', '_', -- with TIME units 'e', 'f', 'g', 'm', 'n', 'o', 'u', 'v', 'w', '}', '~', DEL -- delete = DEL
-- VHDL-93 includes 96 more Latin-1 characters, like (Yen) and -- 32 more control characters, better not to use any of them. );
19
10.6.2 Std_logic_1164 Package Key terms: logic-value system BIT '0' and '1' 'X' (unknown) 'Z' (high-impedance) metalogical value (simbits) Std_logic_1164 package MVL9multivalued logic nine driver resolve resolution function resolved subtype STD_LOGIC unresolved type STD_ULOGIC subtypes are compatible with types overloading STD_LOGIC_VECTOR
STD_ULOGIC_VECTOR dont care logic value '-' (hyphen) type MVL4 is ('X', '0', '1', 'Z'); -- example of a four-value logic system library IEEE; use IEEE.std_logic_1164. all; -- to use the IEEE package package Part_STD_LOGIC_1164 is type STD_ULOGIC is ( 'U', -- Uninitialized 'X', -- Forcing Unknown '0', -- Forcing 0 '1', -- Forcing 1 'Z', -- High Impedance 'W', -- Weak Unknown 'L', -- Weak 0 'H', -- Weak 1 '-' -- Don't Care); type STD_ULOGIC_VECTOR is array (NATURAL range <>) of STD_ULOGIC; function resolved (s : STD_ULOGIC_VECTOR) return STD_ULOGIC; subtype STD_LOGIC is resolved STD_ULOGIC; type STD_LOGIC_VECTOR is array (NATURAL range <>) of STD_LOGIC; subtype X01 is resolved STD_ULOGIC range 'X' to '1'; subtype X01Z is resolved STD_ULOGIC range 'X' to 'Z'; subtype UX01 is resolved STD_ULOGIC range 'U' to '1'; subtype UX01Z is resolved STD_ULOGIC range 'U' to 'Z'; --1 --2 --3 --4 --5 --6 --7 --8 --9 --10 --11 --12 --13 --14 --15 --16 --17 --18 --19
-- Vectorized overloaded logical operators: --20 function "and" (L : STD_ULOGIC; R : STD_ULOGIC)return UX01; --21 -- Logical operators not, and, nand, or, nor, xor, xnor (VHDL-93), --22 -- overloaded for STD_ULOGIC STD_ULOGIC_VECTOR STD_LOGIC_VECTOR. --23 -----Strength strippers and type conversion functions: function To_T (X : F) return T; defined for types, T and F, where F=BIT BIT_VECTOR STD_ULOGIC STD_ULOGIC_VECTOR STD_LOGIC_VECTOR T=types F plus types X01 X01Z UX01 (but not type UX01Z) --24 --25 --26 --27 --28 --29 --30
-- Exclude _'s in T in name: TO_STDULOGIC not TO_STD_ULOGIC -- To_XO1 : L->0, H->1 others->X
20
SECTION 10
VHDL
-- To_XO1Z: Z->Z, others as To_X01 -- To_UX01: U->U, others as To_X01 -- Edge detection functions: function rising_edge (signal s: STD_ULOGIC) return BOOLEAN; function falling_edge ( signal s: STD_ULOGIC) return BOOLEAN;
-- Unknown detection (returns true if s = U, X, Z, W): --36 -- function Is_X (s : T) return BOOLEAN; --37 -- defined for T = STD_ULOGIC STD_ULOGIC_VECTOR STD_LOGIC_VECTOR. --38 end Part_STD_LOGIC_1164; 10.6.3 Textio Package package Part_TEXTIO is -- VHDL-93 version. type LINE is access STRING; -- LINE is a pointer to a STRING value. type TEXT is file of STRING; -- File of ASCII records. type SIDE is (RIGHT, LEFT); -- for justifying output data. subtype WIDTH is NATURAL; -- for specifying widths of output fields. file INPUT : TEXT open READ_MODE is "STD_INPUT"; -- Default input file. file OUTPUT : TEXT open WRITE_MODE is "STD_OUTPUT"; -- Default output. --39
-- The following procedures are defined for types, T, where -- T = BIT BIT_VECTOR BOOLEAN CHARACTER INTEGER REAL TIME STRING -procedure READLINE(file F : TEXT; L : out LINE); -procedure READ(L : inout LINE; VALUE : out T); -procedure READ(L : inout LINE; VALUE : out T; GOOD: out BOOLEAN); -procedure WRITELINE(F : out TEXT; L : inout LINE); -procedure WRITE( -L : inout LINE; -VALUE : in T; -JUSTIFIED : in SIDE:= RIGHT; -FIELD:in WIDTH := 0; -DIGITS:in NATURAL := 0; -- for T = REAL only
21
-UNIT:in TIME:= ns); -- for T = TIME only -- function ENDFILE(F : in TEXT) return BOOLEAN;
end Part_TEXTIO;
Example:
library std; use std.textio.all; entity Text is end; architecture Behave of Text is signal count : INTEGER := 0; begin count <= 1 after 10 ns, 2 after 20 ns, 3 after 30 ns; process (count) variable L: LINE; begin if (count > 0) then write(L, now); -- Write time. write(L, STRING'(" count=")); -- STRING' is a type qualification. write(L, count); writeline(output, L); end if; end process; end;
10.6.4 Other Packages Key terms: arithmetic packages Synopsys std_arith (mis)use of IEEE library math packages [IEEE 1076.2, 1996] synthesis packages component packages 10.6.5 Creating Packages Key terms: packaged constants linking the VHDL world and the real world
package Adder_Pkg is -- a package declaration constant BUSWIDTH : INTEGER := 16; end Adder_Pkg;
use work.Adder_Pkg. all; -- a use clause entity Adder is end Adder; architecture Flexible of Adder is -- work.Adder_Pkg is visible here begin process begin
22
SECTION 10
VHDL
MyLoop : for j in 0 to BUSWIDTH loop -- adder code goes here end loop; wait; -- the wait prevents an endless cycle end process; end Flexible;
package GLOBALS is constant HI : BIT := '1'; constant LO: BIT := '0'; end GLOBALS;
library MyLib; -- use MyLib.Add_Pkg.all; -- use all the package use MyLib.Add_Pkg_Fn.add; -- just function 'add' from the package
entity Lib_1 is port (s : out BIT_VECTOR(3 downto 0) := "0000"); end; architecture Behave of Lib_1 is begin process begin s <= add ("0001", "0010", "1000");wait; end process; end;
There are three common methods to create the links between the le and directory names: Use a UNIX environment variable (SETENV MyLib ~/MyDirectory/MyLibFilefor , example). Create a separate le that establishes the links between the lename known to the operating system and the library name known to the VHDL software. Include the links in an initialization le (often with an '.ini' sufx).
23
Possible modes of interface object, Outside Can you read Outside (RHS of assignment)? Can you update Outside (LHS of assignment)? Modes of Inside that Outside may connect to (see below)
in (default) Yes No in
E2 7
in 7 9 buffer 10 8
out 6
inout
means "legal to associate interface object (Outside) of mode X with formal (Inside) of mode Y"
24
SECTION 10
VHDL
10.7.1 Port Declaration Key terms: ports (connectors) port interface declaration formals locals actuals implicit signal declaration port mode signal kind default value default expression open port map positional association named association default binding Properties of ports Example entity declaration:
entity E is port (F_1:BIT; F_2:out BIT; F_3:inout BIT; F_4:buffer BIT); end; formals --
Example conguration:
for I1 : C use entity E(Behave) port map (F_1 => L_1,F_2 => L_2,F_3 => L_3,F_4 => L_4); -- formals => locals
Interface object, port F Mode of F Can you read attributes of F? [VHDL LRM4.3.2]
F_1 in (default) Yes, but not the attributes: 'STABLE 'QUIET 'DELAYED 'TRANSACTION
F_2 out Yes, but not the attributes: 'STABLE 'QUIET 'DELAYED 'TRANSACTION 'EVENT 'ACTIVE 'LAST_EVENT 'LAST_ACTIVE 'LAST_VALUE
F_3 inout Yes, but not the attributes: 'STABLE 'QUIET 'DELAYED 'TRANSACTION
25
Possible modes of interface object, Inside Modes of Outside that Inside may connect to (see below)
inout inout1
buffer buffer2
E2 7
in mode Y F Inside
E1
1 5 3
in 7
out 6 inout
ports
F formal A actual X Y
buffer
means "legal to associate formal port (Inside) of mode Y with actual port (Outside) of mode X"
1A 2A
signal of mode inout can be updated by any number of sources. signal of mode buffer can be updated by at most one source.
port (port_interface_list)
interface_declaration ::= [signal] identifier {, identifier}:[ n|out|inout|buffer|linkage] i subtype_indication [ bus] [:= static_expression]
entity Association_1 is port (signal X, Y : in BIT := '0'; Z1, Z2, Z3 : out BIT); end;
26
SECTION 10
VHDL
use work.all; -- makes analyzed design entity AndGate(Simple) visible. architecture Netlist of Association_1 is -- The formal port clause for entity AndGate looks like this: -- port (And_in_1, And_in_2: in BIT; And_out : out BIT); -- Formals. component AndGate port (And_in_1, And_in_2 : in BIT; And_out : out BIT); -- Locals. end component; begin -- The component and entity have the same names: AndGate. -- The port names are also the same: And_in_1, And_in_2, And_out, -- so we can use default binding without a configuration. -- The last (and only) architecture for AndGate will be used: Simple. A1:AndGate port map (X, Y, Z1); -- positional association A2:AndGate port map (And_in_2=>Y, And_out=>Z2, And_in_1=>X);-- named A3:AndGate port map (X, And_out => Z3, And_in_2 => Y);-- both end;
entity ClockGen_1 is port (Clock : out BIT); end; architecture Behave of ClockGen_1 is begin process variable Temp : BIT := '1'; begin -- Clock <= not Clock; -- Illegal, you cannot read Clock (mode out), Temp := not Temp; -- use a temporary variable instead. Clock <= Temp after 10 ns; wait for 10 ns; if (now > 100 ns) then wait; end if; end process; end;
10.7.2 Generics Key terms: generic (similar to a port) ports (signals) carry changing information between entities generics carry constant, static information generic interface list
entity AndT is generic (TPD : TIME := 1 ns); port (a, b : BIT := '0'; q: out BIT); end; architecture Behave of AndT is begin q <= a and b after TPD; end;
27
entity AndT_Test_1 is end; architecture Netlist_1 of AndT_Test_1 is component MyAnd port (a, b : BIT; q : out BIT); end component; signal a1, b1, q1 : BIT := '1'; begin And1 : MyAnd port map (a1, b1, q1); end Netlist_1;
configuration Simplest_1 of AndT_Test_1 is use work.all; for Netlist_1 for And1 : MyAnd use entity AndT(Behave) generic map (2 ns); end for; end for; end Simplest_1;
28
SECTION 10
VHDL
type_declaration ::= type identifier ; | type identifier is (identifier|'graphic_character' {, identifier|'graphic_character'}) ; | range_constraint ; | physical_type_definition ; | record_type_definition ; | access subtype_indication ; | file of type_name ; | file of subtype_name ; | array index_constraint of element_subtype_indication ; | array (type_name|subtype_name range <> {, type_name|subtype_name range <>}) of element_subtype_indication ;
entity Declaration_1 is end; architecture Behave of Declaration_1 is type F is range 32 to 212; -- Integer type, ascending range. type C is range 0 to 100; -- Range 0 to 100 is the range constraint. subtype G is INTEGER range 9 to 0; -- Base type INTEGER, descending. -- This is illegal: type Bad100 is INTEGER range 0 to 100; -- don't use INTEGER in declaration of type (but OK in subtype). type Rainbow is (R, O, Y, G, B, I, V); -- An enumeration type. -- Enumeration types always have an ascending range. type MVL4 is ('X', '0', '1', 'Z');
29
-- Note that 'X' and 'x' are different character literals. -- The default initial value is MVL4'LEFT = 'X'. -- We say '0' and '1' (already enumeration literals -- for predefined type BIT) are overloaded. -- Illegal enumeration type: type Bad4 is ("X", "0", "1", "Z"); -- Enumeration literals must be character literals or identifiers. begin end;
entity Arrays_1 is end; architecture Behave of Arrays_1 is type Word is array (0 to 31) of BIT; -- a 32-bit array, ascending type Byte is array (NATURAL range 7 downto 0) of BIT; -- descending type BigBit is array (NATURAL range <>) of BIT; -- We call <> a box, it means the range is undefined for now. -- We call BigBit an unconstrained array. -- This is OK, we constrain the range of an object that uses -- type BigBit when we declare the object, like this: subtype Nibble is BigBit(3 downto 0); type T1 is array (POSITIVE range 1 to 32) of BIT; -- T1, a constrained array declaration, is equivalent to a type T2 -- with the following three declarations: subtype index_subtype is POSITIVE range 1 to 32; type array_type is array (index_subtype range <>) of BIT; subtype T2 is array_type (index_subtype); -- We refer to index_subtype and array_type as being -- anonymous subtypes of T1 (since they don't really exist). begin end;
entity Aggregate_1 is end; architecture Behave of Aggregate_1 is type D is array (0 to 3) of BIT; type Mask is array (1 to 2) of BIT; signal MyData : D := ('0', others => '1'); -- positional aggregate signal MyMask : Mask := (2 => '0', 1 => '1'); --named aggregate begin end;
entity Record_2 is end; architecture Behave of Record_2 is type Complex is record real : INTEGER; imag : INTEGER; end record; signal s1 : Complex := (0, others => 1); signal s2: Complex; begin s2 <= (imag => 2, real => 1); end;
30
SECTION 10
VHDL
declaration ::= type_declaration | subtype_declaration | object_declaration | interface_declaration | alias_declaration | attribute_declaration | component_declaration | entity_declaration | configuration_declaration | subprogram_declaration | package_declaration | group_template_declaration | group _declaration
10.9.1 Object Declarations Key terms and concepts: class of an object declarative region (before the first begin) declare a type with (explicit) initial value (implicit) default initial value is T'LEFT explicit signal declarations shared variable There are four object classes: constant, variable, signal, file You use a constant declaration, signal declaration, variable declaration, or file declaration together with a type Signals represent real wires in hardware Variables are memory locations in a computer
entity Initial_1 is end; architecture Behave of Initial_1 is type Fahrenheit is range 32 to 212; -- Default initial value is 32. type Rainbow is (R, O, Y, G, B, I, V); -- Default initial value is R. type MVL4 is ('X', '0', '1', 'Z'); -- MVL4'LEFT = 'X'. begin end;
31
entity Constant_2 is end; library IEEE; use IEEE.STD_LOGIC_1164. all; architecture Behave of Constant_2 is constant Pi : REAL := 3.14159; -- A constant declaration. signal B : BOOLEAN; signal s1, s2: BIT; signal sum : INTEGER range 0 to 15; -- Not a new type. signal SmallBus : BIT_VECTOR(15 downto 0); -- 16-bit bus. signal GBus : STD_LOGIC_VECTOR(31 downto 0) bus; -- A guarded signal. begin end;
library IEEE; use IEEE.STD_LOGIC_1164. all; entity Variables_1 is end; architecture Behave of Variables_1 is begin process variable i : INTEGER range 1 to 10 := 10; -- Initial value = 10. variable v : STD_LOGIC_VECTOR (0 to 31) := (others => '0'); begin wait; end process; -- The wait stops an endless cycle. end;
32
SECTION 10
VHDL
10.9.2 Subprogram Declarations Key terms and concepts: subprogram function procedure subprogram declaration: a function declaration or a procedure declaration formal parameters (or formals) subprogram invocation actual parameters (or actuals) impure function (now) pure function (default) subprogram specification subprogram body conform private Properties of subprogram parameters Example subprogram declarations:
function my_function(Ff) return BIT is -- Formal function parameter, Ff. procedure my_procedure(Fp); -- Formal procedure parameter, Fp.
Mode of Ff or Fp (formals) in Permissible classes for Af constant (default) (function actual parameter) signal Permissible classes for Ap constant (default) (procedure actual parameter) variable Can you read attributes of Ff or Fp (formals)? signal Yes, except:
'STABLE 'QUIET 'DELAYED 'TRANSACTION
No mode file
file
of a signal
of a signal
of a signal
33
function add(a, b, c : BIT_VECTOR(3 downto 0)) return BIT_VECTOR is -- A function declaration, a function can't modify a, b, or c.
procedure Is_A_Eq_B (signal A, B : BIT; signal Y : out BIT); -- A procedure declaration, a procedure can change Y.
subprogram_body ::= subprogram_specification is {subprogram_declaration|subprogram_body |type_declaration|subtype_declaration |constant_declaration|variable_declaration|file_declaration |alias_declaration|attribute_declaration|attribute_specification |use_clause |group_template_declaration|group _declaration} begin {sequential_statement} end [procedure|function] [identifier|string_literal] ;
function subset0(sout0 : in BIT) return BIT_VECTOR -- declaration -- Declaration can be separate from the body. function subset0(sout0 : in BIT) return BIT_VECTOR is -- body variable y : BIT_VECTOR(2 downto 0); begin if (sout0 = '0') then y := "000"; else y := "100"; end if; return result; end;
procedure clockGen (clk : out BIT) -- Declaration procedure clockGen (clk : out BIT) is -- Specification begin -- Careful this process runs forever: process begin wait for 10 ns; clk <= not clk; end process; end;
34
SECTION 10
VHDL
entity F_1 is port (s : out BIT_VECTOR(3 downto 0) := "0000"); end; architecture Behave of F_1 is begin process function add(a, b, c : BIT_VECTOR(3 downto 0)) return BIT_VECTOR is begin return a xor b xor c; end; begin s <= add("0001", "0010", "1000");wait; end process; end;
package And_Pkg is procedure V_And(a, b : BIT; signal c : out BIT); function V_And(a, b : BIT) return BIT; end;
package body And_Pkg is procedure V_And(a,b : BIT; signal c : out BIT) is begin c <= a and b; end; function V_And(a,b : BIT) return BIT is begin return a and b; end; end And_Pkg;
entity F_2 is port (s: out BIT := '0'); end; use work.And_Pkg. all; -- use package already analyzed architecture Behave of F_2 is begin process begin s <= V_And('1', '1'); wait; end process; end;
10.9.3 Alias and Attribute Declarations alias_declaration ::= alias identifier |character_literal|operator _symbol [ :subtype_indication ] is name [signature];
entity Alias_1 is end; architecture Behave of Alias_1 is begin process variable Nmbr: BIT_VECTOR (31 downto 0); -- alias declarations to split Nmbr into 3 pieces : alias Sign : BIT is Nmbr(31); alias Mantissa : BIT_VECTOR (23 downto 0) is Nmbr (30 downto 7); alias Exponent : BIT_VECTOR ( 6 downto 0) is Nmbr ( 6 downto 0); begin wait; end process; end; -- the wait prevents an endless cycle
35
entity Attribute_1 is end; architecture Behave of Attribute_1 is begin process type COORD is record X, Y : INTEGER; end record; attribute LOCATION : COORD; -- the attribute declaration begin wait ; -- the wait prevents an endless cycle end process; end;
You dene the attribute properties in an attribute specication: attribute LOCATION of adder1 : label is (10,15); positionOfComponent := adder1'LOCATION;
36
SECTION 10
VHDL
Result type3 base(S) BOOLEAN BOOLEAN BIT BOOLEAN BOOLEAN TIME TIME base(S) BOOLEAN base(S)
Result/restrictions S delayed by time T TRUE if no event on S for time T TRUE if S is quiet for time T Toggles each cycle if S becomes active TRUE when event occurs on S TRUE if S is active Elapsed time since the last event on S Elapsed time since S was active Previous value of S, before last event4 TRUE if every element of S is driven5 Value of the driver for S in the current process5
F=function, S=signal. T0 ns. The default, if T is not present, is T=0 ns. type of S.
2Time
3base(S)=base 4
VHDL-93 returns last value of each signal in array separately as an aggregate, VHDL-87 returns the last value of the composite signal. VHDL-93 only.
37
Kind
1
Prex T, A, E2 any scalar scalar scalar scalar scalar scalar scalar discrete discrete discrete discrete discrete discrete array array array array array array array array name name name
Parameter X or N3
Result base(T), use only with other attribute Left bound of T Right bound of T Upper bound of T Lower bound of T
T V V V V V F F F F F F F F F F F F R R V V V V V
BOOLEAN True if range of T is ascending5 base(T) STRING base(T) UI base(T) base(T) base(T) base(T) UI UI UI UI UI UI UI UI STRING String representation of X in T4 base(T) Value in T with representation X4 Position number of X in T (starts at UI 0) base(T) Value of position X in T base(T) Value of position X in T plus one base(T) Value of position X in T minus one base(T) Value to the left of X in T base(T) Value to the right of X in T T(Result) Left bound of index N of array A T(Result) Right bound of index N of array A T(Result) Upper bound of index N of array A T(Result) Lower bound of index N of array A T(Result) Range A'LEFT(N) to A'RIGHT(N)6 T(Result) Opposite range to A'RANGE[(N)] UI Number of values in index N of array A
BOOLEAN True if index N of A is ascending4 STRING Simple name of E4 STRING Path includes instantiated entities4 STRING Path excludes instantiated entities4
38
SECTION 10
VHDL
2any=any 3
type or subtype, scalar=scalar type or subtype, discrete=discrete or physical type or subtype, name=entity name=identier, character literal, or operator symbol. base(T)=base type of T, T=type of T, UI= universal_integer,T(Result)=type of object described in result column. type of T, T=type of T, UI= universal_integer,T(Result)=type of object described in result column. available in VHDL-93. For 'ASCENDING all enumeration types are ascending.
4base(T)=base
5Only 6Or
39
10.10.1 Wait Statement Key terms and concepts: suspending (stopping) a process or procedure sensitivity to events (changes) on static signals sensitivity clause contains sensitivity list after on process resumes at event on signal in the sensitivity set condition clause after until timeout (after for) wait on light makes you wait until a trafc light changes (any change) wait until light = green makes you wait (even at a green light) until the trafc signal changes to green if light = (red or yellow) then wait until light = green; end if; describes the basic rules at a trafc intersection
wait_statement ::= [label:] wait [sensitivity_clause] [condition_clause] [timeout_clause] ; sensitivity_clause ::= on sensitivity_list sensitivity_list ::= signal_name { , signal_name } condition_clause ::= until condition condition ::= boolean_expression timeout_clause ::= for time_expression
wait_statement ::= [label:] wait [on signal_name {, signal_name}] [until boolean_expression] [for time_expression] ;
entity DFF is port (CLK, D : BIT; Q : out BIT); end; architecture Behave of DFF is
--1 --2
40
SECTION 10
VHDL
process begin wait until Clk = '1'; Q <= D ; end process; end;
--3 --4
entity Wait_1 is port (Clk, s1, s2 : in BIT); end; architecture Behave of Wait_1 is signal x : BIT_VECTOR (0 to 15); begin process variable v : BIT; begin wait; -- Wait forever, stops simulation. wait on s1 until s2 = '1'; -- Legal, but s1, s2 are signals so -- s1 is in sensitivity list, and s2 is not in the sensitivity set. -- Sensitivity set is s1 and process will not resume at event on s2. wait on s1, s2; -- resumes at event on signal s1 or s2. wait on s1 for 10 ns; -- resumes at event on s1 or after 10 ns. wait on x; -- resumes when any element of array x -- has an event. -- wait on x(1 to v); -- Illegal, nonstatic name, since v is a variable. end process; end;
entity Wait_2 is port (Clk, s1, s2: in BIT); end; architecture Behave of Wait_2 is begin process variable v : BIT; begin wait on Clk; -- resumes when Clk has an event: rising or falling. wait until Clk = '1'; -- resumes on rising edge. wait on Clk until Clk = '1'; -- equivalent to the last statement. wait on Clk until v = '1'; -- The above is legal, but v is a variable so -- Clk is in sensitivity list, v is not in the sensitivity set. -- Sensitivity set is Clk and process will not resume at event on v. wait on Clk until s1 = '1'; -- The above is legal, but s1 is a signal so -- Clk is in sensitivity list, s1 is not in the sensitivity set. -- Sensitivity set is Clk, process will not resume at event on s1. end process; end;
41
10.10.2 Assertion and Report Statements assertion_statement ::= [label:] assert boolean_expression [ report expression] [ severity expression] ;
entity Assert_1 is port (I:INTEGER:=0); end; architecture Behave of Assert_1 is begin process begin assert (I > 0) report "I is negative or zero"; wait; end process; end;
10.10.3 Assignment Statements Key terms and concepts: A variable assignment statement updates immediately A signal assignment statement schedules a future assignment simulation cycle delta cycle delta time delta, event delay models: transport and inertial delay (the default) pulse rejection limit
entity Var_Assignment is end; architecture Behave of Var_Assignment is signal s1 : INTEGER := 0; begin process variable v1,v2 : INTEGER := 0; begin assert (v1/=0) report "v1 is 0" severity note ; -- this prints v1 := v1 + 1; -- after this statement v1 is 1 assert (v1=0) report "v1 isn't 0" severity note ; -- this prints v2 := v2 + s1; -- signal and variable types must match wait; end process; end;
42
SECTION 10
VHDL
entity Sig_Assignment_1 is end; architecture Behave of Sig_Assignment_1 is signal s1,s2,s3 : INTEGER := 0; begin process variable v1 : INTEGER := 1; begin assert (s1 /= 0) report "s1 is 0" severity note ; -- this prints. s1 <= s1 + 1; -- after this statement s1 is still 0. assert (s1 /= 0) report "s1 still 0" severity note ; -- this prints. wait; end process; end;
entity Sig_Assignment_2 is end; architecture Behave of Sig_Assignment_2 is signal s1, s2, s3 : INTEGER := 0; begin process variable v1 : INTEGER := 1; begin -- s1, s2, s3 are initially 0; now consider the following: s1 <= 1 ; -- schedules updates to s1 at end of 0 ns cycle. s2 <= s1; -- s2 is 0, not 1. wait for 1 ns; s3 <= s1; -- now s3 will be 1 at 1 ns. wait; end process; end;
entity Transport_1 is end; architecture Behave of Transport_1 is signal s1, SLOW, FAST, WIRE : BIT := '0'; begin process begin s1 <= '1' after 1 ns, '0' after 2 ns, '1' after 3 ns ; -- schedules s1 to be '1' at t+1 ns, '0' at t+2 ns,'1' at t+3 ns wait; end process; -- inertial delay: SLOW rejects pulsewidths less than 5ns: process (s1) begin SLOW <= s1 after 5 ns ; end process; -- inertial delay: FAST rejects pulsewidths less than 0.5ns: process (s1) begin FAST <= s1 after 0.5 ns ; end process; -- transport delay: WIRE passes all pulsewidths...
43
process (s1) begin WIRE <= transport s1 after 5 ns ; end process; end;
process (s1) begin RJCT <= reject 2 ns s1 after 5 ns ; end process; 10.10.4 Procedure Call procedure_call_statement ::= [label:] procedure_name [(parameter_association_list)];
package And_Pkg is procedure V_And(a, b : BIT; signal c : out BIT); function V_And(a, b : BIT) return BIT; end;
package body And_Pkg is procedure V_And(a, b : BIT; signal c: out BIT) is begin c <= a and b; end; function V_And(a, b: BIT) return BIT is begin return a and b; end; end And_Pkg;
use work.And_Pkg. all; entity Proc_Call_1 is end; architecture Behave of Proc_Call_1 is signal A, B, Y: BIT := '0'; begin process begin V_And (A, B, Y); wait; end process; end;
10.10.5 If Statement if_statement ::= [if_label:] if boolean_expression then {sequential_statement} {elsif boolean_expression then {sequential_statement}} [else {sequential_statement}] end if [if_label];
44
SECTION 10
VHDL
begin process begin if c = '1' then c <= a ; else c <= b; end if; wait; end process; end;
entity If_Then_1 is end; architecture Behave of If_Then_1 is signal A, B, Y : BIT :='1'; begin process begin if A = B then Y <= A; end if; wait; end process; end;
10.10.6 Case Statement case_statement ::= [case_label:] case expression is when choice {| choice} => {sequential_statement} {when choice {| choice} => {sequential_statement}} end case [case_label];
library IEEE; use IEEE.STD_LOGIC_1164. all; entity sm_mealy is port (reset, clock, i1, i2 : STD_LOGIC; o1, o2 :out STD_LOGIC); end sm_mealy; architecture Behave of sm_mealy is type STATES is (s0, s1, s2, s3); signal current, new : STATES; begin synchronous : process (clock, reset) begin if To_X01(reset) = '0' then current <= s0; elsif rising_edge(clock) then current <= new; end if; end process; combinational : process (current, i1, i2) begin case current is when s0 => if To_X01(i1) = '1' then o2 <='0'; o1 <='0'; new <= s2; else o2 <= '1'; o1 <= '1'; new <= s1; end if; when s1 => if To_X01(i2) = '1' then o2 <='1'; o1 <='0'; new <= s1; else o2 <='0'; o1 <='1'; new <= s3; end if; when s2 => if To_X01(i2) = '1' then o2 <='0'; o1 <='1'; new <= s2;
--1 --2 --3 --4 --5 --6 --7 --8 --9 --10 --11 --12 --13 --14 --15 --16 --17 --18 --19 --20 --21
45
else o2 <= '1'; o1 <= '0'; new <= s0; end if; when s3 => o2 <= '0'; o1 <= '0'; new <= s0; when others => o2 <= '0'; o1 <= '0'; new <= s0; end case; end process; end Behave;
46
SECTION 10
VHDL
10.10.7 Other Sequential Control Statements loop_statement ::= [loop_label:] [while boolean_expression|for identifier in discrete_range] loop {sequential_statement} end loop [loop_label];
package body And_Pkg is function V_And(a, b : BIT) return BIT is begin return a and b; end; end And_Pkg;
entity Loop_1 is port (x, y : in BIT := '1'; s : out BIT := '0'); end; use work.And_Pkg. all; architecture Behave of Loop_1 is begin loop s <= V_And(x, y); wait on x, y; end loop; end;
The next statement [VHDL LRM8.10] forces completion of current loop iteration:
47
loop wait on Clk; exit when Clk = '0'; end loop; -- equivalent to: wait until Clk = '0';
The return statement [VHDL LRM8.12] completes execution of a procedure or function: return_statement ::= [label:] return [expression]; A null statement [VHDL LRM8.13] does nothing: null_statement ::= [label:] null;
48
SECTION 10
VHDL
10.11 Operators
VHDL predened operators (listed by increasing order of precedence) logical_operator ::= relational_operator ::= shift_operator::= adding_operator ::= sign ::= multiplying_operator ::= miscellaneous_operator ::= and | or | nand | nor | xor | xnor = | /= | < | <= | > | >= sll | srl | sla | sra | rol | ror + | | & + | * | / | mod | rem ** | abs | not
entity Operator_1 is end; architecture Behave of Operator_1 is --1 begin process --2 variable b : BOOLEAN; variable bt : BIT := '1'; variable i : INTEGER; --3 variable pi : REAL := 3.14; variable epsilon : REAL := 0.01; --4 variable bv4 : BIT_VECTOR (3 downto 0) := "0001"; --5 variable bv8 : BIT_VECTOR (0 to 7); --6 begin --7 b b bt bv4 i i i i i := := := := := := := := "0000" < bv4; -- b is TRUE, "0000" treated as BIT_VECTOR. 'f' > 'g'; -- b is FALSE, 'dictionary' comparison. '0' and bt; -- bt is '0', analyzer knows '0' is BIT. not bv4; -- bv4 is now "1110". 1 + 2; -- Addition, must be compatible types. 2 ** 3; -- Exponentiation, exponent must be integer. 7/3; -- Division, L/R rounded towards zero, i=2. 12 rem 7; -- Remainder, i=5. In general: -- L rem R = L-((L/R)*R). := 12 mod 7; -- modulus, i=5. In general: -- L mod R = L-(R*N) for an integer N. --8 --9 --10 --11 --12 --13 --14 --15 --16 --17 --18
-- shift := sll | srl | sla | sra | rol | ror (VHDL-93 only) --19 bv4 := "1001" srl 2; -- Shift right logical, now bv4="0100". --20 -- Logical shift fills with T'LEFT. --21 bv4 := "1001" sra 2; -- Shift right arithmetic, now bv4="0111". --22 -- Arithmetic shift fills with element at end being vacated. --23 bv4 := "1001" ror 2; -- Rotate right, now bv4="0110". --24 -- Rotate wraps around. --25 -- Integer argument to any shift operator may be negative or zero. --26
10.12 Arithmetic
49
if (pi*2.718)/2.718 = 3.14 then wait; end if; -- This is unreliable. --27 if (abs(((pi*2.718)/2.718)-3.14)<epsilon)then wait; end if; -Better. --28 bv8 := bv8(1 to 7) & bv8(0); -- Concatenation, a left rotation. wait; end process; end; --29 --30 --31
10.12 Arithmetic
Key terms and concepts: type checking range checking type conversion between closely related types type_mark(expression) type qualification and disambiguation (to persuade the analyzer) type_mark'(expression) entity Arithmetic_1 is end; architecture Behave of Arithmetic_1 is begin process variable i : INTEGER := 1; variable r : REAL := 3.33; variable b : BIT := '1'; variable bv4 : BIT_VECTOR (3 downto 0) := "0001"; variable bv8 : BIT_VECTOR (7 downto 0) := B"1000_0000"; begin ----i bv4 bv4 bv8 := := := := r; bv4 + 2; '1'; bv4; ----you can't you can't you can't an error, --1 --2 --3 --4 --5 --6
assign REAL to INTEGER. --7 add BIT_VECTOR and INTEGER. --8 assign BIT to BIT_VECTOR. --9 the arrays are different sizes. --10 --11 --12 --13 --14 --15 --1 --2 --3 --4 --5 --6 --7 --8 --9 --10 --11
r := REAL(i); -i := INTEGER(r); -bv4 := "001" & '1'; -bv8 := "0001" & bv4; -wait; end process; end;
OK, uses a type conversion. OK (0.5 rounds up or down). OK, you can mix an array and a scalar. OK, if arguments are correct lengths.
entity Arithmetic_2 is end; architecture Behave of Arithmetic_2 is type TC is range 0 to 100; -- Type INTEGER. type TF is range 32 to 212; -- Type INTEGER. subtype STC is INTEGER range 0 to 100; -- Subtype of type INTEGER. subtype STF is INTEGER range 32 to 212; -- Base type is INTEGER. begin process variable t1 : TC := 25; variable t2 : TF := 32; variable st1 : STC := 25; variable st2 : STF := 32; begin --t1 t1 := t2; := st1; -- Illegal, different types. -- Illegal, different types and subtypes.
50
SECTION 10
VHDL
st2 := st1; -st2 := st1 + 1; --- st2 := 213; --- st2 := 212 + 1; -st1 := st1 + 100; -wait; end process; end;
OK to use same base types. OK to use subtype and base type. Error, outside range at analysis time. Error, outside range at analysis time. Error, outside range at initialization.
entity Arithmetic_3 is end; architecture Behave of Arithmetic_3 is --1 type TYPE_1 is array (INTEGER range 3 downto 0) of BIT; --2 type TYPE_2 is array (INTEGER range 3 downto 0) of BIT; --3 subtype SUBTYPE_1 is BIT_VECTOR (3 downto 0); --4 subtype SUBTYPE_2 is BIT_VECTOR (3 downto 0); --5 begin process --6 variable bv4 : BIT_VECTOR (3 downto 0) := "0001"; --7 variable st1 : SUBTYPE_1 := "0001"; variable t1 : TYPE_1 := "0001"; --8 variable st2 : SUBTYPE_2 := "0001"; variable t2 : TYPE_2 := "0001"; --9 begin --10 bv4 := st1; -- OK, compatible type and subtype. --11 -- bv4 := t1; -- Illegal, different types. --12 bv4 := BIT_VECTOR(t1); -- OK, type conversion. --13 st1 := bv4; -- OK, compatible subtype & base type. --14 -- st1 := t1; -- Illegal, different types. --15 st1 := SUBTYPE_1(t1); -- OK, type conversion. --16 -- t1 := st1; -- Illegal, different types. --17 -- t1 := bv4; -- Illegal, different types. --18 t1 := TYPE_1(bv4); -- OK, type conversion. --19 -- t1 := t2; -- Illegal, different types. --20 t1 := TYPE_1(t2); -- OK, type conversion. --21 st1 := st2; -- OK, compatible subtypes. --22 wait; end process; end; --23 10.12.1 IEEE Synthesis Packages package Part_NUMERIC_BIT is type UNSIGNED is array (NATURAL range <> ) of BIT; type SIGNED is array (NATURAL range <> ) of BIT; function "+" (L, R : UNSIGNED) return UNSIGNED; -- other function definitions that overload +, -, = , >, and so on. end Part_NUMERIC_BIT;
package body Part_NUMERIC_BIT is constant NAU : UNSIGNED(0 downto 1) := (others =>'0'); -- Null array.
10.12 Arithmetic
51
constant NAS : SIGNED(0 downto 1):=(others => '0'); -- Null array. constant NO_WARNING : BOOLEAN := FALSE; -- Default to emit warnings.
function MAX (LEFT, RIGHT : INTEGER) return INTEGER is begin -- Internal function used to find longest of two inputs. if LEFT > RIGHT then return LEFT; else return RIGHT; end if; end MAX;
function ADD_UNSIGNED (L, R : UNSIGNED; C: BIT)return UNSIGNED is constant L_LEFT : INTEGER := L'LENGTH-1; -- L, R must be same length. alias XL : UNSIGNED(L_LEFT downto 0) is L; -- Descending alias, alias XR : UNSIGNED(L_LEFT downto 0) is R; -- aligns left ends. variable RESULT : UNSIGNED(L_LEFT downto 0); variable CBIT : BIT := C; begin for I in 0 to L_LEFT loop -- Descending alias allows loop. RESULT(I) := CBIT xor XL(I) xor XR(I); -- CBIT = carry, initially = C. CBIT := (CBIT and XL(I)) or (CBIT and XR(I)) or (XL(I) and XR(I)); end loop; return RESULT; end ADD_UNSIGNED;
function RESIZE (ARG : UNSIGNED; NEW_SIZE : NATURAL)return UNSIGNED is constant ARG_LEFT : INTEGER := ARG'LENGTH-1; alias XARG : UNSIGNED(ARG_LEFT downto 0) is ARG; -- Descending range. variable RESULT : UNSIGNED(NEW_SIZE-1 downto 0) := (others => '0'); begin -- resize the input ARG to length NEW_SIZE if (NEW_SIZE < 1) then return NAU; end if; -- Return null array. if XARG'LENGTH = 0 then return RESULT; end if; -- Null to empty. if (RESULT'LENGTH < ARG'LENGTH) then -- Check lengths. RESULT(RESULT'LEFT downto 0) := XARG(RESULT'LEFT downto 0); else -- Need to pad the result with some '0's. RESULT(RESULT'LEFT downto XARG'LEFT + 1) := ( others => '0'); RESULT(XARG'LEFT downto 0) := XARG; end if; return RESULT; end RESIZE;
function "+" (L, R : UNSIGNED) return UNSIGNED is -- Overloaded '+'. constant SIZE : NATURAL := MAX(L'LENGTH, R'LENGTH); begin -- If length of L or R < 1 return a null array. if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; end if; return ADD_UNSIGNED(RESIZE(L, SIZE), RESIZE(R, SIZE), '0'); end "+"; end Part_NUMERIC_BIT;
52
SECTION 10
VHDL
function TO_INTEGER (ARG : UNSIGNED) return NATURAL; function TO_INTEGER (ARG : SIGNED) return INTEGER; function TO_UNSIGNED (ARG, SIZE : NATURAL)return UNSIGNED; function TO_SIGNED (ARG : INTEGER; SIZE : NATURAL)return SIGNED; function RESIZE (ARG : SIGNED; NEW_SIZE : NATURAL)return SIGNED; function RESIZE (ARG : UNSIGNED; NEW_SIZE : NATURAL)return UNSIGNED; -- set XMAP to convert unknown values, default is 'X'->'0' function TO_01(S : UNSIGNED; XMAP : STD_LOGIC := '0')return UNSIGNED; function TO_01(S : SIGNED; XMAP : STD_LOGIC := '0')return SIGNED;
library IEEE; use IEEE.STD_LOGIC_1164. all; package Part_NUMERIC_STD is type UNSIGNED is array (NATURAL range <>) of STD_LOGIC; type SIGNED is array (NATURAL range <>) of STD_LOGIC; end Part_NUMERIC_STD;
-- function STD_MATCH (L, R: T) return BOOLEAN; -- T = STD_ULOGIC UNSIGNED SIGNED STD_LOGIC_VECTOR STD_ULOGIC_VECTOR
type BOOLEAN_TABLE is array(STD_ULOGIC, STD_ULOGIC) of BOOLEAN; constant MATCH_TABLE : BOOLEAN_TABLE := ( ---------------------------------------------------------------------- U X 0 1 Z W L H --------------------------------------------------------------------(FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, TRUE), -- | U | (FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, TRUE), -- | X | (FALSE,FALSE, TRUE,FALSE,FALSE,FALSE, TRUE,FALSE, TRUE), -- | 0 | (FALSE,FALSE,FALSE, TRUE,FALSE,FALSE,FALSE, TRUE, TRUE), -- | 1 | (FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, TRUE), -- | Z | (FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, TRUE), -- | W | (FALSE,FALSE, TRUE,FALSE,FALSE,FALSE, TRUE,FALSE, TRUE), -- | L | (FALSE,FALSE,FALSE, TRUE,FALSE,FALSE,FALSE, TRUE, TRUE), -- | H | ( TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE));-- | - |
--1 --2
10.12 Arithmetic
53
library IEEE; use IEEE.STD_LOGIC_1164. all; use work.NUMERIC_STD. all; architecture Behave_2 of Counter_1 is signal Clock : STD_LOGIC := '0'; signal Count : UNSIGNED (2 downto 0) := "000"; begin process begin wait for 10 ns; Clock <= not Clock; if (now > 340 ns) then wait; end if; end process; process begin wait until (Clock = '0'); if (Count = 7) then Count <= "000"; else Count <= Count + 1; end if; end process; process (Count) variable L: LINE; begin write(L, now); write(L, STRING'(" Count=")); write(L, TO_INTEGER(Count)); writeline(output, L); end process; end;
--3 --4 --5 --6 --7 --8 --9 --10 --11 --12 --13 --14 --15 --16 --17 --18 --19 --20 --21 --22 --23 --24 --25
54
SECTION 10
VHDL
10.13.1 Block Statement Key terms and concepts: guard expression GUARD guarded signals (register and bus) driver disconnected disconnect statement
block_statement ::= block_label: block [(guard_expression)] [is] [generic (generic_interface_list); [generic map (generic_association_list);]] [port (port_interface_list); [port map (port_association_list);]] {block_declarative_item} begin {concurrent_statement} end block [block_label] ;
architecture Structure_1 of bus_drivers is signal TSTATE: STD_LOGIC bus; signal A, B, OEA, OEB : STD_LOGIC:= '0'; begin process begin OEA <= '1' after 100 ns, '0' after 200 ns; OEB <= '1' after 300 ns; wait; end process; B1 : block (OEA = '1') disconnect all : STD_LOGIC after 5 ns; -- Only needed for float time.
55
begin TSTATE <= guarded not A after 3 ns; end block; B2 : block (OEB = '1') disconnect all : STD_LOGIC after 5 ns; -- Float time = 5 ns. begin TSTATE <= guarded not B after 3 ns; end block; end;
architecture Structure_2 of bus_drivers is signal TSTATE : STD_LOGIC; signal A, B, OEA, OEB : STD_LOGIC := '0'; begin process begin OEA <= '1' after 100 ns, '0' after 200 ns; OEB <= '1' after 300 ns; wait; end process; process(OEA, OEB, A, B) begin if (OEA = '1') then TSTATE <= not A after 3 ns; elsif (OEB = '1') then TSTATE <= not B after 3 ns; else TSTATE <= 'Z' after 5 ns; end if; end process; end;
10.13.2 Process Statement Key terms and concepts: process sensitivity set process execution occurs during a simulation cyclemade up of delta cycles
process_statement ::= [process_label:] [postponed] process [(signal_name {, signal_name})] [is] {subprogram_declaration | subprogram_body | type_declaration | subtype_declaration | constant_declaration | variable_declaration | file_declaration | alias_declaration | attribute_declaration | attribute_specification | use_clause | group_declaration | group _template_declaration} begin {sequential_statement} end [postponed] process [process_label];
56
SECTION 10
VHDL
entity Mux_1 is port (i0, i1, sel : in BIT := '0'; y : out BIT); end; architecture Behave of Mux_1 is begin process (i0, i1, sel) begin -- i0, i1, sel = sensitivity set case sel is when '0' => y <= i0; when '1' => y <= i1; end case; end process; end;
entity And_1 is port (a, b : in BIT := '0'; y : out BIT); end; architecture Behave of And_1 is begin process (a, b) begin y <= a and b; end process; end;
entity FF_1 is port (clk, d: in BIT := '0'; q : out BIT); end; architecture Behave of FF_1 is begin process (clk) begin if clk'EVENT and clk = '1' then q <= d; end if; end process; end;
entity FF_2 is port (clk, d: in BIT := '0'; q : out BIT); end; architecture Behave of FF_2 is begin process begin -- The equivalent process has a wait at the end: if clk'event and clk = '1' then q <= d; end if; wait on clk; end process; end;
entity FF_3 is port (clk, d: in BIT := '0'; q : out BIT); end; architecture Behave of FF_3 is begin process begin -- No sensitivity set with a wait statement. wait until clk = '1'; q <= d; end process; end;
10.13.3 Concurrent Procedure Call package And_Pkg is procedure V_And(a,b:BIT; signal c:out BIT); end;
package body And_Pkg is procedure V_And(a,b:BIT; signal c:out BIT) is begin c <= a and b; end; end And_Pkg;
use work.And_Pkg. all; entity Proc_Call_2 is end; architecture Behave of Proc_Call_2 is signal A, B, Y : BIT := '0';
57
begin V_And (A, B, Y); -- Concurrent procedure call. process begin wait; end process; -- Extra process to stop. end;
10.13.4 Concurrent Signal Assignment Key terms and concepts: There are two forms of concurrent signal assignment statement: A selected signal assignment statement is equivalent to a case statement inside a process statement [VHDL LRM9.5.2]. A conditional signal assignment statement is, in its most general form, equivalent to an if statement inside a process statement [VHDL LRM9.5.1].
selected_signal_assignment ::= with expression select name|aggregate <= [ guarded] [transport|[reject time_expression] inertial] waveform when choice {| choice} {, waveform when choice {| choice} } ;
entity Selected_1 is end; architecture Behave of Selected_1 is signal y,i1,i2 : INTEGER; signal sel : INTEGER range 0 to 1; begin with sel select y <= i1 when 0, i2 when 1; end;
entity Selected_2 is end; architecture Behave of Selected_2 is signal i1,i2,y : INTEGER; signal sel : INTEGER range 0 to 1; begin process begin case sel is when 0 => y <= i1; when 1 => y <= i2; end case; wait on i1, i2; end process; end;
conditional_signal_assignment ::= name|aggregate <= [ guarded] [transport|[reject time_expression] inertial] {waveform when boolean_expression else} waveform [when boolean_expression];
58
SECTION 10
VHDL
entity Conditional_1 is end; architecture Behave of Conditional_1 is signal y,i,j : INTEGER; signal clk : BIT; begin y <= i when clk = '1' else j; -- conditional signal assignment end;
entity Conditional_2 is end; architecture Behave of Conditional_2 is signal y,i : INTEGER; signal clk : BIT; begin process begin if clk = '1' then y <= i; else y <= y ; end if; wait on clk; end process; end;
A concurrent signal assignment statement can look like a sequential signal assignment statement:
entity Assign_1 is end; architecture Behave of Assign_1 is signal Target, Source : INTEGER; begin Target <= Source after 1 ns; -- looks like signal assignment end;
entity Assign_2 is end; architecture Behave of Assign_2 is signal Target, Source : INTEGER; begin process begin Target <= Source after 1 ns; wait on Source; end process; end;
entity Assign_3 is end; architecture Behave of Assign_3 is signal Target, Source : INTEGER; begin process begin wait on Source; Target <= Source after 1 ns; end process; end;
10.13.5 Concurrent Assertion Statement A concurrent assertion statement is equivalent to a passive process statement (without a sensitivity list) that contains an assertion statement followed by a wait statement.
59
If the assertion condition contains a signal, then the equivalent process statement will include a nal wait statement with a sensitivity clause. A concurrent assertion statement with a condition that is static expression is equivalent to a process statement that ends in a wait statement that has no sensitivity clause. The equivalent process will execute once, at the beginning of simulation, and then wait indenitely. 10.13.6 Component Instantiation component_instantiation_statement ::= instantiation _label: [component] component_name |entity entity_name [(architecture_identifier)] |configuration configuration _name [generic map (generic_association_list)] [port map (port_association_list)] ;
out BIT); end; i1 and i2; end; out BIT); end; i1 xor i2; end;
entity Half_Adder_2 is port (a,b : BIT := '0'; sum, cry : out BIT); end; architecture Netlist_2 of Half_Adder_2 is use work.all; -- need this to see the entities Xor_2 and And_2 begin X1 : entity Xor_2(Behave) port map (a, b, sum); -- VHDL-93 only A1 : entity And_2(Behave) port map (a, b, cry); -- VHDL-93 only end;
60
SECTION 10
VHDL
10.13.7 Generate Statement generate_statement ::= generate_label: for generate_parameter_specification |if boolean_expression generate [{block_declarative_item} begin] {concurrent_statement} end generate [generate_label] ;
entity Full_Adder is port (X, Y, Cin : BIT; Cout, Sum: out BIT); end; architecture Behave of Full_Adder is begin Sum <= X xor Y xor Cin; Cout <= (X and Y) or (X and Cin) or (Y and Cin); end;
entity Adder_1 is port (A, B : in BIT_VECTOR (7 downto 0) := (others => '0'); Cin : in BIT := '0'; Sum : out BIT_VECTOR (7 downto 0); Cout : out BIT); end;
component Full_Adder port (X, Y, Cin: BIT; Cout, Sum: out BIT); end component; signal C : BIT_VECTOR(7 downto 0); begin AllBits : for i in 7 downto 0 generate LowBit : if i = 0 generate FA : Full_Adder port map (A(0), B(0), Cin, C(0), Sum(0)); end generate; OtherBits : if i /= 0 generate FA : Full_Adder port map (A(i), B(i), C(i-1), C(i), Sum(i)); end generate; end generate; Cout <= C(7); end;
10.14 Execution
61
10.14 Execution
Key terms and concepts: sequential execution concurrent execution difference between update for signals and variables Variables and signals in VHDL Variables
entity Execute_1 is end; architecture Behave of Execute_1 is begin process variable v1 : INTEGER := 1; variable v2 : INTEGER := 2; begin v1 := v2; -- before: v1 = 1, v2 = 2 v2 := v1; -- after: v1 = 2, v2 = 2 wait; end process; end;
Signals
entity Execute_2 is end; architecture Behave of Execute_2 is signal s1 : INTEGER := 1; signal s2 : INTEGER := 2; begin process begin s1 <= s2; -- before: s1 = 1, s2 = 2 s2 <= s1; -- after: s1 = 2, s2 = 1 wait; end process; end;
Concurrent and sequential statements in VHDL Concurrent [VHDL LRM9] block process concurrent_procedure_call concurrent_assertion concurrent_signal_assignment component_instantiation generate wait assertion signal_assignment variable_assignment procedure_call if Sequential [VHDL LRM8] case loop next exit return null
entity Sequential_1 is end; architecture Behave of Sequential_1 is signal s1, s2 : INTEGER := 0; begin process begin s1 <= 1; -- sequential signal assignment 1 s2 <= s1 + 1; -- sequential signal assignment 2 wait on s1, s2 ;
62
SECTION 10
VHDL
Concurrent_1 is end; architecture Behave of Concurrent_1 is s1, s2 : INTEGER := 0; begin s1 <= 1; -- concurrent signal assignment 1 s2 <= s1 + 1; -- concurrent signal assignment 2
Concurrent_2 is end; architecture Behave of Concurrent_2 is s1, s2 : INTEGER := 0; begin process begin s1 <= 1; wait on s2 ; end process; process begin s2 <= s1 + 1; wait on s1 ; end process;
63
64
SECTION 10
VHDL
component declaration conguration specication conguration declaration block conguration component conguration
entity Half_Adder is port (X, Y: BIT; Sum, Cout: out BIT); end; architecture Netlist of Half_Adder is use work.all; component MX port (A, B: BIT; Z :out BIT);end component; component MA port (A, B: BIT; Z :out BIT);end component; for G1:MX use entity XR2(B) port map(X1 => A,X2 => B,Y => Z); begin G1:MX port map(X, Y, Sum); G2:MA port map(X, Y, Cout); end;
configuration C1 of Half_Adder is use work.all; for Netlist for G2:MA use entity AD2(B) port map(A1 => A,A2 => B,Y => Z); end for; end for; end;
65
conguration specication
66
SECTION 10
VHDL
T_in = temperature in C T_out = temperature in F The conversion formula from Centigrade to Fahrenheit is: T(F) = (9/5)T(C)+ 32
67
A digital lter
library IEEE; use IEEE.STD_LOGIC_1164.all; -- STD_LOGIC type, rising_edge use IEEE.NUMERIC_STD.all; -- UNSIGNED type, "+" and "/" entity filter is generic TPD : TIME := 1 ns; port (T_in : in UNSIGNED(11 downto 0); rst, clk : in STD_LOGIC; T_out: out UNSIGNED(11 downto 0)); end; architecture rtl of filter is type arr is array (0 to 3) of UNSIGNED(11 downto 0); signal i : arr ; constant T4 : UNSIGNED(2 downto 0) := "100"; begin process(rst, clk) begin if (rst = '1') then for n in 0 to 3 loop i(n) <= (others =>'0') after TPD; end loop; else if(rising_edge(clk)) then i(0) <= T_in after TPD;i(1) <= i(0) after TPD; i(2) <= i(1) after TPD;i(3) <= i(2) after TPD; end if; end if; end process; process(i) begin T_out <= ( i(0) + i(1) + i(2) + i(3) )/T4 after TPD; end process; end rtl;
The lter computes a moving average over four successive samples in time.
Then the sum i(0) + i(1) + i(2) + i(3) is 14 bits wide, and the average
is 12 bits wide.
68
SECTION 10
VHDL
If the input is asynchronous (from an A/D converter with a separate clock, for example), we would need to worry about metastability.
69
Reads (pop = 1) and writes (push = 1) are synchronous to the rising edge of the clock. Read and write should not occur at the same time. The width (number of bits in each word) and depth (number of words) are generics.
External signals: clk, clock rst, reset active-high push, write to FIFO pop, read from FIFO Di, data in Do, data out empty, FIFO ag full, FIFO ag
Internal signals: diff, difference pointer Ai, input address Ao, output address f, full ag e, empty ag
70
SECTION 10
VHDL
A FIFO controller
library IEEE;use IEEE.STD_LOGIC_1164.all;use IEEE.NUMERIC_STD.all; entity fifo_control is generic TPD : TIME := 1 ns; port(D_1, D_2 : in UNSIGNED(11 downto 0); sel : in UNSIGNED(1 downto 0) ; read , f1, f2, e1, e2 : in STD_LOGIC; r1, r2, w12 : out STD_LOGIC; D : out UNSIGNED(11 downto 0)) ; end; architecture rtl of fifo_control is begin process (read, sel, D_1, D_2, f1, f2, e1, e2) begin r1 <= '0' after TPD; r2 <= '0' after TPD; if (read = '1') then w12 <= '0' after TPD; case sel is when "01" => D <= D_1 after TPD; r1 <= '1' after TPD; when "10" => D <= D_2 after TPD; r2 <= '1' after TPD; when "00" => D(3) <= f1 after TPD; D(2) <= f2 after TPD; D(1) <= e1 after TPD; D(0) <= e2 after TPD; when others => D <= "ZZZZZZZZZZZZ" after TPD; end case; elsif (read = '0') then D <= "ZZZZZZZZZZZZ" after TPD; w12 <= '1' after TPD; else D <= "ZZZZZZZZZZZZ" after TPD; end if; end process; end rtl;
This handles the reading and writing to the FIFOs under control of the processor (mpu). The mpu can ask for data from either FIFO or for status ags to be placed on the bus.
Inputs: D_1 data in from FIFO1 D_2 data in from FIFO2 sel FIFO select from mpu read FIFO read from mpu f1,f2,e1,e2 ags from FIFOs
Outputs: r1, r2 read enables for FIFOs w12 write enable for FIFOs D data out to mpu bus
71
package TC_Components is component register_in generic (TPD : TIME := 1 ns); port (T_in : in UNSIGNED(11 downto 0); clk, rst : in STD_LOGIC; T_out : out UNSIGNED(11 downto 0)); end component;
component tconv generic (TPD : TIME := 1 ns); port (T_in : in UNSIGNED (7 downto 0); clk, rst : in STD_LOGIC; T_out : out UNSIGNED(7 downto 0)); end component;
component filter generic (TPD : TIME := 1 ns); port (T_in : in UNSIGNED (7 downto 0); rst, clk : in STD_LOGIC; T_out : out UNSIGNED(7 downto 0)); end component;
72
SECTION 10
VHDL
component fifo generic (width:INTEGER := 12; depth : INTEGER := 16); port (clk, rst, push, pop : STD_LOGIC; Di : UNSIGNED (width-1 downto 0); Do : out UNSIGNED (width-1 downto 0); empty, full : out STD_LOGIC); end component;
component fifo_control generic (TPD:TIME := 1 ns); port (D_1, D_2 : in UNSIGNED(7 downto 0); select : in UNSIGNED(1 downto 0); read, f1, f2, e1, e2 : in STD_LOGIC; r1, r2, w12 : out STD_LOGIC; D : out UNSIGNED(7 downto 0)) ; end component; end;
library IEEE; use IEEE.std_logic_1164. all; -- type STD_LOGIC use IEEE.numeric_std. all; -- type UNSIGNED entity test_TC is end;
architecture testbench of test_TC is component T_Control port (T_1, T_2 : in UNSIGNED(11 downto 0); clk : in STD_LOGIC; sensor: in UNSIGNED( 1 downto 0) ; read : in STD_LOGIC; rst : in STD_LOGIC; D : out UNSIGNED(7 downto 0)); end component; signal T_1, T_2 : UNSIGNED(11 downto 0); signal clk, read, rst : STD_LOGIC; signal sensor : UNSIGNED(1 downto 0); signal D : UNSIGNED(7 downto 0); begin TT1 : T_Control port map (T_1, T_2, clk, sensor, read, rst, D); process begin rst <= '0'; clk <= '0'; wait for 5 ns; rst <= '1'; wait for 5 ns; rst <= '0'; T_in1 <= "000000000011"; T_in2 <= "000000000111"; read <= '0'; for i in 0 to 15 loop -- fill the FIFOs clk <= '0'; wait for 5ns; clk <= '1'; wait for 5 ns; end loop; assert (false) report "FIFOs full" severity NOTE; clk <= '0'; wait for 5ns; clk <= '1'; wait for 5 ns; read <= '1'; sensor <= "01"; for i in 0 to 15 loop -- empty the FIFOs clk <= '0'; wait for 5ns; clk <= '1'; wait for 5 ns;
73
end loop; assert (false) report "FIFOs empty" severity NOTE; clk <= '0'; wait for 5ns; clk <= '1'; wait; end process; end;
74
SECTION 10
VHDL
10.17 Summary
Key terms and concepts: The use of an entity and an architecture The use of a configuration to bind entities and their architectures The compile, elaboration, initialization, and simulation steps Types, subtypes, and their use in expressions The logic systems based on BIT and Std_Logic_1164 types The use of the IEEE synthesis packages for BIT arithmetic Ports and port modes Initial values and the difference between simulation and hardware The difference between a signal and a variable The different assignment statements and the timing of updates The process and wait statements
10.17 Summary
75
93LRM 13.8 13.4 13.3 1.11.3 4.3 4.3 14.2 3.2.1 4.3.1.2 4.3.1.3 4.3.2 4.3.2 14.1 8
Identiers (case-insensitive, start with letter) Several basic units of code Connections made through ports Default expression No built-in logic-value system. BIT and BIT_VECTOR (STD). Arrays Two basic types of logic signals Types and explicit initial/default value Implicit initial/default value Predened attributes Sequential statements inside processes model things that happen one after another and repeat Timing with wait statement Update to signals occurs at the end of a simulation cycle Update to variables is immediate Processes and concurrent statements model things that happen at the same time IEEE Std_Logic_1164 (denes logic operators on 1164 types) IEEE Numeric_Bit and Numeric_Std (denes arithmetic operators on BIT and 1164 types)
architecture
port (signal in i : BIT; out o : BIT); port (i : BIT := '1'); -- i='1' if left open type BIT is ('0', '1'); -- predefined signal myArray: BIT_VECTOR (7 downto 0); myArray(1 downto 0) <= ('0', '1'); a signal corresponds to a real wire a variable is a memory location in RAM signal ONE : BIT := '1' ; BIT'LEFT = '0' clk'EVENT, clk'STABLE process begin wait until alarm = ring; eat; work; sleep; end process; wait for 1 ns; -- not wait 1 ns wait on light until light = green; signal <= 1; -- delta time delay signal <= variable1 after 2 ns; variable := 1; -- immediate update process begin process begin process begin
STD_ULOGIC, STD_LOGIC, STD_ULOGIC_VECTOR, STD_LOGIC_VECTOR type STD_ULOGIC is ('U','X','0','1','Z','W','L','H','-'); UNSIGNED and SIGNED X <= "10" * "01" -- OK with numeric pkgs.
76
SECTION 10
VHDL