UNIVERSIDADE REGIONAL DE BLUMENAU M++ Implementação de um microprocessador simples utilizando simulador de circuitos digitais (Digital Works) JONATHAN MANOEL BORGES Blumenau, 20 de janeiro de 2006. Visão Externa da M++ 4 portas de entrada (I0 e I3); 4 portas de saída (O0 a O3); Entrada de sinais de Clock e Reset; Indicativo que execução de uma instrução terminou (Fim Inst); Controle da Memória de Dados e Pilha (RAMcs, RAMwr, RAMrd); Controle da Memória do Programa (ROMrd, ROMcs); Barramento de endereço da Memória de Dados e Pilha (256 - 8bit); Barramento de endereço da Memória de Programa (64k - 16bit); Barramento de Dados Observações Embora o barramento de endereço da memória de programa seja de 16 bits, o Digital Works possui no máximo, memórias de 14 bits. Ou seja, os dois últimos bits nunca serão utilizados neste simulador; Note que o barramento de dados possui 16 saídas. Na verdade o barramento de dados é de 8 bits, porém o Digital Works não permite que um mesmo pino de um circuito seja utilizado tanto para entrada como para saída. Desta forma, 8 dos 16 bits são para entrada e os 8 restante para saída. Deve-se ligar os pinos no barramento de dados das memórias de programa e dados e pilha; Visão Interna da M++ Barramento de Dados O barramento de dados é compartilhado por todos os componentes da M++. Todos os componentes que utilizam o barramento utilizam a porta TriState para utilizar o barramento. Somente um componente de cada vez pode utilizar o componente. Barramento de Endereços Possui dois barramentos de endereço: barramento para a memória de dados e pilha, e para a memória de programa. O barramento da memória de dados e pilha possui dois componentes auxiliares. O registrado DIR, alterado pelo programa do usuário, e o registrado SP. Este último é utilizado para o controle de pilha. Enquanto o DIR pode receber qualquer valor, o SP apenas incrementa ou decrementa o seu valor. Acumulador É utilizado em todas as operações lógicas e aritméticas. Possui conexão direta (sem TriState) com a ULA. Sinal Car carrega o valor do barramento de dados no acumulador. Sinal Enable coloca o valor do acumulador no barramento de dados. Buffer para operação com a ULA Utilizado exclusivamente para operações com a ULA. ULA Realiza as operações lógicas e aritméticas entre dois operandos (A e B, respectivamente Acumulador e Buffer). Sinais de controle S0, S1 e S2 selecionam a operação a ser realizada conforme a lista a sequir: 000 - ADD 001 - SUB 010 - AND 011 - OR 100 - XOR 101 - NOT 110 - BYPASS 111 – INC Os flags FC (indica estouro na operação) e FZ (indica que o resultado da operação é zero) são atualizados assim que o sinal de controle Enable da ULA é ativado, o qual coloca o valor do resultado da operação no barramento de dados. Banco de Registradores Possui 4 registradores de propósito geral, além do acumulador. Os sinais S0 e S1 selecionam o registrador. Sinal Reset zera todos os registradores. Sinal Enable e joga o valor do registrador selecionado no barramento de dados. Sinal Car carrega o valor do barramento de dados no registrador selecionado. Banco de portas de entrada Possui 4 portas de entrada e 4 portas de saída. Sinais S0 e S1 selecionam a porta. Sinal Enable coloca o valor da porta de entrada selecionada no barramento de dados. Sinal Car grava o valor do barramento de dados na porta de saída selecionada. Módulo de Controle RI – registrado de instrução Registrador de 8 bits que armazena a instrução a ser executada. Divisão das funções de cada um dos bits do registrador Os primeiros 3 bits mais significativos são para escolher a operação a ser realizada pela ULA (veja o tópico ULA acima para ver as operações da ULA); Os dois bits seguintes são utilizados para selecionar o Registrador ou a Porta do banco de portas de entrada e saída. Os 3 bits menos significativos são para selecionar o tipo de operação. Estes são decodificados e resultam na posição da memória de controle microprogramada que inicias as micro-instruções do tipo de operação desejado. (veja os tipos de operações adiante). IC - contador de microinstrução Este registrador indica a posição da memória de controle microprogramada que deve ser acionada para gerar os sinais de controle. A cada sinal de clock, o IC é incrementado. No início da execução de uma instrução, após a decodificação da instrução, o IC recebe o valor da posição do início da instrução na memória microprogramada . Memória de decodificação de Instrução Nesta são armazenados a posição do início da instrução (primeira microinstrução) de todas as instruções da M+. Memória de controle microprogramada Nesta são armazenados os sinais de controle para a execução das instruções. Sinais de Controle +--------------------------+ | 01 - ICres | | | | 02 - ICresC | | 03 - ICresZ | | 04 - RIcar | | 05 - SelRI | | 06 - Higth Decoder | | | | 07 - ROMrd | | | | 08 - ROMcs | | 09 - PCHbus | | 10 - PHLbus | | 11 - PCHcar | | 12 - PCLcar | | 13 - SeldataPC | | | | 14 - DIRcar | | | | 15 - SPcar | | 16 - SPinc/dec | | 17 - SelSP | | | | 18 - ULAbus | | 19 - BUFcar | | | | 20 - ACbus | | 21 - ACcar | | | | 22 - REGbus | | 23 - REGcar | | | | 24 - RAMrd | | 25 - RAMwr | | 26 - RAMcs | | | | 27 - INbus | | 28 - OUTcar | +--------------------------+ - internos do módulo de controle - externos do módulo de controle - registradores especiais de endereçamento de memória ram - ula - acumulador - registradores - memória de dados (RAM) - entrada/saída de dados Utilize o software CompMemoM++.exe para gerar os sinais de controle para as memórias de controle e para memória de decoficiação de instrução. Programa contento os sinais de controle da M++ // BUSCA DE INSTRUÇÃO Vazio; ROMrd, ROMcs; RIcar, SelRI, PCHcar, PCLcar; - AC * AC -> AC ACbus; BUFcar; ULAbus; ACcar; ICres; - AC * AC -> REG ACbus; BUFcar; ULAbus; REGcar; ICres; - AC * AC -> RAM ROMrd, ROMcs; DIRcar, PCHcar, PCLcar; ACbus; BUFcar; ULAbus; RAMwr, RAMcs; ICres; - AC * AC -> OUT ACbus; BUFcar; ULAbus; OUTcar; ICres; - AC * REG -> AC REGbus; BUFcar; ULAbus; ACcar; ICres; - AC * RAM -> AC ROMrd, ROMcs; DIRcar, PCHcar, PCLcar; RAMrd, RAMcs; BUFcar; ULAbus; ACcar; ICres; - AC * IN -> AC INbus; BUFcar; ULAbus; ACcar; ICres; - Higth Decoder ROMrd, ROMcs; RIcar, SelRI, PCHcar, PCLcar, HigthDecoder; - AC * ROM -> AC ROMrd, ROMcs; BUFcar, PCHcar, PCLcar; ULAbus; ACcar; ICres; - AC * ROM -> REG ROMrd, ROMcs; BUFcar, PCHcar, PCLcar; ULAbus; REGcar; ICres; - AC * ROM -> RAM ROMrd, ROMcs; BUFcar, PCHcar, PCLcar; ROMrd, ROMcs; DIRcar, PCHcar, PCLcar; ULAbus; RAMwr, RAMcs; ICres; - JMP ROMrd, ROMcs, SPcar, pilha SelSP, RAMwr, RAMcs, ROMrd, ROMcs, SPcar, SelSP, RAMwr, RAMcs; SelSP, RAMrd, RAMcs, // retira da pilha PCLcar, SPcar; SelSP, RAMrd, RAMcs, PCHcar, SPcar; ICres; - JMPC SPincdec; PCHcar, PCLcar; SPincdec; SeldataPC; SeldataPC; // poe na ICresC; ROMrd, ROMcs, SPcar, pilha SelSP, RAMwr, RAMcs, ROMrd, ROMcs, SPcar, SelSP, RAMwr, RAMcs; SelSP, RAMrd, RAMcs, // retira da pilha PCLcar, SPcar; SelSP, RAMrd, RAMcs, PCHcar, SPcar; ICres; - JMPZ ICresZ; ROMrd, ROMcs, SPcar, pilha SelSP, RAMwr, RAMcs, ROMrd, ROMcs, SPcar, SelSP, RAMwr, RAMcs; SelSP, RAMrd, RAMcs, // retira da pilha PCLcar, SPcar; SelSP, RAMrd, RAMcs, PCHcar, SPcar; ICres; SPincdec; // poe na PCHcar, PCLcar; SPincdec; SeldataPC; SeldataPC; SPincdec; // poe na PCHcar, PCLcar; SPincdec; SeldataPC; SeldataPC; - CALL PCHbus, SPcar, SPincdec; // guarda endereço atual na pilha SelSP, RAMwr, RAMcs; PCLbus, SPcar, SPincdec; SelSP, RAMwr, RAMcs; ROMrd, ROMcs, SPcar, SPincdec; // poe na pilha SelSP, RAMwr, RAMcs, PCHcar, PCLcar; ROMrd, ROMcs, SPcar, SPincdec; SelSP, RAMwr, RAMcs; SelSP, RAMrd, RAMcs, SeldataPC; // retira da pilha PCLcar, SPcar; SelSP, RAMrd, RAMcs, SeldataPC; PCHcar, SPcar; ICres; - RET SelSP, RAMrd, RAMcs, SeldataPC; // retira da pilha PCLcar, SPcar; SelSP, RAMrd, RAMcs, SeldataPC; PCHcar, SPcar; ICres; Instruções da M++ Utilize o software AssemblerM++.exe para fazer seus programas na M++. Após compilar e gerar o arquivo objeto, carregue-o na memória de programa. ADD <tipo> SUB <tipo> AND <tipo> OR <tipo> XOR <tipo> NOT <tipo> MOV <tipo> INC <tipo> JMP <rend> JMPC <rend> JMPZ <rend> CALL <rend> RET; <rend> = Endereço 16bits (de #0000 a #FFFF) ou label Exemplo label: inicio: ADD A, A; JMP inicio; <tipo> = A , A A , registrador (B,C,D,E) A , RAM (RAM = Endereço de 8bits #00 a #FF) A, OUT (OUT = OUT0 até OUT3) IN , A registrado , A RAM , A (RAM = endereço de 8 bits) IN , A ROM , A ROM, registrador ROM ,RAM Observação No <tipo>, o primeiro campo (antes da vírgula) indica o operando que será calculado com o acumulador; O segundo campo (após a vírgula) indica onde será gravado o resultado da operação.