vhdl
TRANSCRIPT
INDICE
PARTE I
Apresentação do MaxPlux................................................................................................... 1
Iniciando um Projeto para Descrição em VHDL................................................................. 2
Comandos Principais.............................................................................................. 3
Tipos de Sinais....................................................................................................... 4
Entradas e Saídas do Nosso Projeto - Definindo uma Entidade........................................... 4
Definindo a Arquitetura do Nossa Entidade......................................................................... 5
Definindo um Processo para nossa Arquitetura................................................................... 6
Finalmente vamos escrever o código
Apresentação do Algoritmo da SOMA.................................................................. 8
Em VHDL.............................................................................................................. 8
Código Final........................................................................................................... 10
Agora vamos Copilar o Código Digitado............................................................................. 11
Simulando o Projeto............................................................................................................. 12
Iniciando um Projeto para Desenhar o Circuito (Floorplan)
Símbolos do Floorplan ........................................................................................... 17
Exercícios............................................................................................................................. 21
PARTE I
MaxPlux
Apresentação do MAX+plus
Este software nos será útil para a simplificação e implementação de circuitos digitais. Particularmentetrabalharemos com a parte aritmética, criando uma biblioteca aritmética para ser usada em aplicações futuras.
Para Iniciar umnovo projeto!
Iniciando um Projeto para Descrição em VHDL
Na barra de ferramentas do MAX+plus clique no botão mais a esquerda, após abrir a janela de‘Novo’, você irá informar o que você quer, selecione ‘Text Editor file’ e clique Ok. Abrirá uma janela detexto onde você digitará o seu projeto.
Antes de prosseguir, salve o projeto informado que é um texto que contem uma descrição em VHDL, cliqueno botão salvar . Na janela ‘Salvar’, informe o nome do projeto e indique que a extensão *.VHD, eclique Ok.
Comandos Principais
Agora já podemos digitar nosso projeto:
Em primeiro vamos indicar que queremos usar a biblioteca ieee.
LIBRARY ieee;USE ieee.std_logic_1164.all;
Agora vamos declarar uma entidade, que contém a descrição das entradas e saídas do circuito.
Selecione no Menu Templantes, VHDL Templantes..., e selecione Entity Declaration e clique Ok.
Criará o seguinte código em seu projeto.
ENTITY __entity_name ISPORT(
__input_name, __input_name : IN STD_LOGIC;__input_vector_name : IN
STD_LOGIC_VECTOR(__high downto __low);__bidir_name, __bidir_name : INOUT STD_LOGIC;__output_name, __output_name : OUT STD_LOGIC);
END __entity_name;
__entity_name – Nome da entidade, tem que ser obrigatoriamente o mesmo nome do projeto.__input_name – Nome de um sinal de entrada.__output_name - Nome de um sinal de saída.
Tipos de Sinais
STD_LOGIC – sinal lógico aceita ‘1’ – nível lógico 1, ‘0’ – nível lógico 0.STD_LOGIC_VECTOR(bit downto 0)– um vetor de sinais lógicos com tamanho de bit-1 bits.
Entradas e Saídas do Nosso Projeto – Definindo uma Entidade
Nosso projeto será um somador de 8 bits, e terá como entrada dois vetor, A e B, que serão os operadores e umvetor de saída S que conterá o resultado da soma de A e B.
Faça as substituições necessárias para que o código fique da seguinte maneira:
LIBRARY ieee;USE ieee.std_logic_1164.all;
ENTITY Algo ISGENERIC(byte_entrada: integer := 8; byte_saida: integer := 16);PORT(
clk : IN STD_LOGIC;A, B : IN STD_LOGIC_VECTOR(byte_entrada-1 downto 0);S : OUT STD_LOGIC_VECTOR(byte_saida-1 downto 0));
END Algo;
Note que:GENERIC – Está instrução serve para declarar constantes na entidade, note que usamos as constantesbyte_entrada e byte_saida para indicar o tamanho dos sinais de entrada e saída respectivamente e as usaremosmais a frente em nosso projeto.
O sinal de entrada clk servirá para acionar o somador, qdo. este sinal for de ‘0’ para ‘1’ o circuito apresentaráa soma do sinal A com o sinal B na saída S.
Qdo. o sinal é declarado como INOUT, ele servirá tanto para entrada como para saída. Ou seja, este sinal desaída será um registrador interno também.
Definindo a Arquitetura do Nossa Entidade
Novamente selecione no Menu Templates, VHDL Templantes..., selecione Architecture Body... e clique Ok.
Criará o seguinte código em seu projeto.
ARCHITECTURE a OF __entity_name ISSIGNAL __signal_name : STD_LOGIC;SIGNAL __signal_name : STD_LOGIC;
BEGIN-- Process Statement
-- Concurrent Procedure Call
-- Concurrent Signal Assignment
-- Conditional Signal Assignment
-- Selected Signal Assignment
-- Component Instantiation Statement
-- Generate StatementEND a;
(a) Nome daArquitetura
Nome da Entidadeque a arquiteturadescreve
Declarações de SinaisAuxiliares usados naarquitetura.Descrição dos
processossíncronos eassíncronos
Faça as alterações necessárias para que o código fique da seguinte maneira:
LIBRARY ieee;USE ieee.std_logic_1164.all;
ENTITY Algo ISGENERIC(byte_entrada: integer := 8; byte_saida: integer := 16);PORT(
clk : IN STD_LOGIC;A, B : IN STD_LOGIC_VECTOR(byte_entrada-1 downto 0);S : OUT STD_LOGIC_VECTOR(byte_saida-1 downto 0));
END Algo;
ARCHITECTURE Algo OF Algo IS
BEGIN-- Process Statement
END Algo;
Definindo um Processo para nossa Arquitetura
Posicione o cursor na linha seguinte ao comentário ‘-- Process Statement’ , e vá ao Menu Templates,Templates..., e selecione Process (Combinatorial Logic).... Será criado o seguinte código em seu projeto:
__process_label:PROCESS (__signal_name, __signal_name, __signal_name)
VARIABLE __variable_name : STD_LOGIC;VARIABLE __variable_name : STD_LOGIC;
BEGIN-- Signal Assignment Statement
-- Variable Assignment Statement
-- Procedure Call Statement
-- If Statement
-- Case Statement
-- Loop StatementEND PROCESS __process_label;
Nome do Processo
Declarações de VariáveisAuxiliares usadas dentrodo Processo.
Descrição da seqüência deações que descreve oprocesso.
Faça as alterações necessárias para que o código fique da seguinte maneira:
LIBRARY ieee;USE ieee.std_logic_1164.all;
ENTITY Algo ISGENERIC(byte_entrada: integer := 8; byte_saida: integer := 16);PORT(
clk : IN STD_LOGIC;A, B : IN STD_LOGIC_VECTOR(byte_entrada-1 downto 0);S : OUT STD_LOGIC_VECTOR(byte_saida-1 downto 0));
END Algo;
ARCHITECTURE Algo OF Algo IS
BEGIN-- Process Statement
Algo_Soma:PROCESS (clk)BEGIN
END PROCESS Algo_Soma;
END Algo;
Note que:PROCESS(clk) – clk como parâmetro indica que o processo só será executado qdo. O sinal de entrada clkmudar de estado lógico.
Finalmente vamos escrever o código
Apresentação do Algoritmo da SOMA
SejaA := Operado1 -- NR_MAX_DE_BITSB := Operador2 -- NR_MAX_DE_BITSR := Resultado da soma -- 2 * NR_MAX_DE_BITS
vaium := ‘0’;Para i de 0 até NR_MAX_DE_BITS-1 Faça
R[i]:= A[i] xor B[i] xor vaium;
vaium := ( B[i] and A[i] ) or( B[i] and vaium) or(vaium and A[i] );
Fim;
R[NR_MAX_DE_BITS] := vaium;
Para i de NR_MAX_DE_BITS +1 até 2 * NR_MAX_DE_BITS-1 FaçaR[i]:= ‘0’;
Fim;
Por exemplo: Somar 3H com BH, resultando EH. A e B com 4 bits e R com 8 bits.
carry A(I) B(I) R(O)0 0011 1011 000000001 0011 1011 000000101 0011 1011 000001100 0011 1011 000011100 00001110
000011100000111000001110
Em VHDL
• Na linha abaixo de Process(clk), vamos colocar a declaração da uma variável auxiliar vaium.
--Declara uma variavel auxiliar 'vaium' com tipo: STD_LOGIC--Serão usadas mas adiante no códigoVARIABLE vaium : STD_LOGIC;
• Posicione o cursor entre BEGIN e END PROCESS..., e digite os códigos ou procure no Menu Templates,VHDL Templates... .
• Primeiro vamos informar que nosso circuito só funcionará na borda de subida do clk.
--Só executar a soma se clk for borda de subidaIF clk'EVENT AND clk = '1' THEN
-- Coloque seu código aqui
END IF;
EVENT – Indica que houve um evento de clk.AND clk = ‘1’ – Indica que clk foi para ‘1’
• Satisfazendo a condição de ser borda de subida do clk, vamos iniciar vaium com ‘0’:--Qdo. o processo começar, inicia a var. vaium com 0vaium := ‘0’;
:= , serve para atribuições em variáveis e<=, serve para atribuições em sinais
• Logo após, vamos fazer o loop da Soma.
--Loop PrincipalloopSoma:FOR i IN A'RANGE LOOP S(i) <= A(i) xor B(i) xor vaium;
vaium := ( B(i) and A(i) ) or( B(i) and vaium) or(vaium and A(i) );
END LOOP loopSoma;
A'RANGE – indica que i vai tomar valores de 0 até o tamanho de bits de A, e executar as ações para cada umdeste valor.
• Depois de ter executado o loop da Soma, vamos colocar vaium na posição ‘byte_entrada’ do sinal S.
--Se o resultado excedeu o tamanho de bits da entradaS(byte_entrada) <= vaium ;
• E zerar as demais posições de S, ou seja os bits de byte_entrada até byte_saida-1.
--Zera os bits mais altos não usados na somaloopZera:FOR i IN byte_entrada+1 TO byte_saida-1 LOOP S(i) <= '0';END LOOP loopZera;
• Pronto o sinal S contém o resultado da soma de A com B.
Em seguida listamos o código final do nosso projeto:
Código Final
LIBRARY ieee;USE ieee.std_logic_1164.all;
ENTITY Algo ISGENERIC(byte_entrada: integer := 8; byte_saida: integer := 16);PORT(
clk : IN STD_LOGIC;A, B : IN STD_LOGIC_VECTOR(byte_entrada-1 downto 0);S : OUT STD_LOGIC_VECTOR(byte_saida-1 downto 0));
END Algo;
ARCHITECTURE Algo OF Algo ISBEGIN-- Process Statement
Algo_Soma:PROCESS (clk)
--Declara uma variavel auxiliar 'vaium' com tipo: STD_LOGIC--Serão usadas mas adiante no códigoVARIABLE vaium : STD_LOGIC;
BEGIN
--Só executar a soma se clk for borda de subidaIF clk'EVENT AND clk = '1' THEN
--Qdo. o processo começar, inicia a var. vaium com 0vaium := '0';
--Loop PrincipalloopSoma:FOR i IN A'RANGE LOOP S(i) <= A(i) xor B(i) xor vaium;
vaium := ( B(i) and A(i) ) or( B(i) and vaium) or(vaium and A(i) );
END LOOP loopSoma;
--Se o resultado excedeu o tamanho de bits da entradaS(byte_entrada) <= vaium ;
--Zera os bits mais altos não usados na somaloopZera:FOR i IN byte_entrada+1 TO byte_saida-1 LOOP S(i) <= '0';END LOOP loopZera;
END IF;END PROCESS Algo_Soma;
END Algo;
Agora vamos Copilar o Código Digitado
Antes vá no Menu de Projetos, File – Project, e selecione Set Project to Current File. Assim você informa queo projeto principal é o que está na janela ativa.
Depois no Menu de Projetos clique em Save & Compile, aparecerá mais duas janelas, uma do copilador, eoutra com as mensagens da compilação. No caso do código estiver com erro de sintaxe, no fim da tentativa decompilação será mostrado uma mensagem informando quantos erros ocorreram.
Setar ProjetoPrincipal
Para Copilarou Simular.
Mensagem de Erro, falta ‘;’ nofinal da linha 33. Dê doiscliques na mensagem e corrijaesse erro.
Neste caso, na janela de mensagens são informados o número da linha e o que ocorreu de errado. Dê doiscliques na mensagem de erro e você será levado a linha que foi identificado o erro.Um erro muito comum é o esquecer do ponto e virgula no final da linha.Algumas vezes as mensagens de erro seguinte da primeira são conseqüência dela, ou seja, identificando econcertando o primeiro erro os demais também são consertados. As vezes ocorre o contrario um erro escondeos outros, ou seja, consertando aparentemente o único erro do projeto e copilando novamente, você descobrevários outros.Mas não desista, lembre-se do ditado que diz: aprendemos com nossos próprios erros.
Simulando o Projeto
No Menu MAX+plus II, clique em Waveform Editor. Abrirá a janela do Editor de Forma de Onda. Nela vocêcolocará os sinais de entrada e saída que deseja testar. Seta os sinais de entrada no tempo.Manda simular, e será mostrado os dados de saída em função do tempo.
Com a janela Waveform Editor aberta. Vá ao Menu Node e Selecione Insert Node. Abrirá a seguinte janela,na qual você escolherá os sinais de entrada ou saída que desejar.
Selecione clk(I) e clique Ok. Repta o procedimento, inserindo os sinais A(I), B(I) e S(O).Clique duas vezes em cima de A(I), abrirá uma janela de informações do Grupo de sinal A[0..7].
Selecione HEX e clique Ok. Assim os números serão exibidos em hexadecimal. Repita também para B e S.
Listagem de todos osSinais, de entrada esaída do projeto
Nome do Sinal que seráinserido
Lista sinais.
InsereSinal
Tipo do sinal:Entrada ou Saída.
Seu Waveform deve estar assim:
Agora, vamos colocar os valores em A e B que queremos somar. Selecione A(I), clicando em cima dele.
Com A(I) selecionado clique em na barra de ferramentas a esquerda. Digite um valor e Ok.
Repita o procedimento com B(I), digitando um valor para ele também.
Com o sinal clk, vamos criar uma borda de subida num tempo qualquer maior que 0, claro.
Com o mouse selecione a faixa de tempo que deseja colocar ‘1’ em clk: por exemplo:
E clique em na barra de ferramentas a esquerda. Isso fará com que a faixa selecionada fique em um.
No exemplo, borda de subida em t=100,0ns, onde ocorrerá a soma de A com B e será apresentado o resultadoem S.
Seu Waveform deve estar assim:
Faixaselecionadacom o mouse!
Finalmente com todas as entradas setadas, vamos mandar simular o projeto. Vá ao Menu File, Project, Save &Simulate.
Abrirá uma janela pedindo que você informe um nome para o arquivo WaveForm, clique Ok.
Ele começara o processo de simulação, e se não houver nenhum erro, você verá a seguinte mensagem:
Clique Ok e seu WaveForm deverá estar assim:
Sinais emrelação aotempo
Tempo
CursorNome doSinalI-EntradaO-Saída
Valor dossinais em cimado cursor.
Você pode selecionar um intervalo de tempo para a simulação. No Menu View, clique em Time Range.Na janela Time Range coloque o tempo inicial e final, depois clique Ok.
No Menu View clique em Fit in Windows, que redesenha os sinais colocando-os todos dentro da telaAgora faça mais teste com os sinais, por exemplo:
Note que a soma é feita somente qdo. o sinal clk é levado para ‘1’.
Iniciando um Projeto para Desenhar o Circuito (Floorplan)
Na barra de ferramentas do MAX+plus clique no botão mais a esquerda, após abrir a janela de‘Novo’, você irá informar o que você quer, selecione ‘Graphic Editor file’ e ‘*.gdf’ e clique Ok. Assim Abriráuma janela na qual você desenhará o seu projeto.
Símbolos do Foorplan
Dê um clique duplo dentro da janela de desenho ou selecione no menu Symbol, Enter Symbol..., e abrirá umdialogo permitindo que selecione um símbolo pré-definido. Por exemplo, para iniciarmos nosso projetovamos selecionar três símbolos de entrada (input) e um de saída (output).
Selecione aquia Biblioteca desímbolos.
Selecioneaqui oSímbolos.
Na tela de ‘Lista de Símbolos’, selecione ..\maxplus2\max2lib\prim na biblioteca de símbolo, dando doiscliques nesta opção, será listada os símbolos dessa biblioteca, selecione input., e clique Ok.Será criada em sua janela de trabalho uma porta de entrada:
Para um dar o nome do sinal, selecione este sinal com um clique em cima dele. Clique no botão direito domouse e aparecerá o seguinte menu:
Selecione Edit Pin Name e escolha um nome para este sinal.
Repita este processo mais duas vezes, criando assim três sinais de entradas (A, B e VemUm). E com o mesmoprocesso, só que selecionando output no lugar de input, crie dois sinal de saída (S e VaiUm) para nossoprojeto.
O circuito deverá obedecer as seguintes fórmulas:S := A xor B xor VaiUm;VaiUm := ( B and A ) or ( B and VaiUm) or (VaiUm and A);
RecortarCopiarColarApagar componente
Editar Nome do Sinal
Editar valor Default dosinal (Vcc ou GND)
Roda Componente:Verticalmente,HorizontalmentePor angulo.
Repetindo o processo para selecionar os sinais de entrada e saída (input e output), escolha agora as portaslógicas: duas xor, três and2 e uma or3.Para facilitar, quando o cursor estiver em Symbol Files e você quer selecionar xor, digite ‘X’ no teclado, queserá posicionado o cursor no próximo símbolo que comece com a letra ‘X’.Mais uma, se você já tem um componente na tela e deseja outro igual, selecione-o, clique no botão direito domouse, escolha copiar. Depois no local da tela onde deseja copy o componente, clique novamente no botãodo mouse e selecione paste. Ou, segurando o Ctrl, clique no componente e arraste-o que ele será duplicado.
Sua tela deve estar assim:
Agora com o Menu de Ferramentas posicionado mo lado esquerdo da janela, desenhe as linhas necessárias:
Modo Cursor, Serve paraarrastar componentes.
Para escrever alguminformativo no circuito.
Para fazer linhas de ligaçãocom curvas de 90 º.
Linhas de ligação retas.
Amplia ou Diminui avisualização doscomponentes.
Seu circuito deve ficar assim:
Agora Salve, Compile e Simule o circuito da mesma maneira que foi descrito na parte anterior deste manual.
Digite Ctrl+L ou vá e, Files, Project, Save & Copile. Se todas as ligações foram feitas corretamente, vocêdeve receber uma mensagem ‘Projeto Compilado com sucesso’.
Crie uma nova janela WaveForm para simular o projeto. Insira nela os sinais A, B, VemUm e VaiUm. Nomenu Node, Insert Node. Na janela Insert Node, clique em List, selecione o sinal e clique Ok. Para maisinformação ver Capitulo Simulando o Projeto.
Informe os valores desejados para os sinais de entrada, no menu selecione, Files, Project, Save & Simule oudigite Ctrl+Shift+L para salvar e simular o projeto obtendo assim os valores de saída a partir dos dados deentrada.
Obtendo assim:
Há vários outros símbolos pré-definidos que você pode usar como também todos os seus projetos já copiladostambém estarão disponíveis.
Exercícios:
1) Fazer a descrição em VHDL de um circuito subtrator de n bits. Copilar e Simular.R.:
Apresentação do Algoritmo da Subtração
SejaA := Operado1 -- NR_MAX_DE_BITSB := Operador2 -- NR_MAX_DE_BITSR := Resultado da soma -- NR_MAX_DE_BITS
vaium := ‘0’;Para i de 0 até NR_MAX_DE_BITS-1 Faça
R[i]:= A[i] xor B[i] xor vaium;
vaium := ( B[i] and R[i]) or( B[i] and vaium) or(vaium and R[i]);
Fim;
Por exemplo: Subtrair 3H de BH, resultando 8H. A, B e R com 4 bits.
carry A(I) B(I) R(O)0 0011 1011 00000 0011 1011 00000 0011 1011 00000 0011 1011 1000
Foi feito um flag de erro, que vai para ‘1’ quando o operador B for maior que o operador A. Isso geraria umresultado negativo, não previsto.
Em VHDL:
LIBRARY ieee;USE ieee.std_logic_1164.all;-- Subtração S = A - BENTITY Subr IS
GENERIC(byte_entrada: integer := 8; byte_saida: integer := 8);PORT(
clk : IN STD_LOGIC;A, B : IN STD_LOGIC_VECTOR(byte_entrada-1 downto 0);S : OUT STD_LOGIC_VECTOR(byte_saida-1 downto 0);erro : OUT STD_LOGIC);
END Subr;
ARCHITECTURE Subr OF Subr ISBEGIN-- Process Statement
Subr_Soma:PROCESS (clk)
--Declara uma variavel auxiliar 'vaium' e svlAi com tipo: STD_LOGIC--Serão usadas mas adiante no códigoVARIABLE vaium : STD_LOGIC;VARIABLE auxS: STD_LOGIC;
BEGIN
--Só executar a soma se clk for borda de subidaIF clk'EVENT AND clk = '1' THEN
--Qdo. o processo começar, inicia a var. vaium com 0vaium := '0';
--Loop PrincipalloopSoma:FOR i IN 0 TO byte_entrada-1 LOOP
auxS := (A(i) xor B(i) xor vaium);S(i) <= (A(i) xor B(i) xor vaium);
vaium := ( B(i) and auxS ) or ( B(i) and vaium) or (vaium and auxS ) ;
END LOOP loopSoma;
--Se o A > B, resultado é negativo.erro <= vaium ;
END IF;END PROCESS Subr_Soma;
END Subr;
2) Fazer o desenho em Floorplan de um circuito contador assíncrono. Copilar e Simular.R.
Um contador é um registrador capaz de contar o número de pulsos de relógio que chegaram em suaentrada de relógio.
A fig. Abaixo mostra um contador construído com biestáveis JK.
O Circuito:
A simulação:
PARTE II
Subdividindo o Programa em Funções................................................................................ 24Função Soma.......................................................................................................... 24Função para Rotacionar um Sinal: STD_LOGIC_VECTOR................................. 25Função para Setar um bit no Sinal: STD_LOGIC_VECTOR............................... 26Função para ler um bit no Sinal: STD_LOGIC_VECTOR................................... 27Função para Comparar Numericamente dois sinais............................................... 28Função para retornar ‘um’ se o sinal for zero caso contrário ‘zero’...................... 29Função Subtração.................................................................................................... 30
Divisão para n-Bits.............................................................................................................. 31
Padrão de Interface............................................................................................................... 31
Esqueleto do Programa em VHDL contendo um LAÇO..................................................... 32
Forma de Onda dos Sinais de Entrada e Saída de um Divisor de 8 bits............................... 34
Multiplicação de N-bits........................................................................................................ 35
Forma de Onda dos Sinais de Entrada e Saída de um Multiplicador de 8 bits..................... 37
Raiz Quadrada para Operadores de N-bits.......................................................................... 38
Esqueleto do Programa em VHDL contendo dois LAÇO For...Next Aninhado.................. 39
Forma de Onda dos Sinais de Entrada e Saída ( Raiz Quadrada de 6 bits )........................ 42
Conversão de Hexadecimal para Decimal............................................................................ 43
Esqueleto do Programa em VHDL contendo dois LAÇO Aninhado (While..For...Next...Wend)............. 44
Forma de Onda dos Sinais de Entrada e Saída ( Conversor Hexa para Decimal - 8 bits )............... 47
Conversor de Decimal para Hexadecimal............................................................................ 48
Listagem Completa do Process Para Conversão de Decimal para HexaDecimal................ 49
Forma de Onda dos Sinais de Entrada e Saída ( Conversor Decimal para HexaDecimal ).............. 50
Função Multiplicação........................................................................................................... 51
Forma de Onda De uma Chamada a Função S := Multiplic( A, B ) .................................... 51
Exercícios............................................................................................................................. 52Função Divisão....................................................................................................... 52
Observações......................................................................................................................... 54
PARTE II
Subdividindo o Programa em Funções
Sintaxe:
FUNCTION __function_name(__input_name, MACHINE __state_machine_name)RETURNS (__output_name, __bidir_name, MACHINE __state_machine_name);
Exemplo de Aplicação
Função Soma
----------------------------------------------- S := Soma ( A , B )---------FUNCTION Soma (
A : STD_ULOGIC_VECTOR; B : STD_ULOGIC_VECTOR
)RETURN STD_ULOGIC_VECTOR IS
VARIABLE vaium : STD_ULOGIC;VARIABLE S : STD_ULOGIC_VECTOR(A’Length -1 downto 0);
BEGINvaium := '0';
--Loop PrincipalloopSoma:FOR i IN 0 TO B’Length-1 LOOP
S(i) := A(i) xor B(i) xor vaium;
vaium := ( B(i) and A(i) ) or( B(i) and vaium) or(vaium and A(i) );
END LOOP loopSoma;
LoopSoma2:FOR i IN B’Length TO A’Length -1 LOOP
S(i) := A(i) xor vaium;
vaium := (vaium and A(i) );END LOOP LoopSoma2;
RETURN S;END Soma;
Sinais de Entrada. Ex. A : STD_ULOGIC
Sinal que será retornado
Exemplo de Chamada a Função Soma
...
Algo:PROCESS (clk)
--Declara uma variavel auxiliarVARIABLE AUX : STD_ULOGIC_VECTOR(byte_saida-1 downto 0);A : STD_ULOGIC_VECTOR(byte_entrada-1 downto 0);
BEGIN
...AUX := Soma ( AUX, A );..
END Algo;
FUNÇÃO PARA ROTACIONAR UM SINAL: STD_LOGIC_VECTOR
----------------------------------------------- S := rot ( S )---------FUNCTION rot (S_IN : STD_ULOGIC_VECTOR)
RETURN STD_ULOGIC_VECTOR IS
VARIABLE S : STD_ULOGIC_VECTOR(S_IN'length-1 downto 0);BEGIN
loopRot:FOR i IN S_IN'length-1 DOWNTO 1 LOOP
S(i) := S_IN(i-1);END LOOP loopRot;S(0) := '0';
RETURN S;END rot;
Exemplo:
A: 0 0 0 1 1 0 1
A := rot ( A );
A: 0 0 1 1 0 1 0
FUNÇÃO PARA SETAR UM BIT NO SINAL: STD_LOGIC_VECTOR
----------------------------------------------- S := set ( S, contador, bitset )---------FUNCTION set (S_IN : STD_ULOGIC_VECTOR;
Index : INTEGER RANGE 0 TO S_IN’Length -1;BitSet : STD_ULOGIC)
RETURN STD_ULOGIC_VECTOR IS
VARIABLE S : STD_ULOGIC_VECTOR(S_IN’Length -1 downto 0);BEGIN
loopRot:FOR i IN 0 TO S_IN’Length -1 LOOP
IF i = Index THEN S(i) := bitset;
ELSES(i) := S_IN(i);
END IF;END LOOP loopRot;
RETURN S;END set;
Exemplo:
A: 0 0 0 1 1 0 1I : 3B: 0
A := set( A, I, B );
A: 0 0 0 0 1 0 1
FUNÇÃO PARA LER UM BIT NO SINAL: STD_LOGIC_VECTOR
----------------------------------------------- S := get( S, contador, bitset )---------FUNCTION get (S_IN: STD_ULOGIC_VECTOR;
Index : INTEGER RANGE 0 TO S_IN’Length -1;)
RETURN STD_ULOGIC_VECTOR IS
VARIABLE bitset : STD_ULOGIC;BEGIN
loopRot:FOR i IN 0 TO S_IN’Length -1 LOOP
IF i = Index THEN bitset := S(i);
END IF;END LOOP loopRot;
RETURN bitset;END get;
Exemplo:
A: 0 0 0 1 1 0 1I : 3B: 0
B := get( A, 3, ‘1’ );
B: 1
FUNÇÃO PARA COMPARAR NUMERICAMENTE DOIS SINAIS
----------------------------------------------- S := intcmp ( A, B )-- Retorna: 1 – A >= B-- 0 – B > A---------FUNCTION intcmp (A : STD_ULOGIC_VECTOR;
B : STD_ULOGIC_VECTOR )RETURN STD_ULOGIC IS
VARIABLE S : STD_ULOGIC_VECTOR(A’length -1 downto 0);VARIABLE vaium : STD_ULOGIC;
BEGIN
vaium := '0';loopCmp:FOR i IN 0 TO A’length -1 LOOP
S(i) := (A(i) xor B(i) xor vaium);
vaium := ( B(i) and S(i) ) or ( B(i) and vaium) or(vaium and S(i) ) ;
END LOOP loopCmp;vaium := not vaium;
RETURN vaium;END intcmp;
EXAEMPLO:
A: 150
B: 50
IF INTCMP( A, B ) = ‘0’ THEN -- A < B
...
END IF;
FUNÇÃO PARA RETORNAR ‘UM’ SE O SINAL FOR ZERO CASO CONTRÁRIO ‘ZERO’
----------------------------------------------- S := IsZero ( A , B )---------FUNCTION IsZero ( A : STD_ULOGIC_VECTOR(byte_width-1 downto 0)
)RETURN STD_ULOGIC IS
VARIABLE retorno : STD_ULOGIC;BEGIN
retorno := '1'; --É zero
--Loop PrincipalloopZero:FOR i IN 0 TO A'Length-1 LOOP
IF A(i) = '1' THENretorno := '0'; --Não é zero
END IF;
END LOOP loopZero;
RETURN retorno;END IsZero;
EXAEMPLO:
IF IsZero( A ) THEN -- A = 0
...
END IF;
FUNÇÃO SUBTRAÇÃO
----------------------------------------------- S := Subtracao ( A , B )---------FUNCTION Subtracao (A : STD_ULOGIC_VECTOR;
B : STD_ULOGIC_VECTOR )
RETURN STD_ULOGIC_VECTOR IS
VARIABLE vaium : STD_ULOGIC;VARIABLE S : STD_ULOGIC_VECTOR(A’length -1 downto 0);
BEGIN--Qdo. o processo começar, inicia a var. vaium com 0vaium := '0';
--Loop PrincipalloopSubtr:FOR i IN 0 TO A’length -1 LOOP
S(i) := (A(i) xor B(i) xor vaium);
vaium := ( B(i) and S(i) ) or( B(i) and vaium) or (vaium and S(i) ) ;
END LOOP loopSubtr;RETURN S;
END Subtracao;
Exemplo de Chamada a Função Subtração
...
Algo:PROCESS (clk)
--Declara uma variavel auxiliarVARIABLE AUX : STD_ULOGIC_VECTOR(8 downto 0);A : STD_ULOGIC_VECTOR(8 downto 0);
BEGIN
...AUX := Subtracao( AUX, A );..
END ALGO;
DIVISÃO PARA N-BITS
O algoritmo consiste em girar, juntamente com o ‘Carry’ o Dividendo dentro do Resto, estando esteinicialmente zerado. Um contador do número de Bits (tamanho do Dividendo) deverá ser decrementado cadavez que for realizado uma rotação.
Se o resto for Maior ou Igual ao Divisor o ‘Carry’ será igual a um, sendo este valor na próxima rotaçãoposicionado no bit 2º do dividendo. Toda vez que isto acontecer devemos atualizar o valor do Resto,subtraindo o valor do Divisor.
O final da próxima divisão irá ocorrer quando o contador de Bits for igual a zero, porém aindadevemos posicionar o último ‘Carry’ dentro do Dividendo, sem rotacionar o Resto.
A seguir apresentamos a aplicação do algoritmo para operadores de 8 bits
Dividendo -> 45 HDivisor -> 06 HQuociente -> 0B HResto -> 03 H
Carry Resto Dividendo / Quociente Divisor Contador0 0000 0000 0100 0101 0000 0110 080 0000 0000 1000 1010 0000 0110 070 0000 0001 0001 0100 0000 0110 060 0000 0010 0010 1000 0000 0110 050 0000 0100 0101 0000 0000 0110 040
1
0000 1000-0000 01100000 0010
1010 0000 0000 0110 03
0 0000 0101 0100 0001 0000 0110 020
1
0000 1010-0000 01100000 0100
1000 0010 0000 0110 01
0
1
0000 1001-0000 01100000 0011
0000 0101 0000 0110 00
0 0000 0011 0000 1011 Posiciona o último ‘Carry’0000 0011 0000 1011 Resultado
Padrão de Interface
Faremos três sinais de controle:clk – que será o clock;rst – que será o reset;str – que será o start.prt – vai para um quando o resultado já estiver pronto para leitura
Esqueleto do Programa em VHDL contendo um LAÇO
LIBRARY ieee;USE ieee.std_logic_1164.all;
ENTITY Divi ISGENERIC(width_byte: integer := 8);PORT(
clk,str,rst : IN STD_ULOGIC;A, B : IN STD_ULOGIC_VECTOR(width_byte-1 downto 0);Q, R, prt : OUT STD_ULOGIC_VECTOR(width_byte-1 downto 0));
END Divi;
ARCHITECTURE Divi OF Divi IS-- Declaração das Funções Auxiliares
BEGIN-- Process Statement
Algo_Divi:PROCESS (clk)
--Declara das variáveis auxiliares--Contador, servira para controle de passagem--Como dentro de um laço For..NextVARIABLE Contador : INTEGER RANGE 0 TO width_byte+1;
BEGIN
--Só executar a soma se clk for borda de subidaIF clk'EVENT AND clk = '1' THEN
IF rst = '1' THENContador := 0;prt <= ‘0’;--Zera variaveis de auxiliares--Copia sinais de entrada para variavies auxiliares, qdo. necessario
ELSEIF str = '1' THEN
IF Contador < width_byte THENContador := Contador + 1;-- Declaração dos Processos
ELSIF Contador = width_byte THENContador := Contador + 1;prt <= ‘1’;
--Copia o resultado para Saída Apropriada
END IF;END IF;
END IF;END IF;
END PROCESS Algo_Divi;END Divi;
Variáveis Auxiliares
VARIABLE AUX_Q, AUX_R : STD_ULOGIC_VECTOR(width_byte-1 downto 0);VARIABLE vaiumQuoc, restoMaior : STD_ULOGIC;
AUX_Q - Guardara o Quociente da OperaçãoAUX_R – Guardara o Resto da DivisãovaiumQuoc – Carry, que recebe o bit de maior ordem qdo. rotacionar o QuocienterestoMaior – Vai para ‘1’ se o Resto for maior que o Divisor
Valores Iniciais para Variáveis Auxiliares ( reset )
loopZera:FOR i IN 0 TO width_byte-1 LOOP
AUX_R(i) := '0';END LOOP loopZera;AUX_Q := A;vaiumQuoc := '0';restoMaior := '0';
AUX_Q – recebe o Dividendo e guardara o QuocienteAUX_R – zera a variável que recebera o Resto da divisãoVaiumQuoc, restoMaior – zera variáveis auxiliares
Algoritmo principal que será executado em laço
vaiumQuoc := AUX_Q(width_byte-1);AUX_Q := rotSaida( AUX_Q );AUX_Q(0) := restoMaior;
AUX_R := rotSaida( AUX_R );AUX_R(0) := vaiumQuoc;restoMaior := intcmp( AUX_R, B );
IF restoMaior = '1' THENAUX_R := Subtracao( Aux_R, B );
END IF;
Esse algoritmo será executado a cada pulso de clock depois de começado a operação, conformequantidade de bits dos operadores.
Parte Final: Copia o Resultado para a Saída
AUX_Q := rotSaida( AUX_Q );AUX_Q(0) := restoMaior;loopCopy:FOR i IN 0 TO width_byte-1 LOOP
Q(i) <= AUX_Q(i);R(i) <= AUX_R(i);
END LOOP loopCopy;
Forma de Onda dos Sinais de Entrada e Saída de um Divisor de 8 bits
Com os sinais em Binario
Continuação
Multiplicação de N-bits
O algoritmo consiste em acrescentar zeros a esquerda (shift) do Multiplicador e do Produtoinicialmente zerado, até que o ‘Carry’seja um. Quando isto acontecer soma-se o Multiplicador ao Produtocolocando-se o resultado obtido no próprio Produto. Volta-se a rotacionar o Produto bem como oMultiplicador, até que o contador do número de bits (tamanho do Multiplicador) seja zero.
A seguir apresentamos a aplicação do algoritmo para operadores de 8 Bits:
Multiplicado à 03 HMultiplicador à 05 HResultado à 0F H
Carry Multiplicador Multiplicando Produto Contador0 0000 0101 0000 0011 0000 0000 0000 0000 080 0000 1010 0000 0011 0000 0000 0000 0000 070 0001 0100 0000 0011 0000 0000 0000 0000 060 0010 1000 0000 0011 0000 0000 0000 0000 050 0101 0000 0000 0011 0000 0000 0000 0000 040 1010 0000 0000 0011 0000 0000 0000 0000 031 0100 0000 0000 0011 + 0000 0000 0000 0000
0000 0011 0000 0000 0000 0011
02
0 1000 0000 0000 0011 0000 0000 0000 0000 011 0000 0000 0000 0011 0000 0000 0000 0000
+ 0000 0011 0000 0000 0000 1111
00
Resultado 0000 0000 0000 1111
Usando o Esqueleto já Apresentado Anteriormente. Vamos apresentar as partes adicionais:
Entradas e Saídas
ENTITY Mult ISGENERIC(byte_entrada: integer := 8; byte_saida: integer := 16);PORT(
clk,str,rst : IN STD_ULOGIC;A, B : IN STD_ULOGIC_VECTOR(byte_entrada-1 downto 0);S : OUT STD_ULOGIC_VECTOR(byte_saida-1 downto 0));
END Mult;
Variáveis Auxiliares
VARIABLE AUX : STD_ULOGIC_VECTOR(byte_saida-1 downto 0);VARIABLE AUX_A : STD_ULOGIC_VECTOR(byte_entrada-1 downto 0);VARIABLE vaium : STD_ULOGIC;
AUX – Guardara o Produto da OperaçãoAUX_A – Guardara o Multiplicador para usar na função rotacionarvaium – Carry, que recebe o bit de maior ordem qdo. rotacionar o Multiplicador
Valores Iniciais para Variáveis Auxiliares ( reset )
loopZera:FOR i IN 0 TO byte_saida-1 LOOP
AUX(i) := '0';END LOOP loopZera;loopZera2:FOR i IN 0 TO byte_entrada-1 LOOP AUX_A(i) := A(i);END LOOP loopZera2;vaium := '0';
AUX_A – recebe o Multiplicador e guardara o QuocienteAUX – zera a variável que recebera o Produtovaium – zera variável auxiliar
Algoritmo principal que será executado dentro do laço
AUX := rotSaida( AUX );vaium := AUX_A(byte_entrada-1);IF vaium = '1' THEN
AUX := Soma( AUX, B );END IF;
AUX_A := rotEntrada( AUX_A );
Esse algoritmo será executado a cada pulso de clock depois de começado a operação, conformequantidade de bits dos operadores.
Parte Final: Copia o Resultado para a Saída
loopCopy:FOR i IN 0 TO byte_saida-1 LOOP
S(i) <= AUX(i);END LOOP loopCopy;
Forma de Onda dos Sinais de Entrada e Saída de um Multiplicador de 8 bits
Com os sinais em Binario
Continuação
Raiz Quadrada para Operadores de N-bits
Consiste em fazermos o Bit de maior ordem do local onde ficará o resultado, inicialmente igual a um,mantendo-se o valor dos Bits restantes iguais a zero.
Eleva-se o valor do resultado ao quadrado e subtraímos o valor que desejamos extrair a RaizQuadrada. Se a subtração for bem sucedida ou seja ‘Carry’ Maior ou Igual a zero, mantemos este Bit em nívellógico um. Caso contrário deverá ser trocado para nível zero.
Este processo deverá ser feito com todos os Bits que irão compor o resultado. A seguir apresentamosa implementação do algoritmo para um resultado máximo de 8 Bits.
Valor da Raiz à √(ABCD H) = D1 H
Resultado Resultado ao Quadrado Subtração Carry Bit(1000 0000) = (80) 2 16
(4000) 16
ABCD – 4000 > 0 27= 1
(1100 0000) = (80) 2 16
(9000) 16
ABCD – 9000 > 0 26= 1
(1110 0000) = (80) 2 16
(C400) 16
ABCD – C400 < 0 25= 0
(1101 0000) = (80) 2 16
A900) 16
ABCD – A900 > 0 24= 1
(1101 1000) = (80) 2 16
(B640) 16
ABCD – B640 < 0 23= 0
(1101 0100) = (80) 2 16
(AF90) 16
ABCD – AF90 < 0 22= 0
(1101 0010) = (80) 2 16
(AC44) 16
ABCD – AC44 < 0 21= 0
(1101 0001) = (80) 2 16
(AAA1) 16
ABCD – AAA1 > 0 20= 1
Resultado è 1101 0001 = D1 H
Neste caso há dois LAÇOS a serem executados: o LAÇO principal do algoritmos da extração da Raizque usa uma Multiplicação a cada passagem.
Esta Multiplicação será executado em outro LAÇO secundário.
Então nosso esqueleto será alterado para que possamos executar um LAÇO dentro do outro.
Esqueleto do Programa em VHDL contendo dois LAÇO For...Next Aninhado
BEGIN-- Process Statement
Algo_Raiz:PROCESS (clk)
--Declara as variáveis auxiliares--Contador, servira para controle de passagem--Como dentro de dois laço Aninhado For.For..Next.Next
VARIABLE Contador : INTEGER RANGE 0 TO byte_width+1;VARIABLE ContMult : INTEGER RANGE 0 TO byte_width+1;
BEGIN--Só executar a soma se clk for borda de subidaIF clk'EVENT AND clk = '1' THEN
IF rst = '1' THENContador := 0;ContMult := byte_width;prt <= ‘0‘;
--Zera variaveis auxiliares para primeiro LAÇO--Copia sinais de entrada para variavies auxiliares, qdo. necessario
ELSEIF str = '1' THEN
IF Contador < byte_width THENIF ContMult = byte_width THEN
-- Declaração dos Processos do 1º LAÇO
--Seta variaveis auxiliares para segundo LAÇOContMult := 0;
ELSEContMult := ContMult + 1;-- Aqui coloca os Processo para segundo LAÇOIF ContMult = byte_width THEN
-- Último passo do segundo LAÇO-- Seta valores de retorno de LAÇOContador := Contador + 1;
END IF;
END IF;
ELSIF Contador = byte_width THENContador := Contador + 1;prt <= ‘1’;-- Copia Resultado para sinal de Saida
END IF;END IF;
END IF;END IF;
END PROCESS Algo_Raiz;
Sinais de Entradas e Saídas
ENTITY Raiz ISGENERIC(byte_width: integer := 8);PORT(
clk,str,rst : IN STD_ULOGIC;A : IN STD_ULOGIC_VECTOR(byte_with-1 downto 0);prt : OUT STD_ULOGIC;S : OUT STD_ULOGIC_VECTOR(byte_with-1 downto 0));
END Raiz;
Variáveis Auxiliares
VARIABLE AUX : STD_ULOGIC_VECTOR(2*byte_width-1 downto 0);VARIABLE AUX_R : STD_ULOGIC_VECTOR(byte_width-1 downto 0);VARIABLE ContMult : INTEGER RANGE 0 TO byte_width+1;
AUX_R – Guardará o resultado da Operação, e os valores intermediários.Variáveis usadas no segundo LAÇO, eleva o número ao Quadrado.
AUX – Guardará o Operador para eleva-lo ao quadrado. Servirá também para guardar o resultado.ContMult – Contador para o LAÇO da Multiplicação. Este LAÇO está dentro do LAÇO Principal.
Valores Iniciais para Variáveis Auxiliares ( reset )
ContMult := byte_width;loopZera:FOR i IN 0 TO byte_width-1 LOOP AUX(i) := '0';
AUX_R(i) := '0';END LOOP loopZera;
Algoritmo principal que será executado dentro do LAÇO Principal
AUX_R := set(AUX_R, (byte_width-1-Contador), '1');
loopZera2:FOR i IN 0 TO byte_width-1 LOOP
AUX(i) := AUX_R(i);END LOOP loopZera2;
loopZera3:FOR i IN byte_width TO (2*byte_width)-1 LOOP
AUX(i) := '0';END LOOP loopZera3;
ContMult := 0;
Esse algoritmo será executado a cada pulso de clock depois de começado a operação, conformequantidade de bits dos operadores.
Este Laço coloca ‘0’ na variável ContMult, com isso os próximos pulsos de clocks executaram osegundo LAÇO até o fim, e depois novamente volta a executar o LAÇO Principal.
Algoritmo secundário que será executado dentro do segundo LAÇO
AUX := rot( AUX );
IF get( AUX_R, (byte_width-ContMult) ) = '1' THENAUX := Soma( AUX, AUX_R );
END IF;
IF ContMult = byte_width THENAUX_R := set(AUX_R, (byte_width-1-Contador), intcmp( A, AUX ));Contador := Contador + 1;
END IF;
LAÇO da Multiplicação, é executado dentro de LAÇO Principal. Ex.:
For PRINCIPAL...For MULTIPLICACAO...NEXT
NEXT
Parte Final: Copia o Resultado para a Saída
loopCopy:FOR i IN 0 TO byte_width-1 LOOP
S(i) <= AUX_R(i);END LOOP loopCopy;
Forma de Onda dos Sinais de Entrada e Saída ( Raiz Quadrada de 6 bits )
Continuação
Conversão de Hexadecimal para Decimal
Este tipo de conversão é muito utilizado, pois os valores medidos são manipulados internamente, porém paraque possa ser representados em mostradores, há a necessidade de converte-los afim de que o operador possainterpretá-los.
Sendo assim o algoritmo consiste em efetuar divisões sucessivas, mantendo o divisor constante igual a 0AH(10D), e o dividendo igual ao quociente obtido anteriormente, teremos o valor em decimal visualizado naseqüências dos restos das divisões.
Abaixo mostramos um exemplo de aplicação do algoritmo para números de 16 Bits.
Resultado è ABCD H = 43.981 D
Para implementar esse algoritmo em VHDL usaremos o esqueleto do programa mostradoanteriormente com uma pequena alteração, porque o LAÇO principal agora é uma LAÇO while ‘Enquanto<condição for satisfeita> Faça’ que executa um LAÇO For...Next aninhado. Pois há o laço de divisão paracada passagem.
Os algarismos serão lidos da direita para esquerda ou do menos significativo para o maissignificativo. Quando o digito estiver pronto na saída o sinal de pronto (prt) será levado a nível lógico alto.
Esqueleto do Programa em VHDL contendo dois LAÇO Aninhado (While..For...Next...Wend)
PROCESS (clk)--Declara as variaveis auxiliares
--Contador, servira para controle de passagem--Como dentro de um laço While...For..Next..WendVARIABLE ContFor : INTEGER RANGE 0 TO byte_width+1;VARIABLE CondicaoWhile : STD_ULOGIC;
BEGIN--Só executar a soma se clk for borda de subidaIF clk'EVENT AND clk = '1' THEN
IF rst = '1' THENCondicaoWhile := '1';prt <= '0';ContFor := byte_width;
--Zera variaveis auxiliares e--Copia sinais de entrada para variavies auxiliares, qdo. necessario
ELSEIF str = '1' THEN
IF CondicaoWhile = '1' THENIF ContFor = byte_width THEN
ContFor := 0;--Declaração dos Processos Antes do For..Next
ELSE--Processos dentro do For...Next
ContFor := ContFor + 1;
IF ContFor = byte_width THEN--Processos Executados no fim do LACO For..Next
--Testa o Fim do Laco While...WendIF <Condicao para SAIR do Laço> THEN
CondicaoWhile := '0';END IF;
END IF;
END IF;ELSE
prt <= '1';--Copia o resultado para Saída Apropriada
END IF;END IF;
END IF;END IF;
END PROCESS
Sinais de Entradas e Saídas
ENTITY HtoD ISGENERIC(byte_width: integer := 8);PORT(
clk,str,rst : IN STD_ULOGIC;H : IN STD_ULOGIC_VECTOR(byte_with-1 downto 0);prt : OUT STD_ULOGIC;D : OUT STD_ULOGIC_VECTOR(4 downto 0));
END HtoD;
H – Entrada HexadecimalD – Saída Decimal
Variáveis Auxiliares
variáveis usadas no LAÇO da divisãoVARIABLE AUX_Q, AUX_R : STD_ULOGIC_VECTOR(width_byte-1 downto 0);VARIABLE vaiumQuoc, restoMaior : STD_ULOGIC;
AUX_Q - Guardara o Quociente da Operação de DivisãoAUX_R – Guardara o Resto da DivisãovaiumQuoc – Carry, que recebe o bit de maior ordem qdo. rotacionar o Quociente da DivisãorestoMaior – Vai para ‘1’ se o Resto for maior que o Divisor
VARIABLE AUX _H : STD_ULOGIC_VECTOR(2*byte_width-1 downto 0);
AUX_H – Guardará o Dividendo em Hexa .
Valores Iniciais para Variáveis Auxiliares ( reset )
loopIninc:FOR i IN 0 TO byte_width-1 LOOP AUX_H(i) := H(i);END LOOP loopInic;
Copia sinal de entrada em Hexadecimal para uma variável auxiliar.
Algoritmo principal que será executado dentro do LAÇO Principal
prt <= '0';
loopZera: -- zera a var. que receberá o resto:FOR i IN 0 TO byte_width-1 LOOP
AUX_R(i) := '0';END LOOP loopZera;
--AUX_Q = "0A";AUX_Q(0) := '0';AUX_Q(1) := '1';AUX_Q(2) := '0';AUX_Q(3) := '1';
vaiumQuoc := '0';restoMaior := '0';
-- AUX_Q - recebe o Dividendo e guardara o Quociente-- AUX_R - zera a variável que recebera o Resto da divisão-- VaiumQuoc, restoMaior - zera variáveis auxiliares
Este Laço (while) é executado no primeiro pulso de clock se a condição for verdadeira, os pulsos declock subsequentes serão executados pelo LAÇO aninhado For...Next, incrementando um na variável quecontrola o LAÇO até o limite especificado. Quando o limite especificado para o LAÇO é alcançado, éexecutado ainda um bloco de verificação da condição inicial que valida o primeiro LAÇO, assim, no próximoclock novamente volta a executar o LAÇO Principal se a condição for verdadeira.
Algoritmo secundário que será executado dentro do segundo LAÇO (Divisão)
--Processos dentro do For...NextvaiumQuoc := AUX_H(byte_width-1);AUX_H := rot( AUX_H );AUX_H(0) := restoMaior;AUX_R := rot( AUX_R );AUX_R(0) := vaiumQuoc;restoMaior := intcmp( AUX_R, AUX_Q );
IF restoMaior = '1' THENAUX_R := Subtracao( AUX_R, AUX_Q );
END IF;
Este laço divide o valor em AUX_H por 10D que está em AUX_Q e coloca o resto em AUX_R e oquociente em AUX_H.
Bloco Que Verifica se o Processo já Acabou
Se ainda não acabou, posiciona o resto para ser dividido novamente e assim obter o(s) digito(s) quefalta(m).
--Processos Executados no fim do LACO For..NextAUX_H := rot( AUX_H );AUX_H(0) := restoMaior;
loopSaida:FOR i IN 0 TO 3 LOOP
D(i) <= AUX_R(i);END LOOP loopSaida;
--Testa o Fim do Laco While...WendIF IsZero(AUX_H) = '1' THEN
CondicaoWhile := '0';END IF;
prt <= '1';
A condição que é feita para testar o enquanto é AUX_H = 0, ou seja, quando o quociente da divisãofor zero, não há mas nenhum digito e a operação é encerrada. Caso contrario é processada nova divisão.
Sempre que é obtido um digito o sinal de pronto (prt) é levado a um lógico.
Forma de Onda dos Sinais de Entrada e Saída ( Conversor Hexa para Descimal - 8 bits )
F5H = 245D Leitura é feita do algarismo menos significativo ao mais sgnificativo.
Conversor de Decimal para Hexadecimal
Este tipo de conversão embora menos usual que o anterior se torna necessário quando omicrocontrolador recebe dados externos em forma decimal e tem que utilizá-los para cálculos internamente,ora como sua arquitetura apenas suporta manipulações binárias, devemos converter o dado para a basehexadecimal.
O algoritmo consiste em multiplicar cada dígito do dado decimal por uma constante K=Am, onde mserá função do digito em questão como ilustrado abaixo.
(43981) 10 = 4 x A4 + 3 x A3 + 9 x A2 + 8 x A1 + 1 x A0 =
= 4 x 2710 + 3 x 3E8 + 9 x 64 + 8 x A + 1 x 1
= 9C40 + BB8 + 384 + 50 + 1 = (ABCD) 16
Usaremos para implementar este algoritmo uma função de multiplicação, que realiza a multiplicaçãoem um único clock, por questões de simplicidade.
A função que faz a multiplicação foi deixada para ser apresentada por último.Sua sintaxe é:
P := Multiplic( A, B ); -- P = A * B
Sinais de Entradas e Saídas
ENTITY DtoH ISGENERIC(byte_width: integer := 8);PORT(
clk,str,rst : IN STD_ULOGIC;D : IN STD_ULOGIC_VECTOR(4 downto 0);H : OUT STD_ULOGIC_VECTOR(byte_with-1 downto 0));
END DtoH;
D – Entrada DecimalH – Saída Hexadecimal
Variáveis Auxiliares
--Declara as variaveis auxiliaresVARIABLE K, AUX_H, AUX_D, resParc, AUX_0A : STD_ULOGIC_VECTOR(byte_width-1 downto 0);
--K - Constante A elevado a i (i=posicao do digito decimal)--resParc - Resultados Parciais em Hexadecimal.--AUX_D - Espelho da Entrada Decimal D.--AUX_H - Resultado em Hexadecimal--AUX_0A - Contera o valor constante 0AH.
Valores Iniciais para Variáveis Auxiliares ( reset )
--Zera variaveis de auxiliares--Copia sinais de entrada para variavies auxiliares, qdo. necessarioloopZera:FOR i IN 0 TO byte_width-1 LOOP K(i) := '0';
resParc(i) := '0';AUX_H(i) := '0';AUX_0A(i) := '0';AUX_D(i) := '0';
END LOOP loopZera;
K(0) := '1';AUX_0A(1) := '1'; -- 1010AUX_0A(3) := '1'; -- 1010
Algoritmo principal que será executado dentro do LAÇO
-- Declaração dos Processos-- Faz o Espelho da Entrada D
AUX_D(3 downto 0) := D;resParc := Multiplic( AUX_D, K );AUX_H := Soma( AUX_H, resParc );K := Multiplic2( K, AUX_0A );
--Copia o resultado para Saída ApropriadaloopCopia:FOR i IN 0 TO byte_width-1 LOOP H(i) <= AUX_H(i);END LOOP loopCopia;
Listagem Completa do Process Para Conversão de Decimal para HexaDecimal
-- Process Statement
Algo_DtoH:PROCESS (clk)
--Declara as variaveis auxiliaresVARIABLE K, AUX_H, AUX_D, resParc, AUX_0A : STD_ULOGIC_VECTOR(byte_width-1
downto 0);
--K - Constante A elevado a i (i=posicao do digito decimal)--resParc - Resultados Parciais em Hexadecimal.--AUX_D - Espelho da Entrada Decimal D.--AUX_H - Resultado em Hexadecimal--AUX_0A - Contera o valor constante 0AH.
BEGIN
--Só executar a soma se clk for borda de subidaIF clk'EVENT AND clk = '1' THEN IF rst = '1' THEN --Zera variaveis de auxiliares --Copia sinais de entrada para variavies auxiliares, qdo. necessario LoopZera: FOR i IN 0 TO byte_width-1 LOOP K(i) := '0'; resParc(i) := '0'; AUX_H(i) := '0'; AUX_0A(i) := '0'; AUX_D(i) := '0'; END LOOP loopZera;
K(0) := '1'; AUX_0A(1) := '1'; -- 1010 AUX_0A(3) := '1'; -- 1010ELSE IF str = '1' THEN -- Declaração dos Processos -- Faz o Espelho da Entrada D AUX_D(3 downto 0) := D; resParc := Multiplic( AUX_D, K ); AUX_H := Soma( AUX_H, resParc ); K := Multiplic2( K, AUX_0A ); --Copia o resultado para Saída Apropriada loopCopia: FOR i IN 0 TO byte_width-1 LOOP H(i) <= AUX_H(i); END LOOP loopCopia; END IF;END IF;
END IF;END PROCESS Algo_DtoH;
Forma de Onda dos Sinais de Entrada e Saída ( Conversor Decimal para HexaDecimal )
O sinal H está sendo mostrado na base 10.
Função Multiplicação
Recebe como parâmetro duas variáveis STD_ULOGIC_VECTOR e retorna uma variável queconterá o resultado da multiplicação no formato STD_ULOGIC_VECTOR.
----------------------------------------------- S := Mutiplic ( A , B )---------FUNCTION Multiplic ( A : STD_ULOGIC_VECTOR(byte_entrada-1 downto 0);
B : STD_ULOGIC_VECTOR(byte_entrada-1 downto 0) )RETURN STD_ULOGIC_VECTOR IS
VARIABLE S : STD_ULOGIC_VECTOR(byte_saida-1 downto 0);BEGIN
loopZera:FOR i IN 0 TO byte_saida-1 LOOP
S(i) := '0';END LOOP loopZera;
loopMult:FOR i IN 0 TO byte_entrada-1 LOOP
S := rotSaida( S );
IF A( byte_entrada-1 - i ) = '1' THENS := Soma( S, B );
END IF;
END LOOP loopMult;
RETURN S;END Multiplic;
Forma de Onda De uma Chamada a Função S := Multiplic( A, B )
Executa a chamada quando for borda de subida do sinal clk.
Exercício:
1) Fazer a descrição em VHDL de uma função que faz a Divisão entre dois sinais e sua chamada. Copilar eSimular.
R.:
Função Divisão
----------------------------------------------- S := Divisao ( A, B )---------FUNCTION Divisao (A, B : STD_ULOGIC_VECTOR(width_byte-1 downto 0)
)RETURN STD_ULOGIC_VECTOR IS
VARIABLE AUX_Q, AUX_R : STD_ULOGIC_VECTOR(width_byte-1 downto 0);VARIABLE Retorno : STD_ULOGIC_VECTOR(2*width_byte-1 downto 0);VARIABLE vaiumQuoc, restoMaior : STD_ULOGIC;
BEGINloopZera:FOR i IN 0 TO width_byte-1 LOOP
AUX_Q(i) := A(i);AUX_R(i) := '0';
END LOOP loopZera;vaiumQuoc := '0';restoMaior := '0';
-- Copia Resultado para sinal de SaidaloopMain:FOR i IN 0 TO width_byte-1 LOOP
vaiumQuoc := AUX_Q(width_byte-1);AUX_Q := rotSaida( AUX_Q );AUX_Q(0) := restoMaior;
AUX_R := rotSaida( AUX_R );AUX_R(0) := vaiumQuoc;restoMaior:= intcmp( AUX_R, B );
IF restoMaior = '1' THENAUX_R := Subtracao( Aux_R, B );
END IF;END LOOP loopMain;
AUX_Q := rotSaida( AUX_Q );AUX_Q(0) := restoMaior;
Retorno(width_byte-1 downto 0) := AUX_Q(width_byte-1 downto 0);Retorno(2*width_byte-1 downto width_byte) := AUX_R(width_byte-1 downto 0);
RETURN Retorno;END Divisao;
Chamada a Função Divisão
BEGIN-- Process Statement
Algo_Divi:PROCESS (clk)
--Declara uma variavel auxiliar 'vaium' e svlAi com tipo: STD_ULOGIC--Serão usadas mas adiante no códigoVARIABLE AUX : STD_ULOGIC_VECTOR(2*width_byte-1 downto 0);
BEGIN
--Só executar a soma se clk for borda de subidaIF clk'EVENT AND clk = '1' THEN
AUX := Divisao ( A, B );
loopCopy:FOR i IN 0 TO width_byte-1 LOOP
Q(i) <= AUX(i);R(i) <= AUX(width_byte+i);
END LOOP loopCopy;
END IF;
END PROCESS Algo_Divi;
Simulação:
Observações
Você pode estar se perguntando porque fazer um algoritmo para multiplicação mais complexo e maislento se como mostrado acima, pode se fazer um mais simples e de execução mais rápido (em um único ciclode clock), enquanto o outro demoraria n ciclos de clock (n: número de bits).
O problema é que executar a multiplicação em um único clock se gasta mais hardware que dividindo-a em vários clocks.
Funções como get e set que pegam um sinal de uma variável vetor, poderiam ser substituídas por:A:=AUX(3) em vez de A := get( AUX, 3 ) e AUX(3) := ‘1’ em vez de AUX := set( AUX, 3, ‘1’).
O problema é quando o argumento 3 é um variável declarada, nesta situação o compilador não aceitao comando e reporta um erro. Talvez outro compilador não apresente problema.
No programa para conversão de Decimal para Hexadecimal é preciso fazer duas chamadas a funçãoMultiplic. Novamente o compilador gerou um erro neste caso e por isso foi gerada duas funções Multiplic eMultiplic2, uma para cada chamada.
Até aqui é suposto que o compilador faça todas as minimizações possíveis para o algoritmoindependente da ordem dos comandos passados, ou seja, que ele utilize o menos de portas lógicas paraexecutar o processo. Assim a chamada da função set comentada acima e sua forma alternativa gastaria omesmo hardware pois executa a mesma função.
Quando foi utilizada uma função no projeto, foi preciso especificar o tamanho dos sinais de entrada.Por exemplo na Multiplicação A e B têm byte_entrada bits. ‘byte_entrada’ é uma constante declarada
dentro da Entidade (inicio do programa).
FUNCTION Multiplic ( A : STD_ULOGIC_VECTOR(byte_entrada-1 downto 0); B : STD_ULOGIC_VECTOR(byte_entrada-1 downto 0)
Foi descrito os Algoritmos para implementar laços numa seqüência de clocks. Pode-se utiliza-lospara converter qualquer algoritmo em laço ou em laços aninhados para resolver o problema comentado acima.
A sintaxe dos comandos são descritos no apêndice A.
O programa completo dos algoritmos descritos acima e seus modelos são listados no apêndice B.
PARTE III
Ponto Flutuante..................................................................................................................... 55
PADRÃO DE PONTO-FLUTUANTE IEEE 754............................................................... 56
Variáveis auxiliares.............................................................................................................. 57
Separando os dados de entrada para representação interna.................................................. 57
Soma em Ponto Flutuante (32 bits)...................................................................................... 57
Condições para Adição........................................................................................... 60
Soma de dois números Normalizados.................................................................... 65
Soma de dois números Não-Normalizados............................................................ 68
Retornar a Resultado da Soma em Ponto Flutuante............................................... 69
Multiplicação em Ponto Flutuante (32 bits)......................................................................... 70
Condições para Multiplicação S = A * B............................................................... 72
Função para Regra de Sinal.................................................................................... 73
Simulação: Multiplicação em Ponto Flutuante...................................................... 78
Divisão em Ponto Flutuante (32 bits)................................................................................... 80
Condições para Divisão S = A / B......................................................................... 81
PARTE III
Ponto Flutuante
Nas partes anteriores deste manual, foi apresentados algoritmos de aritmética com números de pontofixo, ou seja, números inteiros. Incluem aí também números com casas decimais exatas, por exemplo:
A multiplicação 3,02 * 4,04 = 12,20 é equivalente a multiplicação: 302 * 404 = 122008.Dividindo o Resultado 122008 por 10000 e respeitando o limite de duas casas decimais nó
chegaremos no resultado 12,20.
Usando este raciocínio é possível aplicar os algoritmos apresentados até aqui para operando dequantas casa decimais desejar.
O problema aparece quando temos que trabalhar com números com quantidade de casas decimaismuito diferentes, . Por exemplo:
A multiplicação e * c, e = massa do elétron 1,8*10-19; c = velocidade da luz no vácuo 3,8*108.Neste caso a matemática com ponto fixo fica quase impossível, pois teria que alocar espaço em
hardware para representar um número com até oito dígitos a esquerda da virgula e mais 19 dígitos a direita davirgula para cada operando, isso seria um desperdício enorme de hardware.
Quando trabalhamos com esses números usamos a notação cientifica: e = 1,8E-19; c = 3,8E8.Nós chamaremos essa representação de ponto flutuante.
Nós também poderemos mostrar em notação científica números binários. Por exemplo:1,0 * 2-1;1,101 * 2-5;1,xxx * 2yyy
A representação de um ponto flutuante na forma binária está a seguir, onde “s” é o sinal do pontoflutuante (negativo igual a 1), expoente é o valor de 8 bits, e a mantissa é um número de 32 bits.
s y y y y y y y Y x x x x x x x x x X x x x x x x x x x x x x xs – é a representação do sinal ( 0 para positivo e 1 para negativo);yyyyyyyy – expoente de base 2 mais o valor do expoente na base binária ( 127 + expoente );xxxxxxxxxxxxxxxxxxxxxxx –significante, é a parte fracionaria na base dois, sendo que esta é
inserida da esquerda para direita.
Representando assim: 1,xxxxxxxxxxxxxxxxxxxxxxx * 2yyyyyyyy.Este número varia de 1,00 * 2-126 a 1,00 * 2126, usando apenas 32 bits para representa-lo.
A expressão abaixo é utilizada para chegar ao resultado de um número na base dois.(-1) s * ( 1 + Significante ) * 2 E
e também temos uma fórmula genérica que pode ser utilizada:(-1) s * [ 1 + (s1*2-1) + (s2+2-2) + ... ] * 2E
A seguir tem-se um exemplo para transformar um número decimal fracionário (real) no formatocompreendido pelo computador.
-0,75 = -3/4 = -(11)2 * 2 2 = -(0,11)2 normalizando fica: -(1,1)2 * 2-1
(-1) s * ( 1 + Significante ) * 2 (bias+exp) bias = 127
Expoente + 127 = -1 + 127 = 126 :
(-1)1 * ( 1 + ,100 0000 0000 0000 0000 0000 ) * 2 126
1 1 1 1 1 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2-12-23
-
-126
Este '1' antes da virgula. Érepresentado implicitamente
PADRÃO DE PONTO-FLUTUANTE IEEE 754
Item Precisão simples Precisão DuplaBits de Sinal 1 1Bits de expoente 8 11Bits de mantissa 23 52Total de bits 32 64Sistema do expoente Excesso de 127 Excesso de 1023Intervalo do expoente -126 a +127 -1022 a 1023O menor, normalizado 2 -126 2 -1022
O maior, normalizado Aprox. 2 +128 Aprox. 2 +1024
Intervalo decimal Aprox. 10-38 a 10 +38 Aprox. 10 -308 a 10 +308
O menor, não normalizado Aprox. 10 -45 Aprox. 10 -324
Normalizado± 0 < Exp < Max Qualquer padrão de bits
Não-Normalizado± 0 Qualquer padrão de bits Diferente de zero
Zero± 0 0
Infinito± 11111...1 0
Not-a-Number ( Não é um número )± 11111...1 Qualquer padrão de bits diferente de zero
Um dos problemas tradicionais com números em ponto flutuante é como lidar com underflow,overflow e números não-inicializados. O padrão IEEE lida com estes problemas explicitamente, com aabordagem parcialmente do tipo CDC 6600. Além dos números normalizados, o padrão provê quatro outrostipos vistos acima.
Em números não-normalizados, o bit 1 implícito à esquerda do ponto binário agora se torna um 0.Números não-normalizados podem distinguir-se dos normalizados, porque não se permite aos normalizadoster um expoente de 0s.
Dois zeros estão presentes neste esquema, positivo e negativo determinado pelo bit de sinal. Ambospossuem um expoente igual a zero e uma mantissa igual a zero. Aqui também o bit a esquerda do pontobinário é implicitamente 0 em vez de 1.
Quando ocorre um overflow é fornecido uma representação especial para infinito, que consiste emum expoente com todos os bits 1 (não permitido para números normalizados) e uma mantissa igual a zero.Este número pode ser usado como operando que se comporta como as regras matemática usuais de infinito.Por exemplo, infinito mais qualquer coisa é infinito. Similarmente qualquer número dividido por zero dainfinito.
E infinito dividido por infinito ? O resultado é indefinido. Para tratar deste caso usa-se outro formatoespecial, denominado NaN (Not a Number). Este pode também ser tratado como operando com resultadosprevisíveis.
Soma em Ponto Flutuante (32 bits)
Operandos de entrada:A, B : IN STD_LOGIC_VECTOR(31 downto 0);
Operandos de Saída:S : OUT STD_LOGIC_VECTOR(31 downto 0));
Bit 31 : bit de sinalBits de 30 à 23 : representam o expoente com excesso de 127Bits de 22 à 0 : representam a mantissa
Variáveis auxiliares
Serão criadas três conjuntos de variáveis para representar internamente um número em ponto flutuante.SinalX : contem o sinal da variável XExpX : contém o expoente da variável XMantX : contém a mantissa de variável X
VARIABLE SinalA, SinalB, SinalR : STD_LOGIC;VARIABLE ExpA, ExpB, ExpR : STD_LOGIC_VECTOR(7 downto 0);VARIABLE MantA, MantB : STD_LOGIC_VECTOR(23 downto 0);VARIABLE MantR : STD_LOGIC_VECTOR(24 downto 0);
Obs: O 25º bit de MantR foi colocado para evitar overflow na soma. Caso este bit for '1' depois de uma soma,desloca-se todos os bits de MantR para direita e soma 1 em ExpR.
Separando os dados de entrada para representação interna
Em primeiro separa o bit de sinal '31', em seguida separamos o expoente, e por último retiramos a mantissa,não esquecendo de verificar se o número é normalizado, '1' no primeiro bit implícito, ou se é não-normalizado, '0' no primeiro bit implícito.
-- Separa os dados de ASinalA := A(31);ExpA(7 downto 0) := A(30 downto 23);-- Explicita sinal implicitoif A(30 downto 23) = "00000000" then
MantA(23) := '0'; -- Numero nao normalizado exp=-126else
MantA(23) := '1'; -- Numero Normalizados 1,xxxend if;MantA(22 downto 0):= A(22 downto 0);
-- Separa os dados de BSinalB := B(31);ExpB(7 downto 0) := B(30 downto 23);if B(30 downto 23) = "00000000" then
MantB(23) := '0';else
MantB(23) := '1';end if;MantB(22 downto 0):= B(22 downto 0);
Representação Interna dos Números em Ponto Flutuante
Simulação do algoritmo descrito acima, que pega a entrada (A), que representa um número em pontoflutuante, decompondo-a em três variáveis interna: SinalA, ExpA, MantA, respectivamente: sinal da entrada,seu expoente e sua mantissa.
Esta simulação também vale para a entrada B, sendo que as variáveis serão, SinalB, ExpB e MantB.
Número Normalizado
Número Não-Normalizado
Representação do Zero
ExpA = 10110011MantA =1,11100011100011100011100
A = -1,88888883591 * 2 ^52A ~ -8,5068E15
ExpA = 00000000MantA =0,11100011100011100011100
A = -0,88888883591 * 2 ^ -127A ~ -5,22442E-39
Representação Interna dos Números em Ponto Flutuante (Continuação)
Representação de Infinito
Representação de um Not-a-Number
Condições para Adição
Condição A B S01 Not-a-Number Qualquer Not-a-Number02 Qualquer Not-a-Number Not-a-Number03 +/- Infinito -/+ Infinito Zero04 Infinito Qualquer A05 Qualquer Infinito B06 Zero Qualquer B07 Qualquer Zero A08 Não-Normalizado Normalizado B09 Normalizado Não-Normalizado A10 Normalizado Normalizado A + B11 Não-Normalizado Não-Normalizado A + B
Testar Condição 01
--Testa se A e NaNif ExpA(7 downto 0) = "11111111" and
not (MantA(22 downto 0) = "00000000000000000000000") then
--A e NaN a saida e NaNSinalR := '0';ExpR := "11111111";MantR := "0111111111111111111111111";
Testar Condição 02
--Testa se B e NaNelsif ExpB(7 downto 0) = "11111111" and
not (MantB(22 downto 0) = "00000000000000000000000") then
--A e NaN a saida e NaNSinalR := '0';ExpR := "11111111";MantR := "0111111111111111111111111";
Testar Condição 03
--Testa se A e B são Infinito com sinais trocadoselsif ExpA(7 downto 0) = "11111111" and MantA(22 downto 0) = "00000000000000000000000"and ExpB(7 downto 0) = "11111111" and MantB(22 downto 0) = "00000000000000000000000"and not SinalA = SinalB then
--Saida e Zero, Sinal Adotaremos PositivoSinalR := '0';ExpR := "00000000";MantR := "0000000000000000000000000";
Testar Condição 04
--Testa se A e Infinitoelsif ExpA(7 downto 0) = "11111111" and
MantA(22 downto 0) = "00000000000000000000000" then
--Saida e Infinito com mesmo sinal de ASinalR := SinalA;ExpR := "11111111";MantR := "0000000000000000000000000";
Testar Condição 05
--Testa se B e Infinitoelsif ExpB(7 downto 0) = "11111111" and
MantB(22 downto 0) = "00000000000000000000000" then
--Saida e Infinito com mesmo sinal de BSinalR := SinalB;ExpR := "11111111";MantR := "0000000000000000000000000";
Testar Condição 06
--Testa se A e Zeroelsif ExpA(7 downto 0) = "00000000" and
MantA(22 downto 0) = "00000000000000000000000" then
--Saida e BSinalR := SinalB;ExpR := ExpB;MantR(23 downto 0) := MantB;MantR(24) := '0'';
Testar Condição 07
--Testa se B e Zeroelsif ExpB(7 downto 0) = "00000000" and
MantB(22 downto 0) = "00000000000000000000000" then
--Saida e BSinalR := SinalA;ExpR := ExpA;MantR(23 downto 0) := MantA;MantR(24) := '0'';
Testar Condição 08
--Testa se A e Não-Normalizado e B Normalizadoelsif ExpA(7 downto 0) = "00000000" and
not ( MantA(22 downto 0) = "00000000000000000000000" ) andnot ( ExpB(7 downto 0) = "00000000" ) then
--Saida e o Normalizado BSinalR := SinalB;ExpR := ExpB;MantR(23 downto 0) := MantB;MantR(24) := '0'';
Testar Condição 09
--Testa se B e Não-Normalizado e A Normalizadoelsif ExpB(7 downto 0) = "00000000" and
not ( MantB(22 downto 0) = "00000000000000000000000" ) andnot ( ExpA(7 downto 0) = "00000000" ) then
--Saida e o Normalizado ASinalR := SinalA;ExpR := ExpA;MantR(23 downto 0) := MantA;MantR(24) := '0'';
Testar Condição 10
--Testa se A e B são Normalizadoelsif not ( ExpA(7 downto 0) = "00000000" ) then
--Saida e a soma dos Normalizado A + B
A Soma dos normalizados A + B está descrita mais à abaixo.
Condição 11
--A e B são Não-Normalizado, foi o que restouelse
--Saida e a soma dos Não-Normalizado A + B
A Soma dos não-normalizados A + B está descrita mais à abaixo.
End if; -- Final das condicoes
Soma de dois números Normalizados
1º Passo:Igualar os expoentes, permanecendo o expoente maior. Aqui um dos números poderá ficar com o
digito zero a esquerda da virgula ao invés de um. Por isso da importância do bit implícito ser representadoexplicitamente para cálculos interno.
2º Passo:Se os sinais forem iguais somam-se as mantissas, caso contrario, subtrai o menor do maior.O expoente e o sinal será igual ao do maior número. Se o número for igual de sinais trocados, o
resultado será zero.
3º Passo:Normaliza o resultado.
Em VHDL
1º Passo:--ExpA > ExpBif ExpA > ExpB then
--Iguala Expoente de B ao de ALoopIgualaExpB:while ( ExpB < ExpA ) loop
MantB(0 downto 22) := MantB(1 downto 23);MantB(23) := '0';ExpB := ExpB + 1;
end loop LoopIgualaExpB;
else--Iguala Expoente de A ao de B, se já não for igualLoopIgualaExpA:while ( ExpA < ExpB ) loop
MantA(0 downto 22) := MantA(1 downto 23);MantA(23) := '0';ExpA := ExpA + 1;
end loop LoopIgualaExpA;
end if;
2º Passo:if SinalA = SinalB then
MantR := MantA + MantB;SinalR := SinalA;ExpR := ExpA;
elsif MantA > MantB thenMantR := A - B;SinalR := SinalA;ExpR := ExpA;
elsif MantB > MantA thenMantR := B - A;
SinalR := SinalB;ExpR := ExpB;
Else --Se são numeros iguais de sinais trocadosSinalR := '1';MantR := "0000000000000000000000000";ExpR := "00000000";
end if;
3º Passo:
Testar o 'bit implícito', o bit que fica à esquerda da virgula, enquanto esse não valer um e o expoentefor diferente de zero, executar os passos descritos abaixo e voltar a testa-lo, até ele se tornar um ou o númerovirar um Não-Normalizado.
Deslocar os bits da mantissa uma posição à esquerda e subtrair uma unidade do expoente.
-- Testa overflowif ( MantR(24) = '1' ) then
MantR(23 downto 0) := MantR(24 downto 1);MantR(24) := '0';ExpR := ExpR + 1;
-- Testa se Foi para Infinitoif ExpR = "11111111" then
MantR := "0100000000000000000000000";end if;
end if;
--Normaliza sinal de saidaloop_Normaliza1:while not ( MantR(23) = '1' or ExpR = "00000000" ) loop
MantR(23 downto 1) := MantR(22 downto 0);MantR(0) := '0';ExpR := ExpR - 1;
end loop loop_Normaliza1;
-- Testa se eh Não-Normalizadoesta e esta proximo ao menor Normalizadoif MantR(23 downto 21) = "111" and ExpR = "00000000" then
--Menor numero normalizadoExpR := "00000001";MantR := "0100000000000000000000000";
end if;
Simulação da Soma entre dois Numeros Normalizados
A = 1.03125 * 2-126
B = 1.5 * 2-113
S =1.50012588501 * 2-113
A = +(1+2-1+2-2 ) * 2 (16-127)
B = -(1+2-1+2-3 ) * 2 (16-127)
S = +(1) * 2 (13-127)
A = 2 (16-127)
B = 2 (16-127)
S = 2 (17-127)
Soma de dois números Não-Normalizados
1º Passo:Se os sinais forem iguais somam-se as mantissas, caso contrario, subtrai o menor do maior.O sinal será igual ao do maior número. Se o número for igual de sinais trocados, o resultado será
zero.
2º Passo:Se o bit implícito do resultado for igual a um, houve OVERFLOW e o resultado é
NORMALIZADO.
Em VHDL
1º Passo:if SinalA = SinalB then
MantR := MantA + MantB;SinalR := SinalA;
elsif MantA > MantB thenMantR := A - B;SinalR := SinalA;
elsif MantB > MantA thenMantR := B - A;SinalR := SinalB;
else --Se são numeros iguais de sinais trocadosSinalR := '1';MantR := "0000000000000000000000000";
end if;
2º Passo:
-- Testa overflowif ( MantR(24) = '1' ) then
MantR(23 downto 0) := MantR(24 downto 1);MantR(24) := '0';ExpR := "00000001";
end if;
Simulação da Soma entre dois Numeros Não-Normalizados
Retornar a Resultado da Soma em Ponto Flutuante
O processo de soma já foi feito, precisamos colocar os dados de nossas variáveis interna para a saída 'S'.
Apenas copiaremos os dados das variáveis para suas respectivas posições na saída 'S'.
S(31) <= SinalR;S(30 downto 23) <= ExpR(7 downto 0);S(22 downto 0) <= MantR(22 downto 0);
E pronto.
A = (2-3 + 2-4 ) * 2-127
B = (2-3 + 2-5 ) * 2-127
S = (2-2 + 2-4 + 2-5 ) * 2-127
A=(2-1+2-2+2-3+2-4+2-5+2-6) * 2-127
B = -(2-1 + 2-5 + 2-6) * 2-127
S = (2-2 + 2-3 + 2-4) * 2-127
A=(2-1+2-2+2-3+2-4+2-5+2-6) * 2-127
B=(2-1+2-2+2-3+2-4+2-5+2-6) * 2-127
S = 2-126
Multiplicação em Ponto Flutuante (32 bits)
Implementarémos o algoritmo para multiplicação em ponto flutuante, usando um contador de estadosinternos. No algoritmo anterior, todos os processos erão realizados em um único ciclo de clock. Isto tornou-omuito rápido, porém, consome muitas células lógicas, hardware.
Para usar um contador de estados, dividirémos o algoritmo em blocos, que chamaremos de estado. No final decada bloco, precisamos falar para o contador de estado qual será o próximo estado que será executado nopróximo ciclo de clock. Cada estado é realizado em um ciclo de clock.
Definindo Estados
Type Testado Is (estEspera, -- aguarda sinal str ficar ativoestSeparaDadosA, -- Separa os dados de AestSeparaDadosB, -- Separa os dados de BestTestarCondicao01, --Testa se A e NaNestTestarCondicao02, --Testa se B e NaNestTestarCondicao03, --Testa se A e ZeroestTestarCondicao04, --Testa se B e ZeroestTestarCondicao05, --Testa se A e InfinitoestTestarCondicao06, --Testa se B e InfinitoestSomaExpoente,estTestaUnderflow,estTestaOverflow,estRetira127,estMultMantissa,estNormalizaEsq,estNormalizaDir,estRetornaResultado);
No código usaremos a condição Case…End Case para separarmos os Blocos de Código em Estados.Exemplo:
Case Estado IsWhen Estado01
-- Executa ação para primeiro estado...Estado := Estado 02;
When Estado02...
End Case;
Sinais de Entrada e Saída
Usaremos o padrão de interface descrita na parte II deste manual, com três sinais de controle:clk – que será o clock;rst – que será o reset;str – que será o start.
prt – vai para um quando o resultado já estiver pronto para leitura
Operandos de entrada:A, B : IN STD_LOGIC_VECTOR(31 downto 0);
Operandos de Saída:S : OUT STD_LOGIC_VECTOR(31 downto 0));
Bit 31 : bit de sinalBits de 30 à 23 : representam o expoente com excesso de 127Bits de 22 à 0 : representam a mantissa
Variáveis auxiliares
Serão criadas três conjuntos de variáveis para representar internamente um número em ponto flutuante.SinalX : contem o sinal da variável XExpX : contém o expoente da variável XMantX : contém a mantissa de variável X
VARIABLE SinalA, SinalB, SinalR : STD_LOGIC;VARIABLE ExpA, ExpB : STD_LOGIC_VECTOR(7 downto 0);VARIABLE ExpR : STD_LOGIC_VECTOR(8 downto 0); -- Para Teste de overflowVARIABLE MantA, MantB : STD_LOGIC_VECTOR(23 downto 0);VARIABLE MantR : STD_LOGIC_VECTOR(47 downto 0);VARIABLE Estado : TEstado;
Obs: Forão colocados o dobro de bits em MantR para evitar overflow na multiplicação.
Esqueleto do Algoritimo para Controle dos Estados
--Só executar a soma se clk for borda de subidaIF clk'EVENT AND clk = '1' THEN
IF rst = '1' THENEstado := estEspera; -- Proximo estadoprt <= ‘0’;
ELSECase Estado IsWhen estEspera =>
IF str = '1' THENEstado := estSeparaDadosA; -- Proximo estado
END IF;
When …When …When …End Case;
END IF;END IF;
Separando os dados de entrada para representação interna
Em primeiro separa o bit de sinal '31', em seguida separamos o expoente, e por último retiramos a mantissa,não esquecendo de verificar se o número é normalizado, '1' no primeiro bit implícito, ou se é não-normalizado, '0' no promeiro bit implícito.
When estSeparaDadosA =>-- Separa os dados de ASinalA := A(31);ExpA(7 downto 0) := A(30 downto 23);-- Explicita sinal implicitoif A(30 downto 23) = "00000000" then
MantA(23) := '0'; -- Numero nao normalizado exp=-126else
MantA(23) := '1'; -- Numero Normalizados 1,xxxend if;MantA(22 downto 0):= A(22 downto 0);Estado := estSeparaDadosB; -- Proximo estado
When estSeparaDadosB =>-- Separa os dados de BSinalB := B(31);ExpB(7 downto 0) := B(30 downto 23);if B(30 downto 23) = "00000000" then
MantB(23) := '0';else
MantB(23) := '1';end if;MantB(22 downto 0):= B(22 downto 0);Estado := estTestarCondicao01; -- Proximo estado
Condições para Multiplicação S = A * B
Condição A B S01 Not-a-Number Qualquer Not-a-Number02 Qualquer Not-a-Number Not-a-Number03 Zero Quaquer Zero04 Qualquer Zero Zero05 Infinito Qualquer R.S. Infinito06 Qualquer Infinio R.S. Infinito07 Não-Normalizado ou
NormalizadoNão-Normalizado ouNormalizado
R.S.Soma os ExpoentesMultipl. Mantissa
R.S. = Regra de Sinal
Função para Regra de Sinal
FUNCTION RegraSinal ( SinalA : STD_ULOGIC; SinalB : STD_ULOGIC
)RETURN STD_ULOGIC IsVARIABLE Sinal : STD_ULOGIC;
BEGINIF SinalA = SinalB THEN
Sinal := '0'; -- POSITIVOELSE
Sinal := '1'; -- NEGATIVOEND IF;
RETURN Sinal;END RegraSinal;
Testar Condição 01
When estTestarCondicao01 =>--Testa se A e NaNif ExpA(7 downto 0) = "11111111" and
not (MantA(22 downto 0) = "00000000000000000000000") then
--A e NaN a saida e NaNExpR := "011111111";MantR := "011111111111111111111111100000000000000000000000";Estado := estRetornaResultado; -- Proximo estado
elseEstado := estTestarCondicao02; -- Proximo estado
end if;
Testar Condição 02
When estTestarCondicao02 =>--Testa se B e NaNif ExpB(7 downto 0) = "11111111" and
not (MantB(22 downto 0) = "00000000000000000000000") then
--A e NaN a saida e NaNExpR := "011111111";MantR := "001111111111111111111111110000000000000000000000";Estado := estRetornaResultado; -- Proximo estado
elseEstado := estTestarCondicao03; -- Proximo estado
end if;
Testar Condição 03
When estTestarCondicao03 =>--Testa se A e Zeroif ExpA(7 downto 0) = "00000000" and
MantA(22 downto 0) = "00000000000000000000000" then
--Saida e ZeroExpR := "000000000";MantR := "000000000000000000000000000000000000000000000000";Estado := estRetornaResultado; -- Proximo estado
elseEstado := estTestarCondicao04; -- Proximo estado
end if;
Testar Condição 04
When estTestarCondicao04 =>--Testa se B e Zeroif ExpB(7 downto 0) = "00000000" and
MantB(22 downto 0) = "00000000000000000000000" then
--Saida e ZeroExpR := "000000000";MantR := "000000000000000000000000000000000000000000000000";Estado := estRetornaResultado; -- Proximo estado
elseEstado := estTestarCondicao05; -- Proximo estado
end if;
Testar Condição 05
When estTestarCondicao05 =>--Testa se A e Infinitoif ExpA(7 downto 0) = "11111111" and
MantA(22 downto 0) = "00000000000000000000000" then
--Saida e InfinitoExpR := "011111111";MantR := "000000000000000000000000000000000000000000000000";Estado := estRetornaResultado; -- Proximo estado
elseEstado := estTestarCondicao06; -- Proximo estado
end if;
Testar Condição 06
When estTestarCondicao06 =>--Testa se B e Infinitoif ExpB(7 downto 0) = "11111111" and
MantB(22 downto 0) = "00000000000000000000000" then
--Saida e InfinitoExpR := "011111111";MantR := "000000000000000000000000000000000000000000000000";Estado := estRetornaResultado; -- Proximo estado
elseEstado := estSomaExpoente; -- Proximo estado
end if;
Condição 07
When estSomaExpoente =>--Soma expoenteExpR := ExpA + ExpB;Estado := estTestaUnderflow; -- Proximo estado
When estTestaUnderflow =>--Testa underflowIf ExpR < 127 then
--Saida e ZeroExpR := "000000000";MantR := "000000000000000000000000000000000000000000000000";Estado := estRetornaResultado; -- Proximo estado
elseEstado := estTestaOverflow; -- Proximo estado
end if;
When estTestaOverflow =>-- Testa Overflowif ExpR > 382 then
--Saida e InfinitoExpR := "011111111";MantR := "000000000000000000000000000000000000000000000000";Estado := estRetornaResultado; -- Proximo estado
elseEstado := estRetira127; -- Proximo estado
end if;
When estRetira127 =>-- A + 127 + B + 127 = R + 254-- Retira 127ExpR := ExpR - 127;Estado := estMultMantissa; -- Proximo estado
When estMultMantissa =>-- Multiplica Mantissa A(24) * B(24) = R(48)MantR := MantA * MantB;Estado := estNormalizaEsq; -- Proximo estado
When estNormalizaEsq =>--Normaliza sinal de saida--Verif. o segundo bit a esquerda da virgulaif MantR(47) = '1' then
-- Verifica overflowif ExpR = "1111111110" then
--Saida e InfinitoExpR := "011111111";MantR := "000000000000000000000000000000000000000000000000";Estado := estRetornaResultado; -- Proximo estado
elseMantR(46 downto 0) := MantR(47 downto 1);MantR(47) := '0';ExpR := ExpR + 1;
End if;End if;Estado := estNormalizaDir; -- Proximo estado
When estNormalizaDir =>--Verif. o primeiro bit a esquerda da virgulaloop_Normaliza1:
while not ( MantR(46) = '1' or ExpR = "000000000" ) loopMantR(46 downto 1) := MantR(45 downto 0);MantR(0) := '0';ExpR := ExpR - 1;
end loop loop_Normaliza1;Estado := estRetornaResultado; -- Proximo estado
Retornar o Resultado da Multiplicação em Ponto Flutuante
O processo de soma já foi feito, precisamos colocar os dados de nossas variáveis interna para a saída 'S'.
Apenas copiaremos os dados das variáveis para suas respectivas posições na saída 'S'.
When estRetornaResultado =>S(31) <= RegraSinal (SinalA, SinalB );S(30 downto 23) <= ExpR(7 downto 0);S(22 downto 0) <= MantR(45 downto 23);prt <= ‘1’;Estado := estEspera; -- Proximo estado
E pronto.
Simulação: Multiplicação em Ponto Flutuante
A = -1,75 * 2
B = -1,75 * 2
S = A * B = 1,53125 * 23
S = (1+ 2-1 + 2-5) * 23
A = (1 + 2-1 + 2-2) * 2(2^7 + 2^6 - 127)
B = (1 + 2-1 + 2-2) * 2(2^7 - 127)
S= A * BS = (1+2-1 + 2-5) * 2(2^7 + 2^6 + 2^1- 127)
Simulação: Multiplicação em Ponto Flutuante (continuação)
Multiplicação entre um número não-normalizado e outro normalizado, gerando o resultado, um númeronormalizado:
Multiplicação entre um número não-normalizado e outro normalizado, dando como resultado um número não-normalizado:
Caso especial: Multiplicação entre um número não-normalizado e outro normalizado, dando como resultadoum número entre o menor normalizado e o maior não-normalizado, neste caso foi arredondado:
A = (2-1 + 2-2) * 2-127
B = (1 + 2-1 + 2-2) * 2(192-127)
S = (1 + 2-2 + 2-4) * 2(65-127)
Divisão em Ponto Flutuante (32 bits)
Implementarémos o algoritmo para divisão em ponto flutuante, usando um contador de estados internos,conforme usado no algoritmo anterior.
A estrutura usada anteriormente será aproveitada, mudando apenas alguns estados e algumas variáveis,descritos abaixo:
Definindo Estados
Type Testado Is (estEspera, -- aguarda sinal str ficar ativoestSeparaDadosA, -- Separa os dados de AestSeparaDadosB, -- Separa os dados de BestTestarCondicao01, --Testa se A e ZeroestTestarCondicao02e03, --Testa se A e NaN ou B e NaNestTestarCondicao04, --Testa se B e ZeroestTestarCondicao05, --Testa se A = BestTestarCondicao06, --Testa se A e InfinitoestSoma127, --Soma 127 ao Resultado antes de Subtrair por BestTestaUnderflow, --se (ExpA+127) >= ExpB, caso negativo UnderflowestSubtraiExpoente, -- Subtrai expoenteestTestaOverflow, -- Testa OverflowestDivMantissa, --Divide Mantissa A(24) / B(24) = R(24)estDivMantissa01,estSomaExpDivisao, -- Soma expoente da divisao com ExpRestTestaOverflowDivisao, -- Testa OverflowestNormalizaDir, --Verif. o primeiro bit a esquerda da virgulaestRetornaResultado);
Sinais de Entrada e Saída
Os sinais de controle permanecem iguais:clk – que será o clock;rst – que será o reset;str – que será o start.
prt – vai para um quando o resultado já estiver pronto para leitura
Operandos de entrada:A, B : IN STD_LOGIC_VECTOR(31 downto 0);
Operandos de Saída:S : OUT STD_LOGIC_VECTOR(31 downto 0));
Bit 31 : bit de sinalBits de 30 à 23 : representam o expoente com excesso de 127Bits de 22 à 0 : representam a mantissa
Variáveis auxiliares
Serão criadas três conjuntos de variáveis para representar internamente um número em ponto flutuante.SinalX : contem o sinal da variável XExpX : contém o expoente da variável X
MantX : contém a mantissa de variável X
VARIABLE SinalA, SinalB, SinalR : STD_LOGIC;VARIABLE ExpA, ExpB : STD_LOGIC_VECTOR(7 downto 0);VARIABLE ExpR : STD_LOGIC_VECTOR(8 downto 0); -- Para Teste de overflowVARIABLE MantA, MantB : STD_LOGIC_VECTOR(23 downto 0);VARIABLE MantR : STD_LOGIC_VECTOR(24 downto 0);VARIABLE Estado : TEstado;
--Variaveis auxiliares para DivisaoVARIABLE Dividendo : STD_LOGIC_VECTOR(23 downto 0);VARIABLE PosVirgula : STD_LOGIC_VECTOR(8 downto 0);VARIABLE ContDiv : STD_LOGIC_VECTOR(8 downto 0);
Obs: Forão colocados o dobro de bits em MantR para evitar overflow na multiplicação.
Condições para Divisão S = A / B
Condição A B S01 Zero Qualquer Zero02 Not-a-Number Qualquer Not-a-Number03 Qualquer Not-a-Number Not-a-Number04 Qualquer Zero R.S. Infinito05 A = B R.S. Um06 Infinito Qualquer R.S. Infinito07 Qualquer Infinito R.S. Zero08 Não-Normalizado ou
NormalizadoNão-Normalizado ouNormalizado
R.S.Subtrai ExpoentesDivide Mantissa
R.S. = Regra de Sinal
A função para calcular a Regra de Sinal, é a mesma descrita na multiplicação.
Testar Condição 01
When estTestarCondicao01 =>--Testa se A e Zeroif ExpA(7 downto 0) = "00000000" and
MantA(22 downto 0) = "00000000000000000000000" then
--Saida e ZeroExpR := "000000000";MantR := "0000000000000000000000000";Estado := estRetornaResultado; -- Proximo estado
elseEstado := estTestarCondicao02e03; -- Proximo estado
end if;
Testar Condição 02 e 03
When estTestarCondicao02e03 =>--Testa se A e NaN ou B e NaNif (ExpA(7 downto 0) = "11111111" and
not (MantA(22 downto 0) = "00000000000000000000000")) or (ExpB(7 downto 0) = "11111111" and
not (MantB(22 downto 0) = "00000000000000000000000"))then
--A ou B e NaN a saida e NaNExpR := "011111111";MantR := "0000000000000000000000000";Estado := estRetornaResultado; -- Proximo estado
elseEstado := estTestarCondicao04; -- Proximo estado
end if;
Testar Condição 04
When estTestarCondicao04 =>--Testa se B e Zeroif ExpB(7 downto 0) = "00000000" and
MantB(22 downto 0) = "00000000000000000000000" then
--Saida e Infinito
ExpR := "011111111";MantR := "0000000000000000000000000";Estado := estRetornaResultado; -- Proximo estado
elseEstado := estTestarCondicao05; -- Proximo estado
end if;
Testar Condição 05
When estTestarCondicao05 =>--Testa se A = Bif (ExpA(7 downto 0) = ExpB(7 downto 0)) and
(MantA(22 downto 0) = MantB(22 downto 0)) then
--Saida e HumExpR := "001111111";MantR := "0100000000000000000000000";Estado := estRetornaResultado; -- Proximo estado
elseEstado := estTestarCondicao06; -- Proximo estado
end if;
Testar Condição 06
When estTestarCondicao06 =>--Testa se A e Infinitoif ExpA(7 downto 0) = "11111111" and
MantA(22 downto 0) = "00000000000000000000000" then
--Saida e InfinitoExpR := "011111111";MantR := "0000000000000000000000000";Estado := estRetornaResultado; -- Proximo estado
else
Estado := estSoma127; -- Proximo estado
end if;
Condição 07
When estSoma127 =>--Soma 127 ao Resultado antes de Subtrair por B--R = A + 127ExpR := ExpA + 127;Estado := estTestaUnderflow; -- Proximo estado
When estTestaUnderflow =>--Testa se (ExpA+127) >= ExpB, caso negativo UnderflowIf ExpR < ExpB then
--Saida e ZeroExpR := "000000000";MantR := "0000000000000000000000000";Estado := estRetornaResultado; -- Proximo estado
elseEstado := estSubtraiExpoente; -- Proximo estado
end if;
When estSubtraiExpoente =>-- Subtrai expoenteExpR := ExpR - ExpB;Estado := estTestaOverflow; -- Proximo estado
When estTestaOverflow =>-- Testa Overflowif ExpR > 255 then
--Saida e InfinitoExpR := "011111111";MantR := "0000000000000000000000000";
Estado := estRetornaResultado; -- Proximo estado
elseEstado := estDivMantissa; -- Proximo estado
end if;
When estDivMantissa =>--Divide Mantissa A(24) / B(24) = R(24)--MantR := MantA / MantB
Dividendo:= MantA;Divisor:= MantB;MantR:= "0000000000000000000000000";PosVirgula := "000000000";;ContDiv:= "000000000";;Estado := estDivMantissa01; -- Proximo estado
When estDivMantissa01 =>
while (ContDiv<24 and not Dividendo=0)If Dividendo >= MantB then
MantR(24-ContDiv) := '1';Dividendo := Dividendo - MantB;ContDiv := ContDiv + 1;
elseIf PosVirgula = 0 then
PosVirgula := ContDiv + 1;else
MantR(24-ContDiv) := '0';ContDiv := ContDiv + 1;
end if;Dividendo (23 downto 1) := Dividendo(22 downto 0);Dividendo (0) := '0';
end if;wend;If PosVirgula = 0 then
PosVirgula := ContDiv + 1;end if;
Estado := estSomaExpDivisao; -- Proximo estado
When estSomaExpDivisao =>-- Soma expoente da divisao com ExpRExpR:= > ExpR + PosVirgula -1;Estado := estTestaOverflowDivisao; -- Proximo estado
When estTestaOverflowDivisao =>-- Testa Overflowif ExpR > 255 then
--Saida e InfinitoExpR := "011111111";MantR := "000000000000000000000000000000000000000000000000";Estado := estRetornaResultado; -- Proximo estado
elseEstado := estNormalizaDir; -- Proximo estado
end if;
When estNormalizaDir =>--Verif. o primeiro bit a esquerda da virgulaloop_Normaliza1:while not ( MantR(24) = '1' or ExpR = "000000000" ) loop
MantR(24 downto 1) := MantR(23 downto 0);MantR(0) := '0';ExpR := ExpR - 1;
end loop loop_Normaliza1;Estado := estRetornaResultado; -- Proximo estado
When estRetornaResultado =>S(31) <= RegraSinal (SinalA, SinalB );S(30 downto 23) <= ExpR(7 downto 0);S(22 downto 0) <= MantR(22 downto 0);prt <= ‘1’;Estado := estEspera; -- Proximo estado
E pronto.