Laboratorul 2: Diferență între versiuni

De la WikiLabs
(Setul de instrucțiuni)
(Procesorul)
Linia 38: Linia 38:
 
Având o singură cale de acces atât pentru instrucțiuni, cât și pentru date, arhitectura von Neumann procesează o instrucțiune în mai mulți pași, în fiecare pas magistrala comună fiind configurată pentru un anumit transfer între blocurile și registrele conectate la aceasta. Secvențierea procesării instrucțiunilor se face cu ajutorul unității de control al procesorului (UCP), aceasta fiind implementată fie ca o mașină de stări, fie ca o structură microprogramabilă.
 
Având o singură cale de acces atât pentru instrucțiuni, cât și pentru date, arhitectura von Neumann procesează o instrucțiune în mai mulți pași, în fiecare pas magistrala comună fiind configurată pentru un anumit transfer între blocurile și registrele conectate la aceasta. Secvențierea procesării instrucțiunilor se face cu ajutorul unității de control al procesorului (UCP), aceasta fiind implementată fie ca o mașină de stări, fie ca o structură microprogramabilă.
  
Pentru a menține simplitatea la un nivel adecvat unui laborator introductiv, se va considera o arhitectură de procesor cu acumulator, fără set de registre, ale cărui instrucțiuni folosesc cel mult un operand din memorie, prin adresare imediată sau adresare directă.
+
Schema bloc a procesorului conține o unitate aritmetico-logică cu registre (RALU), un contor de program (PC) ce se poate incrementa sau încărca cu o valoare dată, un registru pentru adresarea memoriei pentru transferul de date (ADDR), registrul instrucțiunii (IR) ce păstrează codul instrucțiunii pe toată durata procesării acesteia și unitatea de control a procesorului (UCP):
 
 
Schema bloc a procesorului conține o unitate aritmetico-logică (ALU), un contor de program (PC) ce se poate incrementa sau încărca cu o valoare dată, un registru pentru adresarea memoriei (ADDR), registrul instrucțiunii (IR) ce păstrează codul instrucțiunii pe toată durata procesării acesteia, un registru pentru operandul adus din memorie (DATAIN), registrul acumulator (ACC), câțiva biți pentru indicații despre rezultatul ultimei operații efectuate de ALU (F) și unitatea de control a procesorului (UCP). Pentru a nu complica desenul, în schema bloc au fost schițate doar traseele principale (magistrala de date, calea de adresare):
 
  
 
[[Fișier: asc_lab2_microneumann.png]]
 
[[Fișier: asc_lab2_microneumann.png]]
  
 +
Pentru a nu complica desenul, în schema bloc au fost schițate doar traseele principale (căile de date). Semnalele de control generate de UCP controlează actualizarea tuturor registrelor (incrementarea PC, încărcarea PC, încărcarea ADDR, încărcarea instrucțiunii în IR byte cu byte, scrierea în registrul destinație din RALU precum și activarea scrierii în memoria externă. De asemenea semnalele de control configurează căile de date prin selecțiile corespunzătoare pentru multiplexoarele de acces. Adresa de memorie este fie adresa unui byte de instrucțiune (PC), fie adresa unei locații de date (ADDR). Data de pe magistrala comună este selectată din trei surse posibile, ea putând fi rezultatul RALU, sau data citită din memorie sau o dată imediată din instrucțiune (byte-ul inferior al acesteia).
  
 +
Pentru a simplifica procesarea internă și pentru a păstra ordinea câmpurilor instrucțiunii (opcode, destinatie, surse) este prevăzut un multiplexor suplimentar care permite selecția  sursei 1 pentru încărcarea adresei folosite de instrucțiunile de transfer cu memoria.
 +
 
=== PC ===
 
=== PC ===
  
Linia 50: Linia 51:
  
 
<syntaxhighlight lang="Verilog">
 
<syntaxhighlight lang="Verilog">
always @(poosedge clk) begin
+
always @(posedge clk) begin
 
     if(rst)
 
     if(rst)
 
         pc <= 0;
 
         pc <= 0;
 
     else begin
 
     else begin
 
         if(pc_load)
 
         if(pc_load)
             // PC ia valoarea de pe magistrala comună de date
+
             pc <= result;
         else if (pc_incr)
+
         else if(pc_incr)
 
             pc <= pc + 1;
 
             pc <= pc + 1;
 
         else
 
         else
Linia 69: Linia 70:
  
 
<syntaxhighlight lang="Verilog">
 
<syntaxhighlight lang="Verilog">
always @(poosedge clk) begin
+
always @(posedge clk) begin
 +
    if(rst)
 +
        data_addr <= 0;
 +
    else begin
 +
        if(addr_load)
 +
            data_addr <= result;
 +
        else
 +
          data_addr <= data_addr;
 +
    end
 +
end
 +
</syntaxhighlight>
 +
 
 +
 
 +
=== IR ===
 +
 
 +
Instrucțiunea fiind pe 16 biți este nevoie de două accese succesive la memorie, la adrese consecutive, pentru a încărca fiecare byte al registrului instrucțiunii.
 +
 
 +
<syntaxhighlight lang="Verilog">
 +
always @(posedge clk) begin
 
     if(rst)
 
     if(rst)
         raddr <= 0;
+
         instruction <= 0;
 
     else begin
 
     else begin
         if(raddr_load)
+
         if(ir_load_high)
             // ADDR ia valoarea de pe magistrala comună de date
+
             instruction[15:8] <= common_data;
 +
        else if(ir_load_low)
 +
            // încărcarea byte-ului inferior al instrucțiunii  // DE COMPLETAT !!!
 
         else
 
         else
             raddr <= raddr;
+
             instruction <= instruction;
 
     end
 
     end
 
end
 
end
 
</syntaxhighlight>
 
</syntaxhighlight>
  
=== UCP ===
+
Decodarea instrucțiunii este elementară și constă în separarea câmpurilor instrucțiunii:
 +
 
 +
<syntaxhighlight lang="Verilog">
 +
assign opcode    = instruction[15:12];
 +
// dest este al doilea câmp de 4 biți al instrucțiunii;  // DE COMPLETAT !!!
 +
assign sursa1    = instruction[ 7: 4];
 +
assign sursa2    = addr_load ? instruction[ 7: 4] : instruction[ 3: 0];
 +
// instr_data este byte-ul inferior al instrucțiunii    // DE COMPLETAT !!!
 +
</syntaxhighlight>
 +
 
 +
Byte-ul superior este la prima adresa și conține opcode-ul și câmpul destinație.
 +
 
 +
 
 +
== UCP ==
  
 
Unitatea de control a procesorului controlează actualizarea fiecărui registru din procesor, accesul la magistrala comună de date și multiplexarea adreselor spre memorie.
 
Unitatea de control a procesorului controlează actualizarea fiecărui registru din procesor, accesul la magistrala comună de date și multiplexarea adreselor spre memorie.
Ea se implementează ca un FSM cu câteva stări și tranziții ce depind de tipul instrucțiunii. Pentru o instrucțiune aritmetico-logică secvența de procesare are 4 pași, necesitând 4 cicuri de ceas:
+
Ea se implementează ca un FSM cu câteva stări și tranziții ce depind de tipul instrucțiunii.
  
 
[[Fișier: asc_lab1_fsmneumann.png]]
 
[[Fișier: asc_lab1_fsmneumann.png]]
 +
 +
=== tranzițiile ===
 +
 +
<syntaxhighlight lang="Verilog">
 +
always @(posedge clk) begin
 +
    if(rst) begin
 +
        state <= FETCH1;
 +
    end
 +
    else begin
 +
        case(state)
 +
 +
        FETCH1: state <= FETCH2;
 +
 
 +
        FETCH2: begin
 +
            case(opcode)
 +
                4'b0000: state <= FETCH1;  // NOP
 +
                4'b0001: state <= EXECUTE; // ADD
 +
                4'b1000: state <= LDCONST; // LOADC
 +
                4'b1001: state <= LDADDR;  // LOAD
 +
                4'b1010: state <= LDADDR;  // STORE
 +
                4'b1111: state <= HALT;    // HALT
 +
          endcase
 +
        end
 +
 
 +
        LDCONST: state <= FETCH1;
 +
 
 +
        LDADDR : begin
 +
            if(opcode == 4'b1001)
 +
                state <= LD_DATA;
 +
            if(opcode == 4'b1010)
 +
                state <= ST_DATA;
 +
        end
 +
 
 +
        LD_DATA: state <= FETCH1;  
 +
        ST_DATA: state <= FETCH1;  
 +
        EXECUTE: state <= FETCH1;  
 +
        HALT  : state <= HALT;
 +
        default: state <= HALT;
 +
        endcase
 +
    end
 +
end
 +
</syntaxhighlight>

Versiunea de la data 10 octombrie 2019 09:12

Arhitectura von Neumann

Arhitectura de calculator von Neumann este caracterizată printr-o memorie unică, în care se află atât programul cât și datele, și o magistrală unică, folosită pentru transferul instrucțiunilor de la memorie la procesor, a datelor între procesor și memorie sau între procesor și oricare din dispozitivele de intrare/ieșire conectate la magistrală.

În această lucrare de laborator se va realiza un calculator simplu, având doar procesorul și memoria.

Asc lab1 neumann.png

Setul de instrucțiuni

Tabelul 1
mnemonică detalii
ADD R[dest] <- R[sursa1] + R[sursa2]
SUB R[dest] <- R[sursa1] - R[sursa2]
AND R[dest] <- R[sursa1] & R[sursa2]
OR R[dest] <- R[sursa1] | R[sursa2]
XOR R[dest] <- R[sursa1] ^ R[sursa2]
CMP Z <- R[sursa1] == R[sursa2], N <- R[sursa1] >= R[sursa2]
LOADC R[dest] <- instr_data
LOAD R[dest] <- memorie[R[sursa1]]
STORE memorie[R[sursa1]] <- R[sursa2]
HALT halt

Procesorul

Având o singură cale de acces atât pentru instrucțiuni, cât și pentru date, arhitectura von Neumann procesează o instrucțiune în mai mulți pași, în fiecare pas magistrala comună fiind configurată pentru un anumit transfer între blocurile și registrele conectate la aceasta. Secvențierea procesării instrucțiunilor se face cu ajutorul unității de control al procesorului (UCP), aceasta fiind implementată fie ca o mașină de stări, fie ca o structură microprogramabilă.

Schema bloc a procesorului conține o unitate aritmetico-logică cu registre (RALU), un contor de program (PC) ce se poate incrementa sau încărca cu o valoare dată, un registru pentru adresarea memoriei pentru transferul de date (ADDR), registrul instrucțiunii (IR) ce păstrează codul instrucțiunii pe toată durata procesării acesteia și unitatea de control a procesorului (UCP):

Asc lab2 microneumann.png

Pentru a nu complica desenul, în schema bloc au fost schițate doar traseele principale (căile de date). Semnalele de control generate de UCP controlează actualizarea tuturor registrelor (incrementarea PC, încărcarea PC, încărcarea ADDR, încărcarea instrucțiunii în IR byte cu byte, scrierea în registrul destinație din RALU precum și activarea scrierii în memoria externă. De asemenea semnalele de control configurează căile de date prin selecțiile corespunzătoare pentru multiplexoarele de acces. Adresa de memorie este fie adresa unui byte de instrucțiune (PC), fie adresa unei locații de date (ADDR). Data de pe magistrala comună este selectată din trei surse posibile, ea putând fi rezultatul RALU, sau data citită din memorie sau o dată imediată din instrucțiune (byte-ul inferior al acesteia).

Pentru a simplifica procesarea internă și pentru a păstra ordinea câmpurilor instrucțiunii (opcode, destinatie, surse) este prevăzut un multiplexor suplimentar care permite selecția sursei 1 pentru încărcarea adresei folosite de instrucțiunile de transfer cu memoria.

PC

Contorul de program este folosit pentru citirea instrucțiunilor din memorie. Acesta poate fi incrementat sau încărcat cu valoarea de pe magistrala de date, dar numai la comanda UCP.

always @(posedge clk) begin
    if(rst)
        pc <= 0;
    else begin
        if(pc_load)
            pc <= result;
        else if(pc_incr)
            pc <= pc + 1;
        else
            pc <= pc;
    end
end

ADDR

Registrul de adresare a memoriei pentru citirea datelor este un registru elementar ce poate fi doar încărcat:

always @(posedge clk) begin
    if(rst)
        data_addr <= 0;
    else begin
        if(addr_load)
            data_addr <= result;
        else
           data_addr <= data_addr;
    end
end


IR

Instrucțiunea fiind pe 16 biți este nevoie de două accese succesive la memorie, la adrese consecutive, pentru a încărca fiecare byte al registrului instrucțiunii.

always @(posedge clk) begin
    if(rst)
        instruction <= 0;
    else begin
        if(ir_load_high)
            instruction[15:8] <= common_data;
        else if(ir_load_low)
            // încărcarea byte-ului inferior al instrucțiunii   // DE COMPLETAT !!!
        else
            instruction <= instruction;
    end
end

Decodarea instrucțiunii este elementară și constă în separarea câmpurilor instrucțiunii:

assign opcode     = instruction[15:12];
// dest este al doilea câmp de 4 biți al instrucțiunii;  // DE COMPLETAT !!!
assign sursa1     = instruction[ 7: 4];
assign sursa2     = addr_load ? instruction[ 7: 4] : instruction[ 3: 0];
// instr_data este byte-ul inferior al instrucțiunii     // DE COMPLETAT !!!

Byte-ul superior este la prima adresa și conține opcode-ul și câmpul destinație.


UCP

Unitatea de control a procesorului controlează actualizarea fiecărui registru din procesor, accesul la magistrala comună de date și multiplexarea adreselor spre memorie. Ea se implementează ca un FSM cu câteva stări și tranziții ce depind de tipul instrucțiunii.

Asc lab1 fsmneumann.png

tranzițiile

always @(posedge clk) begin
    if(rst) begin
        state <= FETCH1;
    end
    else begin
        case(state)

        FETCH1: state <= FETCH2;
		  
        FETCH2: begin
            case(opcode)
                4'b0000: state <= FETCH1;  // NOP
                4'b0001: state <= EXECUTE; // ADD
                4'b1000: state <= LDCONST; // LOADC
                4'b1001: state <= LDADDR;  // LOAD
                4'b1010: state <= LDADDR;  // STORE
                4'b1111: state <= HALT;    // HALT
           endcase
        end
		  
        LDCONST: state <= FETCH1;
		  
        LDADDR : begin
            if(opcode == 4'b1001)
                state <= LD_DATA;
            if(opcode == 4'b1010)
                state <= ST_DATA;
        end
		  
        LD_DATA: state <= FETCH1;	  
        ST_DATA: state <= FETCH1;	  
        EXECUTE: state <= FETCH1;	  
        HALT   : state <= HALT;
        default: state <= HALT;
        endcase
    end
end