---------------------------------------------------------------- -- Chapter 14 Generate Statements ---------------------------------------------------------------- ---------------------------------------------------------------- -- 14.1 Generating Iterative Structures ---------------------------------------------------------------- -- Example 14.1, Page 450 library ieee; use ieee.std_logic_1164.all; entity register_tristate is generic ( width : positive ); port ( clock : in std_ulogic; out_enable : in std_ulogic; data_in : in std_ulogic_vector(0 to width - 1); data_out : out std_ulogic_vector(0 to width - 1) ); end entity register_tristate; architecture cell_level of register_tristate is component D_flipflop is port ( clk : in std_ulogic; d : in std_ulogic; q : out std_ulogic ); end component D_flipflop; component tristate_buffer is port ( a : in std_ulogic; en : in std_ulogic; y : out std_ulogic ); end component tristate_buffer; begin cell_array : for bit_index in 0 to width - 1 generate signal data_unbuffered : std_ulogic; begin cell_storage : component D_flipflop port map ( clk => clock, d => data_in(bit_index), q => data_unbuffered ); cell_buffer : component tristate_buffer port map ( a => data_unbuffered, en => out_enable, y => data_out(bit_index) ); end generate cell_array; end architecture cell_level; -- Example 14.2, Page 452 architecture behavioral of graphics_engine is type point is array (1 to 3) of real; type transformation_matrix is array (1 to 3, 1 to 3) of real; signal p, transformed_p : point; signal a : transformation_matrix; signal clock : bit; ... begin transform_stage : for i in 1 to 3 generate begin cross_product_transform : process is variable result1, result2, result3 : real := 0.0; begin wait until clock = '1'; transformed_p(i) <= result3; result3 := result2; result2 := result1; result1 := a(i, 1) * p(1) + a(i, 2) * p(2) + a(i, 3) * p(3); end process cross_product_transform; end generate transform_stage; ... -- other stages in the pipeline, etc end architecture behavioral; -- Example 14.3, Page 453 architecture generated of memory is component SRAM is port ( clk : in std_ulogic; a : in std_ulogic_vector(0 to 10); d : inout std_ulogic_vector(0 to 3); en, we : in std_ulogic ); end component SRAM; signal buffered_address : std_ulogic_vector(0 to 10); signal SRAM_data : std_ulogic_vector(0 to 31); signal bank_select : std_ulogic_vector(0 to 3); signal buffered_we : std_ulogic; ... -- other declarations begin bank_array : for bank_index in 0 to 3 generate begin nibble_array : for nibble_index in 0 to 7 generate constant data_lo : natural := nibble_index * 4; constant data_hi : natural := nibble_index * 4 + 3; begin an_SRAM : component SRAM port map ( clk => clk, a => buffered_address, d => SRAM_data(data_lo to data_hi), en => bank_select(bank_index), we => buffered_we ); end generate nibble_array; end generate bank_array; ... -- other component instances, etc end architecture generated; -- Page 455 signal data_unbuffered : std_ulogic_vector(0 to width - 1); ---------------------------------------------------------------- -- 14.2 Conditionally Generating Structures ---------------------------------------------------------------- -- Example 14.4, Page 456 library ieee; use ieee.std_logic_1164.all; entity shift_reg is port ( phi1, phi2 : in std_ulogic; serial_data_in : in std_ulogic; parallel_data : out std_ulogic_vector ); end entity shift_reg; -------------------------------------------------- architecture cell_level of shift_reg is alias normalized_parallel_data : std_ulogic_vector(0 to parallel_data'length - 1) is parallel_data; component master_slave_flipflop is port ( phi1, phi2 : in std_ulogic; d : in std_ulogic; q : out std_ulogic ); end component master_slave_flipflop; begin reg_array : for index in normalized_parallel_data'range generate begin reg : if index = 0 generate cell : component master_slave_flipflop port map ( phi1, phi2, d => serial_data_in, q => normalized_parallel_data(index) ); else generate cell : component master_slave_flipflop port map ( phi1, phi2, d => normalized_parallel_data(index - 1), q => normalized_parallel_data(index) ); end generate other_cell; end generate reg_array; end architecture cell_level; -- Example 14.5, Page 457 adder: for i in width-1 downto 0 generate signal carry_chain : unsigned(width-1 downto 1); begin adder_cell: if i = width-1 generate -- most-significant cell add_bit: component full_adder port map (a => a(i), b => b(i), s => s(i), c_in => carry_chain(i), c_out => c_out); elsif i = 0 generate -- least-significant cell add_bit: component half_adder port map (a => a(i), b => b(i), s => s(i), c_out => carry_chain(i+1)); else generate -- middle cell add_bit: component full_adder port map (a => a(i), b => b(i), s => s(i), c_in => carry_chain(i), c_out => carry_chain(i+1)); end generate adder_cell; end generate adder; -- Example 14.6, Page 458 entity computer_system is generic ( instrumented : boolean := false ); port ( ... ); end entity computer_system; architecture block_level of computer_system is ... -- type and component declarations for cpu and memory, etc signal clock : bit; -- the system clock signal mem_req : bit; -- cpu access request to memory signal ifetch : bit; -- indicates access is -- to fetch an instruction signal write : bit; -- indicates access is a write ... -- other signal declarations begin ... -- component instances for cpu and memory, etc instrumentation : if instrumented generate signal ifetch_freq, write_freq, read_freq : real := 0.0; begin access_monitor : process is variable access_count, ifetch_count, write_count, read_count : natural := 0; begin wait until mem_req; if ifetch then ifetch_count := ifetch_count + 1; elsif write then write_count := write_count + 1; else read_count := read_count + 1; end if; access_count := access_count + 1; ifetch_freq <= real(ifetch_count) / real(access_count); write_freq <= real(write_count) / real(access_count); read_freq <= real(read_count) / real(access_count); end process access_monitor; end generate instrumentation; end architecture block_level; -- Example 14.6, Page 459 for system_under_test : computer_system use entity work.computer_system(block_level) generic map ( instrumented => true ) ... end for; -- Page 459 msb_cell: if i = width-1 generate -- most-significant cell ... end generate msb_cell; lsb_cell: if i = 0 generate -- least-significant cell ... end generate lsb_cell; mid_cell: if i > 0 and i < width-1 generate -- middle cell ... end generate lsb_cell; -- Example 14.7, Page 461 type implementation_type is (single_cycle, multicycle, pipelined); entity complex_multiplier is generic ( implementation : implementation_type; ... ); port ( ... ); end entity complex_multiplier; architecture rtl of complex_multiplier is ... begin mult_structure : case implementation generate when single_cycle => signal real_pp1, real_pp2 : ...; ... begin real_mult1 : component multiplier port map ( ... ); ... end; when multicycle => signal real_pp1, real_pp2 : ...; ... begin mult : component multiplier port map ( ... ); ... end; when pipelined => signal real_pp1, real_pp2 : ...; ... begin mult1 : component multiplier port map ( ... ); ... end; end generate mutl_structure; end architecture rtl; ---------------------------------------------------------------- -- 14.2.1 Recursive Structures ---------------------------------------------------------------- -- Example 14.8, Page 462 library ieee; use ieee.std_logic_1164.all; entity fanout_tree is generic ( height : natural ); port ( input : in std_ulogic; output : out std_ulogic_vector (0 to 2**height - 1) ); end entity fanout_tree; -- Example 14.8, Page 463 architecture recursive of fanout_tree is begin tree : if height = 0 generate output(0) <= input; else generate -- height > 0 signal buffered_input_0, buffered_input_1 : std_ulogic; begin buf_0 : entity work.buf(basic) port map ( a => input, y => buffered_input_0 ); subtree_0 : entity work.fanout_tree(recursive) generic map ( height => height - 1 ) port map ( input => buffered_input_0, output => output(0 to 2**(height - 1) - 1) ); buf_1 : entity work.buf(basic) port map ( a => input, y => buffered_input_1 ); subtree_1 : entity work.fanout_tree(recursive) generic map ( height => height - 1 ) port map ( input => buffered_input_1, output => output(2**(height - 1) to 2**height - 1) ); end; end generate tree; end architecture recursive; -- Example 14.8, Page 464 clock_buffer_tree : entity work.fanout_tree(recursive) generic map ( height => 3 ) port map ( input => unbuffered_clock, output => buffered_clock_array ); -- Page 465 block_0 : block for subtree_0 : fanout_tree use entity work.fanout_tree(recursive); begin subtree_0 : fanout_tree generic map ( height => height - 1 ) port map ( input => buffered_input_0, output => output(0 to 2**(height - 1) - 1) ); end block block_0; ---------------------------------------------------------------- -- 14.3 Configuration of Generate Statements ---------------------------------------------------------------- -- Example 14.9, Page 466 entity computer_system is generic ( instrumented : boolean := false ); port ( ... ); end entity computer_system; architecture block_level of computer_system is ... -- type and component declarations for cpu and memory, etc. signal clock : bit; -- the system clock signal mem_req : bit; -- cpu access request to memory signal ifetch : bit; -- indicates access is -- to fetch an instruction signal write : bit; -- indicates access is a write ... -- other signal declarations begin ... -- component instances for cpu and memory, etc. instrumentation : if instrumented generate use work.bus_monitor_pkg; signal bus_stats : bus_monitor_pkg.stats_type; begin cpu_bus_monitor : component bus_monitor_pkg.bus_monitor port map ( mem_req, ifetch, write, bus_stats ); end generate instrumentation; end architecture block_level; -- Example 14.9, Page 467 configuration architectural of computer_system is for block_level ... -- component configurations for cpu and memory, etc for instrumentation for cpu_bus_monitor : bus_monitor_pkg.bus_monitor use entity work.bus_monitor(general_purpose) generic map ( verbose => true, dump_stats => true ); end for; end for; end for; end configuration architectural; -- Example 14.10, Page 467 library cell_lib; configuration identical_cells of register_tristate is for cell_level for cell_array for cell_storage : D_flipflop use entity cell_lib.D_flipflop(synthesized); end for; for cell_buffer : tristate_buffer use entity cell_lib.tristate_buffer(synthesized); end for; end for; end for; end configuration identical_cells; -- Example 14.11, Page 468 library core_lib; use core_lib.all; configuration behavioral_SRAM of memory is for generated for bank_array for nibble_array for an_SRAM : SRAM use entity SRAM_4M_by_4(behavior); end for; end for; end for; ... -- configurations of other component instances end for; end configuration behavioral_SRAM; -- Example 14.12, Page 469 adder: for i in width-1 downto 0 generate signal carry_chain : unsigned(width-1 downto 1); begin adder_cell: if most_significant: i = width-1 generate add_bit: component full_adder port map (...); elsif least_significant: i = 0 generate add_bit: component half_adder port map (...); else middle: generate add_bit: component full_adder port map (...); end generate adder_cell; end generate adder; -- Example 14.12, Page 470 configuration widget_cfg of arith_unit is for ripple_adder for adder for adder_cell(most_significant) for add_bit: full_adder use entity widget_lib.full_adder(asic_cell); end for; end for; for adder_cell(middle) for add_bit: full_adder use entity widget_lib.full_adder(asic_cell); end for; end for; for adder_cell(least_significant) for add_bit: half_adder use entity widget_lib.half_adder(asic_cell); end for; end for; end for; -- adder end for; -- ripple_adder end configuration widget_cfg; -- Example 14.13, Page 471 mult_structure : case implementation generate when single_cycle_mult: single_cycle => ... when multicycle_mult: multicycle => ... when pipelined_mult: pipelined => ...; end generate mult_structure; configuration wallace_tree of complex_multiplier is for rtl for mult_structure(single_cycle_mult) for real_mult1 : multiplier use entity work.multiplier(wallace_tree); ... end for; end for; for mult_structure(multicycle_mult) for mult : multiplier use entity work.multiplier(wallace_tree); ... end for; end for; for mult_structure(pipelined_mult) for mult1 : multiplier use entity work.multiplier(wallace_tree); ... end for; end for; end for; -- rtl end for wallage_tree; -- Example 14.14, Page 472 architecture cell_level of shift_reg is ... begin reg_array : for index in normalized_parallel_data'range generate begin reg : if first_cell : index = 0 generate cell : component master_slave_flipflop port map ( ... ); else other_cell : generate cell : component master_slave_flipflop port map ( ... ); end generate other_cell; end generate reg_array; end architecture cell_level; library cell_lib; configuration last_high_drive of shift_reg is for cell_level for reg_array ( 0 to parallel_data'length - 2 ) for reg(first_cell) for cell : master_slave_flipflop use entity cell_lib.ms_flipflop(normal_drive); end for; end for; for reg(other_cell) for cell : master_slave_flipflop use entity cell_lib.ms_flipflop(normal_drive); end for; end for; end for; for reg_array ( parallel_data'length - 1 ) for reg(other_cell) for cell : master_slave_flipflop use entity cell_lib.ms_flipflop(high_drive); end for; end for; end for; end for; end configuration last_high_drive; ---------------------------------------------------------------- -- Exercises ---------------------------------------------------------------- -- Exercise 1 synch_delay_line : for stage in 1 to 4 generate delay_ff : component d_ff port map ( clk => sys_clock, d => delayed_data(stage - 1), q => delayed_data(stage) ); end generate synch_delay_line;