En el siguiente tema veremos cómo describir memorias. En SystemVerilog, las memorias RAM y ROM son fundamentales porque permiten modelar almacenamiento dentro del hardware digital.
Algunas aplicaciones de las memorias son: Buffers, Bancos de Registros en CPUs (ver procesador MIPS y arquitectura RISC-V), almacenamiento temporal de variables, etc.
Las características de la RAM que hemos descrito son:
Doble puerto (1 lectura + 1 escritura).
Escritura síncrona; la operación de escritura está dentro del bloque always_ff, se ejecuta en flanco positivo del reloj si write_ena = 1
always_ff @(posedge clk)
begin
if (we)
memory[w_addr] <= w_data;
end
Lectura asíncrona (combinacional, no depende del reloj); si cambia read_addr, cambia inmediatamente read_data
Lectura y escritura pueden ocurrir en el mismo ciclo.
Misma memoria RAM que en ejemplo anterior. Sólo se añade un segundo puerto de lectura read_data1 y se aumenta el número de posiciones a 16.
La escritura sigue siendo síncrona y al lectura puede ser síncrona o asíncrona en uno o los dos puertos read_data0 y read_data1. Sólo hay que quitar los comentarios para habilitar la opción que deseemos.
En SystemVerilog, una ROM (Read-Only Memory) es una estructura fundamental utilizada para almacenar datos constantes que no deben ser modificados durante la ejecución del sistema. A diferencia de la RAM, su contenido se define generalmente durante la fase de diseño.
Usos principales en SystemVerilog
Tablas de Búsqueda (Look-Up Tables - LUT): Se emplean para implementar funciones complejas (como senos, cosenos o logaritmos) donde, en lugar de calcular el valor en tiempo real, se accede a un resultado pre-almacenado usando la entrada como dirección.
Almacenamiento de Instrucciones: En el diseño de procesadores o microcontroladores, la ROM actúa como memoria de programa donde reside el firmware o código ejecutable.
Generación de Caracteres y Patrones: Utilizada en controladores de video (VGA/HDMI) para guardar los mapas de bits de fuentes o iconos estáticos.
Configuración de Hardware: Almacena parámetros de inicialización necesarios para que los componentes arranquen correctamente tras un reset.
Máquinas de Estados Basadas en ROM: Permite implementar lógica de control compleja almacenando el "siguiente estado" y las "salidas" en una tabla, lo que puede optimizar el uso de recursos en ciertos FPGAs.
Método 1: Con la declaración case (cuando es una ROM pequeña). Se sintetiza como lógica combinacional.
module rom_case (
input logic [2:0] addr,
output logic [7:0] data
);
always_comb begin
case(addr)
3'd0: data = 8'hA1;
3'd1: data = 8'hB2;
3'd2: data = 8'hC3;
3'd3: data = 8'hD4;
default: data = 8'h00;
endcase
end
endmodule
Método 2: Con array inicializado (más profesional)
module rom_array (
input logic [3:0] addr,
output logic [7:0] data
);
logic [7:0] mem [0:15];
initial begin
mem[0] = 8'h10;
mem[1] = 8'h20;
mem[2] = 8'h30;
mem[3] = 8'h40;
end
assign data = mem[addr];
endmodule
Método 3: utilizando archivos externos en formato hexadecimal o binario, mediante los comandos $readmemh o $readmemb, donde binary_truth_table.mem es un archivo que contiene los datos de la ROM. En el siguiente ejemplo la ROM tiene 32 posiciones y un tamaño de palabra de 16 bits.
module rom_with_file(
input logic [4:0] addr,
output logic [15:0] data
);
// signal declaration
logic [15:0] rom [0:31];
initial
$readmemb("binary_truth_table.mem", rom);
assign data = rom[addr];
endmodule
Veamos un ejemplo de lectura de una ROM de 32 posiciones y 16 bits de ancho de palabra, cuyos datos están contenidos en un archivo .mem
Emplearemos una señal de reloj customizada, de 50 ms aplicada a un contador CNT que irá recorriendo las 32 posiciones de la ROM. La salida de la ROM es un bus de datos de 16 bits que conectaremos a los 16 ledes de la BASYS 3 para visualizar el contenido de la memoria.
En el módulo top conectamos los módulos simples que forman el proyecto.
Los archivos están disponibles para descargar al final de la página, así como el proyecto completo en Vivado.
Programa tu BASYS 3 y verás un juego de luces con los ledes iluminándose de manera secuencial de derecha a izquierda.
Modificando el contenido de la ROM podemos crear diferentes efectos visuales con los ledes de la BASYS 3.
ECE 4305 - Advanced Digital Design Using SystemVerilog HDL
Ver bloque M4 - Memory Arrays
Many thanks to Mr Anas Salah Eddin for sharing this amazing course.
Descarga el proyecto de la ROM aquí abajo