Após vermos o que é a entidade em VHDL na Parte 1, vamos ver o que é a arquitetura!
architecture
architecture é uma keyword do VHDL que representa uma arquitetura, a qual representa o comportamento interno de uma entidade. A entidade é a caixa preta que efetua a interface com o mundo externo, já a arquitetura é o funcionamento interno desta caixa. Nela declaramos todas as operações do nosso hardware, sejam elas lógicas, aritméticas ou de armazenamento. É aqui que o comportamento do nosso hardware é descrito.

Vamos analisar a sintaxe e o funcionamento da arquitetura com base no código abaixo:
architecture nome_arquitetura of nome_entidade is
-- Declaração de constantes
constant PERIOD_SAMPLE : natural := 6510;
constant HALF_PERIOD_SIGNAL : natural := 127;
-- Declaração de sinais
signal new_sample : std_logic := '0';
signal sum_a_b : std_logic_vector(31 downto 0);
signal multiplied_value_comb_1 : std_logic_vector(31 downto 0);
signal multiplied_value_comb_2 : std_logic_vector(31 downto 0);
signal multiplied_value_reg : std_logic_vector(31 downto 0);
begin
-- component instantiation
adder_inst : entity work.adder
port map (
sysclk => sysclk,
reset_n => reset_n,
a => data_in,
b => PERIOD_SAMPLE,
result => sum_a_b
);
-- combinational process
multiplied_value_comb_1 <= data_in * data_in;
-- combinational process_2
process(data_in)
begin
multiplied_value_comb_2 <= data_in * data_in;
end process;
-- clocked process
process (sys_clk,sys_rst)
begin
if sys_rst = '0' then
multiplied_value_reg <= (others => '0');
elsif rising_edge(sys_clk) then
multiplied_value_reg <= sum_a_b * sum_a_b;
end if;
end process;
end architecture nome_arquitetura;
Linha 1: nome_arquitetura é o nome dado à arquitetura, geralmente utilizo RTL; nome_entidade é o nome da entidade correspondente. No caso da figura acima a entidade se chama “CPU”.
Até chegar a keyword “begin” na linha 13, são declarados sinais que podem representar fios e registradores, e também as constantes. Todos os sinais podem ser inicializados na declaração com o símbolo “:=”, porém, no momento da sintase do circuito, esta inicialização é descartada para registradores e fios, sendo útil apenas para constantes e para a parte da simulação simulação.
Observação: A declaração do nosso componente “adder” também poderia ser incluída nesta primeira parte da arquitetura. Existem dois meios de se instanciar um componente em uma arquitetura: ou apontamos para ele com entity work.adder, como na linha 16, ou então primeiro o declaramos como componente e depois o instanciamos. Para economizar linhas eu prefiro fazer da maneira direta. Este link exemplifica o outro método de instanciação de componentes.
E então chegamos na linha 13. A partir da keyword begin que as coisas de fato acontecem. VHDL é paralelo por definição, ao contrário de linguagens de software, ou seja, componentes e processos executam ao mesmo tempo. O componente “adder” está rodando em paralelo com os dois processos combinacionais e o processo sequencial. Podemos imaginar isto tudo rodando em paralelo no espaço, como circuitos independentes (que é o que de fato ocorre).
Observação 2: Quando se faz uma atribuição combinacional fora de um process é exatamente a mesma coisa que fazer ele em um process:
c <= a and b;
é equivalente a :
process(a,b) begin c <= a and b; end process
process
process é uma keyword do VHDL que representa um processo. É um dos elementos básicos de qualquer descrição de hardware em VHDL e pode ser utilizado tanto para a descrição do comportamento de circuitos combinacionais como de circuitos sequenciais (com memória, registradores). Sintaxe:
process(lista_sensibilidade) -- Declaração de variables begin -- Declaracao 1 -- Declaracao 2 end process;
Um process é ativado sempre que um dos sinais na sua lista de sensibilidade é atualizado. Quando isto ocorre o circuito executa o algoritmo descrito e volta a ficar inativo.
A lista de sensibilidade de um process sequencial deve possuir somente o clock em caso de circuitos com reset síncrono ou o clock e o reset em caso de circuitos com reset assincrono. No primeiro caso o reset só é amostrado na borda do clock logo podemos omitir ele da lista de sensibilidade.
-- Reset assíncrono
process (sys_clk,sys_rst) is
begin
if sys_rst = '0' then
multiplied_value_reg <= (others => '0');
elsif rising_edge(sys_clk) then
multiplied_value_reg <= sum_a_b * sum_a_b;
end process;
-- Reset sincrono
process (sys_clk) is
begin
if rising_edge(sys_clk) then
if sys_rst = '0' then
multiplied_value_reg <= (others => '0');
else
multiplied_value_reg <= sum_a_b * sum_a_b;
end process;
Não interessa colocar outros sinais internos do process em sua lista de sensibilidade pois os valores só serão atualizados com a chegada do clock ou do reset.
Já no caso de circuitos combinacionais é de extrema importância adicionar todas as entradas do process na lista de sensibilidade. Uma lista de sensibilidade incompleta pode gerar uma inconsistência entre a simulação e a síntese já que a síntese observa o comportamento do circuito e gera o hardware a partir disso, muitas vezes ignorando a lista de sensibilidade.
Por exemplo, no mux descrito abaixo, caso o sinal “sel” seja omitido da lista de sensibilidade, o process não será ativado na simulação quando o sel mudar de valor. O mux não funcionará corretamente no ambiente de simulação, mas na síntese ele deve funcionar corretamente. Problemas como estes são chatos de procurar, por isto é muito importante observar a lista de warnings na sua ferramenta de síntese. A omissão de sinais na lista de sensibilidade normalmente é apontada pela ferramenta de CAD.
PROCESS (sel, a, b, c, d)
BEGIN
CASE sel IS
WHEN "00" =>
op <= a;
WHEN "01" =>
op <= b;
WHEN "10" =>
op <= c;
WHEN "11" =>
op <= d;
END CASE;
END PROCESS;
Na Parte 3 veremos um exemplo prático de uma implementação em VHDL e como montar uma simulação.










