---------------------------------------------------------------- -- Chapter 3 Sequential Statements ---------------------------------------------------------------- ---------------------------------------------------------------- -- 3.1 If Statements ---------------------------------------------------------------- -- Page 66 if en then stored_value := data_in; end if; if sel = 0 then result <= input_0; -- executed if sel = 0 else result <= input_1; -- executed if sel /= 0 end if; if mode = immediate then operand := immed_operand; elsif opcode = load or opcode = add or opcode = subtract then operand := memory_operand; else operand := address_operand; end if; if opcode = halt_opcode then PC := effective_address; executing := false; halt_indicator <= true; end if; -- Page 67 if phase = wash then if cycle_select = delicate_cycle then agitator_speed <= slow; else agitator_speed <= fast; end if; agitator_on <= true; end if; -- Example 3.1, Page 67 entity thermostat is port ( desired_temp, actual_temp : in integer; heater_on : out boolean ); end entity thermostat; -------------------------------------------------- architecture example of thermostat is begin controller : process (desired_temp, actual_temp) is begin if actual_temp < desired_temp - 2 then heater_on <= true; elsif actual_temp > desired_temp + 2 then heater_on <= false; end if; end process controller; end architecture example; ---------------------------------------------------------------- -- 3.1.1 Conditional Variable Assignments ---------------------------------------------------------------- -- Page 69 result := a - b when mode = subtract else a + b; if mode = subtract then result := a - b; else result := a + b; end if; ---------------------------------------------------------------- -- 3.2 Case Statements ---------------------------------------------------------------- -- Page 69 type alu_func is (pass1, pass2, add, subtract); case func is when pass1 => result := operand1; when pass2 => result := operand2; when add => result := operand1 + operand2; when subtract => result := operand1 - operand2; end case; -- Page 70 subtype index_mode is integer range 0 to 3; variable instruction_register : integer range 0 to 2**16 - 1; case index_mode'((instruction_register / 2**12) rem 2**2) is when 0 => index_value := 0; when 1 => index_value := accumulator_A; when 2 => index_value := accumulator_B; when 3 => index_value := index_register; end case; -- Page 71 type opcodes is (nop, add, subtract, load, store, jump, jumpsub, branch, halt); when load | add | subtract => operand := memory_operand; case opcode is when load | add | subtract => operand := memory_operand; when store | jump | jumpsub | branch => operand := address_operand; when others => operand := 0; end case; -- Page 72 case opcode is when add to load => operand := memory_operand; when branch downto store => operand := address_operand; when others => operand := 0; end case; subtype control_transfer_opcodes is opcodes range jump to branch; when control_transfer_opcodes | store => operand := address_operand; variable N : integer := 1; case expression is -- example of an illegal case statement when N | N+1 => ... when N+2 to N+5 => ... when others => ... end case; -- Page 73 constant C : integer := 1; case expression is when C | C+1 => ... when C+2 to C+5 => ... when others => ... end case; -- Example 3.2, Page 73 type sel_range is range 0 to 3; library ieee; use ieee.std_logic_1164.all; entity mux4 is port ( sel : in sel_range; d0, d1, d2, d3 : in std_ulogic; z : out std_ulogic ); end entity mux4; -------------------------------------------------- architecture demo of mux4 is begin out_select : process (sel, d0, d1, d2, d3) is begin case sel is when 0 => z <= d0; when 1 => z <= d1; when 2 => z <= d2; when 3 => z <= d3; end case; end process out_select; end architecture demo; ---------------------------------------------------------------- -- 3.2.1 Selected Variable Assignments ---------------------------------------------------------------- -- Page 75 with func select result := operand1 when pass1, operand2 when pass2, operand1 + operand2 when add, operand1 - operand2 when subtract; ---------------------------------------------------------------- -- 3.3 Null Statements ---------------------------------------------------------------- -- Page 75 case opcode is when add => Acc := Acc + operand; when subtract => Acc := Acc - operand; when nop => null; end case; -- Page 76 control_section : process ( sensitivity_list ) is begin null; end process control_section; ---------------------------------------------------------------- -- 3.4 Loop Statements ---------------------------------------------------------------- -- Example 3.3, Page 76 entity counter is port ( clk : in bit; count : out natural ); end entity counter; -------------------------------------------------- architecture behavior of counter is begin incrementer : process is variable count_value : natural := 0; begin count <= count_value; loop wait until clk; count_value := (count_value + 1) mod 16; count <= count_value; end loop; end process incrementer; end architecture behavior; ---------------------------------------------------------------- -- 3.4.1 Exit Statements ---------------------------------------------------------------- -- Page 77 if condition then exit; end if; -- Page 78 loop ... exit when condition; ... end loop; ... -- control transferred to here -- when condition becomes true within the loop -- Example 3.4, Page 78 entity counter is port ( clk, reset : in bit; count : out natural ); end entity counter; -------------------------------------------------- architecture behavior of counter is begin incrementer : process is variable count_value : natural := 0; begin count <= count_value; loop loop wait until clk or reset; exit when reset; count_value := (count_value + 1) mod 16; count <= count_value; end loop; -- at this point, reset = '1' count_value := 0; count <= count_value; wait until not reset; end loop; end process incrementer; end architecture behavior; -- Page 79 loop_name : loop ... exit loop_name; ... end loop loop_name; outer : loop ... inner : loop ... exit outer when condition_1; -- exit 1 ... exit when condition_2; -- exit 2 ... end loop inner; ... -- target A exit outer when condition_3; -- exit 3 ... end loop outer; ... -- target B -- Page 80 exit when reset = '1'; ---------------------------------------------------------------- -- 3.4.2 Next Statements ---------------------------------------------------------------- -- Page 81 loop statement_1; next when condition; statement_2; end loop; loop statement_1; if not condition then statement_2; end if; end loop; ---------------------------------------------------------------- -- 3.4.3 While Loops ---------------------------------------------------------------- -- Page 82 while index > 0 loop ... -- statement A: do something with index end loop; ... -- statement B -- Example 3.5, Page 82 entity cos is port ( theta : in real; result : out real ); end entity cos; -------------------------------------------------- architecture series of cos is begin summation : process (theta) is variable sum, term : real; variable n : natural; begin sum := 1.0; term := 1.0; n := 0; while abs term > abs (sum / 1.0E6) loop n := n + 2; term := (-term) * theta**2 / real(((n-1) * n)); sum := sum + term; end loop; result <= sum; end process summation; end architecture series; ---------------------------------------------------------------- -- 3.4.4 For Loops ---------------------------------------------------------------- -- Page 84 for count_value in 0 to 127 loop count_out <= count_value; wait for 5 ns; end loop; type controller_state is (initial, idle, active, error); for state in controller_state loop ... end loop; erroneous : process is variable i, j : integer; begin i := loop_param; -- error! for loop_param in 1 to 10 loop loop_param := 5; -- error! end loop; j := loop_param; -- error! end process erroneous; -- Page 85 hiding_example : process is variable a, b : integer; begin a := 10; for a in 0 to 7 loop b := a; end loop; -- a = 10, and b = 7 ... end process hiding_example; for i in 10 to 1 loop ... end loop; for i in 10 downto 1 loop ... end loop; -- Example 3.6, Page 86 architecture fixed_length_series of cos is begin summation : process (theta) is variable sum, term : real; begin sum := 1.0; term := 1.0; for n in 1 to 9 loop term := (-term) * theta**2 / real(((2*n-1) * 2*n)); sum := sum + term; end loop; result <= sum; end process summation; end architecture fixed_length_series; ---------------------------------------------------------------- -- 3.4.5 Summary of Loop Statements ---------------------------------------------------------------- ---------------------------------------------------------------- -- 3.5 Assertion and Report Statements ---------------------------------------------------------------- -- Page 87 assert initial_value <= max_value; assert initial_value <= max_value report "initial value too large"; assert current_character >= '0' and current_character <= '9' report "Input number " & input_string & " contains a non-digit"; -- Page 88 assert initial_value <= max_value report "initial value " & to_string(initial_value) & " too large"; type severity_level is (note, warning, error, failure); assert free_memory >= low_water_limit report "low on memory, about to start garbage collect" severity note; assert packet_length /= 0 report "empty network packet received" severity warning; assert clock_pulse_width >= min_clock_width severity error; assert (last_position - first_position + 1) = number_of_entries report "inconsistency in buffer model" severity failure; -- Example 3.7, Page 89 entity SR_flipflop is port ( S, R : in bit; Q : out bit ); end entity SR_flipflop; -------------------------------------------------- architecture checking of SR_flipflop is begin set_reset : process (S, R) is begin assert S nand R; if S then Q <= '1'; end if; if R then Q <= '0'; end if; end process set_reset; end architecture checking; -- Example 3.8, Page 90 entity max3 is port ( a, b, c : in integer; z : out integer ); end entity max3; -------------------------------------------------- architecture check_error of max3 is begin maximizer : process (a, b, c) variable result : integer; begin if a > b then if a > c then result := a; else result := a; -- Oops! Should be: result := c; end if; elsif b > c then result := b; else result := c; end if; assert result >= a and result >= b and result >= c report "inconsistent result for maximum: " & to_string(result) severity failure; z <= result; end process maximizer; end architecture check_error; -- Example 3.9, Page 91 entity edge_triggered_register is port ( clock : in bit; d_in : in real; d_out : out real ); end entity edge_triggered_register; -------------------------------------------------- architecture check_timing of edge_triggered_register is begin store_and_check : process (clock) is variable stored_value : real; variable pulse_start : time; begin if rising_edge(clock) then pulse_start := now; stored_value := d_in; d_out <= stored_value; else assert now = 0 ns or (now - pulse_start) >= 5 ns report "clock pulse too short: " & to_string(now - pulse_start); end if; end process store_and_check; end architecture check_timing; -- Example 3.10, Page 92 transmit_element : process (transmit_data) is ... -- variable declarations begin report "transmit_element: data = " & to_string(transmit_data); ... end process transmit_element; -- Page 92 assert data = expected_data report "%%%ERROR data value miscompare." & LF & " Actual value = " & to_string(data) & LF & " Expected value = " & to_string(expected_data) & LF & " at time: " & to_string(now); -- Page 93 report "Initialization complete"; assert false report "Initialization complete" severity note; ---------------------------------------------------------------- -- Exercises ----------------------------------------------------------------