Tengo un Spartan-6 FPGA conectado a la interfaz de memoria AEMIF en un SoC TI DaVinci DM365 que controlo. La AEMIF está configurada en el modo Select Strobe. Estoy tratando de implementar lectura/escritura de memoria en el FPGA sobre esa interfaz, pero no funciona. El hardware funciona y esta funcionalidad ha estado funcionando antes escrita en VHDL (no escrita por mí). Soy nuevo en HDL, así que tal vez haya algo obviamente falso aquí.
Es difícil saber lo que realmente está pasando ya que el reloj es de 60 MHz y mi analizador lógico/osciloscopio lucha por ir tan rápido.
Editar: desde entonces tengo esto funcionando. Establecer drive_data de forma combinatoria significaba que, al leer, el valor de la memoria anterior se expulsaba en el bus de datos, luego, más tarde, la lógica secuencial tomarí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
Lo hice funcionar, con un cambio específico aunque, para ser honesto, algunas otras ediciones también pueden haber ayudado.
Pensé en cómo se configura drive_data usando lógica combinatoria, pero el registro de outdata está cronometrado. 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 se bloquee la dirección.
"Arreglé" esto cambiando el bloque always que establece outdata para hacerlo en cada reloj, lo que significa que los datos correctos ingresan allí durante la fase de configuración mientras la dirección es válida en el bus, antes de que aparezca la luz estroboscópica OE.
También refactoricé el manejo de mi 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
No estoy seguro de los tiempos exactos de SDRAM, pero solo comentando su estilo Verilog, un par de cosas podrían 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 de inicio inicial fuera de este archivo, ya que normalmente es una construcción de simulación y, en este caso, no será sintetizable de todos modos. Por lo general, 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 inicial de la RAM o diseñar un pequeño bloque que restablezca la RAM al encender.
Buena suerte. Y déjame saber si te ayuda. :)
initial
los bloques pueden sintetizarse para FPGA. Le dicen al compilador qué estado deben tener las cosas al final de la configuración, que no es lo mismo que restablecer.Es difícil saber lo que realmente está pasando ya que el reloj es de 60 MHz y mi analizador lógico/osciloscopio lucha por ir tan rápido.
Utilice ChipScope (Xilinx) o SignalTap (Altera). Es genial para eso y puede darte mucho ancho, si no profundidad.
martin thompson
kevin vermeer
Cambio azúl