ufpecin.ufpe.br/~dllaa/relatorio.doc · web view- centro de informÁtica - profa. dra. edna...
TRANSCRIPT
UNIVERSIDADE FEDERAL DE PERNAMBUCO
- CENTRO DE INFORMÁTICA -
PROFA. DRA. EDNA NATIVIDADE BARROS
CADEIRA DE INFRA-ESTRUTURA DE HARDWARE
Instruction
Registers
Write
register
Read
data1
Read
data2
Read
register1
Read
register2
Write
data
RegWrite
Instruction
Registers
Write
register
Read
data1
Read
data2
Read
register1
Read
register2
Write
data
RegWrite
RELATÓRIO DE DESENVOLVIMENTO:
CPU ARQUITETURA MIPS, 32 BITS
Sumário
1.Equipe de desenvolvimento
2.Concepção do Projeto
2.1 Introdução
2.2 Objetivos
2.3 Recursos Utilizados
2.3.1 Recursos Humanos
2.3.2 Recursos de Software
2.3.3 Recursos de Hardware
3.Especificação do Projeto
3.1 Repertório de Instruções
3.2 Formato das Instruções
3.2.1 Formato F1
3.2.2 Formato F2
3.2.3 Formato F3
4.Unidade de Processamento
4.1 Módulos concedidos
4.1.1 Memória 256 bytes
4.1.2Banco de Registradores
4.1.3Registrador de Instruções
4.1.4Registrador de Deslocamento
4.1.5Unidade Lógica e Aritmética
4.1.6 Registrador comum de dados, 32 bits
4.1.7 RegistradorDesl
4.2 Módulos Desenvolvidos:
4.2.1 Desl2vezes26
4.2.2 Desl2vezes32
4.2.3 ExtensorLUI
4.2.4 Extensor1
4.2.5 Extensor5
4.2.6 Extensor8
4.2.7 Extensor16
4.2.8 StoreBH
4.2.9 MultDiv
4.3 Módulos Auxiliares
4.3.1 mux21
4.3.2 Mux21Cond
4.3.3 mux2_Ndesl
4.3.4 mux21Ext8
4.3.5 mux41
4.3.6 mux41_RegWrite
4.3.7 mux41Ext16
4.3.8 mux81
4.4 Mapeamento da Unidade de Processamento
4.4.1 Codificação do Mapeamento da CPU
4.4.2 Unidade de Controle
5. Referências
1.Equipe de desenvolvimento
__________________________________Rebeka Gomes de Oliveira
- Ciências da Computação
__________________________________
Durval Augusto Lira Queiroz dos Santos
< [email protected] > - Ciências da Computação
__________________________________
David Levy Lucena Alves Aragão
< [email protected] > - Ciências da Computação
__________________________________
Viviane Eugênia Siqueira de Souza
< [email protected] > - Ciências da Computação
2. Concepção do Projeto
2.1 Introdução
O projeto aqui apresentado refere-se à implementação de uma unidade central de processamento de 32 bits, baseada na arquitetura MIPS. Para o desenvolvimento deste projeto fez-se uso da ferramenta QUARTUS II 3.0 da Altera, utilizando a linguagem VHDL (Very High Speed Integrated Circuit Hardware Description Language), a qual descreve o comportamento e a arquitetura do hardware.
A arquitetura MIPS tem sido usada em larga escala por empresas de grande porte da área de sistemas embarcados como BroadCom, Cisco, Sony, NEC, Phillips e Toshiba. Como exemplo A MIPS Technologies, uma das líderes da indústria de arquitetura de processadores para aplicações residenciais e comerciais, anunciou ontem que a arquitertura do seu processador MIPS64 foi licenciada pela Sony Computer Entertainment Inc. (SCEI). Como já é fato, a SCEI sempre foi uma das maiores usuárias da tecnologia MIPS, usada largamente nos produtos da série PlayStation. O PlayStation 2, por exemplo, possui dois processadores desse tipo, incluindo o EmotionEngine de 128-Bits.
Uma das maiores características do processador MIPS é a regularidade, fator que contribui para sua relativa simplicidade.
Essa simplicidade da arquitetura MIPS, um reconhecimento no âmbito comercial, fazendo com que vertentes comerciais façam relevantes investimentos no tocante a desenvolvimentos baseados na mesma.
Dentre outras, algumas caracteristicas pode-se ser ressaltadas, tais como:viabilidade econômica, baixo consumo de potência, eficiência em aplicações pesadas de software e compatibilidade com sistemas de tempo real.
Portanto, este material apesar da natureza acadêmica, reflete uma realidade que pode ser aproveitada num contexto comercial.
2.2 Objetivos
O seguinte projeto, é referente à implementação de um processador MIPS, requerido para avaliação da disciplina de Graduação Infra Estrutura de Hardware, ministrada pela professora Dra. Edna Natividade Barros.
O desenvolvimento do mesmo possibilita o aprendizado, na prática, de uma tecnologia brevemente elucidada na introdução. E, através desse relatório, são apresentadas de maneira detalhada todas as atividades realizadas, bem como os componentes desenvolvidos. É também detalhada a maneira com a qual o processador funciona e seus principais fundamentos..
2.3 Recursos utilizados
2.3.1- Recursos Humanos:
O pessoal alocado para o desenvolvimento do projeto contemplou a prof. Dra. Edna Natividade Barros, com o acompanhamentos periodicos, o monitor Cássio e a seguinte equipe de graduandos em Ciências da Computação:
Rebeka Gomes de Oliveira
Viviane Souza
David Aragão
Durval Augusto Lira
2.3.2 - Recursos de Software:
Microsoft Windows XP Professional - Microsoft Word
Quartus II 3.0
3.Especificação do Projeto
O trabalho consiste na implementação de um Sistema que simule uma CPU,na arquitetura MIPS. O sistema consiste de 32 registradores de 32 bits cada, organizados em uma estrutura a qual se convencionou chamar Banco de Registradores. É fornecido um componente de Memória, com a capacidade de armazenamento de 256 bytes; a palavra de processamento no sistema é um vetor de 32 bits; todas as instruções com que trabalha o processador têm comprimento de 32 bits; a entidade a ser produzida deve processar números de 32 bits, escritos na notação complemento a dois; deve haver suporte a tratamento de exceções; deve haver suporte a rotinas reentrantes e recursivas por meio de utilização do apontador da pilha.
A parte que começa a partir de agora, considerará todos os aspectos mencionados na sucinta descrição de acima. Imediatamente a seguir, foi colocada uma descrição particular e pormenorizada de cada instrução implementada pela unidade central de processamento. Logo após, os formatos de instrução permitidos são especificados em detalhes, contribuindo positivamente especificação da atividade realizada.
3.1Repertório de Instruções
O repertório de instruções a ser implementado é um subconjunto da definição amplamente conhecida do MIPS. Concentra-se nas instruções básicas de referência à memória, operações lógico-aritméticas, desvio e deslocamento. Foram exigidas as operações de multiplicação e divisão para inteiros, não se tornando obrigatório, porém, o suporte ao trabalho com números de ponto-flutuante. As tabelas abaixo apresentam de forma breve o conjunto de instruções em consideração. Em sua estrutura, é apresentado o nome da instrução, seu mnemônico assembly para a maioria dos compiladores de linguagem de máquina, o resumo de sua atividade em notação matemática informal e a descrição breve de sua atuação em linguagem humana escrita.
Descrição geral das instruções implementadas
No Operation
nop: no operation
Executa nenhuma operação por ocasião de sua chamada. Durante um ciclo inteiro de relógio, o dispositivo permanece inerte. Útil em diversos contextos, é instrução fundamental, presente no desenvolvimento de qualquer processador.
Load Word
Lw reg, desl(reg_base): reg = (Memory[reg_base + desl])
Carrega o conteúdo de memória à posição indicada pelo conteúdo do registrador base somado do deslocamento passado como constante no registrador cujo número é especificado.
Store Word
sw reg, desl(reg_base): Memory[reg_base + desl] = reg
Armazena o conteúdo do registrador cujo número é especificado na posição de memória indicada pelo conteúdo do registrador base somado do deslocamento passado como constante.
Load Byte
lb reg, desl(reg_base): reg[7-0] = (Memory[reg_base + desl][7-0])
Carrega byte mais significativo do conteúdo de memória à posição indicada pelo conteúdo do registrador base somado do deslocamento passado como constante no registrador cujo número é especificado.
Load Half
lh reg, desl(reg_base): reg[15-0] = (Memory[reg_base + desl][15-0])
Carrega a meia palavra mais significativa do conteúdo de memória à posição indicada pelo conteúdo do registrador base somado do deslocamento passado como constante no registrador cujo número é especificado.
Store Byte
sb reg, desl(reg_base): Memory[reg_base + desl][7-0] = reg[7-0]
Armazena o byte mais significativo do conteúdo do registrador cujo número é especificado na posição de memória indicada pelo conteúdo do registrador base somado do deslocamento passado como constante.
Store Half
sh reg, desl(reg_base): Memory[reg_base + desl][15-0] = reg[15-0]
Armazena a meia palavra mais significativa do conteúdo do registrador cujo número é especificado na posição de memória indicada pelo conteúdo do registrador base somado do deslocamento passado como constante.
Load Upper Immediate
Lui reg, constante: reg[31-16] = constante
Carrega o valor constante de 16 bits passado como parâmetro na metade mais significativa do registrador cujo número é indicado.
Move High
mfhi rd: rd = (reg_hi)
Move o conteúdo do registrador específico REG_HI, de 32 bits, para o registrador cujo número é indicado como parâmetro da instrução.
Move Low
mflo rd: rd = (reg_lo)
Move o conteúdo do registrador específico REG_LO, de 32 bits, para o registrador cujo número é indicado como parâmetro da instrução.
Addition
add regi, regj, regk: regi = (regj) + (regk)
Coloca no registrador cujo número é passado inicialmente, o resultado da soma do conteúdo dos registradores cujos números são indicados em posição posterior. A Unidade de Controle é sensível ao caso de estouro de caixa, conhecido pela expressão inglesa overflow.
Subtraction
sub regi, regj, regk: regi = (regj) - (regk)
Coloca no registrador cujo número é passado inicialmente, o resultado da operação de subtração entre o conteúdo dos registradores cujos números são indicados em posição posterior. A Unidade de Controle é sensível ao caso de estouro de caixa, conhecido pela expressão inglesa overflow.
Xor Operation
xor regi, regj, regk: regi = (regj) xor (regk)
Coloca no registrador cujo número é passado inicialmente, o resultado da operação de OU exclusivo lógico entre o conteúdo dos registradores cujos números são indicados em posição posterior.
And Operation
and regi, regj, regk: regi = (regj) and (regk)
Coloca no registrador cujo número é passado inicialmente, o resultado da operação de AND lógico entre o conteúdo dos registradores cujos números são indicados em posição posterior.
Addition Unsigned
addu regi, regj, regk: regi = (regj) + (regk)
Coloca no registrador cujo número é passado inicialmente, o resultado da operação aritmética de adição entre o conteúdo dos registradores cujos números são indicados em posição posterior. A Unidade de Controle não considera o caso de estouro de caixa, conhecido pela expressão inglesa overflow.
Subtraction Unsigned
subu regi, regj, regk: regi = (regj) - (regk)
Coloca no registrador cujo número é passado inicialmente, o resultado da operação aritmética de subtração entre o conteúdo dos registradores cujos números são indicados em posição posterior. A Unidade de Controle não considera o caso de estouro de caixa, overflow.
Addition Immediate
addi regi, regj, constant: regi = (regj) + constant
Coloca no registrador cujo número é passado inicialmente, o resultado da operação aritmética de adição entre o conteúdo do registrador passado em segundo lugar e o valor constante passado como parâmetro da instrução. A Unidade de Controle é sensível ao caso de estouro de caixa, overflow.
Addition Immediate Unsigned
addiu regi, regj, constant: regi = (regj) + Constant
Coloca no registrador cujo número é passado inicialmente, o resultado da operação aritmética de adição entre o conteúdo do registrador passado em segundo lugar e o valor constante passado como parâmetro da instrução. A Unidade de Controle não considera o caso de estouro de caixa, overflow.
And Operation Immediate
andi regi, regj, constant: regi = (regj) and constant
Coloca no registrador cujo número é passado inicialmente, o resultado da operação de AND lógico entre o conteúdo do registrador passado em segundo lugar e o valor constante passado como parâmetro da instrução.
Xor Operation Immediate
xori regi, regj, constant: regi = (regj) xori Constant
Coloca no registrador cujo número é passado inicialmente, o resultado da operação de OU exclusivo lógico entre o conteúdo do registrador passado em segundo lugar e o valor constante passado como parâmetro da instrução.
Multiplication
mult rs, rt: reg_hi=reg_lo = rs x rt
Coloca nos registradores específicos REG_HI e REG_LO, respectivamente, a parte mais significativa e a menos significativa da operação aritmética de multiplicação entre o conteúdo dos registradores cujos números são passados como parâmetros da instrução.
Division
Div rs, rt: reg_hi = rs/rt (quociente), reg_lo = (resto da divisão)
Coloca nos registradores específicos REG_HI e REG_LO, respectivamente, o quociente e o resto da operação aritmética de divisão inteira entre o conteúdo dos registradores cujos números são passados como parâmetros da instrução.
Shift Right Artithmetic
Sra regd, regd, n: rd = shift(regs, n)
Coloca no registrador cujo número é passado inicialmente, o resultado da operação de deslocamento aritmético à direita no vetor de 32 bits contido no registrador cujo número é indicado. O número de deslocamentos a serem realizados, contido no intervalo fechado de 0 a 32, é passado como o terceiro parâmetro da instrução.
Shift Right Logical
srl regd, regd, n: rd = shift(regs, n)
Coloca no registrador cujo número é passado inicialmente, o resultado da operação de deslocamento lógico à direita no vetor de 32 bits contido no registrador cujo número é indicado. O número de deslocamentos a serem realizados, contido no intervalo fechado de 0 a 32, é passado como o terceiro parâmetro da instrução.
Shift Left Logical
sll regd, regd, n: rd = shift(regs, n)
Coloca no registrador cujo número é passado inicialmente, o resultado da operação de deslocamento lógico à esquerda no vetor de 32 bits contido no registrador cujo número é indicado. O número de deslocamentos a serem realizados, contido no intervalo fechado de 0 a 32, é passado como o terceiro parâmetro da instrução.
Branch on Equal
beq regi, regj, desl: PC = PC + (desl * 4) (if regj = regk)
Implementa o desvio condicional do contador do programa. Caso o conteúdo dos registradores cujos números são passados como parâmetro for igual, o registrador contador do programa é desviado de tantas instruções quanto o número indicado no conteúdo constante do campo deslocamento, de 16 bits, passado como parâmetro.
Branch if Not Equal
bne regi, regj, desl: PC = PC + (desl * 4) (if regj != regk)
Implementa de outra forma o desvio condicional do contador do programa. Caso os conteúdos dos registradores cujos números são passados como parâmetro forem iguais, o registrador contador do programa é desviado de tantas instruções quanto o número indicado no conteúdo constante do campo deslocamento, de 16 bits, passado como parâmetro.
Set if Less Than
slt regi, regj, regk: regi = 1 if regj < regk and regi = 0 otherwise
Marca o registrador cujo número é indicado inicialmente com o valor 1, caso os registradores cujos números indicados posteriormente contiverem valores iguais e com 0, caso contrário.
Set if Less Than Immediate
slti regi, regj, constant: regi = 1 if regj < constant and regi = 0 otherwise
Marca o registrador cujo número é indicado inicialmente com o valor 1, caso o registrador cujo número é indicado posteriormente contiver valor igual ao da constante passada como parâmetro da instrução e com 0, caso contrário.
Jump
J end: PC = end
Implementa o desvio absoluto do contador do programa. A chamada a jump faz com que o registrador contador do programa receba o valor de 26 bits passado como parâmetro da instrução. Embora o desvio seja absoluto, os 4 bits mais significativos do contador do programa são mantidos. A instrução jump, portanto, não utiliza todo o potencial de endereçamento de memória de 232 referências, utilizando, apenas, um espaço de 226 posições de grupo.
Return from Exception
rte: retorna ao ponto do programa onde houve uma exceção
Dada a ocorrência de uma exceção, o processador faz o registrador contador do programa apontar para uma posição de memória fixa que armazena o endereço efetivo das rotinas específicas de tratamento de exceção. Cada exceção exige uma rotina particular. Ao término da execução desses procedimentos compensatórios, o processador deve retornar ao exato ponto do programa em que ocorreu a exceção. Esse retorno é executado pela chamada da instrução rte.
Break
break: pára a execução do programa (desativa o processador)
A chamada break implementa a saída do caso de exceção impensada, não tratável e crítica do processador. Realiza a parada abrupta da execução de um programa, colocando o dispositivo em um estado de inatividade contínua, do qual se retira apenas pelo reinício das atividades de todo o sistema, indicado pela negação da energia motriz. Por ser também útil em circunstâncias diversas, é padrão na arquitetura de computadores.
Jump Register
j reg: PC = (reg)
Implementa o desvio absoluto completo do contador do programa. A chamada a jump register faz com que o registrador contador do programa receba o valor de 32 bits contido no registrador cujo número é passado como parâmetro da instrução. Neste caso, todo o espaço de endereçamento é utilizado, sendo claramente possível a realização de 232 referências a endereços de memória. Observação importante: não é seguro realizar-se referências aleatórias a posições de memória mediante a permuta e uso das instruções jump e jump register.
Jump and Link
jal end: R31 = PC; PC = end
Implementa outra forma de desvio absoluto completo do contador do programa. A chamada a jump and link permite que o registrador contador do programa receba o valor constante de 26 bits passado como parâmetro da instrução, exatamente como no caso da instrução jump. A diferença significativa encontra-se unicamente no fato de que, neste caso, o valor atual do registrador contador do programa é salvo no registrador específico de número 31, da arquitetura. Essa medida facilita a implementação de chamadas seriais e reentrantes de alto nível de grau 1.
3.2Formato das Instruções
A máquina colocada em funcionamento seguiu o padrão internacional MIPS para formatos de instruções. Segundo essa especificação clara, visando ao favorecimento da regularidade, e tendo em vista que uma boa arquitetura demanda compromisso, todas as instruções devem conter o mesmo tamanho de 32 bits. Os seis bits iniciais são impreterivelmente reservados para a indicação do código da operação, conhecido mais amplamente pelo designativo abreviado”opcode” (do inglês, operation code). Essa medida proporciona extrema simplicidade ao processo interno de decodificação das instruções, reduzindo significativamente a complexidade, tamanho e custo da unidade de processamento e de controle.
De acordo com a definição, há três formatos possíveis de dados nas instruções implementadas pela arquitetura. Em todos os casos, os campos reservados para se fazer referência a registradores específicos do banco de registradores são secções com o comprimento de 5 bits. Trata-se de algo somente esperado, uma vez que o número total de registradores no banco é 32. No tocante a outros campos em particular, há explicações específicas para cada caso; serão consideradas, portanto, as situações individualmente.
3.2.1 Formato F1
O primeiro formato de instruções apresenta a seguinte disposição:
6 bits
5 bits
5 bits
5 bits
5 bits
6 bits
opcode
Rs1
rs2
rd
shamt
funct
Utilizado em todas as instruções aritméticas e lógicas que não envolvam constantes, instruções de deslocamento, de desvio absoluto completo (jump register) e nas instruções de carregamento dos registradores REG_HI e REG_LO (mfhi e mflo), o formato F1 apresenta a disposição mais geral para as instruções implementadas.
Nas instruções aritméticas e lógicas, o campo rs1 indica o número do primeiro registrador operando, o campo rs2 o número do segundo registrador operando e o campo rd o número do registrador destino da operação. Em seu conteúdo será colocado o resultado do que foi analisado pela instrução.
O campo shamt é somente utilizado pelas instruções de deslocamento em vetores de bits, sendo representativo do número de deslocamentos a serem realizados na especificação do projeto esse campo possui 5 bits mas poderia inclusive possuir menos bits.
Em todo caso de instruções aritméticas, deve ser analisado o campo funct pela Unidade de Controle. Indicando a funcionalidade, estabelece a diferença para os casos de instruções com o mesmo código de operação. Trata-se de uma decisão de implementação por parte dos projetistas do MIPS: todas as instruções aritméticas possuem o mesmo código de operação. A distinção se dá pelo campo da funcionalidade.
3.2.2 Formato F2
O segundo possível para a cadeia de bits recebida como instrução por parte do processador implementado é o seguinte:
6 bits
5 bits
5 bits
16 bits
opcode
rs1
rs2
Deslocamento
As instruções que utilizam o formato F2 são todas as de referência à memória, todas as que manipulam constantes e as de desvio condicional relativo (beq e bne).
No caso das que fazem referência à memória para carregamento em registrador (load word, load byte, load half), o campo rs1 indica o número do registrador base da operação e o campo rs2 o número do registrador no qual se deseja carregar o valor armazenado na memória; o campo deslocamento, de 16 bits, armazena o número a ser somado ao valor contido no registrador base para que se encontre a posição de memória na qual há o dado a ser carregado para o registrador. Para as instruções de referência à memória para escrita (store word, store byte, store half) rs2 indica o registrador fonte dos dados para escrita.
A manipulação de constantes é feita por meio do campo deslocamento, sendo nele colocado o dado a ser tratado.
Quanto às instruções de desvio condicional, rs1 indica o número do registrador que armazena o primeiro valor operando para a verificação, rs2 o número do segundo registrador operando e deslocamento o número de instruções a serem desviadas caso o resultado da análise seja positivo.
3.2.3 Formato F3
O terceiro e último formato permitido para instruções na arquitetura em consideração é o seguinte:
6 bits
26 bits
opcode
Deslocamento
O formato F3 é utilizado para a representação de instruções de desvio absoluto incompleto (instruções jump e jump and link).
Em ambos os casos, o campo deslocamento é utilizado para armazenar o número constante passado como parâmetro para o qual deve apontar o registrador contador do programa (program counter, PC). Visto que PC possui, como todo registrador da arquitetura, 32 bits, a estratégia para implementação dessas instruções consiste em estender os 26 bits recebidos para 28, por meio da operação de deslocamento duplo à esquerda (o equivalente à multiplicação por quatro do valor decimal) e concatená-los aos 4 bits mais significativos do PC.
Desse modo, o formato de instrução F3 é o de menor amplitude dentre os três.
4. Unidade de Processamento
A parte inicial do projeto consistiu da estruturação completa da unidade de processamento do sistema a ser implementado incluindo seus componentes. O grupo recebeu da equipe coordenadora uma versão significativamente limitada do datapath a ser produzido. A estrutura fornecida implementava 6 (seis) instruções da arquitetura MIPS. Como primeira etapa, o grupo deveria estendê-la de modo a que fosse capaz de executar todas as 34 apresentadas na especificação oficial fazendo as alterações nescessárias..
De acordo com a orientação a descrição foi realizada nos moldes tradicionais, escrita por lápis em papel cartolina e apresentada como desenho preliminar à equipe de ensino da cadeira vinculada ao trabalho, do Centro de Informática da UFPE. A metodologia sugerida mostrou-se efetivamente prática, dado que o trabalho de construção realizado dessa forma proporciona um nível agradável de abstração quanto à complexidade do modelo teórico de um computador, a saber, o conceito de uma máquina de estados relativamente grande. De modo o trabalho se deu da seguinte forma:
- tomou-se o modelo inicial e limitado de projeto da arquitetura MIPS fornecido pela equipe de ensino (veja a figura 2.1);
- como forma de estudo da versão limitada da unidade de processamento concedida, analisou-se cuidadosamente o fluxo de execução de cada instrução implementada pela estrutura concedida;
- ao término da análise, tomou-se o repertório de instruções extras a serem implementadas e verificou-se, uma a uma, quais as alterações necessárias a serem produzidas na estrutura fornecida para que todas pudessem ser executadas quando o sistema fosse posto em funcionamento.
S
h
i
f
t
l
e
f
t
2
P
C
M
u
x
0
1
R
e
g
i
s
t
e
r
s
W
r
i
t
e
r
e
g
i
s
t
e
r
W
r
i
t
e
d
a
t
a
R
e
a
d
d
a
t
a
1
R
e
a
d
d
a
t
a
2
R
e
a
d
r
e
g
i
s
t
e
r
1
R
e
a
d
r
e
g
i
s
t
e
r
2
I
n
s
t
r
u
c
t
i
o
n
[
1
5
–
1
1
]
M
u
x
0
1
M
u
x
0
1
4
I
n
s
t
r
u
c
t
i
o
n
[
1
5
–
0
]
S
i
g
n
e
x
t
e
n
d
3
2
1
6
I
n
s
t
r
u
c
t
i
o
n
[
2
5
–
2
1
]
I
n
s
t
r
u
c
t
i
o
n
[
2
0
–
1
6
]
I
n
s
t
r
u
c
t
i
o
n
[
1
5
–
0
]
I
n
s
t
r
u
c
t
i
o
n
r
e
g
i
s
t
e
r
A
L
U
c
o
n
t
r
o
l
A
L
U
r
e
s
u
l
t
A
L
U
Z
e
r
o
M
e
m
o
r
y
d
a
t
a
r
e
g
i
s
t
e
r
A
B
I
o
r
D
M
e
m
R
e
a
d
M
e
m
W
r
i
t
e
M
e
m
t
o
R
e
g
P
C
W
r
i
t
e
C
o
n
d
P
C
W
r
i
t
e
I
R
W
r
i
t
e
A
L
U
O
p
A
L
U
S
r
c
B
A
L
U
S
r
c
A
R
e
g
D
s
t
P
C
S
o
u
r
c
e
R
e
g
W
r
i
t
e
C
o
n
t
r
o
l
O
u
t
p
u
t
s
O
p
[
5
–
0
]
I
n
s
t
r
u
c
t
i
o
n
[
3
1
-
2
6
]
I
n
s
t
r
u
c
t
i
o
n
[
5
–
0
]
M
u
x
0
2
J
u
m
p
a
d
d
r
e
s
s
[
3
1
-
0
]
I
n
s
t
r
u
c
t
i
o
n
[
2
5
–
0
]
2
6
2
8
S
h
i
f
t
l
e
f
t
2
P
C
[
3
1
-
2
8
]
1
1
M
u
x
0
3
2
M
u
x
0
1
A
L
U
O
u
t
M
e
m
o
r
y
M
e
m
D
a
t
a
W
r
i
t
e
d
a
t
a
A
d
d
r
e
s
s
Figura 2.1 Unidade de Processamento parcial, concedida.
4.1 Módulos concedidos
A seção que se inicia apresentará exatamente quais blocos da unidade foram concedidos à equipe de desenvolvimento. Neste sentido, ficará completamente evidente a qualquer observador atento o caráter eminentemente didático do trabalho.
Contudo, é fundamental que seja colocado que o espaço de tempo exigido para a conclusão geral das atividades foi de um mês, incluso neste intervalo toda as atividades de análise, projeto, implementação e testes, bem como a edição deste relatório de desenvolvimento. Fica claro, portanto, que a disposição dos módulos expostos a seguir não é informação que restringe o grupo de capacidades ou operabilidades. Trata-se de necessidade puramente situacional.
4.1.1 Memória 256 bytes
O componente representativo da Memória Principal de um sistema de computação concedido para a implementação sistema que inclui a Unidade Central de Processamento em desenvolvimento trabalha com palavras de 32 bits e possui endereçamento por byte. Apesar de o endereço possuir 32 bits, a memória só possui 256 bytes. As entradas e saídas da memória são: a entrada de dados da memória (32 bits), utilizada para o procedimento de escrita; o endereço de entrada da memória (32 bits), colocado para o recebimento do conteúdo à posição indicada; o sinal de escrita, que informa se o procedimento ativo é leitura ou escrita no componente; o clock do sistema; e a saída de Dados da memória (32 bits), informando o conteúdo à posição indicada.
A
B
S
Z
N
O
EQ
LT
GT
ALU
32
32
32
Figura 2.2 Memória 256 bytes com endereçamento por byte
O código VHDL da Memória é apresentado logo a seguir.
--------------------------------------------------------------------------------
-- Title
: Memória da CPU
-- Project
: CPU Multi-ciclo
--------------------------------------------------------------------------------
-- File
: Memoria.vhd
-- Author
: Emannuel Gomes Macêdo
--
Fernando Raposo Camara da Silva
--
Pedro Machado Manhães de Castro
--
Rodrigo Alves Costa
-- Organization : Universidade Federal de Pernambuco
-- Created
: 26/07/2002
-- Last update: 23/11/2002
-- Plataform: Flex10K
-- Simulators: Altera Max+plus II
-- Synthesizers:
-- Targets
:
-- Dependency:
--------------------------------------------------------------------------------
-- Description: Entidade responsável pela leitura e escrita em memória.
--------------------------------------------------------------------------------
-- Copyright (c) notice
--
Universidade Federal de Pernambuco (UFPE).
--
CIn - Centro de Informatica.
--
Developed by computer science undergraduate students.
--
This code may be used for educational and non-educational purposes as
--
long as its copyright notice remains unchanged.
--------------------------------------------------------------------------------
-- Revisions
: 1
-- Revision Number: 1.0
-- Version
: 1.1
-- Date
: 23/11/2002
-- Modifier
: Marcus Vinicius Lima e Machado
--
Paulo Roberto Santana Oliveira Filho
--
Viviane Cristina Oliveira Aureliano
-- Description
:
--------------------------------------------------------------------------------
package ram_constants is
constant DATA_WIDTH : INTEGER := 8;
constant ADDR_WIDTH : INTEGER := 8;
constant INIT_FILE : STRING := "ram_instrucoes.mif";
end ram_constants;
--*************************************************************************
library IEEE;
use IEEE.std_logic_1164.all;
USE ieee.std_logic_arith.all;
library lpm;
use lpm.lpm_components.all;
library work;
use work.ram_constants.all;
--*************************************************************************
--Short name: mem
ENTITY Memoria IS
PORT(
Address: IN BIT_VECTOR(31 DOWNTO 0);-- Endereço de memória a ser lido
Clock: IN BIT;
-- Clock do sistema
Wr
: IN BIT;
-- Indica se a memória será lida (0) ou escrita (1)
Dataout: OUT BIT_VECTOR (31 DOWNTO 0);-- Valor a ser escrito quando Wr = 1
Datain: IN BIT_VECTOR(31 DOWNTO 0)-- Valor lido da memória quando Wr = 0
);
END Memoria;
-- Arquitetura que define o comportamento da memória
-- Simulation
ARCHITECTURE behavioral_arch OF Memoria IS
signal add
: bit_vector(7 downto 0);
signal addS0
: STD_LOGIC_VECTOR (ADDR_WIDTH-1 DOWNTO 0);
signal addS1
: STD_LOGIC_VECTOR (ADDR_WIDTH-1 DOWNTO 0);
signal addS2
: STD_LOGIC_VECTOR (ADDR_WIDTH-1 DOWNTO 0);
signal addS3
: STD_LOGIC_VECTOR (ADDR_WIDTH-1 DOWNTO 0);
signal dataoutS
: STD_LOGIC_VECTOR (31 DOWNTO 0);
signal datainS
: STD_LOGIC_VECTOR (31 DOWNTO 0);
signal dataoutS0: STD_LOGIC_VECTOR (DATA_WIDTH-1 DOWNTO 0);
signal dataoutS1: STD_LOGIC_VECTOR (DATA_WIDTH-1 DOWNTO 0);
signal dataoutS2: STD_LOGIC_VECTOR (DATA_WIDTH-1 DOWNTO 0);
signal dataoutS3: STD_LOGIC_VECTOR (DATA_WIDTH-1 DOWNTO 0);
signal datainS0
: STD_LOGIC_VECTOR (DATA_WIDTH-1 DOWNTO 0);
signal datainS1
: STD_LOGIC_VECTOR (DATA_WIDTH-1 DOWNTO 0);
signal datainS2
: STD_LOGIC_VECTOR (DATA_WIDTH-1 DOWNTO 0);
signal datainS3
: STD_LOGIC_VECTOR (DATA_WIDTH-1 DOWNTO 0);
signal wrS
: STD_LOGIC;
signal clockS
: STD_LOGIC;
signal add0
: integer;
signal add2
: integer;
signal add1
: integer;
signal add3
: integer;
signal addu
: unsigned(7 downto 0);
BEGIN
-- Usa apenas 8 bits menos significativos do endereço
add <= Address(7 downto 0);
-- Conversão de bit-vector em inteiro
addu(0) <= To_StdULogic(add(0));
addu(1) <= To_StdULogic(add(1));
addu(2) <= To_StdULogic(add(2));
addu(3) <= To_StdULogic(add(3));
addu(4) <= To_StdULogic(add(4));
addu(5) <= To_StdULogic(add(5));
addu(6) <= To_StdULogic(add(6));
addu(7) <= To_StdULogic(add(7));
-- Cálculo dos 4 endereços (inteiros) a serem lidos devido ao endereçamento por byte
add1 <= add0 + 1;
add2 <= add0 + 2;
add3 <= add0 + 3;
add0 <= CONV_INTEGER(addu);
-- Conversão dos endereços no formato STD_LOGIC_VECTOR
addS0 <= CONV_STD_LOGIC_VECTOR(add0, 8);
addS1 <= CONV_STD_LOGIC_VECTOR(add1, 8);
addS2 <= CONV_STD_LOGIC_VECTOR(add2, 8);
addS3 <= CONV_STD_LOGIC_VECTOR(add3, 8);
-- Conversão do dado (entrada) no formato STD_LOGIC_VECTOR
datainS <= To_StdLogicVector(datain);
wrS <= To_StdULogic(wr);
clockS <= To_StdULogic(clock);
-- Conversão de dado (saída) para bit_vector
dataout <= To_BitVector(dataoutS);
-- Distribuição dos vetores de dados para os bancos de memória
datainS0 <= datainS(7 downto 0);
datainS1 <= datainS(15 downto 8);
datainS2 <= datainS(23 downto 16);
datainS3 <= datainS(31 downto 24);
dataoutS(7 downto 0) <= dataoutS0;
dataoutS(15 downto 8) <= dataoutS1;
dataoutS(23 downto 16) <= dataoutS2;
dataoutS(31 downto 24) <= dataoutS3;
-- Bancos de memórias (cada banco possui 256 bytes)
MEM: lpm_ram_dq
GENERIC MAP (lpm_widthad => ADDR_WIDTH, lpm_width => DATA_WIDTH, lpm_file => INIT_FILE)
PORT MAP (data => datainS0, Address => addS0, we => wrS, inclock => clockS, outclock => clockS, q => dataoutS0);
MEM_plus_One: lpm_ram_dq
GENERIC MAP (lpm_widthad => ADDR_WIDTH, lpm_width => DATA_WIDTH, lpm_file => INIT_FILE)
PORT MAP (data => datainS1, Address => addS1, we => wrS, inclock => clockS, outclock => clockS, q => dataoutS1);
MEM_plus_Two: lpm_ram_dq
GENERIC MAP (lpm_widthad => ADDR_WIDTH, lpm_width => DATA_WIDTH, lpm_file => INIT_FILE)
PORT MAP (data => datainS2, Address => addS2, we => wrS, inclock => clockS, outclock => clockS, q => dataoutS2);
MEM_plus_Three: lpm_ram_dq
GENERIC MAP (lpm_widthad => ADDR_WIDTH, lpm_width => DATA_WIDTH, lpm_file => INIT_FILE)
PORT MAP (data => datainS3, Address => addS3, we => wrS, inclock => clockS, outclock => clockS, q => dataoutS3);
END behavioral_arch;
Código 4.1 Comportamental VHDL da Memória 256 bytes
4.1.2 Banco de Registradores
O módulo que se convencionou chamar banco de registradores é uma estrutura composta por 32 registradores de 32 bits cada. O componente possui duas saídas de 32 bits, apresentando o conteúdo de dois registradores simultaneamente.
O procedimento interno para a leitura do conteúdo dos registradores é puramente combinacional, isto é se os valores nas entradas ReadRegister1 ou ReadRegister2 forem alterados, os valores nas saídas ReadData1 ou ReadData2 podem ser alterados durante o mesmo ciclo de relógio.
O registrador a ser escrito é selecionado pela entrada WriteRegister. Quando a entrada RegWrite é ativada, com valor igual a 1, o registrador selecionado recebe o conteúdo da entrada WriteData.
É informação importante o fato de que o sinal de reset atribui valor zero a todos os registradores e é assíncrono.
Figura 2.3 Banco de Registradores
O código VHDL para o componente Banco de Registradores é apresentado logo em seguida. Verifique a especificação dos sinais de entrada e saída. Sua relação com os demais blocos do sistema será explicada dentro em breve.
--------------------------------------------------------------------------------
-- Title
: Banco de Registradores
-- Project
: CPU Multi-ciclo
--------------------------------------------------------------------------------
-- File
: Banco_reg.vhd
-- Author
: Emannuel Gomes Macêdo ([email protected])
--
Fernando Raposo Camara da Silva ([email protected])
--
Pedro Machado Manhães de Castro ([email protected])
--
Rodrigo Alves Costa ([email protected])
-- Organization : Universidade Federal de Pernambuco
-- Created
: 29/07/2002
-- Last update: 21/11/2002
-- Plataform: Flex10K
-- Simulators: Altera Max+plus II
-- Synthesizers:
-- Targets
:
-- Dependency:
--------------------------------------------------------------------------------
-- Description: Entidade que armazena o conjunto de registradores da cpu, no
-- qual pode ser efetuado leitura e escrita de dados.
--------------------------------------------------------------------------------
-- Copyright (c) notice
--
Universidade Federal de Pernambuco (UFPE).
--
CIn - Centro de Informatica.
--
Developed by computer science undergraduate students.
--
This code may be used for educational and non-educational purposes as
--
long as its copyright notice remains unchanged.
--------------------------------------------------------------------------------
-- Revisions
: 1
-- Revision Number: 1.0
-- Version
: 1.1
-- Date
: 21/11/2002
-- Modifier
: Marcus Vinicius Lima e Machado ([email protected])
--
Paulo Roberto Santana Oliveira Filho ([email protected])
--
Viviane Cristina Oliveira Aureliano ([email protected])
-- Description
:
--------------------------------------------------------------------------------
--Short name: breg
ENTITY Banco_reg IS
PORT(
Clk
: INbit;
-- Clock do banco de registradores
Reset
: INbit;
-- Reinicializa o conteudo dos registradores
RegWrite: INbit;
-- Indica se a operação é de escrita ou leitura
ReadReg1: INbit_vector (4 downto 0);-- Indica o registrador #1 a ser lido
ReadReg2: INbit_vector (4 downto 0);-- Indica o registrador #2 a ser lido
WriteReg: INbit_vector (4 downto 0);-- Indica o registrador a ser escrito
WriteData : INbit_vector (31 downto 0);-- Indica o dado a ser escrito
ReadData1: OUTbit_vector (31 downto 0);-- Mostra a informaçao presente no registrador #1
ReadData2: OUTbit_vector (31 downto 0)-- Mostra a informação presente no registrador #2
);
END Banco_reg ;
-- Arquitetura que define comportamento do Banco de Registradores
-- Simulation
ARCHITECTURE behavioral_arch OF Banco_reg IS
SIGNAL Reg0
: bit_vector (31 downto 0);
-- Conjunto
SIGNAL Reg1
: bit_vector (31 downto 0);
-- das informações
SIGNAL Reg2
: bit_vector (31 downto 0);
-- pertencentes
SIGNAL Reg3
: bit_vector (31 downto 0);
-- aos registradores.
SIGNAL Reg4
: bit_vector (31 downto 0);
-- Esta CPU
SIGNAL Reg5
: bit_vector (31 downto 0);
-- possui
SIGNAL Reg6
: bit_vector (31 downto 0);
-- 32 registradores
SIGNAL Reg7
: bit_vector (31 downto 0);
-- de uso
SIGNAL Reg8
: bit_vector (31 downto 0);
-- comum.
SIGNAL Reg9 : bit_vector (31 downto 0);
SIGNAL Reg10: bit_vector (31 downto 0);
SIGNAL Reg11: bit_vector (31 downto 0);
SIGNAL Reg12: bit_vector (31 downto 0);
SIGNAL Reg13: bit_vector (31 downto 0);
SIGNAL Reg14: bit_vector (31 downto 0);
SIGNAL Reg15: bit_vector (31 downto 0);
SIGNAL Reg16: bit_vector (31 downto 0);
SIGNAL Reg17: bit_vector (31 downto 0);
SIGNAL Reg18: bit_vector (31 downto 0);
SIGNAL Reg19: bit_vector (31 downto 0);
SIGNAL Reg20: bit_vector (31 downto 0);
SIGNAL Reg21: bit_vector (31 downto 0);
SIGNAL Reg22: bit_vector (31 downto 0);
SIGNAL Reg23: bit_vector (31 downto 0);
SIGNAL Reg24: bit_vector (31 downto 0);
SIGNAL Reg25: bit_vector (31 downto 0);
SIGNAL Reg26: bit_vector (31 downto 0);
SIGNAL Reg27: bit_vector (31 downto 0);
SIGNAL Reg28: bit_vector (31 downto 0);
SIGNAL Reg29: bit_vector (31 downto 0);
SIGNAL Reg30: bit_vector (31 downto 0);
SIGNAL Reg31: bit_vector (31 downto 0);
BEGIN
-- selecao do primeiro registrador
WITH ReadReg1 SELECT
ReadData1 <= Reg0 WHEN "00000",-- acesso às informações do registrador correspondente
Reg1 WHEN "00001",
Reg2 WHEN "00010",
Reg3 WHEN "00011",
Reg4 WHEN "00100",
Reg5 WHEN "00101",
Reg6 WHEN "00110",
Reg7 WHEN "00111",
Reg8 WHEN "01000",
Reg9 WHEN "01001",
Reg10 WHEN "01010",
Reg11 WHEN "01011",
Reg12 WHEN "01100",
Reg13 WHEN "01101",
Reg14 WHEN "01110",
Reg15 WHEN "01111",
Reg16 WHEN "10000",
Reg17 WHEN "10001",
Reg18 WHEN "10010",
Reg19 WHEN "10011",
Reg20 WHEN "10100",
Reg21 WHEN "10101",
Reg22 WHEN "10110",
Reg23 WHEN "10111",
Reg24 WHEN "11000",
Reg25 WHEN "11001",
Reg26 WHEN "11010",
Reg27 WHEN "11011",
Reg28 WHEN "11100",
Reg29 WHEN "11101",
Reg30 WHEN "11110",
Reg31 WHEN "11111";
-- Clocked Process
process (Clk,Reset)
begin
------------------------------------------- Reset inicializa o conjunto de registradores
if(Reset = '1') then
Reg0 <= "00000000000000000000000000000000";
Reg1 <= "00000000000000000000000000000000";
Reg2 <= "00000000000000000000000000000000";
Reg3 <= "00000000000000000000000000000000";
Reg4 <= "00000000000000000000000000000000";
Reg5 <= "00000000000000000000000000000000";
Reg6 <= "00000000000000000000000000000000";
Reg7 <= "00000000000000000000000000000000";
Reg8 <= "00000000000000000000000000000000";
Reg9 <= "00000000000000000000000000000000";
Reg10 <= "00000000000000000000000000000000";
Reg11 <= "00000000000000000000000000000000";
Reg12 <= "00000000000000000000000000000000";
Reg13 <= "00000000000000000000000000000000";
Reg14 <= "00000000000000000000000000000000";
Reg15 <= "00000000000000000000000000000000";
Reg16 <= "00000000000000000000000000000000";
Reg17 <= "00000000000000000000000000000000";
Reg18 <= "00000000000000000000000000000000";
Reg19 <= "00000000000000000000000000000000";
Reg20 <= "00000000000000000000000000000000";
Reg21 <= "00000000000000000000000000000000";
Reg22 <= "00000000000000000000000000000000";
Reg23 <= "00000000000000000000000000000000";
Reg24 <= "00000000000000000000000000000000";
Reg25 <= "00000000000000000000000000000000";
Reg26 <= "00000000000000000000000000000000";
Reg27 <= "00000000000000000000000000000000";
Reg28 <= "00000000000000000000000000000000";
Reg29 <= "00000000000000000000000000000000";
Reg30 <= "00000000000000000000000000000000";
Reg31 <= "00000000000000000000000000000000";
------------------------------------------ Início do processo relacionado ao clock
elsif (Clk = '1' and clk'event) then
if(RegWrite = '1') then
case WriteReg is
when "00000" =>Reg0 <= WriteData;
when "00001" =>Reg1 <= WriteData;
when "00010" =>Reg2 <= WriteData;
when "00011" =>Reg3 <= WriteData;
when "00100" =>Reg4 <= WriteData;
when "00101" =>Reg5 <= WriteData;
when "00110" =>Reg6 <= WriteData;
when "00111" =>Reg7 <= WriteData;
when "01000" =>Reg8 <= WriteData;
when "01001" =>Reg9 <= WriteData;
when "01010" =>Reg10 <= WriteData;
when "01011" =>Reg11 <= WriteData;
when "01100" =>Reg12 <= WriteData;
when "01101" =>Reg13 <= WriteData;
when "01110" =>Reg14 <= WriteData;
when "01111" =>Reg15 <= WriteData;
when "10000" =>Reg16 <= WriteData;
when "10001" =>Reg17 <= WriteData;
when "10010" =>Reg18 <= WriteData;
when "10011" =>Reg19 <= WriteData;
when "10100" =>Reg20 <= WriteData;
when "10101" =>Reg21 <= WriteData;
when "10110" =>Reg22 <= WriteData;
when "10111" =>Reg23 <= WriteData;
when "11000" =>Reg24 <= WriteData;
when "11001" =>Reg25 <= WriteData;
when "11010" =>Reg26 <= WriteData;
when "11011" =>Reg27 <= WriteData;
when "11100" =>Reg28 <= WriteData;
when "11101" =>Reg29 <= WriteData;
when "11110" =>Reg30 <= WriteData;
when "11111" =>Reg31 <= WriteData;
end case;
end if;
end if;
------------------------------------------ Fim do processo relacionado ao clock
end process;
------------------------------------------ Fim da Arquitetura
END behavioral_arch;
Código 4.2 Descrição comportamental VHDL do Banco de Registradores
4.1.3 Registrador de Instruções
Componente fundamental para a ordem no procedimento de análise e decodificação da instrução, o Registrador de Instruções (mais conhecido pelo designativo inglês IR, de Instruction Register) recebe o dado diretamente da Memória e apresenta como saída os diversos campos especificados na definição dos formatos de instrução. Associado ao clock do sistema, possui um sinal de reset, como todo registrador e um sinal de escrita que habilita leitura de seu conteúdo ou carga em seu interior.
ram8
add
Data_in
Data_out
clock
wr
Ram32
add
Data_in
Data_out
clock
wr
Figura 2.4 Registrador de Instruções
O código VHDL do Registrador de Instruções é apresentado a seguir.
--------------------------------------------------------------------------------
-- Title
: Registrador de Intruções
-- Project
: CPU multi-ciclo
--------------------------------------------------------------------------------
-- File
: instr_reg.vhd
-- Author
: Marcus Vinicius Lima e Machado ([email protected])
--
Paulo Roberto Santana Oliveira Filho ([email protected])
--
Viviane Cristina Oliveira Aureliano ([email protected])
-- Organization : Universidade Federal de Pernambuco
-- Created
: 29/07/2002
-- Last update: 21/11/2002
-- Plataform: Flex10K
-- Simulators: Altera Max+plus II
-- Synthesizers:
-- Targets
:
-- Dependency:
--------------------------------------------------------------------------------
-- Description: Entidade que registra a instrução a ser executada, modulando
-- corretamente a saída de acordo com o layout padrão das intruções do Mips.
--------------------------------------------------------------------------------
-- Copyright (c) notice
--
Universidade Federal de Pernambuco (UFPE).
--
CIn - Centro de Informatica.
--
Developed by computer science undergraduate students.
--
This code may be used for educational and non-educational purposes as
--
long as its copyright notice remains unchanged.
--------------------------------------------------------------------------------
-- Revisions
:
-- Revision Number:
-- Version
:
-- Date
:
-- Modifier
:
-- Description
:
--------------------------------------------------------------------------------
-- Short name: ir
entity Instr_reg is
port(
Clk
: in bit;-- Clock do sistema
Reset
: in bit;-- Reset
Load_ir
: in bit;-- Bit para ativar carga do registrador de intruções
Entrada
: in bit_vector (31 downto 0);-- Intrução a ser carregada
Instr31_26: out bit_vector (5 downto 0);-- Bits 31 a 26 da instrução
Instr25_21: out bit_vector (4 downto 0);-- Bits 25 a 21 da instrução
Instr20_16: out bit_vector (4 downto 0);-- Bits 20 a 16 da instrução
Instr15_0: out bit_vector (15 downto 0)-- Bits 15 a 0 da instrução
);
end Instr_reg;
-- Arquitetura que define o comportamento interno do Registrador de Intruções
-- Simulation
architecture behavioral_arch of Instr_reg is
signal saida : bit_vector (31 downto 0); -- Sinal interno que guarda a intrução a ser modulada
begin
-- Clocked process
process (clk, reset)
begin
if(reset = '1') then
saida <= "00000000000000000000000000000000";
elsif (clk = '1' and clk'event) then
if (load_ir = '1')then
saida (31 downto 0) <= entrada; -- Carrega instrução
end if;
end if;
end process;
Instr31_26 <= saida (31 downto 26); -- Modula instrução (31 a 26)
Instr25_21 <= saida (25 downto 21); -- Modula instrução (25 a 21)
Instr20_16 <= saida (20 downto 16); -- Modula instrução (20 a 16)
Instr15_0 <= saida (15 downto 0);-- Modula instrução (15 a 0)
end behavioral_arch;
Código 4.3 Descrição comportamental VHDL do Registrador de Instruções
4.1.4 Registrador de Deslocamento
O registrador de deslocamento é um componente capaz de deslocar um número inteiro de 32 bits para esquerda e para a direita. No deslocamento à direita o sinal pode ser preservado ou não. O número de deslocamentos pode variar entre 0 e 7 e é especificado na entrada n (3 bits) do componente. A funcionalidade desejada do registrador de deslocamento é especificada na entrada shift (3 bits menos significativos) conforme figura abaixo. As atividades discriminadas na entrada shift são síncronas com o clock e o reset é assíncrono.
Reg8
load
clock
clear
Reg32
load
clock
clear
Figura 2.5 Registrador de Deslocamento
O código VHDL do Registrador de Deslocamento é apresentado logo a seguir.
--------------------------------------------------------------------------------
-- Title
: Registrador de Deslocamento
-- Project
: CPU Multi-ciclo
--------------------------------------------------------------------------------
-- File
: RegDesloc.vhd
-- Author
: Emannuel Gomes Macêdo
--
Fernando Raposo Camara da Silva
--
Pedro Machado Manhães de Castro
--
Rodrigo Alves Costa
-- Organization : Universidade Federal de Pernambuco
-- Created
: 10/07/2002
-- Last update: 26/11/2002
-- Plataform: Flex10K
-- Simulators: Altera Max+plus II
-- Synthesizers:
-- Targets
:
-- Dependency:
--------------------------------------------------------------------------------
-- Description: Entidade responsável pelo deslocamento de um vetor de 32
-- bits para a direita e para a esquerda.
--
Entradas:
--
* N: vetor de 3 bits que indica a quantidade de
--
deslocamentos
--
* Shift: vetor de 3 bits que indica a função a ser
--
realizada pelo registrador
--
Abaixo seguem os valores referentes à entrada shift e as
-- respectivas funções do registrador:
--
--
Shift
FUNÇÃO DO REGISTRADOR
--
000
faz nada
--
001
carrega vetor (sem deslocamentos)
--
010
deslocamento à esquerda n vezes
--
011
deslocamento à direita lógico n vezes
--
100
deslocamento à direita aritmético n vezes
--
101
rotação à direita n vezes
--
110
rotação à esquerda n vezes
--------------------------------------------------------------------------------
-- Copyright (c) notice
--
Universidade Federal de Pernambuco (UFPE).
--
CIn - Centro de Informatica.
--
Developed by computer science undergraduate students.
--
This code may be used for educational and non-educational purposes as
--
long as its copyright notice remains unchanged.
--------------------------------------------------------------------------------
-- Revisions
: 2
-- Revision Number: 2.0
-- Version
: 1.2
-- Date
: 26/11/2002
-- Modifier
: Marcus Vinicius Lima e Machado
--
Paulo Roberto Santana Oliveira Filho
--
Viviane Cristina Oliveira Aureliano
-- Description
:
--------------------------------------------------------------------------------
-- Short name: desl
ENTITY RegDesloc IS
PORT(
Clk
: INbit;-- Clock do sistema
Reset: INbit;-- Reset
Shift : INbit_vector (2 downto 0);-- Função a ser realizada pelo registrador
N
: INbit_vector (2 downto 0);-- Quantidade de deslocamentos
Entrada : INbit_vector (31 downto 0);-- Vetor a ser deslocado
Saida: OUTbit_vector (31 downto 0)-- Vetor deslocado
);
END RegDesloc;
-- Arquitetura que define o comportamento do registrador de deslocamento
-- Simulation
ARCHITECTURE behavioral_arch OF RegDesloc IS
signal temp
: bit_vector (31 downto 0);-- Vetor temporário
begin
-- Clocked process
process (Clk, Reset)
begin
if(Reset = '1') then
temp <= "00000000000000000000000000000000";
elsif (Clk = '1' and Clk'event) then
case Shift is
when "000" =>
-- Faz nada
temp <= temp;
when "001" =>
-- Carrega vetor de entrada, não faz deslocamentos
temp <= Entrada;
when "010" =>
-- Deslocamento à esquerda N vezes
case N is
when "000" =>
-- Deslocamento à esquerda nenhuma vez
temp <= temp;
when "001" =>
-- Deslocamento à esquerda 1 vez
temp(0) <= '0';
temp(31 downto 1) <= temp(30 downto 0);
when "010" =>
-- Deslocamento à esquerda 2 vezes
temp(1 downto 0) <= "00";
temp(31 downto 2) <= temp(29 downto 0);
when "011" =>
-- Deslocamento à esquerda 3 vezes
temp(2 downto 0) <= "000";
temp(31 downto 3) <= temp(28 downto 0);
when "100" =>
-- Deslocamento à esquerda 4 vezes
temp(3 downto 0) <= "0000";
temp(31 downto 4) <= temp(27 downto 0);
when "101" =>
-- Deslocamento à esquerda 5 vezes
temp(4 downto 0) <= "00000";
temp(31 downto 5) <= temp(26 downto 0);
when "110" =>
-- Deslocamento à esquerda 6 vezes
temp(5 downto 0) <= "000000";
temp(31 downto 6) <= temp(25 downto 0);
when "111" =>
-- Deslocamento à esquerda 7 vezes
temp(6 downto 0) <= "0000000";
temp(31 downto 7) <= temp(24 downto 0);
end case;
-- Deslocamento à direita lógico N vezes
when "011" =>
case n is
when "000" =>
-- Deslocamento à direita lógico nenhuma vez
temp <= temp;
when "001" =>
-- Deslocamento à direita lógico 1 vez
temp(30 downto 0) <= temp(31 downto 1);
temp(31) <= '0';
when "010" =>
-- Deslocamento à direita lógico 2 vezes
temp(29 downto 0) <= temp(31 downto 2);
temp(31 downto 30) <= "00";
when "011" =>
-- Deslocamento à direita lógico 3 vezes
temp(28 downto 0) <= temp(31 downto 3);
temp(31 downto 29) <= "000";
when "100" =>
-- Deslocamento à direita lógico 4 vezes
temp(27 downto 0) <= temp(31 downto 4);
temp(31 downto 28) <= "0000";
when "101" =>
-- Deslocamento à direita lógico 5 vezes
temp(26 downto 0) <= temp(31 downto 5);
temp(31 downto 27) <= "00000";
when "110" =>
-- Deslocamento à direita lógico 6 vezes
temp(25 downto 0) <= temp(31 downto 6);
temp(31 downto 26) <= "000000";
when "111" =>
-- Deslocamento à direita lógico 7 vezes
temp(24 downto 0) <= temp(31 downto 7);
temp(31 downto 25) <= "0000000";
end case;
-- Deslocamento à direita aritmético N vezes
when "100" =>
case n is
when "000" =>
-- Deslocamento à direita aritmético nenhuma vez
temp <= temp;
when "001" =>
-- Deslocamento à direita aritmético 1 vezes
temp(30 downto 0) <= temp(31 downto 1);
temp(31) <= temp(31);
when "010" =>
-- Deslocamento à direita aritmético 2 vezes
temp(29 downto 0) <= temp(31 downto 2);
temp(30) <= temp(31);
temp(31) <= temp(31);
when "011" =>
-- Deslocamento à direita aritmético 3 vezes
temp(28 downto 0) <= temp(31 downto 3);
temp(29) <= temp(31);
temp(30) <= temp(31);
temp(31) <= temp(31);
when "100" =>
-- Deslocamento à direita aritmético 4 vezes
temp(27 downto 0) <= temp(31 downto 4);
temp(28) <= temp(31);
temp(29) <= temp(31);
temp(30) <= temp(31);
temp(31) <= temp(31);
when "101" =>
-- Deslocamento à direita aritmético 5 vezes
temp(26 downto 0) <= temp(31 downto 5);
temp(27) <= temp(31);
temp(28) <= temp(31);
temp(29) <= temp(31);
temp(30) <= temp(31);
temp(31) <= temp(31);
when "110" =>
-- Deslocamento à direita aritmético 6 vezes
temp(25 downto 0) <= temp(31 downto 6);
temp(26) <= temp(31);
temp(27) <= temp(31);
temp(28) <= temp(31);
temp(29) <= temp(31);
temp(30) <= temp(31);
temp(31) <= temp(31);
when "111" =>
-- Deslocamento à direita aritmético 7 vezes
temp(24 downto 0) <= temp(31 downto 7);
temp(25) <= temp(31);
temp(26) <= temp(31);
temp(27) <= temp(31);
temp(28) <= temp(31);
temp(29) <= temp(31);
temp(30) <= temp(31);
temp(31) <= temp(31);
end case;
-- Rotação à direita N vezes
when "101" =>
case n is
when "000" =>
-- Rotação à direita nenhuma vez
temp <= temp;
when "001" =>
-- Rotação à direita 1 vez
temp(30 downto 0) <= temp(31 downto 1);
temp(31) <= temp(0);
when "010" =>
-- Rotação à direita 2 vezes
temp(29 downto 0) <= temp(31 downto 2);
temp(31 downto 30) <= temp(1 downto 0);
when "011" =>
-- Rotação à direita 3 vezes
temp(28 downto 0) <= temp(31 downto 3);
temp(31 downto 29) <= temp(2 downto 0);
when "100" =>
-- Rotação à direita 4 vezes
temp(27 downto 0) <= temp(31 downto 4);
temp(31 downto 28) <= temp(3 downto 0);
when "101" =>
-- Rotação à direita 5 vezes
temp(26 downto 0) <= temp(31 downto 5);
temp(31 downto 27) <= temp(4 downto 0);
when "110" =>
-- Rotação à direita 6 vezes
temp(25 downto 0) <= temp(31 downto 6);
temp(31 downto 26) <= temp(5 downto 0);
when "111" =>
-- Rotação à direita 7 vezes
temp(24 downto 0) <= temp(31 downto 7);
temp(31 downto 25) <= temp(6 downto 0);
end case;
-- Rotação à esquerda N vezes
when "110" =>
case n is
when "000" =>
-- Rotação à esquerda nenhuma vez
temp <= temp;
when "001" =>
-- Rotação à esquerda 1 vez
temp(0) <= temp(31);
temp(31 downto 1) <= temp(30 downto 0);
when "010" =>
-- Rotação à esquerda 2 vezes
temp(1 downto 0) <= temp(31 downto 30);
temp(31 downto 2) <= temp(29 downto 0);
when "011" =>
-- Rotação à esquerda 3 vezes
temp(2 downto 0) <= temp(31 downto 29);
temp(31 downto 3) <= temp(28 downto 0);
when "100" =>
-- Rotação à esquerda 4 vezes
temp(3 downto 0) <= temp(31 downto 28);
temp(31 downto 4) <= temp(27 downto 0);
when "101" =>
-- Rotação à esquerda 5 vezes
temp(4 downto 0) <= temp(31 downto 27);
temp(31 downto 5) <= temp(26 downto 0);
when "110" =>
-- Rotação à esquerda 6 vezes
temp(5 downto 0) <= temp(31 downto 26);
temp(31 downto 6) <= temp(25 downto 0);
when "111" =>
-- Rotação à esquerda 7 vezes
temp(6 downto 0) <= temp(31 downto 25);
temp(31 downto 7) <= temp(24 downto 0);
end case;
-- Funcionalidade não definida
when others =>
-- Faz nada
end case;
end if;
Saida <= temp;
end process;
END behavioral_arch;
Código 4.4 Comportamental VHDL do componente
Registrador de Deslocamento.
4.1.5 Unidade Lógica e Aritmética
A Unidade Lógico e Aritmética (ALU, do inglês Arithmetic and Logic Unit) é um circuito combinacional que permite a operação com números de 32 bits na notação complemento a dois. A funcionalidade é especificada pela entrada F conforme descrito na tabela abaixo.
Figura 2.6 Unidade Lógica e Aritmética
F
Operação
Descrição
Flags afetados
000
S = A
Nenhum
Z,N
001
S = A + B
Soma
Z,N,O
010
S = A - B
Subtração
Z,N,O
011
S = A and B
And lógico
Z
100
S = inc A
Incremento
Z,N,O
101
S = not A
Complemento
Z
110
S = A xor B
Ou exclusivo
Z
111
S = A comp B
Comparação
EG,GT,LT
Tabela 2.1 Funcionalidades da Unidade Lógica e Aritmética
O código VHDL da Unidade de Lógica e Aritmética é apresentado a seguir.
--------------------------------------------------------------------------------
-- Title
: Unidade de Lógica e Aritmética
-- Project
: CPU multi-ciclo
--------------------------------------------------------------------------------
-- File
: ula32.vhd
-- Author
: Emannuel Gomes Macêdo ([email protected])
--
Fernando Raposo Camara da Silva ([email protected])
--
Pedro Machado Manhães de Castro ([email protected])
--
Rodrigo Alves Costa ([email protected])
-- Organization : Universidade Federal de Pernambuco
-- Created
: 29/07/2002
-- Last update: 21/11/2002
-- Plataform: Flex10K
-- Simulators: Altera Max+plus II
-- Synthesizers:
-- Targets
:
-- Dependency:
--------------------------------------------------------------------------------
-- Description: Entidade que processa as operações lógicas e aritméticas da
-- cpu.
--------------------------------------------------------------------------------
-- Copyright (c) notice
--
Universidade Federal de Pernambuco (UFPE).
--
CIn - Centro de Informatica.
--
Developed by computer science undergraduate students.
--
This code may be used for educational and non-educational purposes as
--
long as its copyright notice remains unchanged.
--------------------------------------------------------------------------------
-- Revisions
: 1
-- Revision Number: 1
-- Version
: 1.1
-- Date
: 21/11/2002
-- Modifier
: Marcus Vinicius Lima e Machado ([email protected])
--
Paulo Roberto Santana Oliveira Filho ([email protected])
--
Viviane Cristina Oliveira Aureliano ([email protected])
-- Description
:
--------------------------------------------------------------------------------
-- Short name: ula
entity Ula32 is
port (
A
: in bit_vector (31 downto 0);-- Operando A da ULA
B
: in bit_vector (31 downto 0);-- Operando B da ULA
Seletor : in bit_vector(2 downto 0);-- Seletor da operação da ULA
S
: out bit_vector (31 downto 0);-- Resultado da operação (SOMA, SUB, AND, NOT, INCREMENTO, XOR)
Overflow : out bit;
-- Sinaliza overflow aritmético
Negativo: out bit;
-- Sinaliza valor negativo
z
: out bit;
-- Sinaliza quando S for zero
Igual
: out bit;
-- Sinaliza se A=B
Maior
: out bit;
-- Sinaliza se A>B
Menor
: out bit
-- Sinaliza se A
);
end Ula32;
-- Simulation
architecture behavioral of Ula32 is
signal s_temp
: bit_vector(31 downto 0);
-- Sinal que recebe valor temporário da operação realizada
signal soma_temp : bit_vector(31 downto 0);
-- Sinal que recebe o valor temporario da soma, subtração ou incremento
signal carry_temp: bit_vector (31 downto 0);
-- Vetor para auxílio no cálculo das operações e do overflow aritmético
signal novo_B
: bit_vector (31 downto 0);
-- Vetor que fornece o operando B, 1 ou not(B) para operações de soma, incremento ou subtração respectivamente
signal i_temp
: bit_vector(31 downto 0);
-- Vetor para calculo de incremento
signal igual_temp: bit;
-- Bit que armazena instancia temporária de igualdade
signal overflow_temp: bit;
-- Bit que armazena valor temporário do overflow
begin
with Seletor select
s_temp <= A
when "000", -- LOAD
soma_temp when "001",-- SOMA
soma_temp when "010",-- SUB
(A and B) when "011",-- AND
(A xor B) when "110", -- A XOR B
not(A) when "101",-- NOT A
soma_temp when "100",-- INCREMENTO
"00000000000000000000000000000000" when others;
-- NAO DEFINIDO
S <= s_temp;
Negativo <= s_temp(31);
i_temp <= "00000000000000000000000000000001";
z <= '1' when s_temp = "00000000000000000000000000000000" else '0';
--------------------------------------------------------------------------------
--
Regiao que calcula a soma, subtracao e incremento
--
--------------------------------------------------------------------------------
with Seletor select
novo_B <= B
when "001", -- Soma
i_temp when "100", -- Incremento
not(B) when others; -- Subtracao e outros
soma_temp(0) <= A(0) xor novo_B(0) xor seletor(1);
soma_temp(1) <= A(1) xor novo_B(1) xor carry_temp(0);
soma_temp(2) <= A(2) xor novo_B(2) xor carry_temp(1);
soma_temp(3) <= A(3) xor novo_B(3) xor carry_temp(2);
soma_temp(4) <= A(4) xor novo_B(4) xor carry_temp(3);
soma_temp(5) <= A(5) xor novo_B(5) xor carry_temp(4);
soma_temp(6) <= A(6) xor novo_B(6) xor carry_temp(5);
soma_temp(7) <= A(7) xor novo_B(7) xor carry_temp(6);
soma_temp(8) <= A(8) xor novo_B(8) xor carry_temp(7);
soma_temp(9) <= A(9) xor novo_B(9) xor carry_temp(8);
soma_temp(10) <= A(10) xor novo_B(10) xor carry_temp(9);
soma_temp(11) <= A(11) xor novo_B(11) xor carry_temp(10);
soma_temp(12) <= A(12) xor novo_B(12) xor carry_temp(11);
soma_temp(13) <= A(13) xor novo_B(13) xor carry_temp(12);
soma_temp(14) <= A(14) xor novo_B(14) xor carry_temp(13);
soma_temp(15) <= A(15) xor novo_B(15) xor carry_temp(14);
soma_temp(16) <= A(16) xor novo_B(16) xor carry_temp(15);
soma_temp(17) <= A(17) xor novo_B(17) xor carry_temp(16);
soma_temp(18) <= A(18) xor novo_B(18) xor carry_temp(17);
soma_temp(19) <= A(19) xor novo_B(19) xor carry_temp(18);
soma_temp(20) <= A(20) xor novo_B(20) xor carry_temp(19);
soma_temp(21) <= A(21) xor novo_B(21) xor carry_temp(20);
soma_temp(22) <= A(22) xor novo_B(22) xor carry_temp(21);
soma_temp(23) <= A(23) xor novo_B(23) xor carry_temp(22);
soma_temp(24) <= A(24) xor novo_B(24) xor carry_temp(23);
soma_temp(25) <= A(25) xor novo_B(25) xor carry_temp(24);
soma_temp(26) <= A(26) xor novo_B(26) xor carry_temp(25);
soma_temp(27) <= A(27) xor novo_B(27) xor carry_temp(26);
soma_temp(28) <= A(28) xor novo_B(28) xor carry_temp(27);
soma_temp(29) <= A(29) xor novo_B(29) xor carry_temp(28);
soma_temp(30) <= A(30) xor novo_B(30) xor carry_temp(29);
soma_temp(31) <= A(31) xor novo_B(31) xor carry_temp(30);
carry_temp(0) <= (seletor(1) and (A(0) or novo_B(0))) or (A(0) and novo_B(0));
carry_temp(1) <= (carry_temp(0) and (A(1) or novo_B(1))) or (A(1) and novo_B(1));
carry_temp(2) <= (carry_temp(1) and (A(2) or novo_B(2))) or (A(2) and novo_B(2));
carry_temp(3) <= (carry_temp(2) and (A(3) or novo_B(3))) or (A(3) and novo_B(3));
carry_temp(4) <= (carry_temp(3) and (A(4) or novo_B(4))) or (A(4) and novo_B(4));
carry_temp(5) <= (carry_temp(4) and (A(5) or novo_B(5))) or (A(5) and novo_B(5));
carry_temp(6) <= (carry_temp(5) and (A(6) or novo_B(6))) or (A(6) and novo_B(6));
carry_temp(7) <= (carry_temp(6) and (A(7) or novo_B(7))) or (A(7) and novo_B(7));
carry_temp(8) <= (carry_temp(7) and (A(8) or novo_B(8))) or (A(8) and novo_B(8));
carry_temp(9) <= (carry_temp(8) and (A(9) or novo_B(9))) or (A(9) and novo_B(9));
carry_temp(10) <= (carry_temp(9) and (A(10) or novo_B(10))) or (A(10) and novo_B(10));
carry_temp(11) <= (carry_temp(10) and (A(11) or novo_B(11))) or (A(11) and novo_B(11));
carry_temp(12) <= (carry_temp(11) and (A(12) or novo_B(12))) or (A(12) and novo_B(12));
carry_temp(13) <= (carry_temp(12) and (A(13) or novo_B(13))) or (A(13) and novo_B(13));
carry_temp(14) <= (carry_temp(13) and (A(14) or novo_B(14))) or (A(14) and novo_B(14));
carry_temp(15) <= (carry_temp(14) and (A(15) or novo_B(15))) or (A(15) and novo_B(15));
carry_temp(16) <= (carry_temp(15) and (A(16) or novo_B(16))) or (A(16) and novo_B(16));
carry_temp(17) <= (carry_temp(16) and (A(17) or novo_B(17))) or (A(17) and novo_B(17));
carry_temp(18) <= (carry_temp(17) and (A(18) or novo_B(18))) or (A(18) and novo_B(18));
carry_temp(19) <= (carry_temp(18) and (A(19) or novo_B(19))) or (A(19) and novo_B(19));
carry_temp(20) <= (carry_temp(19) and (A(20) or novo_B(20))) or (A(20) and novo_B(20));
carry_temp(21) <= (carry_temp(20) and (A(21) or novo_B(21))) or (A(21) and novo_B(21));
carry_temp(22) <= (carry_temp(21) and (A(22) or novo_B(22))) or (A(22) and novo_B(22));
carry_temp(23) <= (carry_temp(22) and (A(23) or novo_B(23))) or (A(23) and novo_B(23));
carry_temp(24) <= (carry_temp(23) and (A(24) or novo_B(24))) or (A(24) and novo_B(24));
carry_temp(25) <= (carry_temp(24) and (A(25) or novo_B(25))) or (A(25) and novo_B(25));
carry_temp(26) <= (carry_temp(25) and (A(26) or novo_B(26))) or (A(26) and novo_B(26));
carry_temp(27) <= (carry_temp(26) and (A(27) or novo_B(27))) or (A(27) and novo_B(27));
carry_temp(28) <= (carry_temp(27) and (A(28) or novo_B(28))) or (A(28) and novo_B(28));
carry_temp(29) <= (carry_temp(28) and (A(29) or novo_B(29))) or (A(29) and novo_B(29));
carry_temp(30) <= (carry_temp(29) and (A(30) or novo_B(30))) or (A(30) and novo_B(30));
carry_temp(31) <= (carry_temp(30) and (A(31) or novo_B(31))) or (A(31) and novo_B(31));
overflow_temp <= carry_temp(31) xor carry_temp(30);
Overflow <= overflow_temp;
--------------------------------------------------------------------------------
--
Regiao que calcula a comparação
--
--------------------------------------------------------------------------------
-- No codigo da comparacao (110) sera executada a subtracao na parte relativa
-- ao calculo da SOMA, SUBTRACAO e INCREMENTO.
igual_temp <= not(overflow_temp) when soma_temp = "00000000000000000000000000000000"
else '0'; -- Quando subtracao e zero
Igual <= igual_temp;
-- Se nao teve overflow -> resultado baseado no bit mais significativo de A - B.
-- Se teve overflow -> A e B possuem, necessariamente, sinais contrarios. Resultado
-- baseado no bit mais significativo de A.
-- Devemos tambem checar se A e B nao sao iguais
Maior <= ( (not(soma_temp(31)) and (not(overflow_temp)) )or (overflow_temp and (not(A(31))))) and (not(igual_temp));
-- Se nao teve overflow -> resultado baseado no bit mais significativo de A - B.
-- Se teve overflow -> A e B possuem, necessariamente, sinais contrarios. Resultado
-- baseado no bit mais significativo de A.
Menor <= ((soma_temp(31) and (not(overflow_temp))) or (overflow_temp and A(31)));
end behavioral;
Código 4.5 Comportamental VHDL da Unidade Lógica e Aritmética
4.1.6 Registrador comum de dados, 32 bits
Componente básico da arquitetura de qualquer computador, um registrador é um conjunto seqüencial de células de memória, conhecidas amplamente no domínio de desenvolvimento de sistemas digitais pelos termos ingleses latches e flip-flops. Conforme já explicado, por definição, no MIPS, todos os registradores de uso interno são componentes capazes de armazenar 32 bits de informação. Para armazenar instruções e dados, bem como o endereço de instruções, serão utilizados esses componentes.
Figura 2.7 Registrador de dados, 32 bits.
O código VHDL para o componente registrador é simples. Encontra-se apresentado abaixo.O registardor é peça fundamental de um processador e como tal é utilizado em várias vezes na nossa implementação.Utilizamos este componente da seguinte forma:Para armazenar a saída da ULA;Para armazenar os sinais HI e LO.Para armazenar os conteúdos que vem do banco de registradores em A e B no caso;Para guardar o PC.Para guardar o conteúdo que sai de MDR.Para guardar o PC atual em EPC.
--------------------------------------------------------------------------------
-- Title
: Registrador de Uso Geral
-- Project
: CPU Multi-ciclo
--------------------------------------------------------------------------------
-- File
: Registrador.vhd
-- Author
: Emannuel Gomes Macêdo ([email protected])
--
Fernando Raposo Camara da Silva ([email protected])
--
Pedro Machado Manhães de Castro ([email protected])
--
Rodrigo Alves Costa ([email protected])
-- Organization : Universidade Federal de Pernambuco
-- Created
: 11/07/2002
-- Last update: 21/11/2002
-- Plataform: Flex10K
-- Simulators: Altera Max+plus II
-- Synthesizers:
-- Targets
:
-- Dependency:
--------------------------------------------------------------------------------
-- Description: Entidade que representa a unidade básica de uma cpu ou um
-- circuito que armazena dados na forma de bits.
--------------------------------------------------------------------------------
-- Copyright (c) notice
--
Universidade Federal de Pernambuco (UFPE).
--
CIn - Centro de Informatica.
--
Developed by computer science undergraduate students.
--
This code may be used for educational and non-educational purposes as
--
long as its copyright notice remains unchanged.
--------------------------------------------------------------------------------
-- Revisions
: 1
-- Revision Number: 1.0
-- Version
: 1.1
-- Date
: 21/11/2002
-- Modifier
: Marcus Vinicius Lima e Machado ([email protected])
--
Paulo Roberto Santana Oliveira Filho ([email protected])
--
Viviane Cristina Oliveira Aureliano ([email protected])
-- Description
:
--------------------------------------------------------------------------------
--Short name: reg
ENTITY Registrador IS
PORT(
Clk
: INbit;
-- Clock do registrador
Reset: INbit;
-- Reinicializa o conteudo do registrador
Load: INbit;
-- Carrega o registrador com o vetor Entrada
Entrada : INbit_vector (31 downto 0);
-- Vetor de bits que possui a informação a ser carregada no registrador
Saida: OUTbit_vector (31 downto 0)
-- Vetor de bits que possui a informação já carregada no registrador
);
END Registrador;
-- Arquitetura que define comportamento do Registrador
-- Simulation
ARCHITECTURE behavioral_arch OF Registrador IS
begin
-- Clocked process
process (Clk, Reset)
begin
------------------------------------------- Reset inicializa o registrador comum
if(Reset = '1') then
Saida <= "00000000000000000000000000000000";
------------------------------------------- Início do processo relacionado ao clock
elsif (Clk = '1' and clk'event) then
if (Load = '1') then
Saida <= Entrada;
end if;
end if;
------------------------------------------- Fim do processo relacionado ao clock
end process;
------------------------------------------- Fim da Arquitetura
END behavioral_arch;
Código 4.6 Descrição comportamental VHDL do Registador 32 bits.
4.2 Módulos Desenvolvidos
Durante a análise do fluxo de execução das instruções implementadas pela estrutura fornecida, desenrolou-se um processo de compreensão profunda do sistema proposto a desenvolvimento. Visando à implementação de uma unidade de processamento capaz de implementar o repertório exigido, a equipe de desenvolvimento produziu módulos, componentes específicos e exclusivos e os alocou convenientemente à unidade parcial em mãos. Segue-se a descrição pormenorizada dos blocos internos desenvolvidos a que se faz referência.
4.2.1 RegistradorDesl
Entidade responsável pelo envio de um vetor que indica a quantidade de deslocamentos a ser realizada no registrador. Esta entidade possibilita que a quantidade de deslocamentos possíveis pelo registrador seja de até 32 deslocamentos. Pois a quantidade é informada por partes (em até 5 partes) para o registrador.
Entradas:
N: vetor de 5 bits que indica a quantidade de deslocamentos
Shift: vetor de 3 bits que indica a função a ser realizada pelo registrador.
Abaixo seguem os valores referentes à entrada shift e as respectivas funções do registrador:
Shift
FUNÇÃO DO REGISTRADOR
000
faz nada
001
carrega vetor (sem deslocamentos)
010
deslocamento à esquerda n vezes
011
deslocamento à direita lógico n vezes
100
deslocamento à direita aritmético n vezes
101
rotação à direita n vezes
110
rotação à esquerda n vezes
Nesta entidade só é utilizado a entrada 001 do Shift para verificar se foi introduzido alguma nova entrada no módulo a fim de zerar todos os sinais desta entidade.
Segue a descrição em VHDL do componente.
--------------------------------------------------------------------------------
-- Title
: Registrador de Deslocamento
-- Project
: CPU Multi-ciclo
--------------------------------------------------------------------------------
-- File
: RegDesloc.vhd
-- Author
: Emannuel Gomes Macêdo
--
Fernando Raposo Camara da Silva
--
Pedro Mach