Actualmente estoy intentando implementar un diseño FPGA utilizando un reloj de 325 MHz, que escribe en el Controlador SDRAM de un Cyclone V 5CSEBA6U23I7 (Grado de velocidad 7).
Cuando ejecuto mi IP Core con 2 MHz, todo funciona bien, pero cuando cambio el reloj PLL a 200 MHz o 325 MHz, los datos que puedo observar con SignalTap se vuelven completamente aleatorios.
He adjuntado una imagen, en la que quiero señalar la 4ª señal (bRun), que debería ser constante en 1, pero en la observación cambia a 0 y vuelve a 1. Algunas otras señales también experimentan un comportamiento completamente aleatorio, como algunos buses internos, que llevan datos que no son cero, cuando deberían estar a cero.
No creo que esto sea un problema de EMC, porque estoy usando una placa de desarrollo (DE10-Nano de terasica) y todas las señales son FPGA interno, que debería poder manejar estas velocidades de reloj.
El IP-Core está escrito en Verilog y me aseguré de sincronizar las operaciones de lectura y escritura en diferentes bordes del reloj respectivo para asegurarnos de que las señales sean estables y no estén en transición cuando se estén leyendo.
A continuación, puede encontrar el código de mi máquina de estado de escritura RAM, pero como se indicó, funciona perfectamente bien a 2 MHz.
Si ustedes tuvieran alguna idea sobre la razón de este comportamiento, estaría muy agradecido.
always@(posedge clock_clk_ram or posedge reset_reset)
begin
if(reset_reset)
begin
imgSize <= 32'b0;
nCntCurPos <= 4'b0;
nOutWord <= 256'b0;
irqFromFPGAMaster <= 0;
state <= 3'b0;
fifo_read <= 0;
avm_m0_address <= 27'b0;
avm_m0_writedata <= 256'b0;
avm_m0_write <= 0;
avm_m0_byteenable <= 32'b0;
end
else
begin
if(clearIrqFromHPS||~bRun)//reset all states after irq has been handled, or if device has been stopped
begin
imgSize <= 32'b0;
nCntCurPos <= 4'b0;
nOutWord <= 256'b0;
irqFromFPGAMaster <= 0;
state <= 3'b0;
fifo_read <= 0;
avm_m0_address <= 27'b0;
avm_m0_writedata <= 256'b0;
avm_m0_write <= 0;
avm_m0_byteenable <= 32'b0;
end
else if(bRun && ~irqFromFPGAMaster && ~clearIrqFromHPS)//RAM access okay
begin
case(state)
'b000://accumulate 256 bit data
begin
if(~fifo_empty)// && fifo_rnuminfifo!='b0001)
begin
imgSize <= imgSize + 'd2;//is going to be incremented in the next cycle (d-flipflop)
nCntCurPos <= nCntCurPos + 4'b1;//is going to be incremented in the next cycle (d-flipflop)
fifo_read <= 1;
irqFromFPGAMaster <= 0;
avm_m0_address <= 27'b0;
avm_m0_writedata <= 256'b0;
avm_m0_write <= 0;
nOutWord[nCntCurPos*16 +: 16] <= fifo_out;
avm_m0_byteenable[nCntCurPos*2 +: 2] <= 2'b11;
if(imgSize >= maxImgSize - 32'd2) //image done, transmit data and fire irq
state <= 3'b101;
else if(nCntCurPos=='d15) //process transfer without irq
state <= 3'b001;
else //else continue to accumulate data
state <= 3'b000;
end
else//FIFO is empty, wait for more data
begin
imgSize <= imgSize;
nCntCurPos <= nCntCurPos;
nOutWord <= nOutWord;
irqFromFPGAMaster <= 0;
state <= 3'b000;
fifo_read <= 0;
avm_m0_address <= 27'b0;
avm_m0_writedata <= 256'b0;
avm_m0_write <= 0;
avm_m0_byteenable <= avm_m0_byteenable;
end
end
'b001,//write to sdram, after that accumulate more data
'b101://write to sdram, after that trigger interrupt
begin
imgSize <= imgSize;
nCntCurPos <= 4'b0;
nOutWord <= nOutWord;
irqFromFPGAMaster <= 0;
fifo_read <= 0;
if(imgSize>32) avm_m0_address <= baseAddress+((imgSize>>5)-27'd1);
else avm_m0_address <= baseAddress;
avm_m0_writedata <= nOutWord;
avm_m0_write <= 1;
avm_m0_byteenable <= avm_m0_byteenable;
if(~avm_m0_waitrequest) state <= state ^ 3'b011;
else state <= state;
end
'b010,//end of single transmit
'b110://end of img,
begin
imgSize <= imgSize;
nCntCurPos <= 4'b0;
nOutWord <= 256'b0;
fifo_read <= 0;
avm_m0_address <= 27'b0;
avm_m0_writedata <= 256'b0;
avm_m0_write <= 0;
avm_m0_byteenable <= 32'b0;
irqFromFPGAMaster <= state[2];
if(state[2]==0) state <= 3'b000;
else state <= state;
end
endcase
end
else//Running, but IRQ hasn't been handled yet, preserve some data
begin
imgSize <= imgSize;
irqFromFPGAMaster <= irqFromFPGAMaster;
//irqFromFPGAMaster <= 0;
//imgSize <= 32'd0;
nCntCurPos <= 4'b0;
nOutWord <= 256'b0;
state <= 3'b0;
fifo_read <= 0;
avm_m0_address <= 27'b0;
avm_m0_writedata <= 256'b0;
avm_m0_write <= 0;
avm_m0_byteenable <= 32'b0;
end
end
end
También solo fyi: la bRun Signal está siendo asignada por un Avalon MM-Slave conectado al procesador ARm del ciclón V. Durante el período observado no ha habido ninguna comunicación con el procesador, por lo que bRun no debería cambiar. . Esto tampoco explicaría el bus NRZ, que debería ser RZ, como se ve en el código de Verilog.