Projetando uma ALU simples


8

Preciso criar uma ALU com duas entradas de 8 bits A e B e controlar as entradas x, ye z que oferecem suporte às seguintes operações:

x  y  z  |  operation

0  0  0  |  S = A-B
0  0  1  |  S = A+B
0  1  0  |  S = A*8
0  1  1  |  S = A/8
1  0  0  | S = A NAND B (bitwise)
1  0  1  | S = A XOR B (bitwise)
1  1  0  | s = reverse the bits of A
1  1  1  | S = NOT A (bitwise)

Isso deve ser feito com um somador de 8 bits e um extensor lógico-aritmético. Ao ler meu livro, vejo que o objetivo de um extensor AL é alterar os bits de entrada para que um somador, em vez de muitos componentes extras, possa ser usado para fazer tudo (ou pelo menos é isso que eu entendo dele) ) Por exemplo, o AL-extensor pode colocar os bits no complemento de dois para que o somador faça uma subtração. Da mesma forma, para as operações lógicas bit a bit, os bits podem ser alterados adequadamente e uma das entradas do somador pode ser apenas zero, para que o resultado seja obtido corretamente.

Mas o que exatamente faço sobre multiplicação? Meu livro é muito vago, então não tenho certeza se um extensor de AL exigiria que eu fizesse algo inteligente para fazer o adicionador fazer o trabalho (basta adicionar 8 vezes no meu caso? ... ha ha), ou se eu pode simplesmente jogar um multiplicador lá. Vou ter que ler sobre divisão, mas aposto que é semelhante à multiplicação.

Bem, enfim, a linha de fundo ainda é, o que um AL-extensor "permitido" pode / pode ter nele? Seu único objetivo é alterar a entrada para que ela possa ser alimentada a um adicionador?

* EDIT: Bem, é multiplicação / divisão por 8, então isso pode ser facilmente realizado com a mudança de esquerda ou direita por 3. Eu ainda teria um extensor de AL real / adequado se adicionasse alguns shifters lá? (Talvez eu esteja pensando demais nisso como iniciante completo ...)


1
O que é 00011111 * 8? O que é 00000000-00000111? Se o seu AL-extender mudar 3 vezes para o código operacional "010", ele poderá atribuir B a 0 e chamar os códigos operacionais "001" ou "000" na ALU.
Tony Ennis

Respostas:


5

A abordagem mais simples seria decodificar as entradas xyz em oito linhas. A partir daí, você implementa a lógica que aciona as linhas de seleção de chips para ativar a unidade apropriada que lida com as entradas, bem como as transformações necessárias para que a unidade execute a operação correta.

Eu não acho que você possa usar um somador para suas operações lógicas porque ele carrega (a menos que tenha alguma entrada que desative o comportamento da propagação de transporte). Mas você pode ter uma única unidade para fazer toda a lógica.

Talvez haja uma razão pela qual eles chamam essas ULAs, com A e L. separados :)

A multiplicação por 8 significa apenas zeros nas três linhas de entrada mais baixas, ignorando as três linhas superiores e mapeando a linha 0 à linha 3, 1 a 4 e assim por diante. É como um interruptor de trem.


6

(Fraude)
A solução mais simples, porém mais poderosa, é usar uma memória Flash como uma tabela de pesquisa para os resultados. 8 bits Um código de operação de entrada + entrada B de 8 bits + 3 bits é de 19 bits. Escolha um 512 k×Flash de 16 bits (cerca de US $ 2), use as 19 linhas de entrada como endereço e programe-o com os resultados para cada combinação de entradas. Dessa forma, você pode ter qualquer operação que desejar. Você quer pecado (A)? Basta adicionar uma tabela de pesquisa de seno de 256 palavras, você pode até obter um resultado preciso de 16 bits. Você não está limitado a multiplicar por 8; você pode multiplicar A por B. Como sábio, você pode dividir A por B, e obter um quociente de 8-bit e um resto de 8 bits. Para a multiplicação e divisão, você usará todos os bits em um bloco de 64 kword, mas, por exemplo, a inversão de bits fará um uso menos eficiente: não depende do valor de B, portanto, você terá 256 valores idênticos para cada entrada A e o byte de alta ordem nem seriam usados. Então, enquanto você só precisa de 256× 8 = 2048 bits para a inversão de bits que você usaria 65536 ×16 = 1048576 bits; isso não é muito eficiente. Você pode chamar isso de uma séria desvantagem da solução Flash, mas eu gostaria que você implementasse um 8× Multiplicador 8 usando portas lógicas básicas por US $ 2.

OK, talvez você não queira isso; portas lógicas são muito mais desafiadoras. Como Kaz diz, comece com um decodificador de 3 a 8 para ter um sinal único para cada código de operação. Você pode fazer isso com portões básicos, mas eu sugiro usar um 74HC238 para começar. Quando a ALU funciona, você ainda pode substituir o HC238 por uma coleção de portões.

O que você não deseja para o multiplicador é um registrador de turnos que muda três vezes para a esquerda. Essa é uma função registrada que precisa de um relógio, em vez de uma função combinatória que produz o resultado imediatamente. (Observe que o Flash também produz qualquer resultado em nanossegundos, embora mais lento que na lógica combinatória.) Tenha um caminho de A0 a Y3, A1 a Y4, etc., que você ativa com o código de operação decodificado "010". Da mesma forma, Y3 será conectado a A6 se o sinal "011" estiver ativo (divisão) e a A4 quando o opcoe for "110" (inversão de bits). Isso significa muita multiplexação.

Para voltar ao Flash, você também pode fazer uma combinação de lógica combinatória para operações simples, como NAND, NOR, shift esquerda, shift direita()e use apenas o Flash para multiplicação e divisão. Você pode usar um Flash menor (128 kword em vez de 512 kword) ou adicionar funções mais avançadas, como o seno que dei como exemplo (talvez não seja o melhor, mas tenho certeza de que pode pensar em alguma coisa).



()Como é possível multiplicar por 8, mas não o turno mais básico que resta? Deslocar para a esquerda / direita, girar para a esquerda / direita (através de carry e não) são obrigatórios para qualquer ALU, e você pode dividir por 8 usando 3 direitos de shift, enquanto você não pode dividir por 2. A reversão de bit é um DSP típico função, mas você não deseja criar um DSP para começar, não é? Eu mudaria as funções para

x  y  z  |  operation

0  0  0  |  S = A - B
0  0  1  |  S = A + B
0  1  0  |  S = shift left A by 1 bit
0  1  1  |  S = shift right A by 1 bit
1  0  0  |  S = A NAND B (bitwise)
1  0  1  |  S = A XOR B (bitwise)
1  1  0  |  S = rotate left A
1  1  1  |  S = NOT A (bitwise)

1

Fiquei preso no mesmo problema do mesmo livro. Felizmente eu tropecei nessa discussão que me deu uma idéia do que fazer. Kaz tem uma opinião muito boa sobre como zeros e linhas de mapeamento. O extensor da ALU neste livro foi projetado para n (n representando o número de bits nos quais operar) componentes combinacionais idênticos, mas separados, e um componente diferente para transporte. Esses componentes têm cinco entradas e duas saídas. As cinco entradas são: 'X', 'Y', 'Z' (para selecionar operação) e 'a', 'b' (bits individuais de A e B com o mesmo significado). Acho que a idéia aqui é dividir o problema em partes menores para ter uma tabela verdade de tamanho razoável. Ou seja, 5 entradas versus 8 + 8 + 3 = 19 entradas, se o extensor aceitar todos os bits de A e B mais as entradas de controle. Agora, se o extensor fosse composto dessa maneira (19 entradas), acho que a lógica da multiplicação poderia ser implementada nesse único componente, mas escrever uma tabela verdade para isso estaria fora de questão. De qualquer forma, minha solução é usar muxes após cada componente que lida com bits individuais a e b, assumindo que o componente já tenha sido projetado de tal maneira que uma entrada XYZ = 010 passe 'um' pouco inalterado e filtre 'b', ou seja, 'b' = 0. O mux deve ter duas entradas, uma do componente acima e uma do componente três posições à direita. Três muxes mais à direita devem ter zeros como segunda entrada. Uma lógica combinatória simples com uma porta AND e dois inversores pode definir os muxes quando XYZ = 010.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.