Experimento de prueba de lectura y escritura de RAM en chip FPGA


Prefacio

Esta sección describe la simulación y prueba de la RAM en chip FPGA. También sabemos que la RAM es una memoria de acceso aleatorio. Como sugiere el nombre, es un módulo que almacena datos. Cuando se trata de aleatoriedad, significa que podemos acceder arbitrariamente algunos espacios de direcciones en él.los datos dentro.

Xilinx nos ha proporcionado el núcleo IP de RAM en Vivado. Solo necesitamos crear una instancia de una RAM a través del núcleo IP y escribir y leer los datos almacenados en la RAM de acuerdo con el tiempo de lectura y escritura de la RAM. En el experimento, a través del analizador lógico en línea ila integrado por VIVADO, podemos observar el tiempo de lectura y escritura de la RAM y los datos leídos de la RAM.


1. Crear y configurar proyectos

1. Crea un proyecto

Crea un nuevo proyecto ram_test
Insertar descripción de la imagen aquí

2. Agregue el núcleo IP de RAM

①. Haga clic en el catálogo de IP en la imagen a continuación , busque ram en la interfaz que aparece a la derecha, busque Block Memory Generator y haga doble clic para abrirlo.
Insertar descripción de la imagen aquí
② Configure la barra de opciones Básica como se muestra a continuación.
Insertar descripción de la imagen aquí

  • Tipo de interfaz : Tipo de interfaz, seleccione Nativo
    • Generalmente hay dos formas de implementar una memoria en la FPGA de XILINX: la primera es diseñarla usted mismo utilizando los recursos lógicos de la FPGA; la segunda es utilizar el generador de memoria de bloque (BMG) dedicado de XILINX . Para los formularios de recursos BRAM, XILINX proporciona dos tipos de interfaz: nativa y AXI4. Las principales características de estos dos núcleos son las siguientes.
      Insertar descripción de la imagen aquí
  • Tipo de memoria: tipo de memoria, seleccione RAM de puerto dual simple
    • Hay cinco tipos de memoria del puerto Nativo. Las diferencias son las siguientes:Insertar descripción de la imagen aquí
    • El tiempo de escritura de la RAM simple de doble puerto es el siguiente
      • Cuando la habilitación de escritura es válida (nivel alto), los datos especificados se escriben en la dirección especificada en el flanco ascendente del reloj.Insertar descripción de la imagen aquí
    • El tiempo de lectura de la RAM simple de doble puerto es el siguiente
      • Hay un cierto retraso en la lectura. Si recopilamos estos datos de salida válidos en el mismo reloj, necesitamos recopilar sus datos válidos en el siguiente ciclo.
        Insertar descripción de la imagen aquí

③ Configure la barra de opciones de Puerto A como se muestra a continuación.
按照这样设置,也就是说可以存储 512 个 16 位数据
Insertar descripción de la imagen aquí

  • Ancho del puerto A (ancho de datos): el ancho del puerto A, aquí configuramos 16 bits de ancho
  • Profundidad del puerto A (cuántos datos se pueden almacenar en la RAM): la profundidad del puerto A, la configuramos aquí en 512
  • Habilitar tipo de puerto: Habilitar siempre, manténgalo habilitado para que no necesitemos controlarlo

④ Configure la barra de opciones de Puerto B como se muestra a continuación.
Insertar descripción de la imagen aquí

  • Ancho del puerto B (ancho de datos): el ancho del puerto B, aquí configuramos 16 bits de ancho
  • Habilitar tipo de puerto: Siempre habilitado (la habilitación del puerto B permanece activada)
  • Registro de salida primitivo: desmarque, su función es agregar un registro a los datos de salida, lo que puede mejorar efectivamente el tiempo, pero los datos leídos se retrasarán dos ciclos con respecto a la dirección . En muchos casos, esta función no está habilitada y los datos se mantienen un ciclo detrás de la dirección.

Para obtener más información sobre otras configuraciones, consulte el documento oficial de XILINX " Block Memory Generator v8.4 LogiCORE IP Product Guide "

⑤ Otras opciones, simplemente mantenga la configuración predeterminada.
Insertar descripción de la imagen aquí

  • Cargar archivo de inicio nos permite inicializar algunos archivos y colocarlos en la RAM, lo que significa que después de encender la FPGA, cargará los datos que haya guardado de antemano en la RAM.

⑥. Haga clic en Aceptar, luego haga clic en Generar para generar la IP de RAM
Insertar descripción de la imagen aquí

3. Agregue el núcleo IP de ILA

①. Haga clic en la barra PROJECT MANAGER a la izquierda -> Catálogo IP o Ventana -> Catálogo IP debajo de la barra de menú, luego busque ILA en la ventana Catálogo IP que aparece a la derecha, haga doble clic para seleccionar ILA en Depurar para Configuración de IP. Los pasos se muestran en la siguiente figura
Insertar descripción de la imagen aquí
②, la opción general agrega dos sondas para recopilar la dirección y los datos que leemos. Configuramos la longitud de los datos muestreados más grande, como se muestra en la siguiente figura
Insertar descripción de la imagen aquí
③. PROBE0 en Probe_Ports ( 0...7) se usa para recopilar la dirección de 9 bits y se usa PROBE1. Recopile datos de 16 bits, como se muestra en la siguiente figura
Insertar descripción de la imagen aquí
④, haga clic en Aceptar y luego haga clic en Generar para generar IP ILA.
Insertar descripción de la imagen aquí

2. Programación

Antes de escribir el programa, primero introduzcamos qué señales involucramos.

Las descripciones de los puertos del módulo RAM de puerto dual simple son las siguientes:

Nombre de la señal dirección ilustrar
clka en Entrada de reloj del puerto A
nosotros en Puerto A habilitado
addra en Entrada de dirección del puerto A
innoble en Entrada de datos del puerto A
clkb en Entrada de reloj del puerto B
dirección en Entrada de dirección del puerto B
duda afuera Salida de datos del puerto B

La escritura y lectura de datos de la RAM se realizan en el flanco ascendente del reloj. Al escribir datos en el puerto A, la señal wea debe establecerse en alto y la dirección y los datos a escribir deben proporcionarse al mismo tiempo. La siguiente figura muestra el diagrama de tiempos de escritura de entrada en la RAM.
Insertar descripción de la imagen aquí
El puerto B no puede escribir datos y solo puede leer datos de la RAM. Siempre que se proporcione la dirección, generalmente se pueden recopilar datos válidos en el siguiente ciclo.
Insertar descripción de la imagen aquí

1. Cree un nuevo programa de prueba

Cree un nuevo archivo fuente ram_test.v y copie los siguientes bloques de programa en
ram_test.v

`timescale 1ns / 1ps

module ram_test(
    input clk,					// 50 MHz 时钟
    input rst_n					// 复位信号,低电平有效
    );

reg     [8 : 0]     w_addr;			// RAM PORTA 写地址
reg     [15 : 0]    w_data;			// RAM PORTA 写数据
reg                 wea;			// RAM PORTA 使能
reg     [8 : 0]     r_addr;			// RAM PORTB 读地址
wire    [15 : 0]    r_data;			// RAM PORTB 读数据

// ************************************************************************
// ** main
// ************************************************************************

// 产生RAM PORTB读地址,读的地址 + 1,模拟写的地址滞后一个周期
always @ (posedge clk or negedge rst_n) begin
    if( !rst_n )
        r_addr <= 9'd0;
    else if( |w_addr )				// w_addr 位或,不等于 0
        r_addr <= r_addr + 1'b1;
    else
        r_addr <= 9'd0;
end

// 产生RAM PORTA写使能信号
always @ (posedge clk or negedge rst_n) begin
    if( !rst_n )
        wea <= 1'b0;
    else begin
        if( &w_addr )				// w_addr 的 bit 位全为1,共写 512 个数据,写入完成
            wea <= 1'b0;
        else
            wea <= 1'b1;			// ram 写使能
    end
end

// 产生RAM PORTA写入的地址及数据
always @ (posedge clk or negedge rst_n) begin
    if( !rst_n ) begin
        w_addr <= 9'd0;
        w_data <= 16'd1;
    end
    else begin
        if( wea ) begin				// ram 写使能有效
            if( &w_addr ) begin		// w_addr 的 bit 位全为 1,共写入 512 个数据,写入完成
                w_addr <= w_addr;	// 将地址和数据的值保持住,只写一次 RAM
                w_data <= w_data;
            end
            else begin
                w_addr <= w_addr + 1'b1;
                w_data <= w_data + 1'b1;
            end
        end
    end
end

// 实例化 RAM
ram_ip ram_ip_instance (
  .clka(clk		),			// input wire clka
  .wea(wea			),      // input wire [0 : 0] wea
  .addra(w_addr		),  	// input wire [8 : 0] addra
  .dina(w_data		),    	// input wire [15 : 0] dina
  .clkb(clk		),    		// input wire clkb
  .addrb(r_addr		),  	// input wire [8 : 0] addrb
  .doutb(r_data		)  		// output wire [15 : 0] doutb
);

// 实例化 ila 逻辑分析仪
ila_0 ila_0_instance (
	.clk(clk), 				// input wire clk
	.probe0(r_addr), 		// input wire [8:0]  probe0  
	.probe1(r_data) 		// input wire [15:0]  probe1
);

endmodule

Insertar descripción de la imagen aquí

2. Cree un nuevo archivo de simulación.

Cree un nuevo archivo de simulación vtf_ram_tb.v y copie los siguientes bloques de programa en
vtf_ram_tb.v

`timescale 1ns / 1ps

module vtf_ram_tb;
// Inputs
reg clk;
reg rst_n;

// Instantiate the Unit Under Test (UUT)
ram_test uut (
	.clk 	(clk),
	.rst_n 	(rst_n)
);

initial 
begin
	// Initialize Inputs
	clk = 0;
	rst_n = 0;
	
	// Wait 100ns for global reset to finish
	#100;
		rst_n = 1;
end

always #10 clk = ~clk;	// 20ns 一个周期,产生 50MHz 时钟源

endmodule

Insertar descripción de la imagen aquí

3. Realizar simulación

①. Haga clic en Ejecutar simulación -> Ejecutar simulación de comportamiento para realizar la simulación
Insertar descripción de la imagen aquí
②. Arrastre las señales relevantes en la RAM a la ventana de observación
(clocka y clockb usan el reloj del sistema, por lo que no es necesario arrastrarlas a la ventana de observación aquí)
Insertar descripción de la imagen aquí
③. Establezca una ejecución de 200 us. Siguiente
Insertar descripción de la imagen aquí
④, analice la forma de onda


Se puede ver que la información de forma de onda inicial es que la dirección de lectura está retrasada con respecto a la dirección de escritura en un ciclo de reloj, y los datos leídos son
Insertar descripción de la imagen aquí
la información de forma de onda que está retrasada con respecto al final de la dirección de escritura en un ciclo de reloj.
Aquí vemos estas señales en formato decimal formulario
Puede ver que la última dirección escrita es 511, el contenido escrito es 512, la última dirección leída es 511 y el contenido leído es 512. Puede
Insertar descripción de la imagen aquí
encontrar que nuestra escritura solo escribe primero, mientras que la lectura siempre continúa.

4. Descargar a FPGA

1. Restricciones de pines y restricciones de tiempo

rst_n -> T11
clk -> U18

Cree un nuevo archivo de restricción de pin ram.xdc, copie las siguientes declaraciones y guárdelo

set_property PACKAGE_PIN T11 [get_ports rst_n]
set_property IOSTANDARD LVCMOS33 [get_ports rst_n]
set_property PACKAGE_PIN U18 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports clk]

create_clock -period 20.000 -name clk -waveform {
    
    0.000 10.000} [get_ports clk]

Insertar descripción de la imagen aquí

2. Generar archivo de bits

Haga clic en "Generar Bitstream" para generar directamente el archivo de bits.
Insertar descripción de la imagen aquí

3. Descarga el programa

Conecte el JTAG y el cable de alimentación, encienda la placa y descargue el programa.
Insertar descripción de la imagen aquí

4. El analizador lógico analiza las formas de onda.

Vea la memoria de lectura y los datos en modo decimal, establezca la condición de activación en "la dirección de lectura es 0", puede ver que los datos leídos en la dirección 0 son 1 y los datos leídos en la dirección 511 son 512. Se puede ver que se cumplan las condiciones para obtener los resultados esperados.
Insertar descripción de la imagen aquí

5. Obtenga recursos usted mismo

Experimento de prueba de lectura y escritura de RAM en chip FPGA


Mi qq: 2442391036, ¡bienvenido a comunicarnos!


Supongo que te gusta

Origin blog.csdn.net/qq_41839588/article/details/133199557
Recomendado
Clasificación