Diferență între revizuiri ale paginii „Laboratorul 4”
Linia 41: | Linia 41: | ||
=== Registrul pipeline R1 === | === Registrul pipeline R1 === | ||
− | Acesta salvează la finalul ciclului de ceas (de citire a instrucțiunii) instrucțiunea primită de la memoria de program. Actualizarea registrului pipeline este oprită dacă procesorul execută instrucțiunea ''HALT''. | + | Acesta salvează la finalul ciclului de ceas (de citire a instrucțiunii) instrucțiunea primită de la memoria de program. Actualizarea registrului pipeline este oprită dacă procesorul execută instrucțiunea ''HALT''. La resetare registrul pipeline este încărcat cu 0, adică cu codul instrucțiunii ''NOP''. |
<syntaxhighlight lang="Verilog"> | <syntaxhighlight lang="Verilog"> | ||
Linia 56: | Linia 56: | ||
=== READ === | === READ === | ||
− | În etapa de citire a operanzilor procesorul accesează setul de registre pe baza câmpurilor sursă ale instrucțiunii din registrul R1, preia datele din registrele sursă și livrează operanzii pentru a fi stocați în registrul pipeline următor, R2. Pentru instrucțiunea ''LOADC'' operandul 2 este preluat direct din câmpul constantă al instrucțiunii din R1. Logica de selecție a multiplexorului operandului 2 se | + | În etapa de citire a operanzilor procesorul accesează setul de registre pe baza câmpurilor sursă ale instrucțiunii din registrul R1, preia datele din registrele sursă și livrează operanzii pentru a fi stocați în registrul pipeline următor, R2. Pentru instrucțiunea ''LOADC'' operandul 2 este preluat direct din câmpul constantă al instrucțiunii din R1. Logica de selecție a multiplexorului operandului 2 se bazează pe comparația codului instrucțiunii curente, '''r1_opcode''', cu codul instrucțiunii ''LOADC''. |
+ | |||
+ | <syntaxhighlight lang="Verilog"> | ||
+ | assign operand2 = (r1_opcode == 4'b1000) ? r1_instr_data : rdata2; // LOADC are în binar codul 1000 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Pentru claritatea codului, folosiți nume dedicate pentru fiecare câmp al instrucțiunii din R1 | ||
+ | |||
+ | <syntaxhighlight lang="Verilog"> | ||
+ | assign r1_opcode = r1[15:12]; | ||
+ | assign r1_dest = r1[11: 8]; | ||
+ | assign r1_sursa1 = r1[ 7: 4]; | ||
+ | assign r1_sursa2 = // <<<<< COMPLETAȚI CODUL ! | ||
+ | assign r1_instr_data = // <<<<< COMPLETAȚI CODUL ! | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === Registrul pipeline R2 === | ||
+ | |||
+ | Acest registru pipeline salvează operanzii și o parte a instrucțiunii ce a trecut de etapa de citire, câmpurile sursă și constantă nemaifiind necesare. | ||
+ | Spre deosebire de registrul R1 care era declarat ca o singură variabilă '''r1''', registrul R2 este compus din patru variabile distincte. | ||
+ | Este foarte important ca după execuția instrucțiunii ''HALT'' acest registru pipeline să nu se mai actualizeze - astfel instrucțiunea ''HALT'' rămâne în registrul pipeline R2 asigurând blocarea procesorului până la resetare. La resetare registrul pipeline este încărcat cu 0, adică cu codul instrucțiunii ''NOP''. | ||
+ | |||
+ | <syntaxhighlight lang="Verilog"> | ||
+ | always @(posedge clk) begin | ||
+ | if(rst) begin | ||
+ | r2_opcode <= 0; | ||
+ | r2_dest <= 0; | ||
+ | r2_operand1 <= 0; | ||
+ | r2_operand2 <= 0; | ||
+ | end | ||
+ | else if(halt) begin | ||
+ | r2_opcode <= // <<<<< COMPLETAȚI CODUL ! | ||
+ | . . . . . | ||
+ | end | ||
+ | else begin | ||
+ | r2_opcode <= r1_opcode; | ||
+ | r2_dest <= // <<<<< COMPLETAȚI CODUL ! | ||
+ | r2_operand1 <= operand1; | ||
+ | r2_operand2 <= // <<<<< COMPLETAȚI CODUL ! | ||
+ | end | ||
+ | end | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === EXECUTE === |
Versiunea de la data 7 noiembrie 2019 02:13
Arhitectura Harvard
Arhitectura de calculator Harvard are magistrale distincte pentru accesul la program și la date, permițând astfel citirea unei instrucțiuni în paralel cu citirea sau scrierea datei altei instrucțiuni. Programul și datele se află în memorii separate sau într-o memorie comună dar cu porturi multiple de acces.
Procesorul pipeline
Procesorul are o structură pipeline cu trei niveluri:
- FETCH - citirea instrucțiunii din memoria de program
- READ - citirea operanzilor din setul de registre
- EXECUTE - execuția operației instrucțiunii/accesul în memoria de date
În această lucrare de laborator se va implementa un procesor pipeline fără gestiunea dependențelor de date sau de control, ce procesează setul de instrucțiuni din laboratoarele precedente. Implementarea va reutiliza integral blocurile ALU și REGS proiectate în laboratorul 1, și cu mici modificări memoria din laboratorul 2.
Schema detaliată a structurii pipeline pune în evidență toate căile de date și semnalele de control. Schema este desenată astfel încât fluxul de instrucțiuni și de date să fie de la stânga la dreapta, cu excepția căii de scriere în setul de registre și a semnalului special de control halt.
PC
Contorul de program incrementează în fiecare ciclu de ceas cu excepția cazului în care procesorul a fost oprit de instrucțiunea HALT.
always @(posedge clk) begin
if(rst)
pc <= 0;
else if(halt)
pc <= pc;
else
pc <= pc + 1;
end
FETCH
Setul de instrucțiuni fiind foarte simplu pentru acest laborator, nu există logică suplimentară în etapa de citire a instrucțiunii. Procesorul trimite spre memoria de program adresa instrucțiunii, adică valoarea PC, și preia instrucțiunea de la ieșirea acesteia.
Registrul pipeline R1
Acesta salvează la finalul ciclului de ceas (de citire a instrucțiunii) instrucțiunea primită de la memoria de program. Actualizarea registrului pipeline este oprită dacă procesorul execută instrucțiunea HALT. La resetare registrul pipeline este încărcat cu 0, adică cu codul instrucțiunii NOP.
always @(posedge clk) begin
if(rst)
r1 <= 0;
else if(halt)
r1 <= r1;
else
r1 <= instr;
end
READ
În etapa de citire a operanzilor procesorul accesează setul de registre pe baza câmpurilor sursă ale instrucțiunii din registrul R1, preia datele din registrele sursă și livrează operanzii pentru a fi stocați în registrul pipeline următor, R2. Pentru instrucțiunea LOADC operandul 2 este preluat direct din câmpul constantă al instrucțiunii din R1. Logica de selecție a multiplexorului operandului 2 se bazează pe comparația codului instrucțiunii curente, r1_opcode, cu codul instrucțiunii LOADC.
assign operand2 = (r1_opcode == 4'b1000) ? r1_instr_data : rdata2; // LOADC are în binar codul 1000
Pentru claritatea codului, folosiți nume dedicate pentru fiecare câmp al instrucțiunii din R1
assign r1_opcode = r1[15:12];
assign r1_dest = r1[11: 8];
assign r1_sursa1 = r1[ 7: 4];
assign r1_sursa2 = // <<<<< COMPLETAȚI CODUL !
assign r1_instr_data = // <<<<< COMPLETAȚI CODUL !
Registrul pipeline R2
Acest registru pipeline salvează operanzii și o parte a instrucțiunii ce a trecut de etapa de citire, câmpurile sursă și constantă nemaifiind necesare. Spre deosebire de registrul R1 care era declarat ca o singură variabilă r1, registrul R2 este compus din patru variabile distincte. Este foarte important ca după execuția instrucțiunii HALT acest registru pipeline să nu se mai actualizeze - astfel instrucțiunea HALT rămâne în registrul pipeline R2 asigurând blocarea procesorului până la resetare. La resetare registrul pipeline este încărcat cu 0, adică cu codul instrucțiunii NOP.
always @(posedge clk) begin
if(rst) begin
r2_opcode <= 0;
r2_dest <= 0;
r2_operand1 <= 0;
r2_operand2 <= 0;
end
else if(halt) begin
r2_opcode <= // <<<<< COMPLETAȚI CODUL !
. . . . .
end
else begin
r2_opcode <= r1_opcode;
r2_dest <= // <<<<< COMPLETAȚI CODUL !
r2_operand1 <= operand1;
r2_operand2 <= // <<<<< COMPLETAȚI CODUL !
end
end