我的SDRAM可以保持数据永远有效,无需刷新,这怎么可能?

问题描述 投票:0回答:1

我用Verilog HDL设计了一个简单的SDRAM驱动模块。该模块定义了一个简单的有限状态机。它在前几个状态中执行SDRAM(Winbond的W9825G6KH 4M * 4Banks * 16bits)的初始化,然后进入正常模式状态以等待微处理器发送的读/写请求。它根据SDRAM数据表中定义的时序图响应每个请求,然后返回正常模式状态。我在 Intel Altera FPGA 上测试了该模块,它似乎按预期工作。数据可以正确写入和读取。然而,我注意到SDRAM似乎能够永远保留存储的数据而无需刷新!目前,该模块没有显式实现任何刷新(至少我是这么认为的)。附件是 FSM。任何人都可以帮助诊断我的代码并提供一些指导吗?代码中是否包含一些隐藏的看不见的逻辑,可以在我不注意的情况下自动刷新 SDRAM?非常感谢。

/////////////////////////////////////////
/////////////////////////////////////////
/////////////////////////////////////////
/* normal operation loop */
5'b01000:  //normal operation starts here
begin
    if((wbRPtr==wbWPtr)&&(rbRPtr==rbWPtr)) //if no CPU request for data (write/read)
    begin
        cs_ <= 1; 
        ras_ <= 1; 
        cas_ <= 1; 
        we_ <= 1; 
        ldqm <= 0; 
        udqm <= 0; 
        cke <= 1;
        dqInEn <= 0;
        next_state <= 5'b01000; //stay on the same state
        counterEnable <= 0;
        rst2 <= 0;
        addr <= 0;
        bs <= 0;
        dq_out <= 0;
        inc <= 0;
        wbRPtrUpdate <= 0;
        rbWPtrUpdate <= 0;
        rbWEn <= 0;
        rtEnable <= 1;
    end
    else if(wbRPtr!=wbWPtr) //CPU has sent a data item to write to the DRAM
    begin
        cs_ <= 0; 
        ras_ <= 0; 
        cas_ <= 1; 
        we_ <= 0; 
        ldqm <= 0; 
        udqm <= 0; 
        cke <= 1;
        dqInEn <= 0;
        next_state <= 5'b01001; //go to precharge waiting
        counterEnable <= 1;
        rst2 <= 1;
        addr <= 0;
        bs <= waddrBuffer[wbRPtr][23:22]; //highest two bits of the buffered address are bank selection
        dq_out <= 0;
        inc <= 0;
        wbRPtrUpdate <= 0;
        rbWPtrUpdate <= 0;
        rbWEn <= 0;
        rtEnable <= 1;
    end
    else //CPU has sent a read request
    begin
        cs_ <= 0; 
        ras_ <= 0; 
        cas_ <= 1; 
        we_ <= 0; 
        ldqm <= 0; 
        udqm <= 0; 
        cke <= 1;
        dqInEn <= 0;
        next_state <= 5'b01110; //go to precharge waiting
        counterEnable <= 1;
        rst2 <= 1;
        addr <= 0;
        bs <= raddrBuffer[rbWPtr][23:22]; //highest two bits of the buffered address are bank selection
        dq_out <= 0;
        inc <= 0;
        wbRPtrUpdate <= 0;
        rbWPtrUpdate <= 0;
        rbWEn <= 0;
        rtEnable <= 1;
    end
end

/////////////////////////////////
/////////////////////////////////
/////////////////////////////////
/*write request handling states*/
5'b01001:
begin
    if(counter<2)
    begin
        cs_ <= 1; 
        ras_ <= 1; 
        cas_ <= 1; 
        we_ <= 1; 
        ldqm <= 0; 
        udqm <= 0; 
        cke <= 1;
        dqInEn <= 0;
        next_state <= 5'b01001; //stay on precharge waiting
        counterEnable <= 1;
        rst2 <= 0;
        addr <= 0;
        bs <= 0;
        dq_out <= 0;
        inc <= 0;
        wbRPtrUpdate <= 0;
        rbWPtrUpdate <= 0;
        rbWEn <= 0;
        rtEnable <= 1;
    end
    else
    begin
        cs_ <= 1; 
        ras_ <= 1; 
        cas_ <= 1; 
        we_ <= 1; 
        ldqm <= 0; 
        udqm <= 0; 
        cke <= 1;
        dqInEn <= 0;
        next_state <= 5'b01010; //go to activate
        counterEnable <= 0;
        rst2 <= 0;
        addr <= 0;
        bs <= 0;
        dq_out <= 0;
        inc <= 0;
        wbRPtrUpdate <= 0;
        rbWPtrUpdate <= 0;
        rbWEn <= 0;
        rtEnable <= 1;
    end
end
5'b01010:
begin
    cs_ <= 0; 
    ras_ <= 0; 
    cas_ <= 1; 
    we_ <= 1; 
    ldqm <= 0; 
    udqm <= 0; 
    cke <= 1;
    dqInEn <= 0;
    next_state <= 5'b01011; //go to activate waiting
    counterEnable <= 1;
    rst2 <= 1;
    addr <= waddrBuffer[wbRPtr][21:9]; //row address extracted from write address buffer
    bs <= waddrBuffer[wbRPtr][23:22]; //bank address extracted from write address buffer
    dq_out <= 0;
    inc <= 0;
    wbRPtrUpdate <= 0;
    rbWPtrUpdate <= 0;
    rbWEn <= 0;
    rtEnable <= 1;
end
5'b01011:
begin
    if(counter<2)
    begin
        cs_ <= 1; 
        ras_ <= 1; 
        cas_ <= 1; 
        we_ <= 1; 
        ldqm <= 0; 
        udqm <= 0; 
        cke <= 1;
        dqInEn <= 0;
        next_state <= 5'b01011; //stay on activate waiting
        counterEnable <= 1;
        rst2 <= 0;
        addr <= 0;
        bs <= 0;
        dq_out <= 0;
        inc <= 0;
        wbRPtrUpdate <= 0;
        rbWPtrUpdate <= 0;
        rbWEn <= 0;
        rtEnable <= 1;
    end
    else
    begin
        cs_ <= 1; 
        ras_ <= 1; 
        cas_ <= 1; 
        we_ <= 1; 
        ldqm <= 0; 
        udqm <= 0; 
        cke <= 1;
        dqInEn <= 0;
        next_state <= 5'b01100; //go to write
        counterEnable <= 0;
        rst2 <= 0;
        addr <= 0;
        bs <= 0;
        dq_out <= 0;
        inc <= 0;
        wbRPtrUpdate <= 0;
        rbWPtrUpdate <= 0;
        rbWEn <= 0;
        rtEnable <= 1;
    end
end
5'b01100:
begin
    cs_ <= 0; 
    ras_ <= 1; 
    cas_ <= 0; 
    we_ <= 0; 
    ldqm <= 0; 
    udqm <= 0; 
    cke <= 1;
    dqInEn <= 0;
    next_state <= 5'b01101; //go to write waiting
    counterEnable <= 1;
    rst2 <= 1;
    addr <= {4'b0000, waddrBuffer[wbRPtr][8:0]}; //column address extracted from write address buffer
    bs <= waddrBuffer[wbRPtr][23:22]; //bank address extracted from write address buffer
    dq_out <= writeBuffer[wbRPtr];
    inc <= 0;
    wbRPtrUpdate <= 1;
    rbWPtrUpdate <= 0;
    rbWEn <= 0;
    rtEnable <= 1;
end
5'b01101:
begin
    if(counter<2)
    begin
        cs_ <= 1; 
        ras_ <= 1; 
        cas_ <= 1; 
        we_ <= 1; 
        ldqm <= 0; 
        udqm <= 0; 
        cke <= 1;
        dqInEn <= 0;
        next_state <= 5'b01101; //stay on write waiting
        counterEnable <= 1;
        rst2 <= 0;
        addr <= 0;
        bs <= 0;
        dq_out <= 0;
        inc <= 0;
        wbRPtrUpdate <= 0;
        rbWPtrUpdate <= 0;
        rbWEn <= 0;
        rtEnable <= 1;
    end
    else
    begin
        cs_ <= 1; 
        ras_ <= 1; 
        cas_ <= 1; 
        we_ <= 1; 
        ldqm <= 0; 
        udqm <= 0; 
        cke <= 1;
        dqInEn <= 0;
        next_state <= 5'b01000; //go back to normal
        counterEnable <= 0;
        rst2 <= 0;
        addr <= 0;
        bs <= 0;
        dq_out <= 0;
        inc <= 0;
        wbRPtrUpdate <= 0;
        rbWPtrUpdate <= 0;
        rbWEn <= 0;
        rtEnable <= 1;
    end
end

//////////////////////////////////
//////////////////////////////////
//////////////////////////////////
/* read request handling states */
5'b01110:
begin
    if(counter<2)
    begin
        cs_ <= 1; 
        ras_ <= 1; 
        cas_ <= 1; 
        we_ <= 1; 
        ldqm <= 0; 
        udqm <= 0; 
        cke <= 1;
        dqInEn <= 0;
        next_state <= 5'b01110; //stay on precharge waiting
        counterEnable <= 1;
        rst2 <= 0;
        addr <= 0;
        bs <= 0;
        dq_out <= 0;
        inc <= 0;
        wbRPtrUpdate <= 0;
        rbWPtrUpdate <= 0;
        rbWEn <= 0;
        rtEnable <= 1;
    end
    else
    begin
        cs_ <= 1; 
        ras_ <= 1; 
        cas_ <= 1; 
        we_ <= 1; 
        ldqm <= 0; 
        udqm <= 0; 
        cke <= 1;
        dqInEn <= 0;
        next_state <= 5'b01111; //go to activate
        counterEnable <= 0;
        rst2 <= 0;
        addr <= 0;
        bs <= 0;
        dq_out <= 0;
        inc <= 0;
        wbRPtrUpdate <= 0;
        rbWPtrUpdate <= 0;
      rbWEn <= 0;
        rtEnable <= 1;      
    end
end
5'b01111:
begin
    cs_ <= 0; 
    ras_ <= 0; 
    cas_ <= 1; 
    we_ <= 1; 
    ldqm <= 0; 
    udqm <= 0; 
    cke <= 1;
    dqInEn <= 0;
    next_state <= 5'b10000; //go to activate waiting
    counterEnable <= 1;
    rst2 <= 1;
    addr <= raddrBuffer[rbWPtr][21:9]; //row address extracted from read address buffer
    bs <= raddrBuffer[rbWPtr][23:22]; //bank address extracted from read address buffer
    dq_out <= 0;
    inc <= 0;
    wbRPtrUpdate <= 0;
    rbWPtrUpdate <= 0;
    rbWEn <= 0;
    rtEnable <= 1;
end
5'b10000:
begin
    if(counter<2)
    begin
        cs_ <= 1; 
        ras_ <= 1; 
        cas_ <= 1; 
        we_ <= 1; 
        ldqm <= 0; 
        udqm <= 0; 
        cke <= 1;
        dqInEn <= 0;
        next_state <= 5'b10000; //stay on activate waiting
        counterEnable <= 1;
        rst2 <= 0;
        addr <= 0;
        bs <= 0;
        dq_out <= 0;
        inc <= 0;
        wbRPtrUpdate <= 0;
        rbWPtrUpdate <= 0;
        rbWEn <= 0;
        rtEnable <= 1;
    end
    else
    begin
        cs_ <= 1; 
        ras_ <= 1; 
        cas_ <= 1; 
        we_ <= 1; 
        ldqm <= 0; 
        udqm <= 0; 
        cke <= 1;
        dqInEn <= 0;
        next_state <= 5'b10001; //go to read
        counterEnable <= 0;
        rst2 <= 0;
        addr <= 0;
        bs <= 0;
        dq_out <= 0;
        inc <= 0;
        wbRPtrUpdate <= 0;
        rbWPtrUpdate <= 0;
      rbWEn <= 0;
        rtEnable <= 1;
    end
end
5'b10001:
begin
    cs_ <= 0; 
    ras_ <= 1; 
    cas_ <= 0; 
    we_ <= 1; 
    ldqm <= 0; 
    udqm <= 0; 
    cke <= 1;
    dqInEn <= 1; //must turn on dq input now
    next_state <= 5'b10010; //go to read waiting
    counterEnable <= 1;
    rst2 <= 1;
    addr <= {4'b0000, raddrBuffer[rbWPtr][8:0]}; //column address extracted from read address buffer
    bs <= raddrBuffer[rbWPtr][23:22]; //bank address extracted from write address buffer
    dq_out <= 0; //read command cycle don't care dq bus value
    inc <= 0;
    wbRPtrUpdate <= 0;
    rbWPtrUpdate <= 0;
  rbWEn <= 0;
    rtEnable <= 1;
end
5'b10010:
begin
    if(counter<2)
    begin
        cs_ <= 1; 
        ras_ <= 1; 
        cas_ <= 1; 
        we_ <= 1; 
        ldqm <= 0; 
        udqm <= 0; 
        cke <= 1;
        dqInEn <= 1;
        next_state <= 5'b10010; //stay on read waiting
        counterEnable <= 1;
        rst2 <= 0;
        addr <= 0;
        bs <= 0;
        dq_out <= 0;
        inc <= 0;
        wbRPtrUpdate <= 0;
        rbWPtrUpdate <= 0;
      rbWEn <= 0;
        rtEnable <= 1;
    end
    else
    begin
        cs_ <= 1; 
        ras_ <= 1; 
        cas_ <= 1; 
        we_ <= 1; 
        ldqm <= 0; 
        udqm <= 0; 
        cke <= 1;
        dqInEn <= 1;
        next_state <= 5'b10011; //go to finishing the read
        counterEnable <= 0;
        rst2 <= 0;
        addr <= 0;
        bs <= 0;
        dq_out <= 0;
        inc <= 0;
        wbRPtrUpdate <= 0;
        rbWPtrUpdate <= 0;
        rbWEn <= 1;
        rtEnable <= 1;
    end
end
5'b10011:
begin
        cs_ <= 1; 
        ras_ <= 1; 
        cas_ <= 1; 
        we_ <= 1; 
        ldqm <= 0; 
        udqm <= 0; 
        cke <= 1;
        dqInEn <= 1;
        next_state <= 5'b01000; //go back to normal
        counterEnable <= 0;
        rst2 <= 0;
        addr <= 0;
        bs <= 0;
        dq_out <= 0;
        inc <= 0;
        wbRPtrUpdate <= 0;
        rbWPtrUpdate <= 1;
        rbWEn <= 0;
        rtEnable <= 1;
end
default:
begin
        cs_ <= 1; 
        ras_ <= 1; 
        cas_ <= 1; 
        we_ <= 1; 
        ldqm <= 0; 
        udqm <= 0; 
        cke <= 1;
        dqInEn <= 0;
        next_state <= 5'b01000; //stay on the same state
        counterEnable <= 0;
        rst2 <= 0;
        addr <= 0;
        bs <= 0;
        dq_out <= 0;
        inc <= 0;
        wbRPtrUpdate <= 0;
        rbWPtrUpdate <= 0;
        rbWEn <= 0;
        rtEnable <= 1;  
end
endcase

结束

我尝试禁用初始化部分所需的 8 个自动刷新周期,但 SDRAM 仍然不知何故自行刷新。我也尝试更换PCB板(我有多个),所有这些都显示出同样的问题。这是 SDRAM pdf 的链接

https://www.mouser.com/datasheet/2/949/w9825g6kh_a04-1489735.pdf?srsltid=AfmBOoqw5VIPM6f-QGWjLmPLCcZ3av1AbZLhvKU7OVS-tlvBYwZGy2x1

fpga
1个回答
0
投票

您没有解释您正在做的测试,特别是访问模式。请记住,访问相关数据本身就会使这些行保持刷新,您不需要专门使用 the 刷新命令来保持所需数据的活动。

要查看数据降级,您必须在相当长的一段时间内不访问这些行。 IE。写入该行特有的内容,对其进行预充电,并且访问时间不要超过 64 毫秒,最好更长。编写一些独特的内容,以避免将别名地址(在出现错误的情况下)误解为不同的,因为频繁访问同一行将使其保持活动状态。

© www.soinside.com 2019 - 2024. All rights reserved.