Design de CPU muito simples no LogiSim


8

Atualmente, sou estudante do ensino médio e tenho interesse em engenharia elétrica / de computadores, especificamente no design de microprocessadores. Li o Code de Charles Petzold , e comecei a ler o Wikibook de design de microprocessador (que parece incompleto.) Ao ler Code , entendo a lógica básica por trás de uma CPU e comecei a criar uma no LogiSim. O capítulo 17 do código detalha a CPU que eu quero construir, mas os circuitos não possuem os principais componentes - sinais de clock e decodificação de instruções. Alguns dos sinais do relógio parecem bastante óbvios (o PC parece precisar de um sinal constante do relógio), mas outros (como travar os valores da RAM), tive que pensar e tentar trabalhar.

Eu posso construir um acumulador de trabalho (acho que não pode ser chamado com precisão de ALU, porque falta a parte L) que alterna entre adição e subtração com uma única entrada e entendo que isso é tudo o que preciso para a parte aritmética - uma vez que os opcodes de salto funcionem, posso implementar a multiplicação e a divisão no código. A parte com a qual estou lutando é a decodificação de instruções. Através de algumas pesquisas no Google, vejo que cada código de operação precisa ser interpretado como várias microinstruções, mas estou perdido quanto à forma como preciso que isso funcione. Atualmente, meu decodificador de instruções é apenas um circuito de análise combinacional com uma única saída binária para cada código de operação - 13 ao todo.

A maneira como o código funciona é que ele possui um valor de código de 8 bits (eu só uso o byte low-end) e, em seguida, dois valores separados de endereço de 8 bits que eu então combino para ser o endereço de 16 bits inserido na RAM. Para travar os valores, tenho um contador separado que conta até 10b e redefine para 00b. É a entrada do relógio para cada trava por sua vez (para as três travas, há a, bec, os segundos relógios têm a 1, enquanto b & c são 0, então b é 1 e 1 & c são 0, então c é um e 1 e b são 0, depois é redefinido). Mas, em instruções como ADD 000Ah, o PC salta para 000AH ... que deveria ser adicionado ao acumulador, mas na verdade é travado na trava de código e, em seguida, interpretado como o próximo código de operação, o que faz com que tudo aconteça louco.

Sinto que estou perdendo algumas informações importantes sobre decodificação de instruções e como preciso fazer sinais de relógio ...

Aqui estão os arquivos .circ do LogiSim: https://dl.dropboxusercontent.com/u/61676438/PetzoldMk5/8BitAdder.circ https://dl.dropboxusercontent.com/u/61676438/PetzoldMk5/8BitAdderSubtractor.circ https: // dl.dropboxusercontent.com/u/61676438/PetzoldMk5/8BitInverter.circ https://dl.dropboxusercontent.com/u/61676438/PetzoldMk5/8BitLatch.circ https://dl.dropboxusercontent.com/u/61676438/PetzoldMk5/8BitInverter.circ ID.circ https://dl.dropboxusercontent.com/u/61676438/PetzoldMk5/PetzoldMk5.circ

PetzoldMk5 é a CPU principal, contando com os outros arquivos a serem importados como bibliotecas.

Aqui está uma lista de códigos de operação (todos binários):

Load                 0001
Add                  0010
Add w/ Carry         0011
Sub                  0100
Sub w/ Borrow        0101
Jump                 0110
Jump w/ Carry        0111
Jump W/ 0            1000
Jump w/o C           1001
Jump W/o 0           1010
Store                1011
Halt                 1100
Reset                1101

1
Você deseja compartilhar seu arquivo .circ da CPU Logisim existente? E apenas para tornar a vida um pouco mais complicada, você deve ler e entender cuidadosamente a ajuda do Logisim, sob o título "Propagação de valor". Se você não tiver, já. (Você pode ter, dado todo o trabalho que você já aplicou. Fico feliz em saber que você aceita isso!) #
1178

@ Jonk obrigado pelas boas palavras. Editando a postagem com os arquivos .circ associados.
Will Hodges

São 6 arquivos, então? (Eu assumo isto é para Logisim 2.7.1, 2011?)
jonk

@jonk sim, é, em ambas as perguntas
Will Hodges

Como você está lidando com subtração? Você usa o / Q de uma trava de entrada para uma das entradas A / B da sua ALU e modifica a bagagem de mão? Ou algum outro método?
jonk

Respostas:


3

Odeio postar um "apenas link" como resposta, mas acho que você deve estar ciente do trabalho de Warren Toomey com CPUs no Logisim, pois provavelmente é exatamente o que você está procurando.

Ele tem alguns tutoriais construindo uma CPU razoavelmente simples aqui ...

http://minnie.tuhs.org/CompArch/Tutes/

E se isso não flutua no seu barco, ele tem uma CPU mais sofisticada aqui ...

http://minnie.tuhs.org/Programs/UcodeCPU/

... Tudo isso está bem explicado e tem downloads para arquivos .circ.


Outro ótimo / CPU CPU / computador DIY é o Magic-1, encontrado em http://www.homebrewcpu.com/ . Embora não seja feito no Logisim, está bastante bem documentado, incluindo fotos, esquemas e descrição. Também é mais do que apenas uma CPU em um simulador. Possui um compilador ANSI C, um sistema operacional e algum software. Também tem a vantagem distinta de ter sido realmente construído em hardware. De fato, atualmente está funcionando e servindo páginas da web!


Finalmente, o Elements of Computing Systems e o site associado nand2tetris.org são o recurso de informação recomendado como o número 1 para a criação de seu próprio computador desde o início, toda vez que eu o analiso . Muito (Todo?) Conteúdo é gratuito, acredito. O YouTube concordaria; muitas pessoas fizeram projetos a partir dessa fonte.


1
Ver o vídeo de Ben Eater em Youtbue sobre a construção de um computador com placa de 8 bits também é muito útil!
Francis Cugler

1

Acho que você está perdendo um aspecto essencial de como as ALUs funcionam. Normalmente, cada bit do acumulador é conectado a cada um dos vários blocos de funções por meio de um desmultiplexador. Usando um byte de comando, a função é selecionada e cada bit do acumulador é conectado à entrada adequada do bloco de funções. O tamanho do desmultiplexador determina quantas funções a ALU pode manipular. No meu exemplo muito rude mostrado abaixo, uma ALU com uma entrada de 4 bits pode fazer referência a 16 funções diferentes usando o desmultiplexador:

Conectando o acumulador a vários blocos funcionais dentro de uma ALU

Observe que na maioria das CPUs, esse design é otimizado em uma confusão de portas para reduzir a contagem de transistores.

Mais funções podem ser usadas com um registro de comando maior, mas isso também exigiria mais ciclos de clock para carregar o comando.

Eu recomendo a leitura do livro a seguir, se você quiser saber mais sobre o design digital: Fundamentos de Logic Design, 7a ed.


Essa resposta meio que confunde instruções com operações da ALU. Especificamente, esse desmultiplexador seria usado apenas para selecionar qual operação aritmética escolher para uma instrução aritmética. Você alimentaria o desmultiplexador com, digamos, 3 bits de uma instrução de 8 bits, para escolher qual operação aritmética. Você precisa de um mecanismo totalmente separado para decodificar e sequenciar as instruções em geral. Como um aparte, a maioria das CPUs que eu analisei não usa um desmultiplexador como este na ALU, mas usa uma bagunça otimizada de portas para executar a operação correta.
Ken Condestáveis

1
@KenShirriff Fiz algumas alterações para maior clareza. Sinta-se à vontade para fazer algumas edições como achar melhor.
Takide

1

Parece que você está no caminho certo.

Ao planejar suas micro instruções, você precisará definir claramente em sua mente o padrão de "tráfego" para sua movimentação de dados através de seus vários blocos. A realização de um ADD exigirá várias etapas. Se você possuir registros para os seus dois operandos da ALU, eles precisarão ser carregados da RAM ou de algum registro ou barramento. Se você possui um barramento interno compartilhado, pode ser necessário carregar um operando por vez. Depois de saber quais bytes (endereço, literal imediato, dados de RAM, ponteiro) precisam se mover para onde, planeje a ordem do movimento dos bytes através do (s) barramento (s) para dentro e para fora dos vários registradores. Você pode ficar paralisado e precisar adicionar um registro de retenção interno, porque algum valor intermediário deve ser preservado até a próxima etapa de micro-instrução.

Eu acho que o que você suspeita está faltando é a complexidade necessária para a lógica pegar a instrução ou o código de operação e traduzi-la em vários estados dentro da sua CPU. Pode ser complexo, mas é possível criar uma máquina de estado um tanto simples e expandi-la com conceitos lógicos básicos.

Por exemplo, digamos que você esteja criando as etapas de micro-instruções para uma operação MOVE. Isso pode ser descrito livremente em 3 etapas: 1) Assegurar o conteúdo do registro de origem no barramento interno, 2) disparar o relógio de gravação do registrador de destino, 3) Anular o conteúdo do registro de origem do barramento interno. As etapas 1) a 3) descrevem o tempo para uma ativação de saída de registro (OE) e uma ativação de gravação de registro (WE) que podem ser seletivamente distribuídas para qualquer registro de origem e qualquer registro de destino conectado ao barramento interno compartilhado com desmultiplexadores.

Se você não tem muita prática na criação de máquinas de estado finito, pode ser útil examinar as diferentes abordagens para fornecer a você outro elemento básico para gerar os sinais de controle do seu micro-seqüenciador.

Fique com ele. A quantidade de conhecimento que você adquirir será fenomenal. E espero que você se divirta muito.

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.