CID Seminar 5

De la WikiLabs

În acest seminar veţi învăţa să descrieţi memorii de tip Random Access (RAM) și Read Only (ROM) folosind vectori de date în Verilog.

Cuvinte cheie: memorie, vector, RAM, ROM

Sintaxă Verilog: $readmemh, $readmemb, parameter

Memoriile reprezintă structuri fizice de stocare de date, caracterizate prin două măsuri:

  • numărul de cuvinte N;
  • numărul de biți ai fiecărui cuvânt stocat, W;

Capacitatea de stocare este NxW biți.

Astfel, veți întâlni deseori terminologia de memorie 1024x8b, ceea ce descrie o memorie cu o capacitate de 1024 de cuvinte a 8 biți fiecare.

Memoriile pot fi clasificate în funcție de capacitatea lor de a suprascrie valorile stocate cu valori noi:

  • memoriile Random-Access (RAM) permit și operații de suprascriere a conținutului cuvintelor stocate;
  • memoriile Read-Only (ROM) permit doar citirea.

De asemenea, memoriile pot fi clasificate în funcție de caracterul lor sincron sau asincron:

  • asincron – citirea se face imediat ce se prezintă comanda;
  • sincrone – toate operațiile sunt sincronizate de unul din fronturile semnalului de ceas.

Din considerente de implementare fizică, scrierea este întotdeauna sincronă.

Orice memorie RAM are următorul set de semnale de interfață, care formează un port al memoriei:

  • adresa – intrare – specifică indexul cuvântului pe care îl dorim accesat, pentru scriere sau citire;
  • datele pentru scriere – intrare – datele care vor fi scrise la indexul specificat de adresă;
  • datele citite – ieșire – datele care au fost citite de la indexul specificat de adresă;
  • comanda de scriere – intrare – specifică dacă se dorește scriere sau citire;
  • semnalul de ceas.

În funcție de configurația portului de memorie, unele din aceste semnale pot lipsi. De exemplu, un port Write-Only nu va avea date citite. Asemănător, un port Read-Only nu va avea date pentru scriere. Un port Read-Write va avea toate aceste semnale. Adresa este semnalul care definește portul memorie, și nu poate lipsi.

Observații: A nu se face confuzia între porturi ale unui modul Verilog și porturile unei memorii.

Exerciţiul 1

Să se descrie în Verilog o memorie RAM cu citire asincronă, de 128 de cuvinte de 8 biți, cu un singur port Read-Write. Se va simula funcționarea memoriei scriind în trei locații de memorie, apoi citind din cele trei locații de memorie și comparând valorile citite cu valorile scrise anterior.

Explicaţie suplimentară

Se va folosi un vector de date în Verilog:

reg [W-1:0] memory[0:N-1];

În acest exemplu am declarat un vector de date numit memory, care este format din cuvinte de W biți, și are N elemente. Elementele vectorului sunt accesate în următorul fel:

  • memory[3] reprezintă elementul 4 al vectorului memory, element care are W biți;
  • memory[3][0] reprezintă bitul zero al elementului 4 al vectorului memory.

Exerciţiul 2

Să se implementeze o memorie RAM de 128 de cuvinte de 8 biţi cu două porturi: un port de scriere şi un port de citire sincronă. Să se testeze această memorie.

Explicaţie suplimentară

Pentru a putea modifica dimensiunile unei memorii şi a refolosi codul Verilog putem declara ca parametri numărul de biţi de adresă, numărul de locaţii şi dimensiunea cuvântului. Sintaxa este, de exemplu:

	parameter adr_size = 7;


Exerciţiul 3

Să se implementeze o memorie FIFO cu 32 locaţii a câte 4 biţi folosind memoria de la exerciţiul 2. Să se testeze funcţionarea acestei memorii, scriind şi citind succesiv diferite valori.

Explicaţie suplimentară

Memoria FIFO (first-in-first-out) permite citirea datelor numai în ordinea în care au fost scrise. Operaţiile de scriere şi citire nu se fac la orice adresă, prin urmare o memorie FIFO nu are intrare de adresă.

Porturile acestei memorii sunt:

module memorie_fifo( 
		input clock, rst, // semnal de ceas si reset
		input write_enable, // comanda de scriere
		read_enable, // comanda de citire
		input [word_width-1 : 0] data_in, // date de intrare, aici pe 4 biti
		output [word_width-1 : 0] data_out, // date de iesire, aici pe 4 biti
		output reg empty, // semnal de iesire care este activ cand memoria este goala
		           full, // semnal de iesire care este activ cand memoria este plina
		output reg [adr_size:0] fifo_counter 	//nr locatii folosite, maxim 32

    );

Exerciţiul 4

Să se iniţializeze conţinutul memoriei de la exerciţiul 3 cu ajutorul funcţiilor de sistem $readmemh() și $readmemb().

Explicatii suplimentare

Funcțiile se folosesc conform următorului șablon:

	$readmem[hb]("fișier de inițializare",numele vectorului,adr1,adr2)

Funcțiile citesc date în format hexazecimal sau binar din fisierul specificat, și le încarcă în vectorul specificat din modulul Verilog, începând de la adresa adr1 până la adresa adr2.

Conținutul fișierului memorie.txt (32 de valori de 4 biți, in hexazecimal, una sub alta):

1
2
a
f
...
b

TEMA

1. Să se modifice codul de la exerciţiul 1 pentru a implementa o memorie cu citire sincronă.

2. Să se adauge memoriei descrise anterior (TEMA 1) un al doilea port de citire sincronă (Read-Only), şi să se simuleze citirea simultană din două locaţii diferite ale memoriei, prin cele două porturi, cât şi situaţia în care unul din porturi scrie în o locaţie de memorie în timp ce al doilea port citeşte din aceeaşi locaţie de memorie.

3. Să se implementeze o memorie 512x8b folosind patru memorii 128x8b, conectate corespunzător.

4. Să se implementeze o memorie 128x16b folosind două memorii 128x8b, conectate corespunzător.


Reguli de bună practică

Se vor grupa semnalele de interfață ale porturilor, și se vor denumi astfel încât să fie ușor identificabile ca fiind parte din portul respectiv (e.g., addrA, dataA, weA, addrB, dataB, weB)