270 likes | 362 Views
Computação Reconfigurável. Aula teórica 4. Objetivos. Compreender como utilizar blocos de memória embutidos (da aula anterior) . Como criar projetos mais complicados baseados em blocos predefinidos. Máquinas de Estados Finitos. Unidade de Controlo e Unidade de Execução.
E N D
Computação Reconfigurável Aula teórica 4
Objetivos • Compreender como utilizar blocos de memória embutidos (da aula anterior). • Como criar projetos mais complicados baseados em blocos predefinidos. • Máquinas de Estados Finitos. • Unidade de Controlo e Unidade de Execução. • Paralelismo e concorrência. • Processos combinatórios e sequenciais. • Sinais e variáveis. 14 de março – aula teórica,15h-17h - anfiteatro V. Tema: VHDL sintetizável para projetos em FPGA
Blocos de memória embutidos 2 1 5 3 4
Blocos de memória embutidos -- Ensure that the <ram_name> is correctly defined. Please refer to the RAM Type -- Declaration template for more info. process (<clock>) begin if (<clock>'event and <clock> = '1') then if (<enableA> = '1') then if (<write_enableA> = '1') then <ram_name>(conv_integer(<addressA>)) <= <input_dataA>; end if; <ram_outputA> <= <ram_name>(conv_integer(<addressA>)); <ram_outputB> <= <ram_name>(conv_integer(<addressB>)); end if; end if; end process; entity RAM_block is generic ( ram_addr_bits : integer := 8; ram_width : integer := 8 ); Port ( clk : in std_logic; enableA : in std_logic; write_enableA : in std_logic; addressA : in std_logic_vector(ram_addr_bits-1 downto 0); addressB : in std_logic_vector(ram_addr_bits-1 downto 0); input_dataA : in std_logic_vector (ram_width-1 downto 0); ram_outputA : out std_logic_vector (ram_width-1 downto 0); ram_outputB : out std_logic_vector (ram_width-1 downto 0) ); end RAM_block;
Blocos de memória embutidos entity RAM_block is generic ( ram_addr_bits : integer := 8; ram_width : integer := 8 ); Port ( clk : in std_logic; enableA : in std_logic; write_enableA : in std_logic; addressA : in std_logic_vector(ram_addr_bits-1 downto 0); addressB : in std_logic_vector(ram_addr_bits-1 downto 0); input_dataA : in std_logic_vector (ram_width-1 downto 0); ram_outputA : out std_logic_vector (ram_width-1 downto 0); ram_outputB : out std_logic_vector (ram_width-1 downto 0) ); end RAM_block; architecture Behavioral of RAM_block is type Example_of_BRAM is array (2**ram_addr_bits-1 downto 0) of std_logic_vector (ram_width-1 downto 0); signal my_RAM: Example_of_BRAM; begin process (clk) begin if rising_edge(clk) then if (enableA = '1') then if (write_enableA = '1') then my_RAM(conv_integer(addressA)) <= input_dataA; end if; ram_outputA <= my_RAM(conv_integer(addressA)); ram_outputB <= my_RAM(conv_integer(addressB)); end if; end if; end process; end Behavioral;
Blocos de memória embutidos architecture Behavioral of RAM_block is type Example_of_BRAM is array (2**ram_addr_bits-1 downto 0) of std_logic_vector (ram_width-1 downto 0); signal my_RAM: Example_of_BRAM; begin process (clk) begin if rising_edge(clk) then if (enableA = '1') then if (write_enableA = '1') then my_RAM(conv_integer(addressA)) <= input_dataA; end if; ram_outputA <= my_RAM(conv_integer(addressA)); ram_outputB <= my_RAM(conv_integer(addressB)); end if; end if; end process; end Behavioral;
Blocos de memória embutidos begin enableA <= '1'; process (clk) begin if falling_edge(clk) then addressA <= addressA + 1; end if; end process; input_dataA <= addressA(ram_addr_bits-1 downto ram_addr_bits/2) * addressA(ram_addr_bits/2-1 downto 0); addressB <= op2 & op1; ram_output <= ram_outputB; binary <= "0000"&ram_outputB; BRAM1 : entity work.RAM_block generic map (ram_addr_bits=>ram_addr_bits, ram_width=>ram_width ) port map ( clk, enableA,write_enableA,addressA,addressB, input_dataA,ram_outputA,ram_outputB); end Behavioral;
Blocos de memória embutidos begin enableA <= '1'; process (clk) begin if falling_edge(clk) then addressA <= addressA + 1; end if; end process; input_dataA <= addressA(ram_addr_bits-1 downto ram_addr_bits/2) * addressA(ram_addr_bits/2-1 downto 0); addressB <= op2 & op1; ram_output <= ram_outputB; binary <= "0000"&ram_outputB; BRAM1 : entity work.RAM_block generic map (ram_addr_bits=>ram_addr_bits, ram_width=>ram_width ) port map ( clk, enableA,write_enableA,addressA,addressB, input_dataA,ram_outputA,ram_outputB); end Behavioral; entity Memories_top is generic (ram_addr_bits : integer := 8; ram_width : integer := 8 );
Blocos de memória embutidos entity RAM_block is generic ( ram_addr_bits : integer := 8; ram_width : integer := 8); A begin enableA <= '1'; process (clk) begin if falling_edge(clk) then addressA <= addressA + 1; end if; end process; input_dataA <= addressA(ram_addr_bits-1 downto ram_addr_bits/2) * addressA(ram_addr_bits/2-1 downto 0); addressB <= op2 & op1; ram_output <= ram_outputB; binary <= "0000"&ram_outputB; BRAM1 : entity work.RAM_block generic map (ram_addr_bits=>ram_addr_bits, ram_width=>ram_width ) port map ( clk, enableA,write_enableA,addressA,addressB, input_dataA,ram_outputA,ram_outputB); end Behavioral; RAM B 4 4 op1: in std_logic_vector(3 downto 0); op2: in std_logic_vector(3 downto 0);
Blocos de memória embutidos A begin enableA <= '1'; process (clk) begin if falling_edge(clk) then addressA <= addressA + 1; end if; end process; input_dataA <= addressA(ram_addr_bits-1 downto ram_addr_bits/2) * addressA(ram_addr_bits/2-1 downto 0); addressB <= op2 & op1; ram_output <= ram_outputB; binary <= "0000"&ram_outputB; BRAM1 : entity work.RAM_block generic map (ram_addr_bits=>ram_addr_bits, ram_width=>ram_width ) port map ( clk, enableA,write_enableA,addressA,addressB, input_dataA,ram_outputA,ram_outputB); end Behavioral; RAM B multiplicação de endereços endereço = multiplicação de operandos
Blocos de memória embutidos Exemplo: 0000 0000 0001 0000 0010 0000 0011 0000 0100 0000 0101 0001 0110 0010 0111 0011 1000 0000 1001 0010 1010 0100 1011 0110 1100 0000 1101 0011 1110 0110 1111 0001 Operando 1 Resultado Operando 2 6 9 3 * 2 3 * 3
Blocos de memória embutidos Sequential (FSM-based) circuit Distributed ROM 3 LSB Distributed ROM 3-bit result 6-bit binary vector Distributed ROM 3-bit result 6-bit binary vector contar número de 1s num vetor binário LSB – less significant bits 2-bit result 2-bit result a) 3-bit result Adder 6-bit binary vector MSB – most significant bits b) 3 MSB c)
Como criar projetos mais complicados baseados em blocos predefinidos Displays de segmentos Multiplicação baseada em RAM/ROM Didplays com segmentos Multiplicação baseado em RAM/ROM Converter código binário para BCD Controlo de 4 displays Controlo de segmentos
Como criar projetos mais complicados baseados em blocos predefinidos entity RAM_block is generic ( ram_addr_bits : integer := 8; ram_width : integer := 8 ); Port ( clk : in std_logic; enableA : in std_logic; write_enableA : in std_logic; addressA : in std_logic_vector(ram_addr_bits-1 downto 0); addressB : in std_logic_vector(ram_addr_bits-1 downto 0); input_dataA : in std_logic_vector (ram_width-1 downto 0); ram_outputA : out std_logic_vector (ram_width-1 downto 0); ram_outputB : out std_logic_vector (ram_width-1 downto 0) ); end RAM_block; BRAM1 : entity work.RAM_block generic map (ram_addr_bits=>ram_addr_bits, ram_width=>ram_width ) port map ( clk, enableA,write_enableA,addressA,addressB, input_dataA,ram_outputA,ram_outputB); binTO_BCD: entity work.BinToBCD12 Port map ( clk,reset,'1',ready,converted,binary,BCD3,BCD2,BCD1,BCD0); DispCont: entity work.FourDisplayControl Port map ( clk,BCD3,BCD2,BCD1,BCD0,displays,segments); decoder : entitywork.segment_decoder port map (convert_me,segments);
Máquinas de Estados Finitos unsigned int IGCD(unsigned int A, unsigned int B) { unsigned inttmp; while (B > 0) { if(B > A) { tmp=A; A=B; B=tmp; } else { tmp=B; B= A%B; A=tmp; }} return A; }
Máquinas de Estados Finitos entity Iterative_GCD is -- circuit with synchronization by one clock edge Port ( clk : in STD_LOGIC; reset : in STD_LOGIC; A : in std_logic_vector(3 downto 0); -- we consider 4-bit values of A and B B : in std_logic_vector(3 downto 0); Result : out std_logic_vector(3 downto 0) ); end Iterative_GCD; architecture Behavioral of Iterative_GCD is signal FSM_A, FSM_B, FSM_A_next, FSM_B_next : std_logic_vector(3 downto 0); type state_type is (init, run_state, rest_of_division); signal C_S, N_S : state_type; signal tmp, tmp_next,Res,Res_next : std_logic_vector(3 downto 0); begin process (clk,reset) -- this process described functionality of FSM register in Figure 12 and begin -- registers of RTL if (reset = '1') then C_S <= init; elsifrising_edge(clk) then C_S <= N_S; FSM_A <= FSM_A_next; FSM_B <= FSM_B_next; tmp <= tmp_next; Res <= Res_next; end if; end process;
Máquinas de Estados Finitos process (C_S,A,B,FSM_A,FSM_B,tmp,Res) -- this is a combinational process begin N_S <= C_S; FSM_A_next <= FSM_A; FSM_B_next <= FSM_B; tmp_next <= tmp; Res_next <= Res; case C_S is when init => if ((A = 0) or (B = 0)) then Res_next <= (others => '0'); N_S <= init; elsif (B>A) then FSM_A_next <= B; FSM_B_next <= A; N_S <= run_state; else tmp_next <= A; FSM_A_next <= B; FSM_B_next <= B; N_S <= rest_of_division; end if; when run_state => if (FSM_B>0) then if (FSM_B>FSM_A) then FSM_A_next <= FSM_B; FSM_B_next <= FSM_A; N_S <= run_state; else tmp_next <= FSM_A; FSM_A_next <= FSM_B; N_S <= rest_of_division; end if; else Res_next <= FSM_A; N_S <= init; end if; when rest_of_division => if (tmp >= FSM_B) then tmp_next <= tmp-FSM_B; N_S <= rest_of_division; else FSM_B_next <= tmp; N_S <= run_state; end if; when others => N_S <= init; end case; end process; Result <= Res; end Behavioral;
Máquinas de Estados Finitos architecture Behavioral of Iterative_GCD is -- synchronization with two clock edges signal FSM_A, FSM_B : std_logic_vector(3 downto 0); type state_type is (init, run_state, rest_of_division); signal C_S, N_S : state_type; begin process (clk,reset) begin if (reset = '1') then C_S <= init; elsifrising_edge(clk) then C_S <= N_S; end if; end process; process (clk) -- this process describes functionality at RTL variable tmp : std_logic_vector(3 downto 0); begin if falling_edge(clk) then -- of FSM combinational circuit case C_S is when init => if ((A = 0) or (B = 0)) then Result <= (others => '0'); N_S <= init; elsif (B>A) then FSM_A <= B; FSM_B <= A; N_S <= run_state; else tmp := A; FSM_A <= B; FSM_B <= B; N_S <= rest_of_division; end if; when run_state => if (FSM_B>0) then if (FSM_B>FSM_A) then FSM_A <= FSM_B; FSM_B <= FSM_A; N_S <= run_state; else tmp := FSM_A; FSM_A <= FSM_B; N_S <= rest_of_division; end if; else Result <= FSM_A; N_S <= init; end if; when rest_of_division => if (tmp >= FSM_B) then tmp := tmp-FSM_B; N_S <= rest_of_division; else FSM_B <= tmp; N_S <= run_state; end if; when others => N_S <= init; end case; end if; end process; end Behavioral;
Máquinas de Estados Finitos architecture Behavioral of Iterative_GCD is -- synchronization with two clock edges signal FSM_A, FSM_B : std_logic_vector(3 downto 0); type state_type is (init, run_state, rest_of_division); signal C_S, N_S : state_type; begin process (clk,reset) begin if (reset = '1') then C_S <= init; elsif rising_edge(clk) then C_S <= N_S; end if; end process; process (clk) -- this process describes functionality at RTL variable tmp : std_logic_vector(3 downto 0); begin
if falling_edge(clk) then -- of FSM combinational circuit case C_S is when init => if ((A = 0) or (B = 0)) then Result <= (others => '0'); N_S <= init; elsif (B>A) then FSM_A <= B; FSM_B <= A; N_S <= run_state; else tmp := A; FSM_A <= B; FSM_B <= B; N_S <= rest_of_division; end if; when run_state => if (FSM_B>0) then if (FSM_B>FSM_A) then FSM_A <= FSM_B; FSM_B <= FSM_A; N_S <= run_state; else tmp := FSM_A; FSM_A <= FSM_B; N_S <= rest_of_division; end if; else Result <= FSM_A; N_S <= init; end if; when rest_of_division => if (tmp >= FSM_B) then tmp := tmp-FSM_B; N_S <= rest_of_division; else FSM_B <= tmp; N_S <= run_state; end if; when others => N_S <= init; end case; end if; end process; end Behavioral;
Unidade de Controlo e Unidade de Execução Unidade de controlo Unidade de execução rising_edge(clk) falling_edge(clk)
Paralelismo e concorrência Processos combinatórios e sequenciais combinational: process(dipswitches) begin case dipswitches(1 downto 0) is when "00" => leds <= dipswitches; when "01" => leds <= not dipswitches; when "10" => leds <= dipswitches(3 downto 0) & dipswitches(7 downto 4); when "11" => leds(7 downto 0) <= "01010101"; when others => null; end case; end process combinational;
Paralelismo e concorrência Processos combinatórios e sequenciais -- the second two processes are sequential sequential: process(divided_clk,reset) variablevar_tmp : integer range 0 to 9; begin if rising_edge(divided_clk) then if reset = '1' then left <= (others=>'0'); near_left <= (others=>'0'); var_tmp := 0; sig_tmp <= 0; else var_tmp := var_tmp + 3; sig_tmp <= sig_tmp + 3; -- 3 is added to the signal sig_tmp. However, in -- the line below only left is incremented and near_left is unchanged until the -- next activation of the process. Even after the next activation the near-left -- is incremented (by one) but it is not increased by 3 left <= conv_std_logic_vector( (var_tmp),4 ); near_left <= conv_std_logic_vector( (sig_tmp),4 ); sig_tmp <= sig_tmp + 1; -- this line will determine the final value of -- the sig_tmp only at the end of the process activation. Thus, anywhere above -- just the previous value of the sig_tmp is valid end if; end if; end process sequential; architecture Behavioral of ….. signal sig_tmp : integer range 0 to 9; begin
Paralelismo e concorrência Sinais e variáveis -- the second two processes are sequential sequential: process(divided_clk,reset) variablevar_tmp : integer range 0 to 9; begin if rising_edge(divided_clk) then if reset = '1' then left <= (others=>'0'); near_left <= (others=>'0'); var_tmp := 0; sig_tmp <= 0; else var_tmp := var_tmp + 3; sig_tmp <= sig_tmp + 3; -- 3 is added to the signal sig_tmp. However, in -- the line below only left is incremented and near_left is unchanged until the -- next activation of the process. Even after the next activation the near-left -- is incremented (by one) but it is not increased by 3 left <= conv_std_logic_vector( (var_tmp),4 ); near_left <= conv_std_logic_vector( (sig_tmp),4 ); sig_tmp <= sig_tmp + 1; -- this line will determine the final value of -- the sig_tmp only at the end of the process activation. Thus, anywhere above -- just the previous value of the sig_tmp is valid end if; end if; end process sequential; architecture Behavioral of ….. signal sig_tmp : integer range 0 to 9; begin
Paralelismo e concorrência Sinais e variáveis process(divided_clk,reset) variable var_tmp : integer range 0 to 9; -- var_tmp here is different from var_tmp -- in the previous process begin if falling_edge(divided_clk) then if reset = '1' then near_right <= (others=>'0'); right <= (others=>'0'); var_tmp := 0; else var_tmp := var_tmp + 1; -- near_right and right below are changed at the same time and for the same -- values. This is because the sig_tmp was changed in the previous process. -- Note that synchronisation is done at rising edge in the previous process -- and at falling_edge in this process. near_right <= conv_std_logic_vector((var_tmp),4); right <= conv_std_logic_vector((sig_tmp),4); end if; end if; end process;