This is an old revision of the document!
Task 00: Descărcați scheletul de laborator Schelet laborator și deschideți fișierul .xpr cu programul Vivado.
Task 01: Jocuri de lumini, memoria ROM (3p):
Analizați codul memoriei ROM din fișierul task01.v. Ce capacitate are această memorie ROM? Câți biți? Câți octeți?
Observați vreo greșeală în modulul rom din fișierul task01.v ? Dacă da, corectați aceste erori.
Analizați codul Verilog din fișierul read_rom.v. Modulul read_rom va citi conținutul memoriei rom și îl va afișa pe ledurile plăcii Nexys A7.
Completați TODO 1.1 din read_rom.v - adică instanțiați modulul rom.
Generați bitstream-ul pentru modulul read_rom. Încarcați acest bitstream pe placa FPGA. Modificați valoarea intrării read_frequency din switch-urile din dreapta de pe placa FPGA. Ce se afișează pe cele 16 leduri ?
(Opțional) Completați TODO 1.2 din fișierul task01.v, în interiorul modului rom pentru a încărca și un alt joc de lumini.
Semnalul data
trebuie declarat ca reg
din cauza restricției sintactice a limbajului Verilog, ca toate semnalele atribuite în interiorul unui bloc always
să fie de tipul reg
.
Blocul always trebuie să fie asincron față de ceas deci trebuie să fie declarat @*
În realitate, memoria va fi sintetizată ca un mare multiplexor, cu intrările hardcodate pentru fiecare selecție posibilă.
Memoria ROM cu conținut cu adevărat nemodificabil nu este nimic altceva decăt un circuit combinațional care primește ca intrare o adresă și scoate la ieșire o valoare hardcodată pentru acea adresă.
Pentru a adresa toți cei 16 octeți este nevoie de o lățime a adreselor de 4 biți.
// Pseudocod pentru o memorie ROM cu conținutul [1,2,4,8,16,32,64,128,170,85,3,5,1,0,53,13]:
module rom (input[4] adress, output[8] data)
{
always
case(adress)
4'd0: data = 8'd1
4'd1: data = 8'd2
4'd2: data = 8'd4
4'd3: data = 8'd8
4'd4: data = 8'd16
4'd5: data = 8'd32
4'd6: data = 8'd64
4'd7: data = 8'd128
4'd8: data = 8'd170
4'd9: data = 8'd85
4'd10: data = 8'd3
4'd11: data = 8'd5
4'd12: data = 8'd1
4'd13: data = 8'd0
4'd14: data = 8'd53
4'd15: data = 8'd13
default: data = 8'd0
end case
end always
}
Task 02: Memoria SRAM (4p) Implementați o memorie SRAM în fișierul task02.v pornind de la pseudocodul de mai jos și de la Structura interioară a unui bloc SRAM.
Urmăriți și rezolvați TODO-urile din task02.v
Completați TODO-urile din modulul de simulare test_sram existent în fișierul task02_test.v
Rulați simularea pentru modulul test_sram. Asigurați-vă că scrierile și citirile se fac corect.
Dacă ați completat toate TODO-urile ar trebui să vedeți în simulare ceva similar cu
Simulare task 02
De ce data_out este 'Z' după 650 ns ?
Activați Constraint file-ul pentru task-ul 02 astfel:
-
-
Generați bitstream-ul pentru modulul task02 și încărcați-l pe placa FPGA.
La fel ca în simulare scrieți valorile 0,1 și 2 la adresele 0x00, 0x01 și 0x02.
/*
* clk - clock
* oe - output enable, active high
* cs - chip select, active high
* we - write enable: 0 = read, 1 = write
* adresa - adrese pentru 32 de intrari
* data_in - intrare de date de 8 biti
* data_out - iesire de date de 8 biti
*/
module sram (input clk, input oe, input cs, input we, input[5] adresa, input[8] data_in, output[8] data_out)
{
registru[8] memorie
registru[8] buffer
always (clk)
if cs:
if we:
memorie[adresa] = data_in
else:
buffer = memorie[adresa]
end if
end if
end always
if cs & oe & !we:
data_out = buffer
else:
data_out = 8'bz
end if
}
Atentie! Porturile de date
vor fi de tip wire. Asta înseamna că nu vom mai putea face atribuiri pe aceste porturi în interiorul blocurilor procedurale. Va trebui să găsiți o altă metodă de a modifica aceste porturi, care să fie validă în interiorul acestor blocuri. Utilizați pseudocodul de mai sus pentru a rezolva exercițiul și pentru a identifica modul în care a fost rezolvată problema porturilor de tip wire.
Task 03 (3p) Descărcați scheletul Verilog al microcontrolerului Scheletul de laborator. Acest schelet îl vom folosi în laboratoarele viitoare. Astăzi ne vom familiariza cu structura acestuia. Identificați memoria de instrucțiuni. Ce tip de memorie este aceasta? Identificați modulele din cheatsheet-ul de mai sus.
În scheletul de laborator sunt câteva fișiere de interes:
alu.v execută operații aritmetice și logice. Aici vom calcula rezultatele operațiilor aritmetice.
checker Acest fișier instanțiază modulul principal - cpu.
check_view și checker vor fi utilizate doar pentru a simula procesorul și a verifica funcționalitatea acestuia înainte de a fi sintetizat pe FPGA
decode_unit.v se ocupă de decodificarea instrucțiunilor. Aici vom adăuga logica de decodificare pentru instrucțiunile noi.
control_unit.v implementează logica de control. Aici vom translata opcode_type primit de la decode_unit în alu_opsel - semnal transmis mai departe la unitatea aritmetică logică.
rom.v conține codul ce va fi executat (instrucțiunile în cod mașină)
Găsiți răspunsurile pentru următoarele întrebări:
Deschideți modulul cpu. Cum se numește parametrul ce definește lățimea datelor? Pe câți biți e definit ?
Câte registre generale are procesorul din schelet în memoria SRAM ? Care e lățimea registrelor ? (Nr. biti)
Câți bytes poate stoca memoria rom folosită pentru instrucțiuni așa cum e instanțiată în modulul cpu ? Câți bytes sunt scriși deja în memorie (cât ocupă instrucțiunile deja scrise)?
Câte stagii are pipeline-ul procesorului ? (Deschideți modulul state_machine)
Cu se stagiu al pipeline-ului se ocupă alu.v ? (Deschideți modulul control_unit)
Care este valoarea inițială a registrului r7 ?
Registrul SREG este registrul Status Register. Citiți despre acest registru în
setul de instructiuni AVR. Pentru procesorul din schelet acest registru conține 8 flag-uri, fiecare de câte un bit. Ce reprezintă flag-ul
S? Cum și unde este calculat pentru instrucțiunea (implementată deja)
Add with Carry din schelet?
Cheatsheeturi: