EEE515 VHDL Notes from “Digital System Design with VHDL” Mark Zwolinski, Pearson/Prentice Hall, 2nd Edition See also “The Student’s Guide to VHDL” Peter Ashenden, 2nd edition Morgan Kaufman (under £20) Ian McCrum Room 5B16 Tel: 90 366364 voice mail on 6th ring Email: IJ.McCrum@Ulster.ac.uk Web site: http://www.eej.ulst.ac.uk www.eej.ulst.ac.uk/~ian/modules/EEE515 1/48 VHDL: Resources • “The Student’s Guide to VHDL” Peter Ashenden, 2nd edition Morgan Kaufman (under £20) His online guides • VHDL Cookbook (dated, older version of VHDL) • VHDL-quick-start.pdf (42 slides) • VHDL_Tutorial, (84 Pages) online - check copyright status Do the quick start then come back here – this highlights usage instead of reference/understanding. www.eej.ulst.ac.uk/~ian/modules/EEE515 2 Combinational logic using VHDL gate models entity And2 is port (x, y end entity And2; architecture ex1 begin z <= x and end architecture BIT is a predefined type with two values: ‘0’ and ‘1’. : in BIT; z: out BIT); of And2 is y; ex1; We can also use inout or buffer or omit the in keyword The entity name at the end is optional, The entity part describes a black box. We can see the inputs and outputs of the black box, together with their types, but we know nothing of the internals of the circuit. www.eej.ulst.ac.uk/~ian/modules/EEE515 3 The architecture describes the function and/or structure of the circuit. In this example, the functionality of the circuit is described in terms of Boolean operations. The reason for having this split is that it is possible to have more than one architecture for each entity, perhaps describing alternative implementations or different levels of description. For instance, we can describe an AND gate in terms of a Boolean operator, as shown, but we could also write a truth table. In either case, the entity, i.e. the ‘black box’, is the same, but there would be two architectures, one for each model. VHDL has the following operators defined for type BIT: not, and, or, nand, nor, xor and xnor www.eej.ulst.ac.uk/~ian/modules/EEE515 4 Structural VHDL -- in addition to the AND gate entity Or2 is port (x, y : in BIT; z: out BIT); end entity Or2; architecture ex1 of Or2 is begin z <= x or y; end architecture ex1; entity Not1 is port (x : in BIT; z: out BIT); end entity Not1; architecture ex1 of Not1 is begin z <= not x; end architecture ex1; architecture netlist of comb_function is signal p, q, r : BIT; begin g1: entity WORK.Not1(ex1) port map (a, p); g2: entity WORK.And2(ex1) port map (p, b, q); g3: entity WORK.And2(ex1) port map (a, c, r); g4: entity WORK.Or2(ex1) port map (q, r, z); end architecture netlist; Note several styles exist for structural VHDL. We will not use structural except for testbenches if not using the simple simulator. Note the signal keyword Also work is the current working library – more tool and system independent than specifying folder location! www.eej.ulst.ac.uk/~ian/modules/EEE515 5 Structural VHDL 2 architecture netlist2 of comb_function is component And2 is port (x, y : in BIT; z: out BIT); end component And2; component Or2 is port (x, y : in BIT; z: out BIT); end component Or2; component Not1 is port (x : in BIT; z: out BIT); end component Not1; signal p, q, r : BIT; begin g1: Not1 port map (a, p); g2: And2 port map (p, b, q); g3: And2 port map (a, c, r); g4: Or2 port map (q, r, z); end architecture netlist2; www.eej.ulst.ac.uk/~ian/modules/EEE515 6 Signal assignments z <= x and y; z <= not ((x and y) or (a and b)); z <= x after 4 NS; This is an inertial delay. In other words, the signal is delayed by 4 ns, and in addition, any pulse that is less than 4 ns wide is suppressed, as shown below. www.eej.ulst.ac.uk/~ian/modules/EEE515 A pure or transport delay is modelled with: z <= transport x after 4 NS; (Note the space between 4 and NS.) Any pulse is now transmitted. We can include the keyword inertial if we want to be very specific about the delay model. 7 Generics z <= x and y after 5 ns; -- better to be general… z <= x and y after delay; To define delay as a parameter to the VHDL model using a generic: entity And2 is generic (delay : DELAY_LENGTH); port (x, y : in BIT; z: out BIT); end entity And2; www.eej.ulst.ac.uk/~ian/modules/EEE515 8 Testbenches If we wish to simulate our circuit to verify that it really does work as expected, we need to apply some test stimuli. We could, of course, write out some test vectors and apply them, or, more conveniently, write the test data in VHDL. This type of VHDL model isoften known as a testbench. Testbenches have a distinctive style. Below is a testbench for a two-input AND gate. entity TestAnd2 is end entity TestAnd2; architecture io of TestAnd2 is signal a,b,c : BIT; begin g1: entity WORK.And2(ex2) port map (x=>a, y=>b, z=>c); a<= '0', '1' after 100 NS; b<= '0', '1' after 150 NS; end architecture io; Because this is a testbench, i.e. a description of the entire world that affects the model we are testing, there are no inputs or outputs in the entity. This is characteristic of testbenches. www.eej.ulst.ac.uk/~ian/modules/EEE515 9 Three-state buffers A buffer with input and output that has an additional input called EN or ENABLE. When active it switched the output off, (both pullup and pulldown transistors) Usually called the high impedance state ‘Z’ BIT is no longer adequate to represent logic signal values. We can define a new type to represent logic signals in VHDL: type tri is ('0', '1', 'Z'); -- can declare signals & ports.. www.eej.ulst.ac.uk/~ian/modules/EEE515 10 In VHDL, functions and operators can be overloaded. For example, the and operator normally takes two operands of type bit and returns the Boolean AND of the two operands. We can write a new AND operator to take two operands of type tri and return the values shown in the truth table. The syntax of this function will become clear later. function "and" (Left, Right: tri) return tri is type tri_array is array (tri, tri) of tri; constant and_table : tri_array := (('0', '0', '0'),('0', '1', '1'),('0', '1', '1')); begin return and_table(Left, Right); end function "and"; www.eej.ulst.ac.uk/~ian/modules/EEE515 11 Standard logic package Having defined a new type with values ‘0’, ‘1’ and ‘Z’, we would have to write VHDL functions for the various logical operations. Moreover, we might wonder whether three states are sufficient for everything we might wish to model. IEEE standard 1164 defines an enumerated type with nine values: ‘U’ Uninitialized ‘X’ Forcing (i.e. strong) unknown ‘0’ Forcing 0 ‘1’ Forcing 1 ‘Z’ High impedance ‘W’Weak unknown ‘L’Weak 0 ‘H’Weak 1 ‘–’ Don’t care www.eej.ulst.ac.uk/~ian/modules/EEE515 12 std_ulogic The standard logic type is defined by: type std_ulogic is ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '–'); The and function for std_ulogic is given by the following truth table. The two inputs are given by the first row and column. www.eej.ulst.ac.uk/~ian/modules/EEE515 13 std_ulogic If we write a model using signals of type BIT or std_ulogic, we must ensure that two models do not attempt to put a value onto the same signal. In VHDL terms, a signal may have one or more sources. A source may be an out, inout or buffer port of an instantiated component or a driver. In simple terms, a driver is the righthand side of a signal assignment. The one occasion when we do try to connect two or more outputs together is when we use three-state buffers. We still have to be careful that no more than one output generates a logic 1 or 0 and the rest of the outputs are in the high-impedance state, but we want the simulator to tell us if there is a design mistake. This cannot be done with std_ulogic – a VHDL simulator does not treat ‘Z’ as a special case. www.eej.ulst.ac.uk/~ian/modules/EEE515 14 std_logic The IEEE 1164 standard defines std_logic, which allows more than one output to be connected to the same signal. Std_logic is defined as a subtype of std_ulogic, for which a resolution function is declared. The resolved function defines the state of a signal if, for example, a ‘Z’ and a ‘1’ are driven onto the same signal. Because VHDL is strongly typed, operations involving two or more types must be explicitly defined. A subtype may, however, be used in place of the type from which it is derived, without causing an error. subtype std_logic is resolved std_ulogic; www.eej.ulst.ac.uk/~ian/modules/EEE515 15 Ideally, we should use std_ulogic for all signals unless we intend that any contention should be resolved. If we were to do this, the simulator would immediately tell us (by halting) if we were erroneously trying to force two conflicting values onto the same piece of wire. 1 In practice, however, some synthesis tools have difficulties with std_ulogic. The use of std_logic now seems to be the accepted industry standard, so in the rest of this book we will use std_logic as the types of all Boolean signals. Contention can be recognized by the unexpected appearance of ‘X’ values in a simulation. Use std_logic_1164 for all real signals! www.eej.ulst.ac.uk/~ian/modules/EEE515 16 library IEEE; use IEEE.std_logic_1164.all; -- The various standard logic types and the -- functions needed to use them are gathered -- together in a package. The various standard -- logic types and the functions needed to use -- them are gathered together in a package. every VHDL model that uses the standard logic package must be prefixed with the 2 lines above www.eej.ulst.ac.uk/~ian/modules/EEE515 17 VHDL Concurrent statements When . . . else library IEEE; use IEEE.std_logic_1164.all; entity three_state is port (a, enable : in std_logic; z : out std_logic); end entity three_state; architecture when_else of three_state is begin z <= a when enable = '1' else 'Z'; -- a tri state -- if you want a delay use z <= a after 4 NS when enable = '1' else 'Z'; end architecture when_else; www.eej.ulst.ac.uk/~ian/modules/EEE515 18 Decoders • type std_logic_vector is array (NATURAL range <>) of std_logic; library IEEE; use IEEE.std_logic_1164.all; entity decoder is port (a : in std_logic_vector(1 downto 0); -- could use to if you want z : out std_logic_vector(3 downto 0)); end entity decoder; architecture when_else of decoder is begin z <= "0001" when a = "00" else "0010" when a = "01" else "0100" when a = "10" else "1000" when a = "11" else "XXXX"; end architecture when_else; www.eej.ulst.ac.uk/~ian/modules/EEE515 If the final else is omitted, z continues to take the last value assigned to it. In VHDL, a signal takes a value until a new value is assigned. This may be interpreted as z holding its value in a latch. 19 With . . . select statement An alternative to the when . . . else statement is the with . . . select statement. Another model of the 2 to 4 decoder is shown below. architecture with_select of decoder is begin with a select z <= "0001" when "00", "0010" when "01", "0100" when "10", "1000" when "11", "XXXX" when others; end architecture with_select; -- all tests done in parallel -- a can have non 0 or 1 values -- so must have others just in case www.eej.ulst.ac.uk/~ian/modules/EEE515 20 Seven segment decoder library IEEE; use IEEE.std_logic_1164.all; entity seven_seg is port (a : in std_logic_vector(3 downto 0); z : out std_logic_vector(6 downto 0)); end entity seven_seg; architecture with_select of seven_seg is begin with a select z <= "1110111" when "0000", "0010010" when "0001", "1011101" when "0010", "1011011" when "0011", "0111010" when "0100", "1101011" when "0101", "1101111" when "0110", "1010010" when "0111", "1111111" when "1000", "1111011" when "1001", "1101101" when "1010"|"1011"|"1100"| "1101"|"1110"|"1111", "0000000" when others; end architecture with_select; www.eej.ulst.ac.uk/~ian/modules/EEE515 21 n to 2n decoder – shift operators We have seen two ways to describe a 2 to 4 decoder. The same structures could easily be adapted to model a 3 to 8 decoder or a 4 to 16 decoder. Although these devices are clearly more complex than the 2 to 4 decoder, conceptually there is little difference. It would be convenient to have a general n to 2n decoder that could be described once but used for any application. We saw in the previous chapter that generics can be used to pass parameters, such as delays, to VHDL models. We can similarly use a generic to define the size of a structure. library IEEE; use IEEE.std_logic_1164.all; entity decoder is generic (n : POSITIVE); port (a : in std_logic_vector(n-1 downto 0); z : out std_logic_vector(2**n-1 downto 0)); end entity decoder; We can also define constants: constant z_out : std_logic_vector(2**n-1 downto 0) := (0 => '1', others => '0'); www.eej.ulst.ac.uk/~ian/modules/EEE515 22 VHDL shift operators • sll, sla, rol, srl, sra, and ror www.eej.ulst.ac.uk/~ian/modules/EEE515 23 VHDL’s strong typing These operators are defined, by default, to shift a BIT_VECTOR by an integer number of places. We will want to shift a std_logic_vector by a number of places given by the integer interpretation of another std_logic_vector. Therefore, it would be easier to declare z_out as a BIT_VECTOR, to convert a to an INTEGER and to convert the final result to a std_logic_vector. This last conversion can be done by a function in the std_logic_1164 package. The other conversion function is not, however, provided. To do this we need to use another package, numeric_std, that provides a set of numeric operators for vectors of std_logic – but not std_logic_vectors! Because vectors of bits can be interpreted to be either signed (two’s complement) or unsigned integers, we need to distinguish the operations performed on such vectors. Therefore the numeric_std package defines two new types: signed and unsigned. VHDL’s strong typing means that we cannot mix signed, unsigned and std_logic_vector by accident, but because all three types consist of arrays of std_logic, www.eej.ulst.ac.uk/~ian/modules/EEE515 24 we can explicitly convert from one to the other using statements of the kind x <= unsigned(y); y <= std_logic_vector(x); where x is of type unsigned and y is of type std_logic_vector. Although these look like function calls, no such function has been defined. These are known as type conversions (sometimes such a conversion is known as a cast). On the other hand, to convert from an unsigned to an INTEGER does require a function call because the possible values (‘X’, ‘Z’, etc.) of the std_logic type need to be interpreted. The function to_integer is provided in numeric_std to achieve this. To convert from an INTEGER to an unsigned type, the to_unsigned(i, n) function should be used, where i is the integer and n is the number of bits in the result. www.eej.ulst.ac.uk/~ian/modules/EEE515 25 Complete Model for Generic decoder library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; entity decoder is generic (n : POSITIVE); port ( a : in std_logic_vector(n-1 downto 0); z : out std_logic_vector(2**n-1 downto 0)); end entity decoder; architecture rotate of decoder is constant z_out : BIT_VECTOR(2**n-1 downto 0) := (0 => '1', others => '0'); begin z <= to_StdLogicVector (z_out sll to_integer(unsigned(a))); end architecture rotate; www.eej.ulst.ac.uk/~ian/modules/EEE515 26 Multiplexers library IEEE; use IEEE.std_logic_1164.all; entity mux is port (a, b, c, d : in std_logic; s: in std_logic_vector(1 downto 0); end entity mux; architecture mux1 of mux is begin with s select y <= a when "00", b when "01", c when "10", d when "11", 'X' when others; end architecture mux1; Can use either architecture, or tristates to implement a multiplexor architecture mux2 of mux is begin y <= a when s = "00" else b when s = "01" else c when s = "10" else d when s = "11" else 'X'; end architecture mux2; www.eej.ulst.ac.uk/~ian/modules/EEE515 27 Using three-state logic to build a multiplexer library IEEE; use IEEE.std_logic_1164.all; entity mux is port (a, b, c, d: in std_logic; s: in std_logic_vector(1 downto 0); y: out std_logic); end entity mux; architecture three_state of mux is begin y <= a when s = "00" else 'Z'; y <= b when s = "01" else 'Z'; y <= c when s = "10" else 'Z'; y <= d when s = "11" else 'Z'; end architecture three_state; www.eej.ulst.ac.uk/~ian/modules/EEE515 28 Priority encoder library IEEE; use IEEE.std_logic_1164.all; entity priority is port (a: in std_logic_vector(3 downto 0); y: out std_logic_vector(1 downto 0); valid: out std_logic); end entity priority; architecture DontCare of priority is begin with a select y <= "00" when "0001", "01" when "001-", "10" when "01--", "11" when "1---", "00" when others; valid <= '1' when a(0) = '1' or a(1) = '1' or a(2) = '1' or a(3) = '1' else '0'; end architecture DontCare; www.eej.ulst.ac.uk/~ian/modules/EEE515 DOES NOT WORK – the don’t know value ‘-’ is just treated as a specific value 29 Note how to get at bits of a vector architecture Ordered of priority is begin y <= "11" when a(3) = '1' else "10" when a(2) = '1' else "01" when a(1) = '1' else "00" when a(0) = '1' else "00"; valid <= '1' when a(0) = '1' or a(1) = '1' or a(2) = '1' or a(3) = '1' else '0'; end architecture Ordered; www.eej.ulst.ac.uk/~ian/modules/EEE515 30 The numeric_std package includes a function, std_match, that treats the don’t care value as a real don’t care condition. We can’t use std_match in a with . . . select statement because the choices must be constant. We can write instead: use IEEE.numeric_std.all; -- can out this here – only applies to this arch architecture Match of priority is begin y <= "00" when std_match(a, "0001") else "01" when std_match(a, "001-") else "10" when std_match(a, "01--") else "11" when std_match(a, "1---") else "00"; valid <= '1' when a(0) = '1' or a(1) = '1' or a(2) = '1' or a(3) = '1' else '0'; end architecture Match; www.eej.ulst.ac.uk/~ian/modules/EEE515 31 Sequential VHDL There are three styles of VHDL: structural, dataflow and sequential. All the examples in this chapter have used the dataflow style. Dataflow statements are concurrent signal assignment statements. Structural VHDL consists of component instantiations. Sequential VHDL resembles a conventional programming language. Sequential VHDL statements can be used only in subprograms (procedures and functions) or processes. www.eej.ulst.ac.uk/~ian/modules/EEE515 32 Sequential VHDL architecture Sequential of priority is The process has a sensitivity list begin process (a) is with one signal, a. The process is begin evaluated only when the signals if a(3) = '1' then in the sensitivity list change. Thus y <= "11"; valid <= '1'; it is important that the sensitivity elsif a(2) = '1' then list includes all signals that might y <= "10"; cause an output to change. In valid <= '1'; elsif a(1) = '1' then this case, a is a vector and the y <= "01"; process is evaluated when any valid <= '1'; bit of a changes. elsif a(0) = '1' then y <= "00"; valid <= '1'; the following rule should be observed: if else an assignment is made to a signal in one y <= "00"; valid <= '0'; path through a process, an assignment end if; should be made to that signal in all paths. end process; 33 end architecture Sequential; www.eej.ulst.ac.uk/~ian/modules/EEE515 Adders library IEEE; use IEEE.std_logic_1164.all, IEEE.numeric_std.all; entity NBitAdder is generic (n: NATURAL :=4); port ( A, B: in std_logic_vector(n-1 downto 0); Cin : in std_logic; Sum : out std_logic_vector(n-1 downto 0); Cout : out std_logic); end entity NBitAdder; www.eej.ulst.ac.uk/~ian/modules/EEE515 34 Addition We can use the arithmetic operator, +, defined in numeric_std to perform the adding operation. This operator takes two vectors, of type signed or unsigned, and returns a result of the same length as the longest operand. The addition of two n-bit integers produces a result of length n 1, where the most significant bit is the carry out bit. Therefore within the VHDL description we must convert Cin from a single bit to a vector of length n 1, convert A and B to vectors of length n1 and separate the result into an n-bit sum and a carry out bit. The code below performs these actions for unsigned addition. www.eej.ulst.ac.uk/~ian/modules/EEE515 35 Conatenation The ampersand, ‘&’, is the concatenation operator. Thus '0' & unsigned(A) concatenates a single bit and an n-bit vector to give a vector of length n +1. So A and B are converted to type unsigned. After addition of three n 1 bit vectors, the lowest n bits of the result are converted back to a std_logic_vector and the most significant bit is taken as the carry out. www.eej.ulst.ac.uk/~ian/modules/EEE515 36 Adder for positive numbers architecture unsgned of NBitAdder is signal result : unsigned(n downto 0); signal carry : unsigned(n downto 0); constant zeros : unsigned(n-1 downto 0) := (others =>'0'); begin carry <= (zeros & Cin); result <= ('0' & unsigned(A)) + ('0' & unsigned(B)) + carry; Sum <= std_logic_vector(result(n-1 downto 0)); Cout <= result(n); end architecture unsgned; www.eej.ulst.ac.uk/~ian/modules/EEE515 37 Adder for signed numbers The major difference here is that the most significant bits of the A and B vectors are used to extend those vectors to the left. If A or B is negative, its most significant bit would be ‘1’ and this must be preserved. architecture sgned of NBitAdder is signal result : signed(n downto 0); signal carry : signed(n downto 0); constant zeros : signed(n-1 downto 0) := (others => '0'); begin carry <= (zeros & Cin); result <= (A(n-1) & signed(A)) + (B(n-1) & signed(B)) + carry; Sum <= std_logic_vector(result(n-1 downto 0)); Cout <= result(n); end architecture sgned; www.eej.ulst.ac.uk/~ian/modules/EEE515 38 Ripple adder library IEEE; use IEEE.std_logic_1164.all; This model contains two assignments, to Sum and Cout. Note that in VHDL, entity FullAdder is these two port (a, b, Cin : in std_logic; assignments are concurrent Sum, Cout: out std_logic); – it does not matter in which end entity FullAdder; order statements are written. The simple rule to architecture concurrent of FullAdder is remember is that unless begin otherwise stated, all Sum <= a xor b xor Cin; Cout <= (a and b) or (a and Cin) or (b and Cin); statements in VHDL are concurrent. end architecture concurrent; www.eej.ulst.ac.uk/~ian/modules/EEE515 39 Parity checker library IEEE; use IEEE.std_logic_1164.all; entity parity is port (a : in std_logic_vector; y : out std_logic); end entity parity; architecture iterative of parity is begin process (a) is variable even : std_logic; begin even := '0'; for i in a'RANGE loop If a(i) = '1' then even := not even; end if; end loop; y <= even; end process; end architecture iterative Note the loop structure here and the use of attributes, put after an object with a tick symbol. Various attributes exist. Also the use of a variable: A variable can only be declared inside a process (a signal may not be declared in a process) and an assignment to a variable (denoted by ‘:=’) takes immediate effect. A signal assignment does not take effect until the process restarts. www.eej.ulst.ac.uk/~ian/modules/EEE515 40 State machines in VHDL Although state machines can be described using concurrent VHDL constructs, the task is far easier using sequential VHDL. We have seen that a VHDL process is evaluated when a signal in its sensitivity list changes. A process may alternatively contain one or more wait statements. A process cannot have both a sensitivity list and wait statements. A sensitivity list is equivalent to putting a wait statement with the signals listed at the end of the process. A state machine changes state at a clock edge. Therefore, the sensitivity list of a process modelling a state machine must include the clock, or the clock must be included in a wait statement. A decision to change state then has to be made on the appropriate clock edge. The state of the system must be held in an internal variable. The state can be represented by an enumerated type. The possible values of this type are the state names, e.g. type state_type is (G, R); -- e.g for traffic lights www.eej.ulst.ac.uk/~ian/modules/EEE515 41 Traffic lights If a car is detected on the minor road, the signals change to red for the major road and green for the minor road. When the lights change, a timer is started. Once that timer completes, a ‘TIMED’ signal is asserted, which causes the lights to change back to their default state. library IEEE; use IEEE.std_logic_1164.all; entity traffic is port ( clock, timed, car : in std_logic; start_timer, major_green, minor_green : out std_logic); end entity traffic; www.eej.ulst.ac.uk/~ian/modules/EEE515 42 Traffic Light Problem There are two graphical design tools commonly used: State diagrams (above) or ASM charts as on the left www.eej.ulst.ac.uk/~ian/modules/EEE515 43 process (clock) is type state_type is (G, R); variable state : state_type; begin start_timer <= '0'; wait until clock = '1' case state is when G => major_green <= '1'; minor_green <= '0'; if (car = '1') then start_timer <= '1'; state := R; end if; when R => major_green <= '0'; minor_green <= '1'; if (timed = '1') then state := G; end if; end case; end process; www.eej.ulst.ac.uk/~ian/modules/EEE515 44 Synthesis Tools As most synthesis tools and the 1076.6 RTL Synthesis standard expect there to be one edge-sensitive statement in a process, it is not possible to correctly model state machines with Mealy outputs using a single VHDL process. A common modelling style for state machines therefore uses two processes. One process is used to model the state registers, while the second process models the next state and output logic. Communication between the two processes is achieved using the present and next values of the state registers. www.eej.ulst.ac.uk/~ian/modules/EEE515 45 Classical two process FSM – USE this!!! architecture asm2 of traffic is type state_type is (G, R); signal present_state, next_state : state_type; begin -- First of two processes… seq: process (clock) is begin if(rising_edge(clock)) then present_state <= next_state; end if; end process seq; www.eej.ulst.ac.uk/~ian/modules/EEE515 46 com: process (car, timed, present_state) is begin start_timer <= '0'; case present_state is when G => major_green <= '1'; minor_green <= '0'; if (car = '1') then start_timer <= '1'; -- note this is a Mealy machine. next_state <= R; else next_state <= G; end if; when R => major_green <= '0'; minor_green <= '1'; if (timed = '1') then next_state <= G; else next_state <= R; end if; end case; end process com; www.eej.ulst.ac.uk/~ian/modules/EEE515 end architecture asm2; 47 VHDL models of sequential logic blocks Latches Flip-flops JK and T flip-flops Registers and shift registers Counters Memory Sequential multiplier Testbenches for sequential building blocks www.eej.ulst.ac.uk/~ian/modules/EEE515 48