Você está na página 1de 13

Centro Federal de Educação Tecnológica de Minas Gerais

Engenharia de Computação
Laboratório de Arquitetura e Organização de Computadores I
1º Trabalho Prático. Data de Entrega: 08/02. Valor: 20 pontos.

Implementação de um processador simples

A figura 1 apresenta um sistema digital que contém registradores de 16 bits, um multiplexador,


um somador/subtrator, um contador e uma unidade de controle. Neste sistema os dados
são alimentados através da entrada DIN. Estes dados podem ser encaminhados através do
multiplexador em vários registradores, R0, …, R7 e A. O multiplexador também permite que
dados sejam transferidos de um registrador para outro. A saída do multiplexador é chamada de
bus, que nada mais é que um barramento, ou seja, um conjunto de conexões que permite que os
dados sejam transferidos de uma parte do sistema para outra.

A adição ou subtração é realizada pelo uso do multiplexador num primeiro momento, permitindo
a cópia do primeiro operando, um número de 16 bits, para o registrador A. Realizado este passo,
o segundo número de 16 bits é colocado no barramento, o somador/subtrator realiza a operação
e o resultado é carregado no registrador G. Finalmente o dado em G podem ser transferido para
algum dos outros registradores.
Figura 1

O sistema pode realizar diferentes operações em cada ciclo de clock de acordo com a
determinação da unidade de controle. Esta determina quando um dado é colocado no barramento
e determina também em qual dos registradores o dado deve ser escrito. Exemplificando: se a
unidade de controle atribui os sinais R0out e Ain, então o multiplexador deverá colocar o conteúdo
do registrador R0 no barramento e este dado deverá ser carregado na próxima borda ativa de
clock no registrador A.

Um sistema como este é geralmente chamado de processador. Ele executa operações


especificadas na forma de instruções. A tabela 1 lista as instruções que este processador suporta.
A coluna da esquerda apresenta o nome de uma instrução e seus operandos. RX ← [RY]
significa que o conteúdo do registrador RY será carregado no registrador RX. A instrução
mv (move) permite que determinado dado seja copiado de um registrador para outro. Para a
instrução mvi (move immediate) a expressão RX ← D indica que uma constante de 16 bits será
carregada no registrador RX.
Operação Função realizada
mv Rx, Ry RX ← [RY]
mvi Rx, #D Rx ← D
add Rx, Ry RX ← [RX] + [RY]
sub Rx, Ry RX ← [RX] - [RY]
Tabela 1

Cada instrução pode ser armazenada no registrador IR e é codificada da seguinte forma: Palavra
de 9 bits IIIXXXYYY onde III representa o opcode, XXX o endereço do registrador X e YYY o
endereço do registrador Y.

Apesar de serem necessários somente 2 bits para codificar as 4 instruções, serão usados 3 bits
para possam ser adicionados outras instruções no futuro. Dado o comprimento da instrução, é
necessário que a entrada de IR seja ligada a apenas 9 dos 16 bits de DIN conforme indicado na
figura 1. Para a instrução mvi o campo YYY não tem significado e o imediato, #D é fornecido na
entrada DIN logo após a instrução mvi ser armazenada no registrador IR.

Algumas instruções, como a soma e a subtração levam mais de um ciclo de clock para completar
porque muitas transferências tem de ser feitas utilizando-se o barramento. O processador começa
a execução da instrução na porta DIN quando o sinal RUN é ativado. O processador por sua vez
ativa o sinal DONE quando a instrução é terminada. A tabela 2 indica os sinais de controle que
são atribuídos a cada passo de tempo para a implementação da tabela 1. Note que o único sinal
de controle atribuído no passo 0 é o IRin e que este passo não é apresentado na tabela.

T1 T2 T3
(mv): I0 RYout, RXin, Done
(mvi): I1 DINout, RXin, Done
(add): I2 RXout, Ain RYout, Gin Gout, RXin, Done
(sub): I3 Rxout, Ain RYout, Gin, AddSub Gout, Rxin, Done
Tabela 2

Parte I

Implemente o processador apresentado na figura 1 seguindo os passos descritos abaixo e usando


o código Verilog apresentado adiante:

1. Crie um novo projeto do Quartus II para esta implementação.


2. Realize uma simulação funcional para verificar se o código está correto. Um exemplo
de saída esperada para a simulação é apresentada na figura 3. É mostrado o valor (2000)
16 da entrada DIN sendo carregado no registrador IR aos 30 ns. Este padrão representa a

instrução mvi R0,#D, onde o valor D = 5 é carregado em R0 na borda de clock aos 50


ns. A simulação então apresenta a instrução mv R1, R0 aos 90 ns, add R0, R1 ao 110 ns
e sub R0, R0 aos 190 ns. Note que a saída da simulação apresenta DIN com um número
hexadecimal de 4 dígitos e que o conteúdo de IR é um número octal de 3 dígitos.
Figura 3

// Estrutura para uso como ponto de partida da implementação

module proc (DIN, Resetn, Clock, Run, Done, BusWires);


input [15:0] DIN;
input Resetn, Clock, Run;
output Done;
output [15:0] BusWires;
. . . declare variables
wire Clear = . . .
upcount Tstep (Clear, Clock, Tstep_Q);
assign I = IR[1:3];
dec3to8 decX (IR[4:6], 1’b1, Xreg);
dec3to8 decY (IR[7:9], 1’b1, Yreg);
always @(Tstep_Q or I or Xreg or Yreg)
begin
. . . specify initial values
case (Tstep_Q)
2’b00: // store DIN in IR in time step 0
begin
IRin = 1’b1;
end
2’b01: //define signals in time step 1
case (I)
...
endcase
2’b10: //define signals in time step 2
case (I)
...
endcase
2’b11: //define signals in time step 3
case (I)
...
endcase
endcase
end
regn reg_0 (BusWires, Rin[0], Clock, R0);
. . . instantiate other registers and the adder/subtracter unit
. . . define the bus
endmodule

module upcount(Clear, Clock, Q);


input Clear, Clock;
output [1:0] Q;
reg [1:0] Q;
always @(posedge Clock)
if (Clear)
Q <= 2’b0;
else
Q <= Q + 1’b1;
endmodule
module dec3to8(W, En, Y);
input [2:0] W;
input En;
output [0:7] Y;
reg [0:7] Y;
always @(W or En)
begin
if (En == 1)
case (W)
3’b000: Y = 8’b10000000;
3’b001: Y = 8’b01000000;
3’b010: Y = 8’b00100000;
3’b011: Y = 8’b00010000;
3’b100: Y = 8’b00001000;
3’b101: Y = 8’b00000100;
3’b110: Y = 8’b00000010;
3’b111: Y = 8’b00000001;
endcase
else
Y = 8’b00000000;
end
endmodule
module regn(R, Rin, Clock, Q);
parameter n = 16;
input [n-1:0] R;
input Rin, Clock;
output [n-1:0] Q;
reg [n-1:0] Q;
always @(posedge Clock)
if (Rin)
Q <= R;
endmodule

Parte II

Nesta parte o processador implementado na parte I deverá ser conectado à um módulo de


memória e um contador de acordo com o circuito apresentado na figura 4. O contador é usado
para ler o conteúdo de sucessivos endereços de memória e os dados providos serão o fluxo de
instruções para o processador. Para simplificação do projeto e do teste o cirtuito terá 2 sinais
separados de clock, Pclock e Mclock.

Figura 4
1. Crie um novo projeto no Quartus II para testar o circuito.
2. Crie um arquivo Verilog que instancie o processador, a memória e o contador. Use o
Quartus II MegaWizard Plug-In para criar um módulo de memória a partir da biblioteca
de módulos parametrizáveis da Altera. O módulo está na categoria Memory Compiler e
chama-se ROM:1-PORT. Siga as instruções do wizard para criar a memória que tenha uma
porta de leitura de dados de 16 bits e 32 posições diferentes.
Para inserir instruções na memória é necessário a especificação de valores iniciais. Isto poderá
ser feito no wizard executado no momento da criação do módulo de memória através da
indicação de um arquivo do tipo MIF (memory initialization file). Use o help do Quartus para
aprender sobre o formato do MIF e como criar um arquivo que tenha instruções suficientes para
testar o seu circuito.
3. Faça um simulação funcional para testar o circuito.
Figura 5
Figura 6

Parte III

As partes anteriores deste projeto apresentaram a estrutura de um processador simples. A parte


I apresentou o projeto e na parte II o processador foi conectado a um contador externo e a uma
unidade de memória. Nesta nova etapa serão descritas outras partes do projeto deste processador.
O primeiro passo é a extensão do processador de maneira que um contador externo não seja
necessário e que e adição da habilidade de realização de operações de leitura e escrita usando
dispositivos de memória. Serão adicionadas três novos tipos de instruções ao processador
conforme apresentado na tabela 1. A instrução ld (load) carrega no registrador RX o dado
encontrado na memória na posição encontrada no registrador RY. A instrução st (store)
armazena o dado contido no registrador RX na posição de memória cujo endereço está no
registrador RY. Finalmente, a instrução mvnz (move if not zero) permite que a operação mv seja
executada somente sob a condição de que o conteúdo do registrador G não seja igual à 0.

Operação Função realizada


ld Rx, [Ry] RX ← [[RY]]
st Rx, [Ry] [Ry] ← [Rx]
mvnz Rx, Ry if G != 0, Rx ← [RY]

Tabela 1

Um diagrama esquemático do processador aprimorado é dado na figura 7. Os registradores R0


a R6 são os mesmos da implementação do processador simples mas o R7 foi substituido por
um contador. Este é usado para prover o endereço de memória em que o processador busca sua
instrução e será citado como o contador do programa (PC). Quando o sinal reset do processador
é ativado o PC é setado com o valor 0. No início de cada instrução (no passo de tempo 0) o
conteúdo do PC é usado como um endereço para a leitura de uma instrução encontrada na
memória. A instrução é então armazenada no IR e o PC é automaticamente incrementado para
o endereço da próxima instrução (no caso de um mvi o PC provê o endereço do dado e então é
incrementado novamente).

A unidade de controle imprementa o PC através do uso de um sinal incr_PC que nada mais é do
que um enable para o próprio contador. Também é possível caregar diretamente o endereço no
PC (R7) fazendo com que o processador execute uma instrução mv ou mvi na qual o registrador
de destino seja especificado com R7. Neste caso a unidade de controle realiza um carregamento
paralelo no contador. Desta maneira o processador pode executar instruções de qualquer
endereço da memória. De maneira similar o conteúdo do PC pode ser copiado em qualquer outro
registrador através do uso da instrução mv. Um exemplo de código que utilize o registrador PC
para a implementação de um loop é apresentado abaixo, os textos depois do caracter "%" são
apenas comentários. A instrução mv R5, R7 coloca no R5 o endereço de memória da instrução
sub R4, R2. Então a instrução mvnz R7, R5 provoca a execução da instrução sub até que o valor
em R4 seja 0.

mvi R2,#1
mvi R4,#10000000 % binary delay value
mv R5,R7 % save address of next instruction
sub R4,R2 % decrement delay count
mvnz R7,R5 % continue subtracting until delay count gets to 0

Figura 1
A figura 1 mostra dois registradores no processador que são usados para transferencia de dados.
O registrador ADDR é usado para enviar o endereço à um dispositivo externo como um módulo
de memória, por exemplo, e o registrador DOUT é usado pelo processador para prover os dados
que serão armazenados fora do processador. Um dos usos do registrador ADDR é para a leitura
ou busca de instruções da memória; quando o processador precisa buscar uma instrução, o
conteúdo do PC (R7) é transferido no barramento e carrehado em ADDR. Este endereço é então
provido à memória. Além da busca de instruções, o processador pode ler dados de qualquer
posição de memória através da utilização deste mesmo registrador ADDR. Tanto dados quanto
instruções são recebidos no processador pela entrada DIN. O processador pode escrever dados
em um dispositivo externo através do armazenamento do endereço no registrador ADDR, do
armazenamento dos dados no registrador DOUT e da habilitação do sinal W (write).

A figura 2 ilustra como este processador aprimorado é conectado à memória e a outros


dispositivos. A unidade de memória da figura suporta operações de leitura e escrita, possui
entrada de dados e de endereço e também uma entrada que ative a escrita. Além destes sinais,
a memória possui uma entrada de clock porque os dados são carregados quando há uma borda
ativa do sinal de clock. Este tipo de memória é geralmente chamada de synchronous random
access memory (synchronous RAM). A figura 2 inclui também um registrador de 16-bits que
pode ser usado para armazenar dados vindos do processador e que por sua vez é conectado à um
conjunto de leds que permitem a apresentação dos dados na placa DE2. Para que seja possivel
a seleção da unidade de memória ou do registrador quando ocorre uma operação de escrita, este
circuito inclui algumas portas lógicas que realizam a decodificação do endereço; se as linhas
A15A14A13A12 = 0000 então será escrito na posição de memória dado pelo endereço na linhas
de indíce mais baixos. A figura 2 apresenta n linhas linhas de endereço conectadas à memória;
para este trabalho uma memória com 128 palavras é suficiente, o que implica que n=7 e que a
porta de endereço da memória é ligada às linhas A6 ... A0. Quando o endereço começado por
A15A14A13A12 = 0001, então os dados escritos no processador serão carregados no registrador
que tem sua saída ligada nos leds.
Figura 2

Você também pode gostar