Baixe o app para aproveitar ainda mais
Prévia do material em texto
Projeto de Unidade Lógica Aritmética Gustavo Henrique Leal e Rafael Almeida de Bem 22 de outubro de 2018 Sumário 1 Introdução 4 2 Operações 5 2.1 Somador/subtrator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.1.1 Full adder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.1.2 Carry Look Ahead Adder . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2.1.3 Somador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.1.4 Subtrator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.2 Demais operações . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.2.1 Complemento de 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.2.2 Paridade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.2.3 Complemento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.2.4 Não-Ou lógico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.2.5 Ou Exclusivo lógico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.2.6 Não-E lógico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 3 ULA 16 3.1 O que é . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 3.1.1 Qualificadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 3.2 Operações . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 4 Simulações 18 5 Codificadores 27 6 Considerações finais 30 1 Lista de Figuras 2.1 Circuito Full Adder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 2.2 Ripple Carry Adder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2.3 Diagrama Carry Look Ahead Adder . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.4 CLA 8 bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.5 Subtrator 8 bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.6 Não-Ou lógico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.7 Ou exclusivo lógico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.8 Não-E lógico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 3.1 Unidade Lógica Aritmética . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 4.1 Simulação com undefined . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 4.2 Simulação de 0 a 180 ns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 4.3 Simulação de 180 a 360 ns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 4.4 Simulação de 2560 a 2740 ns . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 4.5 Simulação de 2740 a 2920 ns . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 4.6 Simulação de 12800 a 112980 ns . . . . . . . . . . . . . . . . . . . . . . . . . . 24 4.7 Simulação de 20480 a 2650 ns . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 5.1 Display de 14 Segmentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2 Lista de Tabelas 2.1 Tabela verdade Full Adder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 2.2 Tabela de Comparação entre FAs . . . . . . . . . . . . . . . . . . . . . . . . . . 7 3.1 Portas da ULA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 3.2 Tabela de Operações da ULA . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 5.1 Tabela de Conversão para 14 segmentos . . . . . . . . . . . . . . . . . . . . . . . 27 3 Introdução O presente relatório tem por objetivo apresentar o desenvolvimento e resultados encontrados na elaboração de uma unidade lógica aritmética (ULA) de 8 bits, acompanhada por dois codifica- dores (COD) para a conversão de 4 bits em uma representação em um display de 14 segmentos. As especificações do projeto seguem o proposto em documento passado pelo requisitante Prof. Edson Moreno. A ULA desenvolvida apresenta as operações aritméticas de soma, subtração, complemento de 2 e paridade e também as operações lógicas de complemento, não-ou lógico (nor), ou exclusivo lógico (xor) e não-e lógico (nand). A descrição de cada operação é dada em seções especificas. 4 Operações A ULA proposta depende da elaboração de 8 operações para seu desenvolvimento. Esta operações são classificadas como aritméticas e lógicas, havendo 4 de cada tipo. As operações aritméticas são: 1. Soma 2. Subtração 3. Complemento de 2 4. Paridade Destas 4, a soma e subtração se assemelham e utilizam o mesmo módulo de circuito para sua realização. Este módulo é composto por outros circuitos apresentados nas próximas seções. As operações lógicas são definidas por: 1. Complemento 2. Não-Ou lógico 3. Ou exclusivo lógico 4. Não-E lógico 2.1 Somador/subtrator 2.1.1 Full adder As operações básicas de soma e subtração em binário são realizadas bit a bit. Ambas operam de forma semelhante, porém para subtração é necessário a utilização de complemento de 2, permitindo a diferenciação de valores negativos e positivos. Para somar dois bits faz-se como em uma operação em decimal, adicionando um valor ao outro. Já na subtração, aplicamos o conceito de complemento de 2 ao segundo operando e então é feita a soma. O resultado da subtração é, também, interpretado com complemento de dois. Para aplicarmos estes conceitos em hardware, utilizamos um circuito básico conhecido por Full Adder (adicionador completo). O circuito citado tem seu comportamento tal qual o permite realizar a soma, retornar este valor e, assim como em operações decimais, caso tenha a necessidade da adição de um valor à esquerda, ou em termos técnicos, o valor resultante seja maior que o máximo representável com apenas 1 bit, o mesmo consiga retornar um valor extra conhecido como Carry Out. O mesmo circuito pode ser encadeado, permitindo assim a soma de valores maiores que 1 bit. Sendo assim, o valor resultante em um Carry Out deve ser considero na realização da soma dos próximos bits dos operandos. Para permitir que isto seja aplicado, o Full Adder possui uma terceira entrada além dos operandos, definida por um 5 valor extra que deve ser somado juntamente com os operandos A e B. Esse valor extra recebe o nome de Carry In. O comportamento de um Full Adder pode ser observado na Tabela2.1 verdade abaixo. a b CarryIn Soma CarryOut 0 0 0 0 0 0 0 1 1 0 0 1 0 1 0 0 1 1 0 1 1 0 0 1 0 1 0 1 0 1 1 1 0 0 1 1 1 1 1 1 Tabela 2.1: Tabela verdade Full Adder A partir desta tabela, podemos extrair o circuito digital capaz de realizar o comportamento esperado, como visto na Figura 2.1 A B CarryIn Sum • • • • • • CarryOut • • • Figura 2.1: Circuito Full Adder O mesmo circuito pode ser implementado fisicamente utilizando componentes TTL ou através da descrição em hardware por uma linguagem apropriada e produzido adequadamente. Para este trabalho, é feita a descrição do hardware com VHDL (VHSIC Hardware Descrip- tion Language). A descrição, por padrão, é divida em entidade e comportamento. A entidade utilizada para descrever o full adder neste trabalho pode ser vista a seguir: 1 port ( 2 bit0 : in std_logic; 3 bit1 : in std_logic; 4 cin : in std_logic; 5 cout : out std_logic; 6 sum : out std_logic 7 ); O comportamento pode ser descrito de diversas maneiras. De maneira simples, foi descrito para este caso como: 1 cout <= ((bit0 xor bit1) and cin) or (bit0 and bit1); 2 sum <= (bit0 xor bit1) xor cin; 6 O Full Adder em cascata é gerado quando o Carry Out de um circuito é recebido pelo Carry In do seguinte, como mostra o diagrama na Figura 2.2. Quando dispostos desta maneira, o circuito gerado é chamado Ripple Carry Adder. A sáıda de cada módulo representa um bit na representação final daoperação. FullAdder cout s cin ba FullAdder cout s cin ba a1 b1 a0 b0 0c s1 s0 Figura 2.2: Ripple Carry Adder O Ripple Carry Adder (RCA) apresenta um problema no tempo de propagação devido à construção atribúıda. Cada módulo depende do anterior para ser processado, visto que o valor de Carry In só será definido uma vez que o módulo anterior finalize o processamento e defina sua sáıda de Carry Out. Para o desenvolvimento da ULA proposta neste projeto, conforme especificações do requisitante, será utilizado o circuito chamado Carry Look Ahead Adder, também conhecido como Full Adder de rápida propagação. 2.1.2 Carry Look Ahead Adder Motivação A Tabela 2.2 apresenta uma comparação entre três tipos de Adders: Ripple Carry Adder (RCA), Carry Lookahead Adder (CLA) e Carry Bypass Adder (CByA), realizada por R. UMA, Vidya Vijayan, M. Mohanapriya e Sharon Paul em seu artigo Area, Delay and Power Comparison of Adder Topologies. O artigo cita que que os testes foram realizados sob as condições padrões: VCC = 1.2V , temperatura ambiente de 27oC e tensões de alimentação para I/O de 2.5V . Tipo de Adder Dissipação de Energia (mW ) Área (µm2) Tempo de Propagação (ns) RCA 0.206 2214 4.208 CLA 0.312 2160 3.100 CByA 0.459 3116 3.010 Fonte: http://www.aircconline.com/vlsics/V3N1/3112vlsics13.pdf Tabela 2.2: Tabela de Comparação entre FAs Como pode ser observado, o RCA possui um tempo de propagação de 1.2ns a mais se comparado ao CLA. O menor tempo para a realização da sua função garante maior performance ao sistema aplicado. O CByA garante um tempo menor ainda em relação ao RCA, mas por requisição o circuito desenvolvido neste trabalho será o CLA. 7 Comportamento Diferente de um Ripple Carry Adder, o CLA não trabalha de maneira recursiva, ou seja, ele independe do resultado da soma do módulo anterior para realizar a próxima operação. A lógica de um sistema CLA utiliza conceitos de geração e propagação de Carry. No caso de uma adição binária A+B, há a geração de Carry se e somente se tanto A quanto B valerem 1. Escrevendo G(A, B) como a representação da geração de um Carry, + como representação da operação lógica or e · como representação da operação lógica and temos: G(A,B) = A ·B No caso da propagação do Carry, teremos 1 se ou A ou B forem 1. Tomando P(A, B) como a representação lógica da propagação de um Carry, temos: P (A,B) = A+B No contexto de geração e propagação, para que haja um Carry é necessário que ou G(A, B) seja 1 ou que o Carry da operação anterior seja 1 e que P(A, B) seja 1. Escrevendo em lógica booleana, tendo Ci como o Carry da operação i: Ci+1 = Gi + (Pi · Ci) Segundo a definição acima podemos concluir que o cálculo de um Carry é uma operação recur- siva. Segue o algoritmo para i = 4: 1. C1 = G0 + (P0 · C0) 2. C2 = G1 + (P1 · C1) 3. C3 = G2 + (P2 · C2) 4. C4 = G3 + (P3 · C3) Substituindo C1 em C2, C2 em C3 e C3 em C4 temos a seguinte expansão: 5. C2 = G1 + P1 ·G0 + P0 · C0 6. C3 = G2 + P2 ·G1 + P1 ·G0 + P0 · C0 7. C4 = G3 + P3 ·G2 + P2 ·G1 + P1 ·G0 + P0 · C0 Um CLA de 4 bits pode ser descrito utilizando dois agrupamentos de geração e propagação separadamente. As lógicas booleanas para o grupo de geração GG e para o grupo de propagação GP são, respectivamente: GG = G0 +G1 +G2 +G3 GP = P0 · P1 · P2 · P3 Com esses dois módulos, podemos descrever o grupo de Carry GC de 4 bits: GC = GG+GP · Cin A expressão acima é equivalente ao C4 representado anteriormente. Circuitama O circuito expresso na seção anterior pode ser representado em diagrama por: 8 G0 P0 R0 G1 P1 R1 G2 P2 R2 G3 P3 R3 FullAdder cout s cinba FullAdder cout s cinba FullAdder cout s cinba FullAdder cout s cinba a3 b3 c3 a2 b2 c2 a1 b1 c1 a0 b0 c0 c0• • •• •• •• • • • • • • • • • • • • • • • • cout • • • • • • s0s1s2s3 •••• Figura 2.3: Diagrama Carry Look Ahead Adder A montagem deste circuito acima gera um comportamento correspondente ao descrito no na seção anterior. O mesmo pode ser representado de diversas maneiras, mas para fins deste projeto o diagrama desenvolvido será este. O mesmo pode ser descrito em VHDL utilizando a instanciação de módulos Full Adder. A descrição da entidade do módulo carry look ahead adder pode ser vista como: 1 port ( 2 a : in std_logic_vector(3 downto 0); 3 b : in std_logic_vector(3 downto 0); 4 cin : in std_logic; 5 sum : out std_logic_vector(3 downto 0); 6 cout : out std_logic 7 ); Já o seu comportamento necessita da delaração de sinais para armazenarem os valores de propagação e Carry para cada bit, como visto em: 9 1 signal g, p, r: std_logic_vector(3 downto 0); 2 begin 3 sb0: entity work.full_adder port map ( 4 bit0 => a(0), 5 bit1 => b(0), 6 cin => cin, 7 sum => sum(0), 8 cout => open 9 ); 10 g(0) <= a(0) and b(0); 11 p(0) <= a(0) or b(0); 12 r(0) <= g(0) or (p(0) and cin); 13 14 sb1: entity work.full_adder port map ( 15 bit0 => a(1), 16 bit1 => b(1), 17 cin => r(0), 18 sum => sum(1), 19 cout => open 20 ); 21 g(1) <= a(1) and b(1); 22 p(1) <= a(1) or b(1); 23 r(1) <= g(1) or (p(1) and (g(0) or (p(0) and cin))); 24 25 sb2: entity work.full_adder port map ( 26 bit0 => a(2), 27 bit1 => b(2), 28 cin => r(1), 29 sum => sum(2), 30 cout => open 31 ); 32 g(2) <= a(2) and b(2); 33 p(2) <= a(2) or b(2); 34 r(2) <= g(2) or (p(2) and (g(1) or (p(1) and (g(0) or (p(0) and cin)))));↪→ 35 36 sb3: entity work.full_adder port map ( 37 bit0 => a(3), 38 bit1 => b(3), 39 cin => r(2), 40 sum => sum(3), 41 cout => open 42 ); 43 g(3) <= a(3) and b(3); 44 p(3) <= a(3) or b(3); 45 r(3) <= g(3) or (p(3) and (g(2) or (p(2) and (g(1) or (p(1) and (g(0) or (p(0) and cin)))))));↪→ 46 cout <= r(3); Utilizando a descrição acima é posśıvel realizar a construção de módulos para somas de valores maiores que 4 bits. Este projeto contempla operações com valores de 8 bits em um 10 módulo descrito a partir da instanciação de dois módulos deste. 2.1.3 Somador Como já dito anteriormente, o somador em binário atua sobre cada bit operado. O circuito responsável por este comportamento é o Full Adder, utilizando na montagem do CLA de 4 bits. Porém, a ULA em desenvolvimento utiliza operandos de 8 bits em suas entradas e sáıda. Um CLA de 8 bits pode ser gerado a partir da instanciação de dois CLA de 5 bits, como mostra o diagrama abaixo: CLA 4bitscout s4bits cin b4bitsa4bits CLA 4bitscout s4bits cin b4bitsa4bits a7...4 b7...4 a3...0 b3...0 0cout s7...4 s3...0 Figura 2.4: CLA 8 bits Cada módulo realiza a soma de 4 bits, sendo o módulo a esquerda responsável pelos 4 bits mais significantes e o direito pelos 4 bits menos significantes. O mesmo circuito pode ser descrito em VHDL por: 1 library ieee; 2 use ieee.std_logic_1164.all; 3 use ieee.numeric_std.all; 4 entity cla_8bits is 5 port( 6 a : in std_logic_vector(7 downto 0); 7 b : in std_logic_vector(7 downto 0); 8 cin : in std_logic; 9 sum : out std_logic_vector(7 downto 0); 10 cout : out std_logic 11 ); 12 end cla_8bits; 13 architecture behavioral of cla_8bits is 14 signal c : std_logic; 15 begin 16 --* Faz a operacao com os 4 bits menos significativos de A e B 17 sb0: entity work.cla_4bits port map( 18 a => a (3 downto 0), 19 b => b (3 downto 0), 20 cin => cin, 21 sum => sum (3 downto 0), 22 cout => c 23 ); 24 --* Faz a operacao com os 4 bits mais significativos de A e B 11 25 sb1: entity work.cla_4bits port map( 26 a => a (7 downto 4), 27 b => b (7 downto 4), 28 cin => c, 29 sum => sum (7 downto 4), 30 cout => cout 31 ); 32 end behavioral; A descrição acima permite a soma de valores de 8 bits. A existência de um valor verdadeiro em Carry out sinaliza um resultado representável apenas com um numero maior de bits, o que indica o caso de overflow. 2.1.4 Subtrator A subtração binária possui um comportamento semelhante a somabinária. O que difere uma operação da outra é o sinal atribúıdo ao segundo operando, que deve ser negativo. Para alcançar o funcionamento desejado, aplica-se o conceito de complemento de 2 ao segundo operando, invertendo seu valor e adicionando 1. O funcionamento do complemento de 2 é explicado na Seção 2.2.1. Dada a semelhança no comportamento, um módulo subtrator pode ser criado a partir de um módulo somador, bastando inverter o valor do segundo operando e aplicar o valor ’1’ ao Carry In. A Figura 2.5 mostra o diagrama de um subtrator de 8 bits criado a partir de 2 módulos CLA de 4 bits, que podem ser resumidos a um somador de 8 bits. CLA 4bitscout s4bits cin b4bitsa4bits CLA 4bitscout s4bits cin b4bitsa4bits a7...4 Inv b7...4 a3...0 Inv b3...0 1cout s7...4 s3...0 Figura 2.5: Subtrator 8 bits A descrição para um módulo subtrator de 8 bits, utilizando o somador definido na subseção Subseção 2.1.3, pode ser vista abaixo. 1 library ieee; 2 use ieee.std_logic_1164.all; 3 use ieee.numeric_std.all; 4 entity fs_8bits is 5 port( 6 a : in std_logic_vector(7 downto 0); 7 b : in std_logic_vector(7 downto 0); 8 sub : out std_logic_vector(7 downto 0); 9 cout : out std_logic 10 ); 12 11 end fs_8bits; 12 13 architecture behavioral of fs_8bits is 14 signal invb : std_logic_vector(7 downto 0); 15 begin 16 sb0: entity work.cla_8bits port map( 17 a => a, 18 b => invb, 19 cin => '1', 20 sum => sub, 21 cout => cout 22 ); 23 invb <= not b; 24 end behavioral; Como é aplicado o complemento de 2 ao segundo operando, ambos os valores passam a ser representados em complemento de dois para identificação do sinal apresentado. A sáıda do módulo passa a ser representada como tal, e os valores representáveis tomam um limitação menor que em complemento de 1. São posśıveis de representação 128 valores negativos e 127 positivos. 2.2 Demais operações 2.2.1 Complemento de 2 O complemento de 2 é uma forma de representação de valores binários com sinal. O bit mais significativo (MSB) passa a ser a representação do sinal atribúıdo ao valor, sendo ’0’ para valores positivos e ’1’ para valores negativos. A aplicação do complemento de 2 é dada a partir da inversão do valor binário seguida da soma de ’1’ ao mesmo. Logo, o valor ’-1’ é representado em 8 bits por ’1111 1111’, enquanto o menor valor posśıvel é ’-128’, representado por ’1000 0000’. Já para valores positivos, a representação se mantém normal, porém o range é diminúıdo, limitando-se a ’127’ como ’0111 1111’. 2.2.2 Paridade A paridade consiste em verificar se um valor é par ou impar. Porém, para esta aplicação, conforme especificações do requisitante, a paridade será dada pela contagem de aparições do número ’1’ em um valor binário qualquer. A sáıda esperada para cada caso é ’0’ para valores pares e ’1’ para valores ı́mpares. Para fazer este cálculo usou-se um contador que soma 1 a si mesmo sempre que um dos valores da entrada A for 1. O código deste algoritmo é como segue: 1 variable count : integer := 0; 2 for i in 0 to 7 loop 3 if a(i) = '1' then 4 count <= count + 1; 5 else 6 count <= count; 7 end if; 8 end loop; 9 if (count mod 2) = '0' then --* Verifica se o número de '1' é par 13 10 sgnExit <= "00000001"; 11 else 12 sgnExit <= "00000000"; --* Retorna '1' se for ı́mpar 13 end if; No código, sgnExit é o sinal de sáıda da ULA e a representa a entrada A de 8 bits. sgnExit recebe 00000000 quando o número de ’1’ na entrada a for par e 00000001 do contrário. 2.2.3 Complemento O complemento de um valor é dado pela diferença entre ele e o valor máximo obtido na base determinada. Em uma representação de 8 bits, sem sinal, o valor máximo obtido é ’1111 1111’, ou ’255’ em decimal. Se analisarmos o número ’0011 0000’, 48 em decimal, seu complemento deve ser ’1100 1111’, que representa o valor ’207’. Analisando os dois valores binários, nota-se que o complemento do valor escolhido é seu inverso. Portanto, para a aplicação da operação de complemento, basta inverter cada bit presente na representação binária. comp <= neg a; Onde comp recebe o complemento de a e, posteriormente, é enviado para a sáıda do módulo. 2.2.4 Não-Ou lógico O Não-Ou lógico é a aplicação da da porta lógica NOR entre cada bit das entradas a e b. a7...0 b7...0 ext7...0 Figura 2.6: Não-Ou lógico Também pode ser posta na expressão: ext = a+ b Já em VHDL, a descrição do seu comportamento é: ext = a nor b; 2.2.5 Ou Exclusivo lógico O Ou Exclusivo lógico é a aplicação da da porta lógica XOR entre cada bit das entradas a e b. a7...0 b7...0 ext7...0 Figura 2.7: Ou exclusivo lógico Também pode ser posta na expressão: ext = a⊕ b Já em VHDL, a descrição do seu comportamento é: ext = a xor b; 14 2.2.6 Não-E lógico O Não-E lógico é a aplicação da da porta lógica NAND entre cada bit das entradas a e b. a7...0 b7...0 ext7...0 Figura 2.8: Não-E lógico Também pode ser posta na expressão: ext = a · b Já em VHDL, a descrição do seu comportamento é: ext = a nand b; 15 ULA 3.1 O que é A ULA, ou Unidade Lógica Aritmética, é um módulo de circuito digital que realiza operações lógicas e aritméticas dependendo da valoração de seu seletor. Pode ser interpretada como um multiplexador (ou mux ) que realiza operações lógicas e aritméticas. ULA ext(7...0) op b(7...0)a(7...0) coutn,z,o,c Figura 3.1: Unidade Lógica Aritmética Porta Tipo Comentário a(7...0) in entrada A b(7...0) in entrada B op(2...0) in seletor de operação h, l(13...0) out sáıdas codificadas para display de 14 bits n out qualificador negativo z out qualificador zero c out qualificador carry o out qualificador overflow ext(7...0) out sáıda da ULA Tabela 3.1: Portas da ULA A ULA projetada para este trabalho segue o seguinte modo de operação: dependendo da entrada em op, será feita uma operação ou lógica ou aritmética nas entradas A, B. 3.1.1 Qualificadores No projeto de circuitos digitais complexos, faz-se o uso de qualificadores para verificar o bom andamento de alguma operação qualquer. Neste trabalho foram utilizados quatro qualificadores: 16 n, z, c e o, cada um com seu respectivo uso. Qualificador n O qualificador n indica se um número é negativo ou positivo. Em um número de 8 bits com sinal, o qualificador valerá ’1’ se o bit mais significativo for ’1’, indicando que ele é negativo e ’0’ caso contrário. Qualificador z O qualificador z indica se um número é zero ou não, recebendo ’1’ caso seja zero e ’0’ do contrário. Qualificador c O qualificador c indica se há Carry Out de operações aritméticas, valendo ’1’ caso haja Carry e ’0’ caso contrário. Qualificador o O qualificador o indica se houve um overflow(estouro de buffer) após uma operação aritmética. Por exemplo, quando somamos, em binário, 01 à 11, o resultado é 100. Entretanto quando se trabalha com vetores de tamanho limitado à 2 bits, o resultado é 00 com um Carry Out valendo ’1’. 3.2 Operações A Tabela 3.2 representa as operações realizadas quando o seletor op for um determinado valor de 3 bits. Seletor Tipo de Operação Descrição 000 Aritmética Soma de A+B 001 Aritmética Subtração de A−B 010 Aritmética Complemento de 2 em A 011 Aritmética Paridade de A 100 Lógica Complemento em A 101 Lógica Não-Ou em A 110 Lógica Ou-Exclusivo em A 111 Lógica Não-E em A Tabela 3.2: Tabela de Operações da ULA 17 Simulações Para comprovação do funcionamento da ULA foi desenvolvido um testbench onde uma ULA foi instanciada para a realização de cada operação, permitindo uma visualização paralela do resultado de cada operação. A descrição aplicada ao testbench pode ser vista abaixo. 1 library ieee; 2 use ieee.std_logic_1164.all; 3 use ieee.std_logic_unsigned.all; 4 5 entity ulatb is 6 end ulatb; 7 8 architecture behavioural of ulatb is 9 signal sia, sib : std_logic_vector(7downto 0) := (others => '0');↪→ 10 signal sop : std_logic_vector(2 downto 0) := "011"; 11 signal sum, sub, comp2 : std_logic_vector(7 downto 0) := (others => '0');↪→ 12 signal pari, comp, nol : std_logic_vector(7 downto 0) := (others => '0');↪→ 13 signal oel, nel : std_logic_vector(7 downto 0) := (others => '0');↪→ 14 signal n,z,c,o : std_logic := '0'; 15 begin 16 uut0: entity work.ula port map ( 17 a => sia, b => sib, op => "000", n => n, z => z, c => c, o => o, 18 ext => sum 19 ); 20 uut1: entity work.ula port map ( 21 a => sia, b => sib, op => "001", n => n, z => z, c => c, o => o, 22 ext => sub 23 ); 24 uut2: entity work.ula port map ( 25 a => sia, b => sib, op => "010", n => n, z => z, c => c, o => o, 26 ext => comp2 27 ); 28 uut3: entity work.ula port map ( 29 a => sia, b => sib, op => "011", n => n, z => z, c => c, o => o, 30 ext => pari 31 ); 32 uut4: entity work.ula port map ( 33 a => sia, b => sib, op => "100", n => n, z => z, c => c, o => o, 18 34 ext => comp 35 ); 36 uut5: entity work.ula port map ( 37 a => sia, b => sib, op => "101", n => n, z => z, c => c, o => o, 38 ext => nol 39 ); 40 uut6: entity work.ula port map ( 41 a => sia, b => sib, op => "110",n => n, z => z, c => c, o => o,↪→ 42 ext => oel 43 ); 44 uut7: entity work.ula port map ( 45 a => sia, b => sib, op => "111", n => n, z => z, c => c, o => o, 46 ext => nel 47 ); 48 sib <= sib+1 after 10 ns; 49 sia <= sia+1 after 2560 ns; 50 end behavioural; As simulações foram feitas no software GTK Wave. Por serem posśıveis 256 valores nas entradas a e b, as imagens contém apenas trechos aleatórios da simulação, permitindo a com- provação do funcionamento. Os módulos constrúıdos em cima do circuito CLA apresentaram um delay de 10 ns no seu funcionamento, gerando um momento de undefined, como pode ser visto na Figura4.1. Figura 4.1: Simulação com undefined Para as próximas imagens as ondas iniciadas com valores undefined foram ’adiantadas’ para que os resultados das mesmas se mantenham alinhados às entradas. 19 Figura 4.2: Simulação de 0 a 180 ns Alguns resultados explicitados em hexadecimal: 0 ns • Entrada a [7:0] = 00; • Entrada b [7:0] = 00; • Soma[7:0] = 00; • Subtração[7:0] = 00; • Complemento de 2[7:0] = 00; • Paridade[7:0] = 00; • Complemento[7:0] = FF; • Não-Ou lógico [7:0] = FF; • Ou Exclusivo lógico [7:0] = 00; • Não-E lógico [7:0] = FF; 100 ns • Entrada a [7:0] = 00; • Entrada b [7:0] = 0A; • Soma[7:0] = 0A; • Subtração[7:0] = F6; • Complemento de 2[7:0] = 00; • Paridade[7:0] = 00; 20 • Complemento[7:0] = FF; • Não-Ou lógico [7:0] = F5; • Ou Exclusivo lógico [7:0] = 0A; • Não-E lógico [7:0] = FF; Figura 4.3: Simulação de 180 a 360 ns 200 ns • Entrada a [7:0] = 00; • Entrada b [7:0] = 14; • Soma[7:0] = 14; • Subtração[7:0] = EC; • Complemento de 2[7:0] = 00; • Paridade[7:0] = 00; • Complemento[7:0] = FF; • Não-Ou lógico [7:0] = EB; • Ou Exclusivo lógico [7:0] = 14; • Não-E lógico [7:0] = FF; 300 ns • Entrada a [7:0] = 00; • Entrada b [7:0] = 1E; 21 • Soma[7:0] = 1E; • Subtração[7:0] = E2; • Complemento de 2[7:0] = 00; • Paridade[7:0] = 00; • Complemento[7:0] = FF; • Não-Ou lógico [7:0] = E1; • Ou Exclusivo lógico [7:0] = 1E; • Não-E lógico [7:0] = FF; Figura 4.4: Simulação de 2560 a 2740 ns 2600 ns • Entrada a [7:0] = 01; • Entrada b [7:0] = 04; • Soma[7:0] = 05; • Subtração[7:0] = FD; • Complemento de 2[7:0] = 01; • Paridade[7:0] = 01; • Complemento[7:0] = FE; • Não-Ou lógico [7:0] = FA; • Ou Exclusivo lógico [7:0] = 05; 22 • Não-E lógico [7:0] = FF; 2700 ns • Entrada a [7:0] = 01; • Entrada b [7:0] = 0E; • Soma[7:0] = 0F; • Subtração[7:0] = F3; • Complemento de 2[7:0] = 01; • Paridade[7:0] = 01; • Complemento[7:0] = FE; • Não-Ou lógico [7:0] = F0; • Ou Exclusivo lógico [7:0] = 0F; • Não-E lógico [7:0] = FF; Figura 4.5: Simulação de 2740 a 2920 ns 2800 ns • Entrada a [7:0] = 01; • Entrada b [7:0] = 18; • Soma[7:0] = 19; • Subtração[7:0] = E9; • Complemento de 2[7:0] = 01; 23 • Paridade[7:0] = 01; • Complemento[7:0] = FE; • Não-Ou lógico [7:0] = E6; • Ou Exclusivo lógico [7:0] = 19; • Não-E lógico [7:0] = FF; 2900 ns • Entrada a [7:0] = 01; • Entrada b [7:0] = 22; • Soma[7:0] = 23; • Subtração[7:0] = DF; • Complemento de 2[7:0] = 01; • Paridade[7:0] = 01; • Complemento[7:0] = FE; • Não-Ou lógico [7:0] = DC; • Ou Exclusivo lógico [7:0] = 23; • Não-E lógico [7:0] = FF; Figura 4.6: Simulação de 12800 a 112980 ns 12840 ns • Entrada a [7:0] = 05; 24 • Entrada b [7:0] = 04; • Soma[7:0] = 09; • Subtração[7:0] = 01; • Complemento de 2[7:0] = 05; • Paridade[7:0] = 00; • Complemento[7:0] = FA; • Não-Ou lógico [7:0] = FA; • Ou Exclusivo lógico [7:0] = 01; • Não-E lógico [7:0] = FB; 2930 ns • Entrada a [7:0] = 05; • Entrada b [7:0] = 0D; • Soma[7:0] = 12; • Subtração[7:0] = F8; • Complemento de 2[7:0] = 05; • Paridade[7:0] = 00; • Complemento[7:0] = FA; • Não-Ou lógico [7:0] = F2; • Ou Exclusivo lógico [7:0] = 08; • Não-E lógico [7:0] = FA; Figura 4.7: Simulação de 20480 a 2650 ns 25 20500 ns • Entrada a [7:0] = 08; • Entrada b [7:0] = 02; • Soma[7:0] = 0A; • Subtração[7:0] = 06; • Complemento de 2[7:0] = 08; • Paridade[7:0] = 01; • Complemento[7:0] = F7; • Não-Ou lógico [7:0] = F5; • Ou Exclusivo lógico [7:0] = 0A; • Não-E lógico [7:0] = FF; 20600 ns • Entrada a [7:0] = 08; • Entrada b [7:0] = 0C; • Soma[7:0] = 14; • Subtração[7:0] = FC; • Complemento de 2[7:0] = 08; • Paridade[7:0] = 01; • Complemento[7:0] = F7; • Não-Ou lógico [7:0] = F3; • Ou Exclusivo lógico [7:0] = 04; • Não-E lógico [7:0] = F7; Analisando cada imagem e seus resultados, percebe-se que as operações estão apresentando os resultados esperados. Os codificadores foram descritos de maneira comportamental, portanto dispensam a necessidade de simulação. 26 Codificadores O circuito é composto por dois codificadores (CODs) que convertem uma entrada s de quatro bits em uma sáıda e de quatorze bits, que servirá de entrada para um display de quatorze segmentos. Para fazer a conversão, toma-se o valor de s, converte-o para hexadecimal e ligam- se os segmentos correspondentes para formar um número hexadecimal de 0 até F. A tabela de conversão é a seguinte: Valor Binário de 4 bits Valor Hexadecimal Codificação em 14 segmentos a b c d e f g1 h i j g2 m l k 0000 0 1 1 1 1 1 1 0 0 0 1 0 0 0 1 0001 1 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0010 2 1 1 0 1 1 0 1 0 0 0 1 0 0 0 0011 3 1 1 1 1 0 0 0 0 0 0 1 0 0 0 0100 4 0 1 1 0 0 1 1 0 0 0 1 0 0 0 0101 5 1 0 1 1 0 1 1 0 0 0 1 0 0 0 0110 6 1 0 1 1 1 1 1 0 0 0 1 0 0 0 0111 7 1 1 1 0 0 0 0 0 0 0 1 0 0 0 1000 8 1 1 1 1 1 1 1 0 0 0 1 0 0 0 1001 9 1 1 1 1 0 1 1 0 0 0 1 0 0 0 1010 A 1 1 1 0 1 1 1 0 0 0 1 0 0 0 1011 B 1 1 1 1 0 0 0 0 1 0 1 0 1 0 1100 C 1 0 0 1 1 1 0 0 0 0 0 0 0 0 1101 D 1 1 1 1 0 0 0 0 1 0 0 0 1 0 1110 E 1 0 0 1 1 1 1 0 0 0 0 0 0 0 1111 F 1 0 0 0 1 1 1 0 0 0 0 0 0 0 Tabela 5.1: Tabela de Conversão para 14 segmentos Cada valor em 1 na coluna de codificação equivale ao estado ”ligado”de cada um dos 14 segmentos do display. Em 0, o segmento está desligado. Como só podemos representar valores de um algarismo hexadecimal segundo a Figura 5.1, fez-se necessário que utilizássemos dois displays de 14 segmentos para representar corretamente os valores resultantes das operações requisitadas, podendo representar até FF16, sem levar em consideração os qualificadores de Carry e de overflow. Neste circuito não é utilizada a sáıda dp dos displays porque no esquema especificado ela não foi apresentada. O código em VHDL do codificador foi criado de maneira comportamental e é como segue: 27 Figura 5.1: Display de 14 Segmentos Fonte: https://commons.wikimedia.org/wiki/File:14-segment.png 1 entity cod is 2 port( 3 s : in std_logic_vector(3 downto 0); 4 e : out std_logic_vector(13 downto0) 5 ); 6 end cod; 7 architecture behavioral of cod is 8 begin 9 cod_mux : process(s) 10 begin 11 case s is 12 when "0000" => e <= "11111100010001"; --* 0 13 when "0001" => e <= "01100000010000"; --* 1 14 when "0010" => e <= "11011010001000"; --* 2 15 when "0011" => e <= "11110000001000"; --* 3 16 when "0100" => e <= "01100110001000"; --* 4 17 when "0101" => e <= "10110110001000"; --* 5 18 when "0110" => e <= "10111110001000"; --* 6 19 when "0111" => e <= "11100000001000"; --* 7 20 when "1000" => e <= "11111110001000"; --* 8 21 when "1001" => e <= "11110110001000"; --* 9 22 when "1010" => e <= "11101110001000"; --* A 23 when "1011" => e <= "11110000101010"; --* B 24 when "1100" => e <= "10011100000000"; --* C 28 25 when "1101" => e <= "11110000100010"; --* D 26 when "1110" => e <= "10011110000000"; --* E 27 when "1111" => e <= "10001110000000"; --* F 28 when others => e <= "11111111111111"; --* U: undefined 29 end case; 30 end process cod_mux; 31 end behavioral; Ao fazer a análise do código, conclui-se que a sáıda e de 14 bits recebe uma sequência de bits espećıfica diretamente dependente da entrada s, o que caracteriza um codificador. Como o codificador foi projetado de maneira comportamental, ele satisfaz o funcionamento esperado em todos os casos, até em excessões(when others => e <= "11111111111111";). 29 Considerações finais Este trabalho nos fez ir à fundo em tópicos diversos sobre a linguagem VHDL e sobre circuitos digitais, ampliando nossos conhecimentos nesses assuntos. Além disso, horas de pesquisa foram feitas sobre LaTeX para gerar um arquivo PDF de qualidade. Todo o projeto foi desenvolvido em softwares e ferramentas gratuitas de maneira a não limitar a execução dos módulos descritos neste. Os softwares e ferramentas utilizadas foram: BitBucket, Discord, GHDL, GtkWave, Overleaf, VHDocL e Visual Studio Code. No diretório docs deste projeto são encontrados o enunciado do trabalho, este código em LaTeX, a documentação, as imagens das simulações, duas fotos da gata Adelaide Leal e os arquivos de Makefile. No diretório src encontram-se os códigos-fonte na extensão VHD, um arquivo Makefile e um script run.sh. O script checa a sintaxe, analiza o código, compila, cria um executável e gera a onda. Após a simulação, também é aberto o GtkWave para ser feita a análise da simulação. Quando analisadas as simulações da ULA, notou-se um padrão: sempre que fora utilizado dois sinais no mesmo processo (um associado ao outro), a sáıda recebia um delay de um clock, iniciando como U (undefined). Isso ocorre porque sinais em VHDL só recebem um valor no final de um processo, e quando associamos um sinal à outro, acabamos por somar os delays. Durante os testes experimentais, encadeamos três sinais e notamos um delay de dois clocks. Encadeando quatro sinais, tivemos um delay de três clocks, e assim por diante. Esta caracteŕıstica foi tida como comportamento normal de um circuito digital. O projeto funcionou como esperado e o consideramos um sucesso. 30 Introdução Operações Somador/subtrator Full adder Carry Look Ahead Adder Somador Subtrator Demais operações Complemento de 2 Paridade Complemento Não-Ou lógico Ou Exclusivo lógico Não-E lógico ULA O que é Qualificadores Operações Simulações Codificadores Considerações finais
Compartilhar