Pacote Aritmético - Bit Vector • VHDL => operações aritméticas para tipos pré-definidos. • Bit vector => transformação de tipo bit vector para o tipo mais adequado (integer ou natural) Pacote Aritmético - Bit Vector • Pacote de funções aritméticas bit vector package bv_arithmetic is function bv_to_natural ( bv : in bit_vector ) return natural; function natural_to_bv ( nat : in natural; length : in natural ) return bit_vector; function bv_to_integer ( bv : in bit_vector ) return integer; function integer_to_bv ( int : in integer; length : in natural ) return bit_vector; Pacote Aritmético - Bit Vector • Pacote de funções aritméticas bit vector - cont procedure bv_add ( bv1, bv2 : in bit_vector; bv_result : out bit_vector; overflow : out boolean ); function "+" ( bv1, bv2 : in bit_vector ) return bit_vector; procedure bv_sub ( bv1, bv2 : in bit_vector; bv_result : out bit_vector; overflow : out boolean ); function "-" ( bv1, bv2 : in bit_vector ) return bit_vector; procedure bv_addu ( bv1, bv2 : in bit_vector; bv_result : out bit_vector; overflow : out boolean ); Pacote Aritmético - Bit Vector Pacote de funções aritméticas bit vector - cont function bv_addu ( bv1, bv2 : in bit_vector ) return bit_vector; procedure bv_subu ( bv1, bv2 : in bit_vector; bv_result : out bit_vector; overflow : out boolean ); function bv_subu ( bv1, bv2 : in bit_vector ) return bit_vector; procedure bv_neg ( bv : in bit_vector; bv_result : out bit_vector; overflow : out boolean ); Pacote Aritmético - Bit Vector • Pacote de funções aritméticas bit vector - cont function "-" ( bv : in bit_vector ) return bit_vector; procedure bv_mult ( bv1, bv2 : in bit_vector; bv_result : out bit_vector; overflow : out boolean ); function "*" ( bv1, bv2 : in bit_vector ) return bit_vector; procedure bv_multu ( bv1, bv2 : in bit_vector; bv_result : out bit_vector; overflow : out boolean ); function bv_multu ( bv1, bv2 : in bit_vector ) return bit_vector; Pacote Aritmético - Bit Vector • Pacote de funções aritméticas bit vector - cont procedure bv_div ( bv1, bv2 : in bit_vector; bv_result : out bit_vector; div_by_zero : out boolean; overflow : out boolean ); function "/" ( bv1, bv2 : in bit_vector ) return bit_vector; procedure bv_divu ( bv1, bv2 : in bit_vector; bv_quotient : out bit_vector; bv_remainder : out bit_vector; div_by_zero : out boolean ); procedure bv_divu ( bv1, bv2 : in bit_vector; bv_quotient : out bit_vector; div_by_zero : out boolean ); Pacote Aritmético - Bit Vector • Pacote de funções aritméticas bit vector - cont function bv_divu ( bv1, bv2 : in bit_vector ) return bit_vector; function bv_lt ( bv1, bv2 : in bit_vector ) return boolean; function bv_le ( bv1, bv2 : in bit_vector ) return boolean; function bv_gt ( bv1, bv2 : in bit_vector ) return boolean; function bv_ge ( bv1, bv2 : in bit_vector ) return boolean; function bv_sext ( bv : in bit_vector; length : in natural ) return bit_vector; function bv_zext ( bv : in bit_vector; length : in natural ) return bit_vector; end package bv_arithmetic; Pacote Aritmético - Bit Vector • Corpo do Pacote package body bv_arithmetic is -- corpo dos procedimentos e funções end package body bv_arithmetic Pacote Aritmético - Bit Vector • Corpo do Pacote - cont. function bv_to_natural ( bv : in bit_vector ) return natural is variable result : natural := 0; begin for index in bv'range loop result := result * 2 + bit'pos( bv(index) ); end loop; return result; end function bv_to_natural; Pacote Aritmético - Bit Vector • Corpo do Pacote - cont. function natural_to_bv ( nat : in natural; length : in natural ) return bit_vector is variable temp : natural := nat; variable result : bit_vector(length - 1 downto 0) := (others => '0'); begin for index in result'reverse_range loop result(index) := bit'val( temp rem 2 ); temp := temp / 2; exit when temp = 0; end loop; return result; end function natural_to_bv; Pacote Aritmético - Bit Vector • Corpo do Pacote - cont. procedure bv_add ( bv1, bv2 : in bit_vector; bv_result : out bit_vector; overflow : out boolean ) is alias op1 : bit_vector(bv1'length - 1 downto 0) is bv1; alias op2 : bit_vector(bv2'length - 1 downto 0) is bv2; variable result : bit_vector(bv_result'length - 1 downto 0); variable carry_in : bit; variable carry_out : bit := '0'; Pacote Aritmético - Bit Vector • Corpo do Pacote - cont. begin if bv1'length /= bv2'length or bv1'length /= bv_result'length then report "bv_add: operands of different lengths"severity failure; else for index in result'reverse_range loop carry_in := carry_out; -- of previous bit result(index) := op1(index) xor op2(index) xor carry_in; carry_out := (op1(index) and op2(index)) or (carry_in and (op1(index) xor op2(index))); end loop; bv_result := result; overflow := carry_out /= carry_in; end if; end procedure bv_add; Pacote Aritmético - Bit Vector • Corpo do Pacote - cont. procedure bv_neg ( bv : in bit_vector; bv_result : out bit_vector; overflow : out boolean ) is constant zero : bit_vector(bv'range) := (others => '0'); begin bv_sub( zero, bv, bv_result, overflow ); end procedure bv_neg; Guards e Blocks signal identificador {,....} : subtype [ register | bus ] [:= expressão] Guarded signals - resolved signals para os quais se pode desconectar os drivers, ou seja, fazer com que um ou mais drivers parem de contribuir com a definição do valor do sinal. function pulled_up ( drivers : bit_vector ) return bit is begin for index in drivers'range loop if drivers(index) = '0' then return '0'; end if; end loop; return '1'; end function pulled_up; type state_type is (init_state, state1, state2, state3); type state_vector is array (integer range <>) of state_type; function resolve_state ( drivers : state_vector ) return state_type is begin return drivers(drivers'left); end function resolve_state; signal interrupt_request : pulled_up bit bus; signal stored_state : resolve_state state_type register := init_state; Guards e Blocks architecture top_level of computer_system is function resolve_bits ( bits : bit_vector ) return bit is variable result : bit := '0'; begin for index in bits'range loop result := result or bits(index); exit when result = '1'; end loop; return result; end function resolve_bits; signal write_en : resolve_bits bit bus; ... constant Tpd : delay_length := 2 ns; signal clock, hold_req : bit := '0'; begin CPU : process is ... begin write_en <= '0' after Tpd; ... loop wait until clock = '1'; if hold_req = '1' then write_en <= null after Tpd; wait on clock until clock = '1' and hold_req = '0'; write_en <= '0' after Tpd; end if; ... end loop; end process CPU; ... clock_gen : clock <= '1' after 5 ns, '0' after 10 ns when clock = '0'; stimulus : hold_req <= '1' after 40 ns, '0' after 80 ns; process is begin write_en <= null, '1' after 50 ns, '0' after 60 ns, null after 70 ns; wait; end process; end architecture top_level; Guards e Blocks architecture rtl of processor is subtype word is bit_vector(0 to 31); type word_vector is array (natural range <>) of word; function resolve_unique ( drivers : word_vector ) return word is begin return drivers(drivers'left); end function resolve_unique; signal source1, source2 : resolve_unique word register; ... type alu_op_type is (pass1, pass2, add, subtract); procedure perform_alu_op ( signal alu_opcode : in alu_op_type; signal source1, source2 : in word; signal destination : out word; constant ignored : in integer := 0 ) is begin null; end procedure perform_alu_op; signal phase1, source1_reg_out_en,other_signal : bit; signal alu_opcode : alu_op_type; signal destination : word; begin source1_reg : process (phase1, source1_reg_out_en) is variable stored_value : word; begin ... if source1_reg_out_en = '1' and phase1 = '1' then source1 <= stored_value; stored_value := not stored_value; else source1 <= null; end if; end process source1_reg; alu : perform_alu_op ( alu_opcode, source1, source2, destination, open ); ... process is begin wait for 10 ns; source1_reg_out_en <= '1'; phase1 <= '1', '0' after 10 ns; wait for 20 ns; source1_reg_out_en <= '1'; phase1 <= '1', '0' after 10 ns; wait; end process; end architecture rtl; Guarded Ports subtype byte is bit_vector(0 to 7); type byte_array is array (integer range <>) of byte; function resolve (bytes : byte_array) return byte; subtype resolved_byte is resolve byte; entity tri_state_reg is port( d : in resolved_byte; q : out resolved_byte bus; clock, out_enable : in bit); end entity tri_state_reg; function resolve ( bytes : byte_array ) return byte is variable result : byte := b"0000_0000"; begin for index in bytes'range loop result := result or bytes(index); end loop; return result; end function resolve; architecture behavioral of tri_state_reg is begin reg_behavior : process (d, clock, out_enable) is variable stored_byte : byte; begin if clock'event and clock = '1' then stored_byte := d; end if; if out_enable = '1' then q <= stored_byte; else q <= null; end if; end process reg_behavior; end architecture behavioral; Guarded Signals Parameters architecture high_level of data_logger is subtype byte is bit_vector(7 downto 0); type byte_array is array (integer range <>) of byte; function resolver ( bytes : byte_array ) return byte is begin if bytes'length > 0 then return bytes( bytes'left ); else return X"00"; end if; end function resolver; subtype resolved_byte is resolver byte; procedure reg ( signal clock, out_enable : in bit; signal d : in byte; signal q : out resolved_byte ) is variable stored_byte : byte; begin loop if clock = '1' then stored_byte := d; end if; if out_enable = '1' then q <= stored_byte; else q <= null; end if; wait on clock, out_enable, d; end loop; end procedure reg; signal data_bus : resolved_byte bus; ... signal a_reg_clk, b_reg_clk, a_reg_read, b_reg_read : bit := '0'; signal port_a, port_b : byte := X"00"; begin a_reg : reg (a_reg_clk, a_reg_read, port_a, data_bus); b_reg : reg (b_reg_clk, b_reg_read, port_b, data_bus); ... stimulus : process is begin port_a <= X"11"; a_reg_clk <= '1', '0' after 5 ns; wait for 10 ns; a_reg_read <= '1', '0' after 5 ns; wait for 10 ns; port_b <= X"21"; b_reg_clk <= '1', '0' after 5 ns; wait for 10 ns; b_reg_read <= '1', '0' after 5 ns; wait for 10 ns; a_reg_read <= '1', '0' after 5 ns; b_reg_read <= '1', '0' after 5 ns; wait; end process stimulus; end architecture high_level; Blocks e atribuição a Guarded Signals architecture test of fg_16_07 is constant reg0 : std_logic_vector(7 downto 0) := "00000000"; constant reg1 : std_logic_vector(7 downto 0) := "11111111"; signal dbus : std_logic_vector(7 downto 0); signal reg_sel, read, reg_addr : X01 := '0'; begin reg_read_selector : block (reg_sel = '1' and read = '1') is begin dbus <= reg0 when guard and reg_addr = '0' else reg1 when guard and reg_addr = '1' else "ZZZZZZZZ"; end block reg_read_selector; stimulus : process is begin reg_sel <= '1'; wait for 10 ns; read <= '1', '0' after 5 ns; wait for 10 ns; reg_sel <= '0'; wait for 10 ns; read <= '1', '0' after 5 ns; wait for 10 ns; reg_addr <= '1'; wait for 10 ns; reg_sel <= '1'; wait for 10 ns; read <= '1', '0' after 5 ns; wait for 10 ns; wait; end process stimulus; end architecture test; Blocks e atribuição a Guarded Signals architecture dataflow of processor_node is subtype word is bit_vector(31 downto 0); type word_vector is array (natural range <>) of word; function resolve_unique ( drivers : word_vector ) return word is begin if drivers'length > 0 then return drivers(drivers'left); else return X"00000000"; end if; end function resolve_unique; signal address_bus : resolve_unique word bus; signal cache_miss, dirty, replace_section, snoop_hit, flag_update : bit := '0'; constant tag_section0 : bit_vector(11 downto 0) := X"000"; constant tag_section1 : bit_vector(11 downto 0) := X"001"; constant set_index : bit_vector(15 downto 0) := X"6666"; constant snoop_address : word := X"88888888"; begin cache_to_address_buffer : block ( cache_miss = '1' and dirty = '1' ) is begin address_bus <= guarded tag_section0 & set_index & B"0000” when replace_section = '0' else tag_section1 & set_index & B"0000"; end block cache_to_address_buffer; snoop_to_address_buffer : block ( snoop_hit = '1' and flag_update = '1' ) is begin address_bus <= guarded snoop_address(31 downto 4) &B"0000”; end block snoop_to_address_buffer; stimulus : process is begin wait for 10 ns; dirty <= '0'; cache_miss <= '1', '0' after 5 ns; wait for 10 ns; dirty <= '1'; cache_miss <= '1', '0' after 5 ns; wait for 10 ns; replace_section <= '1'; cache_miss <= '1', '0' after 5 ns; wait for 10 ns; flag_update <= '0'; snoop_hit <= '1', '0' after 5 ns; wait for 10 ns; flag_update <= '1'; snoop_hit <= '1', '0' after 5 ns; wait for 10 ns; wait; end process stimulus; end architecture dataflow; Blocks e atribuição a Guarded Signals architecture test of fg_16_09 is entity latch is generic ( width : positive ); port ( enable : in bit; d : in bit_vector(0 to width - 1); q : out bit_vector(0 to width - 1) ); end entity latch; architecture behavioral of latch is begin transfer_control : block ( enable = '1' ) is begin q <= guarded d; end block transfer_control; end architecture behavioral; signal enable : bit := '0'; signal d, q : bit_vector(0 to 7); begin dut : entity work.latch(behavioral) generic map ( width => 8 ) port map ( enable => enable, d => d, q => q ); stimulus : process is begin wait for 10 ns; d <= X"11"; wait for 10 ns; enable <= '1'; wait for 10 ns; d <= X"AA"; wait for 10 ns; enable <= '0'; wait for 10 ns; d <= X"00"; wait for 10 ns; wait; end process stimulus; end architecture test; Guarded Signals Explicito architecture abstract of computer_system is subtype word is bit_vector(31 downto 0); type word_vector is array (natural range <>) of word; function resolve_word ( drivers : word_vector ) return word is begin if drivers'length > 0 then return drivers(drivers'left); else return X"00000000"; end if; end function resolve_word; ... signal address_bus : resolve_word word bus; signal hold_req : bit; ... signal clk : bit := '0'; begin cpu : block is signal guard : boolean := false; signal cpu_internal_address : word; ... begin cpu_address_driver: address_bus <= guarded cpu_internal_address; -- other bus drivers controller : process is ... begin ... -- determine when to disable cpu bus drivers guard <= false; wait on clk until hold_req = '0' and clk = '1'; guard <= true; -- re-enable cpu bus drivers ... wait until clk = '1'; end process controller; -- cpu datapath processes cpu_internal_address <= X"11111111"; end block cpu; -- blocks for DMA and other modules clk <= '1' after 10 ns, '0' after 20 ns when clk = '0'; end architecture abstract; Disconnection Specifications architecture test of ch_16_04 is subtype word is bit_vector(0 to 31); type word_array is array (integer range <>) of word; function resolve_words ( words : word_array ) return word is begin if words'length > 0 then return words(words'left); else return X"00000000"; end if; end function resolve_words; subtype resolved_word is resolve_words word; signal memory_data_bus : resolved_word bus; disconnect memory_data_bus : resolved_word after 3 ns; signal mem_sel, mem_write : boolean; signal cache_data_bus : word; begin mem_write_buffer : block (mem_sel and mem_write) is begin memory_data_bus <= guarded reject 2 ns inertial cache_data_bus after 4 ns; end block mem_write_buffer; stimulus : process is begin cache_data_bus <= X"DDDDDDDD"; wait for 10 ns; mem_sel <= true; mem_write <= true; wait for 10 ns; cache_data_bus <= X"AAAAAAAA"; wait for 10 ns; mem_sel <= false; mem_write <= false; wait for 10 ns; cache_data_bus <= X"11111111"; wait; end process stimulus; end architecture test; null é atribuido ao sinal de forma implícita Disconnection Specifications architecture test of ch_16_05 is subtype word is bit_vector(0 to 31); type word_array is array (integer range <>) of word; function resolve_words ( words : word_array ) return word is begin if words'length > 0 then return words(words'left); else return X"00000000"; end if; end function resolve_words; subtype resolved_word is resolve_words word; signal source_bus_1, source_bus_2 : resolved_word bus; signal address_bus : resolved_word bus; disconnect all : resolved_word after 2 ns; signal s : word; signal g : boolean; begin b : block (g) is begin source_bus_1 <= guarded s after 4 ns; source_bus_2 <= guarded s after 4 ns; address_bus <= guarded s after 4 ns; end block b; stimulus : process is begin s <= X"DDDDDDDD"; wait for 10 ns; g <= true; wait for 10 ns; s <= X"AAAAAAAA"; wait for 10 ns; g <= false; wait for 10 ns; s <= X"11111111"; wait; end process stimulus; end architecture test, Disconnection Specifications architecture test of ch_16_06 is subtype word is bit_vector(0 to 31); type word_array is array (integer range <>) of word; function resolve_words ( words : word_array ) return word is begin if words'length > 0 then return words(words'left); else return X"00000000"; end if; end function resolve_words; subtype resolved_word is resolve_words word; signal source_bus_1, source_bus_2 : resolved_word bus; signal address_bus : resolved_word bus; disconnect address_bus : resolved_word after 3 ns; disconnect others : resolved_word after 2 ns; signal s : word; signal g : boolean; begin b : block (g) is begin source_bus_1 <= guarded s after 4 ns; source_bus_2 <= guarded s after 4 ns; address_bus <= guarded s after 4 ns; end block b; stimulus : process is begin s <= X"DDDDDDDD"; wait for 10 ns; g <= true; wait for 10 ns; s <= X"AAAAAAAA"; wait for 10 ns; g <= false; wait for 10 ns; s <= X"11111111"; wait; end process stimulus; end architecture test; Uso de Blocks para Modularização entity counter is generic ( tipd_reset, tipd_clk, topd_q : delay_length; tsetup_reset, thold_reset : delay_length ); -- input prop delay on reset -- input prop delay on clk -- output prop delay on q -- setup: reset before clk -- hold time: reset after clk port ( reset, clk : in bit; q : out bit_vector ); -- synchronous reset input -- edge triggered clock input -- counter output end entity counter; Uso de Blocks para Modularização architecture detailed_timing of counter is signal next_count : bit_vector(q'range); signal reset_ipd, -- data input port delayed clk_ipd : bit; -- clock input port delayed signal q_zd : bit_vector(q'range); -- q output with zero delay begin input_port_delay : block is begin reset_ipd <= reset after tipd_reset; clk_ipd <= clk after tipd_clk; end block input_port_delay; functionality : block is function increment ( bv : bit_vector ) return bit_vector is variable result : bit_vector(bv'range) := bv; variable carry : bit := '1'; begin for index in result'reverse_range loop result(index) := bv(index) xor carry; carry := bv(index) and carry; exit when carry = '0'; end loop; return result; end function increment; begin next_count <= increment(q_zd) when reset_ipd = '0' else (others => '0'); q_zd <= next_count when clk_ipd = '1' and clk_ipd'event; end block functionality; output_port_delay : block is begin q <= q_zd after topd_q; end block output_port_delay; timing_checks : block is begin -- check setup time: reset before clk -- . . . -- check hold time: reset after clk -- . . . end block timing_checks; end architecture detailed_timing; Uso de Blocks para Modularização entity fg_16_13 is end entity fg_16_13; architecture test of fg_16_13 is signal reset, clk : bit := '0'; signal q : bit_vector(3 downto 0); begin dut : entity work.counter(detailed_timing) generic map ( tipd_reset => 2 ns, tipd_clk => 3 ns, topd_q => 4 ns, tsetup_reset => 3 ns, thold_reset => 1 ns ) port map ( reset => reset, clk => clk, q => q ); clk_gen : clk <= '1' after 10 ns, '0' after 20 ns when clk = '0'; reset <= '1' after 62 ns, '0' after 106 ns; end architecture test; Generics e ports em Blocks architecture contrived of example_entity is constant sig_width : positive := 16; signal s1, s2, s3 : bit_vector (0 to sig_width - 1); signal sel : bit; ... begin mux : block is generic ( width : positive ); generic map ( width => sig_width ); port ( d0, d1 : in bit_vector(0 to width - 1); y : out bit_vector(0 to width - 1); sel : in bit); port map ( d0 => s1, d1=> s2, y => s3, sel => sel ); constant zero : bit_vector(0 to width - 1) := ( others => '0' ); signal gated_d0, gated_d1 : bit_vector(0 to width - 1); begin gated_d0 <= d0 when sel = '0' else zero; gated_d1 <= d1 when sel = '1' else zero; y <= gated_d0 or gated_d1; end block mux; ... stimulus : process is begin s1 <= X"1111"; s2 <= X"2222"; sel <= '0'; wait for 10 ns; s1 <= X"0101"; wait for 10 ns; s2 <= X"0202"; wait for 10 ns; sel <= '1'; wait for 10 ns; s1 <= X"0001"; wait for 10 ns; s2 <= X"0002"; wait for 10 ns; wait; end process stimulus; end architecture contrived; Configuração de projetos com Blocks begin entity circuit is generic ( inpad_delay, outpad_delay : delay_length ); port ( in1, in2, in3 : in bit; out1, out2 : out bit ); end entity circuit; architecture with_pad_delays of circuit is component subcircuit is port ( a, b : in bit; y1, y2 : out bit ); end component subcircuit; signal delayed_in1, delayed_in2, delayed_in3 : bit; signal undelayed_out1, undelayed_out2 : bit; input_delays : block is begin delayed_in1 <= in1 after inpad_delay; delayed_in2 <= in2 after inpad_delay; delayed_in3 <= in3 after inpad_delay; end block input_delays; functionality : block is signal intermediate : bit; begin cell1 : component subcircuit port map ( delayed_in1, delayed_in2, undelayed_out1, intermediate ); cell2 : component subcircuit port map ( intermediate, delayed_in3, undelayed_out2, open ); end block functionality; output_delays : block is begin out1 <= undelayed_out1 after outpad_delay; out2 <= undelayed_out2 after outpad_delay; end block output_delays; end architecture with_pad_delays; Configuração de projetos com Blocks entity real_subcircuit is port ( a, b : in bit; y1, y2 : out bit ); end entity real_subcircuit; architecture basic of real_subcircuit is begin y1 <= a and b after 10 ns; y2 <= a nand b after 10 ns; end architecture basic; configuration full of circuit is for with_pad_delays -- configure the architecture for functionality -- configure the block for all : subcircuit use entity work.real_subcircuit(basic); end for; end for; end for; end configuration full; entity fg_16_16 is end entity fg_16_16; library util; use util.stimulus_generators.all; architecture test of fg_16_16 is signal in1, in2, in3, out1, out2 : bit; signal test_vector : bit_vector(1 to 3); begin dut : configuration work.full generic map ( inpad_delay => 2 ns, outpad_delay => 3 ns ) port map ( in1 => in1, in2 => in2, in3 => in3, out1 => out1, out2 => out2 ); stimulus : all_possible_values ( test_vector, 50 ns ); (in1, in2, in3) <= test_vector; end architecture test;