¿Qué está mal con este intento de una memoria SDR RAM en Verilog?

2

Tengo un Spartan-6 FPGA conectado a la interfaz de memoria AEMIF en una SoC Da365 de DM365 que controlo. El AEMIF está configurado en el modo Seleccionar luz estroboscópica. Estoy tratando de implementar la lectura / escritura de memoria en el FPGA a través de esa interfaz, pero no está funcionando. El hardware funciona y esta funcionalidad ha estado funcionando antes de escribirse en VHDL (no escrito por mí). Soy nuevo en HDLs, así que quizás haya algo obviamente falso aquí.

Es difícil decir lo que realmente sucede, ya que el reloj es de 60MHz y mi analizador de alcance / lógica se esfuerza por ir tan rápido.

Editar: desde entonces he conseguido este trabajo. Establecer drive_data de forma combinatoria significa en la lectura, el valor de la memoria anterior se eliminó en el bus de datos, y luego la lógica secuencial recogería la nueva dirección y cambiaría los datos durante el ciclo.

module main(
    input EM_A_3,
    input EM_A_7,
    input EM_CLK,
    inout [15:0] EM_D,
    input EM_nCE1,
    input EM_nOE,
    input EM_nWE
    );

wire [1:0] em_addr;
/* temporary storage for emif "registers" */
reg [15:0] mem [0:3];
reg [15:0] em_outdata;

supply0 rst;        // reset always 0 for now
wire drive_data;

initial
begin: FOO
    integer i;
    for (i = 0; i < 4; i = i + 1) begin
        mem[i] = 8'b0;
    end
    em_outdata = 8'b1;
end

// drive EM_D when CE1, OE are low, and WE is high
assign drive_data = !EM_nCE1 && !EM_nOE && EM_nWE;
assign EM_D = drive_data ? em_outdata : 8'bz;
assign em_addr = {EM_A_7, EM_A_3};

// clocked version (not working yet)
always @ (posedge EM_CLK)
begin
    if (!EM_nCE1 && !EM_nWE) begin
        mem[em_addr] <= EM_D;
    end
    if (!EM_nCE1 && !EM_nOE && EM_nWE) begin
        em_outdata <= mem[em_addr];
    end
end

endmodule
    
pregunta blueshift

3 respuestas

2

Conseguí este trabajo, con un cambio específico, aunque para ser honesto, otras ediciones también podrían haber ayudado.

Pensé en cómo se configura drive_data usando lógica combinatoria, pero el registro de datos de salida está sincronizado. Confirmado con simulación de comportamiento, esto significa que los datos obsoletos se eliminan durante la primera parte de un ciclo de lectura, antes de que la dirección se trabe.

"Arreglo" esto cambiando el bloque siempre que establece los datos de salida para hacerlo en cada reloj, lo que significa que los datos correctos entran allí durante la fase de configuración, mientras que la dirección es válida en el bus, antes de que aparezca la luz estroboscópica OE.

También reprogramé mi manejo del bus de memoria en un submódulo (invirtiendo las señales de control).

module emif(
    input clk,
    input [1:0] addr,
    inout [15:0] data,
    input ce,           // note these signals are active high
    input we,           // (opposite to the PCB signals)
    input oe
    );

wire drive_data;
reg [15:0] mem [0:3];
reg [15:0] em_outdata;

assign drive_data = ce && oe && !we;
assign data = drive_data ? em_outdata : 16'bz;

// writes data to small mem
always @ (posedge clk)
begin
    if (ce && we) begin
        mem[addr] <= data;
    end
end

// reads data from small mem
always @ (posedge clk)
begin
    em_outdata <= mem[addr];
end

endmodule
    
respondido por el blueshift
1

No estoy seguro de los tiempos exactos de SDRAM, pero solo comentando tu estilo de Verilog, un par de cosas pueden ayudar. Tienes que empezar a pensar en términos de hardware. Esto puede ser más fácil de entender.

assign EM_D = drive_data ? em_outdata : 16'bz;
assign drive_data = !EM_nCE1 & !EM_nOE & EM_nWE;

// writes data to small mem
always @ (posedge EM_CLK)
begin
    if (!EM_nCE1 && !EM_nWE) begin
        mem[em_addr] <= EM_D;
    end
end

// reads data from small mem
always @ (posedge EM_CLK)
begin
    if (!EM_nCE1 && !EM_nOE && EM_nWE) begin
        em_outdata <= mem[em_addr];
    end
end

// see any problem? please change this logic. it doesn't seem to go anywhere.
always @ (posedge EM_CLK)
begin
    if (!EM_nCE1 && !EM_nWE) begin
        outbit <= 1;
    end else if (!EM_nCE1 && !EM_nOE && EM_nWE) begin
        outbit <= 0;
    end else
        outbit <= X; // *** Not sure what's the default/reset cond is.
end

Además, es posible que desee mover su bloque inicio inicial fuera de este archivo, ya que generalmente es una construcción de simulación y, en este caso, no será sintetizable de todos modos. Normalmente es mejor separar las construcciones de simulación de las construcciones sintetizables.

Si desea restablecer el contenido de la RAM, puede usar la herramienta FPGA para configurar el contenido de la RAM inicial o diseñar un pequeño bloque que reinicie la RAM en el encendido.

Buena suerte. Y déjame saber si te ayuda. :)

    
respondido por el sybreon
0
  

Es difícil decir lo que realmente está sucediendo ya que el reloj es de 60MHz y   mi analizador de alcance / lógica se esfuerza por ir tan rápido.

Utilice ChipScope (Xilinx) o SignalTap (Altera). Es genial para eso y puede darte mucho ancho, si no profundidad.

    
respondido por el Brian Carlton

Lea otras preguntas en las etiquetas