O Circuito Lógico da Divisão
Na Figura 1 está representado um circuito de divisão para números de 8 bits em complemento para 2. Este circuito foi construído juntando diversos circuitos lógicos que achámos necessários para executarem os vários passos da operação. É um circuito imaginário onde qualquer comparação com a realidade é pura coincidência. Foi sendo construído conforme o íamos descrevendo. O nosso propósito foi, mais uma vez, o raciocínio lógico e a dedução lógica desta vez temporizada (clocked).
Para atingirmos o nosso propósito já encontrámos os componentes que vão executar os vários passos do algoritmo, no artigo anterior. Agora vamos implementar o circuito juntando todos os componentes e interligando-os. Vamos olhar essencialmente para a propagação dos sinais no circuito durante o ciclo do clock e ao comportamento de cada circuito relativamente a esse ciclo de clock.
Implementando o Circuito
Ao implementarmos em circuito o algoritmo da divisão, vamos ter que interligar todos os componentes e conhecer bem o comportamento próprio de cada um. Vamos dar especial atenção à propagação dos sinais ao longo do circuito e ao consequente comportamento dos componentes tendo em atenção as suas interconexões. A forma como com a lógica se consegue que cada circuito funcione internamente, em questões que não tenham relação com a prioridade atrás enunciada, é matéria que vamos deixar para vossa análise, o que poderão fazer com o esquema do circuito junto. Pode acompanhar esta descrição junto com a Figura 1 do artigo anterior e com esta Figura 1 abertas em janelas separadas.
Voltamos a relembrar os componentes de um ciclo de clock na Figura 2 aqui junto.
O circuito que vamos implementar, é apresentado com o clock em baixa (C=0) e no final do ciclo de inicialização do circuito. Considerámos concluídas todas as modificações e propagações que aconteceram durante o ciclo a terminar. O estado das variáveis no início deste ciclo, o que aconteceu no ciclo anterior para assim estarem, a sua variação durante este ciclo e o seu estado no final deste ciclo, com o qual influenciarão o ciclo seguinte, serão analisados.
Circuitos 1 e 2
O que estes dois circuitos fazem já vimos na sua atribuição ao Passo 1 do algoritmo. Agora vamos ver ao que ligam. O circuito 1, o do dividendo, liga diretamente às entradas de carregamento em paralelo do Registo 5. O circuito 2, o divisor, está ligado ao 2º operando do Somador 4 e aí vai permanecer inalterável durante toda a operação. Afinal, em todas as iterações o valor a diminuir ao 1º operando, o tal que se vê se cabe ou não cabe, é sempre o do divisor.
Na Figura 3 pode-se verificar que a divisão realmente realizada será sempre de 101 por 5 quer o dividendo seja (+101) ou (-101) e o divisor seja (+5) ou (-5). Após a passagem por algum destes circuitos a sua representação binária será sempre a do inteiro sem sinal do número, ou seja, 01100101(101) e 00000101(5). Reparem que os circuitos 1 e 2 tratam 7 bits,tendo o 8º bit na saída como carry out, e aqueles a que ligam tratam 8 bits. Tendo em atenção o facto de estarmos a lidar com números de 8 bits em complemento para 2, agora positivos e sem sinal, para quê o 8 º bit? Esta questão já foi tratada no final do parágrafo sobre a multiplicação, no Capítulo sobre Operações Aritméticas. Desta vez é tarefa vossa analisar e perceber porquê.
Circuito 3
É o Contador 3. O que é e o que faz já descrevemos na sua atribuição ao Passo 12 do algoritmo. PL3 é o sinal de carregamento em paralelo deste circuito e encontra-se agora a 0, na parte baixa do ciclo de clock de inicialização.
Mas PL3 não deveria estar a 1?
Aparentemente sim, pois neste circuito PL é ativo a 1 e acabou de ser feito um carregamento em paralelo, por isso com PL3 a 1. Efetivamente, durante o ciclo de clock em que se dá a deteção de zero, anterior a este em que estamos, o valor de Z passa a 1 e consequentemente o valor de PL3 também. Portanto PL3 está a 1 e o valor a carregar está nas entradas das Básculas deste circuito quando se dá o flanco ascendente do ciclo de clock que estamos a analisar. E o carregamento é efetuado e esse valor memorizado.
Mas agora vem a tal história da propagação de sinais. Uma vez memorizado este valor, Z passa a 0 e consequentemente PL3 também, acabando portanto este ciclo com PL3 a 0, com a sua função cumprida e já preparado para a contagem no próximo ciclo.
Circuito 4
Este é o Somador 4, atribuído ao Passo 8 do algoritmo, onde o essencial que havia a referir sobre este circuito, suas ligações e resultados já foi descrito.
Circuito 5
Este circuito é o Registo 5, atribuído aos Passos 3, 6 e 8 do algoritmo, onde o que ele faz, o que liberta, o que carrega em PL e o bit que admite, já foi descrito. Vamos analisar neste circuito como se resolve um problema resultante da propagação de sinais que exige um bom conhecimento das componentes do ciclo de clock e que vai evidenciar a importância da lógica temporizada na sincronização de todos os acontecimentos dispersos num circuito ou num computador.
Os Corredores de Estafetas
No flanco ascendente deste clock os valores no Registo 5 são deslocados à esquerda, sendo que é o bit libertado por este (o de maior ordem), um dos que vão ser memorizados (o de menor ordem) no Registo 6 como 1º operando para esta iteração. Este é o nosso corredor de estafetas inicial.
É o valor do 1º operando que se vai propagar no circuito durante este clock e que, uma vez chegado ao Somador 4, ao ser-lhe subtraído o divisor, vai gerar um carry out dessa operação que determina o valor do nosso corredor de estafetas final, que vai então correr através do Circuito 9c diretamente para o Registo 5.
Aqui chegado e porque se trata de um Registo, o nosso corredor de estafetas vai parar à entrada da respetiva Báscula. Mas chega lá muito depois do flanco ascendente deste clock. Vai ficar na entrada, à espera do ciclo seguinte.
Mas não era este o bit que devia ter entrado como quociente para o Registo 5 quando ele deslocou à esquerda?
Efetivamente era, e o problema está precisamente aí. É que os outros já lá vão, e como este chegou atrasado deixaram-no para trás e levaram no lugar dele o que ainda estava nesta entrada do Registo e que pertencia a outra história.
Mas assim vai ficar tudo errado, não?
Pois vai. Mas a cada deslocamento que se efetua, um por cada ciclo de clock, um bit tem que entrar e os outros não podem ficar à espera dele. Os colegas dele são corredores de velocidade e não sabem que ele é corredor de estafetas.
E como é que isto se resolve?
Reparem que, o problema neste caso resulta de o valor do bit que entra num deslocamento do Registo 5 depender do valor do bit que sai nesse mesmo deslocamento.
Então, se o deslocamento se desse só depois de ele chegar estaria tudo resolvido?
Certo. E isso conseguia-se desde que as Básculas do Registo 5 forem sensíveis ao flanco descendente do clock, pois assim o valor que entra no deslocamento já estaria correto, porque o nosso corredor de estafetas final já teria entretanto chegado ao seu lugar.
Mas assim o bit que vai ser memorizado no Registo 6 não vai estar certo, porque como ainda não se deu o deslocamento no Registo 5, ele ainda não foi libertado?
Não, agora vendo bem isso não é bem assim. O bit que vai ser libertado é o bit de maior ordem das saídas do Registo 5 e está ligado ao bit de menor ordem das entradas do Registo 6. Assim, por força desta ligação, ele já está na sua entrada 0 e, no flanco ascendente do clock é o seu valor que é nele memorizado e segue os passos atrás descritos como corredor de estafetas inicial transportando o valor certo para que o corredor de estafetas final também tenha o valor correto ao chegar à entrada do Registo 5, antes de se dar o deslocamento neste.
No flanco descendente do ciclo de clock, dá-se o deslocamento à esquerda, o nosso corredor de estafetas entra para o quociente e o bit libertado desaparece para sempre, passando a ser o bit de ordem seguinte, agora o de maior ordem, o que vai ser libertado no ciclo seguinte e que fica desde já ligado à entrada do Registo 6.
Assim já parece que fica tudo certo com este circuito.
Pois é, aparentemente sim. Está tudo bem para uma iteração normal, a que acabámos de ver.
O Carregamento em Paralelo
O ciclo de clock que devíamos estar a analisar é aquele em que é feita a inicialização do circuito. O Registo 5 é inicializado com o valor do dividendo, portanto com uma carga em paralelo. Neste Registo o sinal de PL é representado por PL5 e é ativo a 1. Na análise que acabámos de fazer ao Circuito 3, constatámos que durante este ciclo de clock o valor de Z passava a 0. Ora assim sendo, o valor de PL5, que está ligado a Z, também passa a 0 e quando chegarmos ao flanco descendente do clock PL5 vai estar a 0 e não efetua a carga. Enquanto este Registo era sensível ao flanco ascendente do clock esse problema não existia, porque aí Z e PL5 ainda eram 1.
Então como é que resolvemos isto?
Atrasando o PL5 em relação a Z em um ciclo de clock.
E como é que se faz isso?
No Circuito 9b integra-se uma báscula na linha que liga Z ao PL5. Assim, quando Z passa a 1 assume esse valor à entrada da Báscula, só passando à saída (PL5) no ciclo seguinte (a inicialização). É durante este ciclo, após o flanco ascendente do clock, que PL5 fica a 1 e seleciona o valor do dividendo a carregar para as entradas do Registo 5, onde será memorizado no flanco descendente do clock. Na Figura 4 podemos ver a evolução das variáveis e do estado do circuito desde o flanco ascendente do clock em que acontece a deteção de zero até ao flanco descendente do clock em que se dá a primeira iteração.
Circuito 6
Este circuito é o Registo 6, atribuído aos Passos 4, 7 e 10 do algoritmo, onde o que ele faz, o que liberta, o que carrega em PL e o bit que admite, já foi descrito. Quando o carry out do Somador 4 é 0, desloca os bits à esquerda e introduz o bit libertado do Registo 5, o que baixa do dividendo. Quando é 1, carrega os bits das saídas deste somador, desloca-os à esquerda e admite o bit libertado do Registo 5, o que baixa do dividendo.
Tudo isto só num ciclo de clock ? Carregar e deslocar são feitos em 2 ciclos. Está-se a juntar tudo num? Como?
É verdade. E nós não temos esse tempo todo, pois os outros circuitos não param à espera deste. No primeiro destes 2 ciclos o 1º operando tem que estar no Somador 4 pronto para ser subtraído do valor do divisor. Então vamos ter que arranjar um estratagema para fazer as duas operações de uma só vez. Ora vejamos. Quando o Registo 6 carrega em paralelo não desloca à esquerda.
E que tal se conseguíssemos carregar de tal forma que um deslocamento à esquerda fosse simulado?
É possível. Ligando as saídas do Somador 4 às entradas de ordem imediatamente superior do Registo 6, isto é, o L0 ao E1, o L1 ao E2 e assim sucessivamente. A E0 estaria ligado o bit de maior ordem do Registo 5, o que baixa. Desta forma, ao efetuarmos o carregamento em paralelo, já o deixamos deslocado à esquerda. Certo?
Então e o bit L7 do resultado da subtração?
Esse seria o bit a sair do Registo 6 durante o deslocamento. Não o ligando, fica simulada a sua saída. A inicialização deste circuito é feita por um Clear às suas básculas no flanco ascendente deste ciclo de clock (o ciclo seguinte à deteção de Zero). Existindo esta relação, vamos ligar CL (Clear) ao sinal Z. O valor de Z durante o ciclo anterior passou a 1. Portanto no flanco ascendente do clock deste ciclo de inicialização estará a 1. O mesmo em que se pretende executar o Clear. Então, no Circuito 9b como CL é ativo a 0 será ligado à negação de Z.
Circuito 7
Este é o Circuito 7, atribuído ao Passo 15 do algoritmo, onde o essencial que havia a referir sobre este circuito, suas ligações e resultados já foi descrito.
Circuito 8
Este é o Circuito 8, atribuído ao Passo 14 do algoritmo, onde o essencial que havia a referir sobre este circuito, suas ligações e resultados já foi descrito.
Circuito 9
Este é a Unidade de Controlo 9 do circuito. Contém outros pequenos circuitos que analisam sinais produzidos dentro do circuito e os transformam e enviam para os locais onde vão ser utilizados. O Circuito 9a é o que analisa os sinais dos operandos e determina os sinais:
- do resto, que envia para o Circuito 8 e
- do resultado, que envia para o Circuito 7.
O Circuito 9b faz a análise da deteção de Zero (Z), atribui o valor de Z a PL5 e a PL3, a negação de Z a CL e informa o exterior do circuito sobre o seu valor. O Circuito 9c faz a leitura do carry out do Circuito 4 e atribui o seu valor a PL5, a PL6 e ao bit de seleção do MUX do Circuito 8. O Circuito 9d verifica se o valor do divisor é (-1) e se o valor do dividendo é (-128), caso em que o resultado será (+128) ou em binário 1 0000 0000 um resultado possível para a gama de operações deste circuito mas não representável em 8 bits. Se este for o caso é emitido um sinal de erro para o exterior. O Circuito 9e quando deteta a divisão de um número por zero emite um sinal de erro para o exterior.
Vamos agora apreciar a evolução dos valores nos diferentes componentes do circuito ao longo das diversas iterações até chegar à deteção de zero. Vamos começar pela inicialização do circuito, o que se dá no ciclo de clock seguinte ao ciclo de deteção de zero. A deteção de zero será analisada no final da operação, onde se encontra descrita.