1 Universidade Federal Fluminense - UFF Centro Tecnológico - CTC Escola de Engenharia - TCE Departamento de Engenharia de Telecomunicações TET Técnicas Digitais A Laboratório nº 3: Somadores. Data do laboratório: 17/07/2010
2 Objetivo: Usando as ferramentas apresentadas no laboratório anterior simular o funcionamento de um somador. Aspectos Teóricos: Como foi visto em sala, continuaremos usando circuitos combinacionais através da montagem de somador que pode ter outras funções (de um subtrator dependendo apenas de um arranjo de portas lógicas). Tais circuitos exercem funções aritméticas, utilizando uma combinação de portas lógicas. Como numa soma com números de mais de 1 bit temos a necessidade de considerar a soma das entradas com um possível carry, para isso montamos um circuito combinacional que faz a soma de 3 bit, apresenta o resultado desta soma e o possível carry. S i = A i B i C i 1 C i 1 = A i. B i + A i. C i 1 + B i. C i 1 Procedimento Experimental: Continuando com a utilização da linguagem VHDL, vamos montar um código que descreve o funcionamento de um Full Adder. E a partir deste código vamos montar o código de um circuito que faz a soma de dois números de 4 bits. A partir do que já foi visto podemos construir o código do Full Adder: ENTITY fulladder IS PORT ( a, b, cin : IN BIT; cout, r : OUT BIT); END fulladder; ARCHITECTURE somador OF fulladder IS cout <= (a and b) or (a and cin) or (cin and b) ; r <= (a xor b) xor cin; END somador;
3 Lembrando que devemos escrevê-lo e salvá-lo com o mesmo nome da entidade e extensão.vhd. Agora para construirmos o código do circuito que faz a soma de dois números de 4 bits devemos usar de um projeto hierárquico. Para isso é de bom grado que a entidade que usaremos seja salva num local onde o compilador encontre-a, declarar os components e os sinais e em seguida apresentar o conteúdo de component para cada instância, seguindo este padrão: ENTITY entity_name IS PORT ( input and output definitions); END entity_name; ARCHITECTURE arch_name OF entity_name IS --component declaration(s); --signal declaration(s); --Component instantiation(s); --Other statements; END arch_name; Seguindo esse modelo montamos o seguinte código: ENTITY soma2n4b IS PORT( c0 : IN BIT; a, b : IN BIT_VECTOR (4 downto 1); c4 : OUT BIT; s : OUT BIT_VECTOR (4 downto 1)); END soma2n4b; ARCHITECTURE adder OF soma2n4b IS Descrição das portas do circuito que desejamos descrever o funcionamento. Descrição de portas que são um vetor de entradas/saídas, onde a(4) é a entrada mais significativa. COMPONENT fulladder PORT ( a, b, cin : IN BIT; cout, r : OUT BIT); END COMPONENT; Declaração do component a ser usado na hierarquia. SIGNAL c : BIT_VECTOR (3 downto 1); Declaração dos sinais usados internamente. adder1: fulladder PORT MAP (a => a(1), b => b(1), cin => c0, cout => c(1), r => s(1)); adder2: fulladder PORT MAP (a => a(2), b => b(2), cin => c(1), cout => c(2), r => s(2)); adder3: fulladder PORT MAP (a => a(3), b => b(3), cin => c(2), cout => c(3), r => s(3)); adder4: fulladder PORT MAP (a => a(4), b => b(4), cin => c(3), cout => c4, r => s(4)); END adder; Declaração das funções lógicas das saídas. Usadas pelas instâncias do component.
4 Se quisermos usar apenas algumas portas do component ou usá-las em uma ordem diferente devemos usar a notação acima. Mas quando iremos usar todas as portas do component as linhas sublinhadas acima podem ser reescritas de forma mais eficiente da seguinte forma: PORT MAP (a(1), b(1), c0, c(1), s(1)); Basta listar as portas no PORT MAP na ordem correta. Assim podemos substituir o código sublinhado por: adder1: fulladder PORT MAP (a(1), b(1), c0, c(1), s(1); adder2: fulladder PORT MAP (a(2), b(2), c(1), c(2), s(2)); adder3: fulladder PORT MAP (a(3), b(3), c(2), c(3), s(3)); adder4: fulladder PORT MAP (a(4), b(4), c(3), c4, s(4)); END adder; Podemos escrever aquelas linhas de uma forma mais eficiente ainda, observando que ela é uma linha comum e as outras podem ser obtidas a partir dela através de iterações, dai temos adder(i): fulladder PORT MAP (a(i), b(i), c(i-1), c(i), s(i)); Assim podemos substituir o código sublinhado por: SIGNAL c : BIT_VECTOR (4 downto 0); c(0) <= c0; adders: FOR i IN 1 to 4 GENERATE adder: fulladder PORT MAP (a(i),b(i),c(i-1),c(i),s(i)); END GENERATE; c4 <= c(4); END adder; A declaração GENERATE criará hardware que corresponde ao intervalo de variáveis indexadas por i. Neste caso, i vai de 1 a 4, a instrução instancia quatro instâncias do Full Adder. Já que temos uma entrada, saída e três sinais internos, devemos utilizar um sinal interno de 5 bits (BIT_VECTOR (4 downto 0)), se quisermos incluir todos bits de forma indexada. A entrada de carry c0, definido na declaração de entidade, é atribuída ao elemento do vetor c(0). Da mesma forma, para a saída c4, é atribuída o valor do elemento c(4). É fácil de expandir o somador mudando a declaração do intervalo do FOR GENERATE.
5 Após montarmos o projeto hierárquico, devemos simulá-lo. Para isso vamos em Waveform editor e clicamos com o botão direito e selecionamos Enter Node From SNF, então selecionamos List, => e OK. Teremos uma janela como mostra a Figura 1. Figura 1 - Simulação do Full Adder Podemos alterar as entradas clicando com o botão direito sobre o ícone da entrada e selecionar Ungroup, então veremos (na Figura 2) que a variável a irá se dividir em quatro. Agora podemos alterar cada entrada do vetor a. Depois fazemos o mesmo para o vetor b. Figura 2 - Alterando um vetor de entradas
6 Após alterar as entradas devemos agrupá-las novamente, para facilitar a visualização do funcionamento do circuito proposto. Para isso basta selecionar as entradas que desejamos agrupar e clicar com o botão direito sobre o ícone da entrada e selecionar Enter Group, dar um nome para o grupo e selecionar que seja mostrado em Decimal, como segue nas Figura 3 e Figura 4. Figura 3 - Agrupando variáveis de um vetor Figura 4 - Agrupando variáveis de um vetor Lembrando sempre de respeitar a ordem dos algarismos mais significativos, eles devem estar na parte superior e que a saída da soma de dois números de 4 bits deve ser representada com 5 bits, logo o carry out do somador de 2 números de 4 bits representa uma saída e deve ser agrupado com as variáveis de saída.
7 Agora sim podemos simular o código VHDL proposto, como mostra a Figura 5. Figura 5 - Simulação do Full Adder Uma vez que aprendemos a fazer um projeto hierárquico, propomos que realize uma expansão desse projeto e crie um código que descreva um circuito que faça a soma de dois números de 16 bits e em seguida simule para observar o bom funcionamento do circuito.