Um Em 1974, a Hewlett-Packard desenvolveu um microprocessador para controlar várias funções em seus produtos, de unidades de disquete a voltímetros. Este processador simples não era compatível com os microprocessadores padrão - nem mesmo suportava adição ou subtração - por isso foi chamado de "nanoprocessador". As principais características do nanoprocessador eram baixo custo e alta velocidade de trabalho: em comparação com o moderno Motorola 6800, que custava US $ 360, o nanoprocessador custava US $ 15 e as operações de controle eram muito mais rápidas.
Embora não tivesse uma operação de adição, o Nanoprocessador podia (lentamente) adicionar números aumentando ou diminuindo repetidamente (as operações que ele suportava). Em outros casos, por exemplo, com um voltímetro da Hewlett-Packard, chips ALU (74LS181) foram adicionados ao produto, os quais foram ativados em uma adição rápida - eles foram acessados como dispositivos de E / S. Naturalmente, sendo Turing completo, o nanoprocessador poderia teoricamente fazer tudo, desde calcular funções de ponto flutuante até lançar um jogo Crysis; só seria muito lento.
A máscara fotográfica do processador pode ser baixada do link (122 MB PSD).

HP Nanoprocessor, 1820-1691. , -2,5 , – . , .
Nas décadas seguintes, o processador permaneceu desconhecido até recentemente seu desenvolvedor, Larry Bauer, compartilhou as fotomáscaras e a documentação do chip com o projeto CPU Shack. Lá eles escanearam as fotomáscaras e escreveram um artigo sobre Nanoprocessador. Depois que Antoine Berkovichi juntou as imagens em uma, escrevi uma revisão do Nanoprocessador com base nele . Esta é a segunda parte do artigo, onde discuto alguns dos detalhes do circuito do Nanoprocessador ao fazer engenharia reversa com base em fotomáscaras. Blocos funcionais de Nanoprocessador são interessantes de estudar, pois ele contorna a implementação mínima das funções necessárias, enquanto permanece um microprocessador útil.
Nanoprocessador interno
Como a maioria dos processadores daquela época, o Nanoprocessador é de 8 bits. No entanto, ele não oferece suporte à memória de acesso aleatório e o código é executado a partir de uma ROM externa de 2 KB. Possui 16 registradores de 8 bits - mais do que a maioria dos processadores e o suficiente para compensar a falta de memória para muitos aplicativos. O Nanoprocessador tinha 48 instruções - significativamente menos do que as 72 instruções do Motorola 6800. No entanto, o Nanoprocessador tinha um conjunto útil de operações definidas, limpas e de verificação que outros processadores da época não tinham. Ele também tinha vários comandos de E / S que suportavam portas de E / S e pinos de E / S de uso geral, facilitando o controle de outros dispositivos com ele.
O nanoprocessador não tinha instruções para suportar o manuseio de memória, pois foi projetado para operações que não exigiam armazenamento de dados. No entanto, em alguns aplicativos, o Nanoprocessador usa RAM como um dispositivo de E / S. Um endereço foi enviado para uma das portas de E / S e um byte de dados foi lido da outra. Nanoprocessador combinado de fotomáscaras (clicável) A partir da imagem de fotomáscara acima, podemos concluir que o Nanoprocessador é simples. As linhas azuis são condutores de metal no topo do chip, as verdes são silício com impurezas. Quadrados pretos em todo o perímetro - 40 locais para comunicação com contatos externos do IC. As pequenas áreas pretas dentro são transistores. Se você olhar de perto, você pode contar 4.639 deles.

Se levarmos em conta que o decodificador de instruções consiste em pares de pequenos transistores, o que é feito para a conveniência do arranjo dos componentes, e contarmos esses pares como um, teremos 3829 transistores. Destes, 1061 são pull-ups e 2668 estão ativos. Em comparação, o 6502 tinha 4.237 transistores, 3.218 dos quais estavam ativos. O 8008 tinha 3500 transistores, enquanto o Motorola 6800 tinha 4100.
O diagrama de blocos abaixo mostra a estrutura interna do Nanoprocessador. No meio, há 16 registradores de retenção. O comparador permite comparar dois valores para fornecer ramificação condicional. A unidade lógica de controle lida com as operações de incremento, decremento, deslocamento e bit do acumulador. Ele não possui as operações aritméticas e lógicas da ALU padrão. O contador de programa (direita) recupera uma instrução do registro de instrução (esquerda); interrupções e chamadas de sub-rotina têm suas próprias pilhas de um item para armazenar endereços de retorno.

Fluxograma de trabalho a partir das instruções do Nanoprocessador
Deixe-me enfatizar que, apesar de sua simplicidade e falta de operações aritméticas, Nanoprocessador não é uma espécie de processador "brinquedo" que muda as linhas de controle. É um processador rápido e poderoso usado para realizar operações complexas. Por exemplo, o módulo de relógio em tempo real HP 98035 usou Nanoprocessador para processar duas dezenas de strings de controle ASCII diferentes, bem como para contar o número de dias em um mês.
Um projeto interessante e divertido pode ser a criação de uma versão FPGA do Nanoprocessador - já que o Nanoprocessador é talvez a versão mais simples de um processador comercial real. As instruções para ele descrevem todos os comandos e fornecem exemplos de código que você pode executar.
Registros
A foto do cristal abaixo mostra que uma parte significativa do Nanoprocessador está ocupada por seus 16 registradores. Eles se comunicam com o resto dos componentes por meio do barramento de dados. As cadeias no topo selecionam um determinado registro. Registre R0, à direita, ao lado do comparador.

Uma parte significativa do Nanoprocessador é ocupada por seus registros 16.
O bloco de construção de um registro são dois inversores no loop de feedback, armazenando um bit como mostrado abaixo. Se o condutor superior for 0, o inversor direito dará saída 1 para o condutor inferior.Em seguida, o inversor esquerdo dará 0 para o condutor superior, completando o ciclo. O circuito permanece estável ao “lembrar” 0. Da mesma forma, se o condutor superior for 1, ele é invertido para 0 na parte inferior e de volta para 1 na parte superior. A rede pode armazenar 0 ou 1 dessa forma, formando um local de memória de 1 bit.

Dois inversores em um circuito de armazenamento de bits estável
O diagrama abaixo mostra como esse armazenamento de dois inversores é implementado em um chip. A localização física dos componentes é mostrada à esquerda, com base em uma fotomáscara. O layout é otimizado para que a célula ocupe o mínimo de espaço possível. Linhas azuis - camada de metal, verde - silício. No meio, é mostrado um diagrama do circuito correspondente com transistores. Cada inversor consiste em um par de transistores, conforme mostrado à direita. Transistores na parte superior e inferior - "através", eles fornecem acesso à célula de armazenamento.

Armazenando um bit no Nanoprocessador. Cada bit é implementado em 6 transistores (célula 6T SRAM).
Um conjunto de registros consiste em uma matriz de tais células de bits. O barramento de seleção de registro seleciona um registro (uma coluna) para leitura ou escrita. Os transistores de passagem superior e inferior conectam os inversores às suas respectivas linhas de bit horizontais. Para leitura, a linha de bits superior fornece o valor armazenado na célula; existem oito linhas de bits para os oito bits armazenados no registro. Para escrita, o valor é transferido para a linha de bit superior e o valor invertido é transferido para a linha inferior. Esses valores substituem os sinais dos inversores, fazendo com que eles tomem o valor desejado e armazenem este bit. Assim, uma grade de linhas de bits horizontais e linhas de seleção verticais permite que um valor seja lido ou escrito em um determinado registro.
Comandos de decodificação
Os circuitos de decodificação estão engajados em pegar o código binário da instrução (por exemplo, 01101010) e determinar o que é a instrução (neste caso, "carregar acumulador do registro 10"). Comparado a muitos processadores, as instruções do Nanoprocessador são bastante simples: ele tem relativamente poucos (48), e o código de instrução é sempre de um byte. O diagrama abaixo mostra que a lógica de decodificação da instrução (vermelho) ocupa uma parte significativa do chip. O registro de instrução (verde) é um conjunto de oito travas que mantêm a instrução atual. O registro do comando está localizado próximo aos pinos de dados, para os quais o comando vem da ROM. Nesta seção, vamos quebrar a cadeia de decodificação mostrada em amarelo.

A decodificação é feita por portas NOR. Cada porta NOR reconhece um comando específico ou grupo de comandos. A porta NOR aceita bits de comando ou seu complemento como entrada. Quando todos os bits de entrada são zero, a porta NOR relata uma correspondência. Isso permite que você pesquise jogos em toda a equipe como um todo e em parte da equipe. Por exemplo, o comando "carregar acumulador do registro R" possui um formato binário 0110rrrr, no qual os últimos quatro bits indicam o registro necessário. A porta NOR (bit7 + bit6 '+ bit5' + bit4) 'corresponderá a este comando.
Um decodificador de instruções estruturado dessa maneira é bom porque pode ser montado a partir de circuitos compactos e repetitivos. Geralmente é chamado de PLM (Programmable Logic Array). A ideia é que os sinais de entrada para a matriz sejam alimentados horizontalmente e os de saída sejam alimentados verticalmente. Em cada interseção pode haver um transistor e, então, o sinal de entrada faz parte do portão; se não houver transistor, esta entrada é ignorada. O resultado são válvulas NOR compactamente dispostas. Nos primeiros microprocessadores, o decodificador era frequentemente feito de uma matriz de portas NOR - por exemplo, esse era o caso do 6502.
O diagrama abaixo mostra três decodificadores ampliados no lado direito, que estão circulados em amarelo no diagrama acima. Este diagrama corresponde ao decodificador mais à esquerda. Preste atenção à correspondência dos transistores no diagrama com os pontos rosa dos transistores no layout. A ideia é que, se qualquer sinal de entrada ativar o transistor, o transistor puxa a saída para o terra. Caso contrário, a saída é puxada por um resistor. Os inversores na parte inferior amplificam o sinal de forma que haja corrente suficiente para alimentar todas as oito partes da bateria. Curiosamente, esse layout usa pares de transistores com aterramento e saída conectada - não vejo nenhuma vantagem em usar apenas um único transistor. Em qualquer caso, observe como o PLM fornece um arranjo denso de decodificadores.
Observe que o inversor no decodificador de instrução é aumentado para 12 V, não 5 V. Isso ocorre porque o nanoprocessador usa transistores de porta de metal em vez dos mais avançados transistores de porta de silício encontrados em outros microprocessadores da época. A desvantagem de um transistor com uma porta de metal é uma tensão de limiar aumentada, de modo que a tensão de saída do transistor é muito menor do que a tensão na porta. A saída de um inversor convencional é muito pequena para alimentar a porta do transistor de passagem, uma vez que sua tensão de saída cairá novamente. A solução é usar uma fonte de alimentação de 12 V para os inversores do decodificador que controla os transistores de passagem da bateria, para que os sinais tenham tensão suficiente para acionar os transistores de passagem. Em outras palavras, o nanoprocessador precisa de 12+ V adicionais,pois usa transistores de porta de metal em vez dos mais avançados transistores de porta de silício.

Um dos circuitos decodificadores do Nanoprocessador. O diagrama à esquerda corresponde ao decodificador mais à esquerda dos três mostrados à direita.
Este circuito gera um sinal de incremento / decremento que é alimentado no circuito do acumulador. A linha detecta uma correspondência quando o nível do sinal do gerador de relógio, solicitação, 6º bit de comando e 2º bit de comando é baixo - uma correspondência é encontrada como x0xxx0xx durante a fase de execução. Esses comandos incluem “Incremento Binário” (00000000), “Incremento BCD” (00000010), “Decremento Binário” (00000001) e “Decremento BCD” (00000011).
A cadeia mostrada no diagrama procura correspondências com comandos do formato x0xxx0xx, portanto, a correspondência é encontrada com muitos mais comandos do que apenas incremento e decremento. Por que não está procurando uma correspondência completa? A razão é que, se o acumulador não estiver em uso, a ativação do sinal de incremento / decremento não importa. Ao expandir a lista de opções de correspondência, os desenvolvedores podem se livrar de alguns dos transistores do circuito. É importante que a cadeia substitua outras instruções relacionadas à bateria, como "Limpar o acumulador" (00000100) ou "Carregar o acumulador do registro" (0110rrrr).
Comparador
Um circuito nanoprocessador importante é um comparador que compara o valor armazenado no acumulador com o valor do registrador R0. O comparador usa um circuito único, mas complicado, para compará-los. Essencialmente, o algoritmo compara dois números começando com os bits mais significativos. Se os bits forem iguais, continue com os mais baixos. A diferença do primeiro bit determina qual valor é maior (por exemplo, no caso de 10101010 e 10100111, isso determina o 4º bit da direita).
O algoritmo é implementado em oito etapas, uma de cada vez, começando com o bit mais significativo na parte inferior. Cada etapa consiste em duas partes simétricas - uma determina se a desigualdade A> R0 é válida e sua parte adicional verifica a desigualdade A <R0. Se os números ainda fossem iguais, mas uma diferença fosse encontrada neste estágio, o estágio gera um sinal de "mais" ou "menos". Caso contrário, ele passa a decisão para um nível inferior. A decisão final é feita pelo degrau mais alto. Observe que a comparação de igualdade no comparador ocorre "gratuitamente" - se não houver sinais "mais" ou "menos" na saída, então os valores são iguais.

Uma das etapas de um comparador de 8 bits
O diagrama abaixo mostra o layout físico dos dois estágios do comparador. Um truque do layout do comparador é que ele fica entre o registrador 0 à esquerda e o acumulador à direita, o que minimiza o comprimento dos fios. O comparador acessa o registrador 0 diretamente, ignorando os caminhos usuais de seleção de registrador e barramento de dados.

Duas etapas do comparador - conforme especificado na fotomáscara
Os comandos de ramificação condicional do nanoprocessador podem inspecionar a saída do comparador. Os circuitos de ramificação condicional são bastante simples: alguns bits da instrução de ramificação selecionam uma verificação específica por meio do multiplexador. Então, o 7º bit do comando decide se deve selecionar "esta ramificação se for verdadeira" ou "esta ramificação se for falsa". Ao contrário da maioria dos processadores, o nanoprocessador não permite a ramificação para nenhum endereço. Ele simplesmente pula dois bytes de comando se a condição for atendida (e geralmente esses dois bytes contêm o comando para ir para o destino desejado, mas às vezes há outros comandos). O esquema de salto é simples: o contador do programa é chamado novamente, aumentando o valor não em 1, mas em 2, saltando dois comandos. Acontece que o Nanoprocessor implementa uma ampla gama de verificações condicionais em um número relativamente pequeno de redes.
O nanoprocessador tem um grande conjunto de condições de ramificação - surpreendentemente grande para um processador tão simples. Você pode verificar as seguintes condições: A> R0, A> = R0, A <R0, A <= R0, A == R0 ou A! = R0. Além disso, a ramificação condicional pode depender de se o valor no acumulador é zero ou não, se um determinado bit do valor armazenado no acumulador é igual a zero, se o sinalizador de estouro está definido ou se um determinado bit do registro de E / S está definido.
Bateria e dispositivo lógico de controle
O acumulador é um registro especial de 8 bits que armazena o byte que está sendo processado no momento. As operações com a bateria são realizadas por um dispositivo lógico de controle (ULU), que é denominado "coração do nanoprocessador" nas instruções do processador. ULU é o equivalente a uma unidade lógica aritmética (ALU) na maioria dos processadores, mas não executa operações aritméticas ou lógicas. Ao mesmo tempo, o ULU não é tão inútil quanto parece à primeira vista. Ele pode aumentar ou diminuir o valor no acumulador, tanto em binário quanto em decimal codificado em binário (BCD). O BCD armazena duas casas decimais em um byte. Este é um modo muito útil para E / S ou visores. Além disso, a ULU pode encontrar o complemento do binário do acumulador ou redefini-lo, bem como definir e limpar um determinado bit. Finalmente,ele suporta operações de deslocamento para a esquerda e direita.

Circuitos relacionados à bateria
O diagrama acima mostra a bateria e os circuitos ULD. Na primeira seção, várias redes são localizadas, definindo um valor zero, suportando BCD e fornecendo transporte deslizante - geração rápida de transporte a partir dos 4 bits menos significativos. A segunda seção contém a bateria principal e os circuitos ULU. A terceira seção distribui os sinais de controle da lógica de decodificação acima para as oito partes do acumulador. A última seção contém a lógica de decodificação da instrução que decodifica as operações de bit e envia o sinal para a parte desejada do acumulador.
O corpo principal do acumulador / ULU consiste em 8 partes, uma por bit, com o bit menos significativo no topo. Veremos quatro circuitos de cada parte: um gerador de carry para operações de incremento / decremento, um gerador de bits para operações de incremento / decremento, um multiplexador para selecionar um novo valor de acumulador e um latch onde o valor de acumulador é armazenado.
Cada parte do dispositivo de incremento / decremento (abaixo) é implementada usando um meio somador. A direção da cadeia de incremento / decremento determina o opcode: 0 no bit de ordem inferior do opcode indica incremento e 1 para decremento. A cadeia de transporte à esquerda gera um sinal de transporte. Para um incremento, crie uma saída de transporte se uma entrada de transporte for recebida e o bit atual for 1 (desde então, ele será incrementado para o binário 10). Para decremento, a linha de transporte sinaliza um empréstimo , então uma saída de transporte é gerada quando há uma entrada de transporte (ou seja, empréstimo) e o bit atual é 0.

Uma parte da cadeia de incremento / decremento
A linha à direita atualiza o bit atual com um incremento ou decremento. O bit atual é alternado quando uma entrada de transporte está presente - essencialmente uma implementação XOR por meio de três portas NOR. Uma das dificuldades é o ajuste para BCD. Para a operação de incremento BCD, o transporte ocorre quando o dígito 9 é incrementado, e para a operação de decremento BCD, o dígito 0 diminui para 9 em vez do binário 1111.
O multiplexador gerencia as várias operações da bateria. Dependendo da operação, um transistor de passagem é ativado, selecionando o valor desejado. Por exemplo, para uma operação de incremento / decremento, o transistor superior seleciona a saída do circuito de incremento / decremento descrito acima. O transistor ativa o decodificador de instrução descrito anteriormente, que encontrou a instrução de incremento / decremento correspondente. Da mesma forma, um comando de deslocamento para a direita ativa o transistor de deslocamento para a direita aplicando n + 1 bits de bateria a cada uma das partes do acumulador para deslocar o valor.

Circuito para uma trava que armazena um bit da bateria e um multiplexador que seleciona a entrada para a bateria
A trava armazena um bit para o acumulador. Quando o transistor de retenção da bateria é ativado, as duas portas NOR formam um loop de retenção. Se, em vez disso, o transistor de carga da bateria for ativado, a bateria carrega o valor desejado do multiplexador. As linhas para limpar o bit n e definir o bit n permitem que os comandos alterem bits individuais do acumulador; o multiplexador então atualiza todos os bits do acumulador de uma vez.
Contador e endereçamento de programa
Outro grande bloco de cadeias é o contador de programa de 11 bits localizado no canto esquerdo inferior do Nanoprocessador. Também neste bloco há uma trava que armazena o endereço de retorno da sub-rotina e outra que armazena o contador do programa após a interrupção. Pense neles como uma pilha de um único elemento. O contador de software possui um dispositivo de incremento que é responsável por mover para o próximo comando. Ele também sabe como incrementar em dois de uma vez, permitindo que as instruções de desvio condicional ignorem duas instruções (tal dispositivo de incremento é implementado simplesmente aumentando o primeiro bit em vez do 0º). Para acelerar a operação do dispositivo de incremento, ele tem uma função de transferência; se todos os seis bits menos significativos forem 1, ele aumentará o 6º bit de uma vez, sem esperar que o transporte passe por todos os bits menos significativos.
Controle e frequência de relógio
A última parte do Nanoprocessador é o circuito de controle. Comparado com outros microprocessadores, o esquema de controle do Nanoprocessador parece quase trivial: o processador vai do relógio de solicitação ao relógio de execução e volta (com interrupções periódicas). O circuito de controle é apenas um par de flip-flops e portões, então não há muito a dizer sobre ele.
Conclusão
O diagrama abaixo mostra os principais blocos funcionais do Nanoprocessador. O nanoprocessador conseguiu encaixá-los muito bem, muito melhor do que eu esperaria da tecnologia desatualizada das venezianas de metal. A engenharia reversa mostra que esses blocos funcionais são implementados com circuitos simples, mas cuidadosamente projetados.
O nanoprocessador usava transistores de porta de metal, enquanto outros microprocessadores começaram a mudar para transistores de porta de silício por vários anos. A diferença pode parecer incompreensível, mas tem um efeito significativo na localização dos componentes: na fabricação de um transistor com portas de silício, é adicionada uma camada de polissilício com condutores. Isso torna muito mais fácil posicionar os componentes, pois você tem duas camadas de condutores à sua disposição que podem passar pela camada adjacente. Se você tiver apenas uma camada de metal, é muito mais difícil posicionar os componentes, pois os condutores ficam no caminho. Em outros chips, estudei que usava tecnologia de transistor de porta de metal,o layout dos componentes era nojento - um monte de fios emaranhados trazendo sinais para cada transistor mantinha a densidade dos transistores baixa. Por outro lado, os blocos de função do nanoprocessador são projetados com muito cuidado e todos os sinais funcionam perfeitamente. Há um pouco de espaço extra, por exemplo, para o barramento de dados, mas no geral estou impressionado com a densidade do layout do Nanoprocessador.

Componentes funcionais do nanoprocessador baseados no meu
Nanoprocessador de engenharia reversa - o processador é incomum. À primeira vista, até me pareceu um "processador falso", devido à falta de operações aritméticas básicas. No entanto, depois de estudá-lo com mais detalhes, ainda fiquei impressionado. Seu design simples permite que ele funcione mais rápido do que outros processadores da época. O conjunto de comandos pode fazer mais do que aparenta. A Hewlett-Packard usou o nanoprocessador em muitos de seus produtos nas décadas de 1970 e 1980, em funções mais complexas do que se poderia esperar, como análise de strings e execução de cálculos. Depois que suas máscaras forem publicadas, podemos aprender todos os segredos das cadeias graças às quais funcionava o Nanoprocessador.

Nanoprocessador (chip branco) como parte do módulo de temporização de precisão da Hewlett-Packard. Observe a tensão escrita à mão; cada chip exigia sua própria tensão de polarização.