Вы находитесь на странице: 1из 6

5.

Usando uma linguagem de descrio de hardware para projetar e simular um processador

Como mencionamos no Apndice B, a Verilog pode descrever processadores para simulao ou com o objetivo de que a especificao Verilog seja sintetizada. Para obter resultados de sntese aceitveis em tamanho e velocidade, uma especificao comportamental destinada sntese precisa delinear com cuidado as partes altamente combinacionais do projeto, como um caminho de dados, por meio do controle. O caminho de dados pode ento ser sintetizado usando bibliotecas disponveis. Uma especificao Verilog destinada sntese normalmente maior e mais complexa. Ilustramos essa dicotomia com duas descries Verilog de um processador MIPS: uma destinada a simulaes e outra adequada para a sntese.

Usando a Verilog para especificao comportamental com simulao


Para ilustrar o uso da Verilog para descrever implementaes comportamentais, a Figura 5.8.1 fornece uma especificao comportamental da implementao multiciclo do processador MIPS. Essa verso apresenta o mesmo comportamento de contagem de ciclo da implementao multiciclo anterior neste captulo, mas ela no usa o caminho de dados estrutural. Devido ao uso das operaes comportamentais, seria difcil sintetizar um caminho de dados e unidade de controle separados com qualquer eficincia razovel.
module CPU (clock); parameter LW = 6b100011, SW = 6b101011, BEQ=6b000100, J=6d2; input clock; //o clock uma entrada externa // Os registradores arquitetonicamente visveis e os registradores de rascunho para a implementao reg [31:0] PC, Regs[0:31], Memory [0:1023], IR, ALUOut, MDR, A, B; reg [2:0] state; // estado do processador wire [5:0] opcode; //usado para obter o opcode facilmente wire [31:0] SignExtend,PCOffset; //usado para obter o campo offset com sinal estendido assign opcode = IR[31:26]; //o opcode so os 6 bits mais significativos assign SignExtend = {{16{IR[15]}},IR[15:0]}; //extenso de sinal dos 16 bits menos significativos da instruo assign PCOffset = SignExtend << 2; //O offset do PC deslocado // Coloca o PC como 0 e inicia o controle no estado 0 initial begin PC = 0; state = 1; end //A mquina de estados disparada uma transio de subida do clock always @(posedge clock) begin Regs[0] = 0; //Faz R0 = 0 //modo rpido de garantir que R0 sempre seja 0 case (state) //a ao depende do estado 1: begin // primeira etapa: buscar a instruo, incrementar o PC, ir para o prximo estado IR <= Memory[PC>>2]; PC <= PC + 4; state=2; //prximo estado end 2: begin // segunda etapa: Decodificao da instruo, busca dos registradores, tambm calcula endereo de desvio A <= Regs[IR[25:21]]; B <= Regs[IR[20:16]]; state= 3; ALUOut <= PC + PCOffset; // calcula o destino de desvio relativo ao PC

5.8-2

5.8

Usando uma linguagem de descrio de hardware para projetar e simular um processador

ELSEVIER

end 3: begin // terceira etapa: execuo de load/store, execuo da ALU, concluso do branch state =4; // prximo estado padro if ((opcode==LW) |(opcode==SW)) ALUOut <= A + SignExtend; //calcula endereo efetivo else if (opcode==6b0) case (IR[5:0]) //case para as vrias instrues tipo R 32: ALUOut= A + B; //operao de soma default: ALUOut= A; //outras operaes tipo R: subtrao, SLT etc. endcase else if (opcode == BEQ) begin if (A==B) PC <= ALUOut; // desvio tomado atualiza o PC state = 1; end else if (opocde=J) begin PC = {PC[31:28], IR[25:0],2b00}; // o PC de destino do jump state = 1; end //Jumps else ; // outros opcodes ou exceo para instruo indefinida entrariam aqui end 4: begin if (opcode==6b0) begin //operao da ALU Regs[IR[15:11]] <= ALUOut; // escreve o resultado state =1; end //tipo R termina else if (opcode == LW) begin // instruo load MDR <= Memory[ALUOut>>2]; // l a memria state =5; // prximo estado end else if (opcode == LW) begin Memory[ALUOut>>2] <= B; // escreve na memria state = 1; // retorna para o estado 1 end //store termina else ; // outras instrues entram aqui end 5: begin // LW a nica instruo ainda em execuo Regs[IR[20:16]] = MDR; // escreve o MDR no registrador state = 1; end //completa uma instruo LW endcase end endmodule
FIGURA 5.8.1 Uma especificao comportamental do projeto MIPS multiciclo. Isso apresenta o mesmo comportamento de ciclo do projeto multiciclo, mas unicamente para simulao e especificao. Essa especificao no pode ser usada para sntese.

Essa verso tambm demonstra outro mtodo para o controle usando uma mquina de estados finitos de Mealy (veja a Seo B.10 do Apndice B). O uso de uma mquina de Mealy, que permite que a sada dependa das entradas e do estado atual, nos permite diminuir o nmero total de estados para 5.

5.8

Usando uma linguagem de descrio de hardware para projetar e simular um processador

5.8-3

Usando a Verilog para especificao comportamental e para sntese


Como uma verso do projeto MIPS destinada sntese consideravelmente mais complexa, baseamo-nos em diversos mdulos da Verilog especificados no Apndice B, incluindo os seguintes:
n n n n

O multiplexador 4 para 1 mostrado na Figura B.4.2 e o multiplexador 3 para 1 que pode ser normalmente derivado com base no multiplexador 4 para 1. A ALU MIPS mostrada na Figura B.5.15. O controle da ALU MIPS definido na Figura B.5.16. O banco de registradores MIPS definido na Figura B.8.11.

Agora, vejamos uma verso Verilog do processador MIPS destinado para a sntese. A Figura 5.8.2 mostra a verso estrutural do caminho de dados MIPS. A Figura 5.8.3 usa o mdulo de caminho de dados para especificar a CPU MIPS. Essa verso tambm demonstra outro mtodo para implementar a unidade de controle, bem como algumas otimizaes baseadas nas relaes entre vrios sinais de controle. Observe que a especificao da mquina de estados apenas fornece as aes de seqenciao. A decomposio entre o controle principal e o caminho de dados a mesma feita na Seo 5.5.

module Datapath (ALUOp, RegDst, MemtoReg, MemRead, MemWrite, IorD, RegWrite, IRWrite, PCWrite, PCWriteCond, ALUSrcA, ALUSrcB, PCSource, opcode, clock); // as entradas de controle + clock input [1:0] ALUOp, ALUSrcB, PCSource; // sinais de controle de 2 bits input RegDst, MemtoReg, MemRead, MemWrite, IorD, RegWrite, IRWrite, PCWrite, PCWriteCond, ALUSrcA, clock; // sinais de controle de 1 bit output [5:0] opcode ;// opcode necessrio como uma sada pelo controle reg [31:0] PC, Memory [0:1023], MDR,IR, ALUOut; // estado da CPU + alguns temporrios wire [31:0] A,B,SignExtendOffset, PCOffset, ALUResultOut, PCValue, JumpAddr, Writedata, ALUAin, ALUBin,MemOut; // esses so sinais derivados dos registradores wire [3:0] ALUCtl; //as linhas de controle da ALU wire Zero; // O sinal Zero de sada da ALU wire[4:0] Writereg;// os sinais usados para indicar o registrador destino initial PC = 0; // inicializa o PC com 0

// Sinais combinacionais usados no caminho de dados // L usando endereo em words com ALUOut ou PC como a origem do endereo assign MemOut = MemRead ? Memory[(IorD ? ALUOut : PC)>>2]:0; assign opcode = IR[31:26];// atalho de opcode // Obtm o endereo do registrador de escrita de um dos dois campos dependendo de RegDst assign Writereg = RegDst ? IR[15:11]: IR[20:16]; // Obtm os dados do registrador de escrita de ALUOut ou do MDR assign Writedata = MemtoReg ? MDR : ALUOut; // Estende o sinal da metade inferior do IR dos offsets de load/store/ branch assign SignExtendOffset = {{16{IR[15]}},IR[15:0]}; // estende o sinal dos 16 bits inferiores; // O offset de branch tambm deslocado para torn-lo um offset de word assign PCOffset = SignExtendOffset << 2; // A entrada A para a ALU o registrador rs ou o PC assign ALUAin = ALUSrcA ? A : PC; // a entrada da ALU PC ou A // Compe o endereo de jump assign JumpAddr = {PC[31:28], IR[25:0],2b00}; // O endereo de jump

5.8-4

5.8

Usando uma linguagem de descrio de hardware para projetar e simular um processador

ELSEVIER

// Cria uma instncia da unidade de controle da ALU (veja o mdulo definido na Figura B.5.16) // Entrada ALUOp atvada pela unidade de controle e usada para descrever a classe de instruo como no Captulo 5 // Entrada IR[5:0] o campo de cdigo de funo para uma instruo que usa a ALU // Sada ALUCtl so os bits de controle da ALU como no Captulo 5 ALUControl alucontroller (ALUOp,IR[5:0],ALUCtl); // unidade de controle da ALU

// Cria um multiplexador de 3 para 1 usado para selecionar a origem do prximo PC // Entradas so ALUResultOut (o PC incrementado), ALUOut (o endereo de desvio), o endereo de destino do desvio // PCSource a entrada do seletor e PCValue a sada do multiplexador Mult3to1 PCdatasrc (ALUResultOut,ALUOut,{PC[31:28],IR[25:0], 2b00}, PCSource , PCValue);

// Cria um multiplexador de 4 para 1 usado para selecionar a entrada B da ALU // As entradas so o registrador B, a constante 4, a metade menos significativa de IR com o sinal estendido, a metade menos significativa de IR com o sinal estendido << 2 // ALUSourceB a entrada do seletor // ALUBin a sada do multiplexador Mult4to1 ALUBinput (B,32d4,SignExtendOffset,PCOffset,ALUSrcB,ALUBin);

// Cria uma ALU MIPS // As entradas so ALUCtl (o controle da ALU), entradas de valor da ALU (ALUAin, ALUBin) // As sadas so ALUResultOut (a sada de 32 bits) e Zero (sada de deteco de zero) MIPSALU ALU (ALUCtl, ALUAin, ALUBin, ALUResultOut,Zero); //a ALU

// Cria um banco de registradores MIPS // As entradas so // os campos rs e rt do IR usados para especificar que registradores ler, // Writereg (o nmero do registrador de escrita), Writedata (os dados a serem escritos), RegWrite (indica uma escrita), o clock // As sadas so A e B, registradores lidos registerfile regs (IR[25:21],IR[20:16],Writereg,Writedata,RegWrite,A,B,clock); // Banco de registradores

// As aes disparadas pelo clock do caminho de dados always @(posedge clock) begin if (MemWrite) Memory[ALUOut>>2] <= B; // Escreve na memria precisa ser um store ALUOut <= ALUResultOut; // Salva o resultado da ALU para uso em um ciclo de clock posterior if (IRWrite) IR <= MemOut; // Escreve em IR se for a busca de uma instruo MDR <= MemOut; // Sempre salva o valor de leitura da memria // O PC escrito incondicionalmente (controlado por PCWrite) ou condicionalmente if (PCWrite || (PCWriteCond & Zero)) PC <=PCValue; end endmodule
FIGURA 5.8.2 Uma verso Verilog do caminho de dados MIPS multiciclo que apropriada para sntese. Este caminho de dados se baseia em vrias unidades do Apndice B. Instrues iniciais no sintetizam e uma verso usada para sntese precisaria incorporar um sinal reset que tivesse esse efeito. Observe tambm que redefinir R0 para 0 em cada clock no a melhor maneira de garantir que R0 permanea como 0; em vez disso, modificar o mdulo do banco de registradores para produzir 0 sempre que R0 lido e ignorar escritas em R0 seria uma soluo mais eficiente.

5.8

Usando uma linguagem de descrio de hardware para projetar e simular um processador

5.8-5

module CPU (clock); parameter LW = 6b100011, SW = 6b101011, BEQ=6b000100, J=6d2; //constantes input clock; reg [2:0] state; wire [1:0] ALUOp, ALUSrcB, PCSource; wire [5:0] opcode; wire RegDst, MemRead, MemWrite, IorD, RegWrite, IRWrite, PCWrite, PCWriteCond, ALUSrcA, MemoryOp, IRWwrite, Mem2Reg;

// Cria uma instncia do caminho de dados MIPS, as entradas so os sinais de controle; opcode apenas sada Datapath MIPSDP (ALUOp,RegDst,Mem2Reg, MemRead, MemWrite, IorD, RegWrite, IRWrite, PCWrite, PCWriteCond, ALUSrcA, ALUSrcB, PCSource, opcode, clock); initial begin state = 1; end // Inicializa a mquina de estados no estado 1

// Estas so as definies dos sinais de controle assign IRWrite = (state==1); assign Mem2Reg = ~ RegDst; assign MemoryOp = (opcode==LW)|(opcode==SW); // uma operao de acesso memria assign ALUOp = ((state==1)|(state==2)|((state==3)&MemoryOp)) ? 2b00 : // soma ((state==3)&(opcode==BEQ)) ? 2b01 : 2b10; // subtrai ou usa o cdigo de funo assign RegDst = ((state==4)&(opcode==0)) ? 1 : 0; assign MemRead = (state==1) | ((state==4)&(opcode==LW)); assign MemWrite = (state==4)&(opcode==SW); assign IorD = (state==1) ? 0 : (state==4) ? 1 : X; assign RegWrite = (state==5) | ((state==4) &(opcode==0)); assign PCWrite = (state==1) | ((state==3)&(opcode==J)); assign PCWriteCond = (state==3)&(opcode==BEQ); assign ALUSrcA = ((state==1)|(state==2)) ? 0 :1; assign ALUSrcB = ((state==1) | ((state==3)&(opocde==BEQ))) ? 2b01 :(state==2) ? 2b11 : ((state==3)&MemoryOp) ? 2b10 : 2b00; // operao de acesso memria ou outra assign PCSource = (state==1) ? 2b00 : ((opcode==BEQ) ? 2b01 : 2b10);

// Aqui est a mquina de estados, que precisa apenas seqenciar estados always @(posedge clock) begin // todas as atualizaes de estado em uma transio de clock positiva case (state) 1: state = 2; // prximo estado no condicional 2: state = 3; // prximo estado no condicional 3: // terceira etapa: jumps e branches completos state = ((opcode==BEQ) | (opcode==J)) ? 1 : 4;// branch ou jump voltam para outro estado 4: state = (opcode==LW) ? 5 : 1; //tipo R e SW terminam 5: state =1; // volta endcase end endmodule
FIGURA 5.8.3 A CPU MIPS usando o caminho de dados da Figura 5.8.2.

A definio das linhas de controle feita com uma srie de instrues assign que dependem do estado e do campo opcode do registrador de instruo. Se fssemos organizar a definio do controle na especificao de estados, isso iria parecer a unidade de controle de estados finitos no estilo de Mealy. Como a definio das linhas de controle especificada usando instrues assign fora do bloco always, a maioria dos sistemas de sntese de lgica ir gerar uma pequena implementao de uma mquina de estados finitos que determina a definio do registrador de estado e, depois, gerar a lgica externa para derivar as entradas de controle para o caminho de dados.

5.8-6

5.8

Usando uma linguagem de descrio de hardware para projetar e simular um processador

ELSEVIER

Ao escrever essa verso do controle, tambm tiramos proveito de diversos insights sobre a relao entre vrios sinais de controle, bem como situaes em que no nos importamos com o valor do sinal de controle; alguns exemplos disso so fornecidos no seguinte Detalhamento. Detalhamento: quando especificam controle, os projetistas freqentemente tiram proveito do conhecimento do controle de modo a simplificar ou reduzir a especificao do controle. Aqui esto alguns exemplos da especificao nas Figuras 5.8.2 e 5.8.3. 1. MemtoReg definido apenas em dois casos e, depois, sempre o inverso de RegDst; portanto, usamos apenas o inverso de RegDst. 2. IRWrite definido apenas no estado 1. 3. A ALU no opera em todo fim de estado e, quando vaga, pode seguramente fazer qualquer coisa. 4. RegDst 1 em apenas um caso e pode, de outro modo, ser definido como 0. Na prtica, pode ser melhor defini-lo explicitamente quando necessrio e, caso contrrio, defini-lo como X, como fazemos para IorD. Primeiro, ele permite possibilidades de otimizao de lgica adicionais por meio da explorao de termos dont care (veja o Apndice C para obter mais informaes e exemplos). Segundo, ele uma especificao mais precisa, e isso permite a simulao para modelar mais fielmente o hardware, revelando erros adicionais na especificao.

Вам также может понравиться