Lamdeli

SRRAM驱动(一)

0
阅读(1009)

SDRAM驱动流程:

(一)   初始化:

image.png

图一

SDRAM初次上电时,需要对内部的逻辑控制单元进行初始化。如图一所示,初始化的具体流程如下:

1、 延时200us。

2、 对所有L-Bank进行预充电。具体操作:拉高所有rBA,rA地址,发送PR(预充电)命令。

3、 延时TRP。

4、 进行自刷新,发送AR(自刷新)命令。

5、 延时TRRC。

6、 重复步骤4和5。

7、 发送LMR(设置命令)命令与相关设置内容。详细设置见SDRAM模式寄存器设置。

8、 延时TMRD。

具体代码如下(参考:Verilog 那些事儿,驱动篇I):

 

        //Initial      

        case (i)

        0: //Dealy 200US

        begin

                if(C1 == T200US -1)

                       begin

                               i <= i + 1'b1;

                              C1 <= 14'd0;

                        end

                else

                        begin

                             C1 <= C1 + 1'b1;

                       end

          end

            

            1: //Set Precharg Command

            begin

                    rCMD  <= _PR;

                    rBA <= 2'b11;

                    rA <= 13'h1fff;

                    i <= i + 1'b1;

            end

            

            2://Delay TRP 20ns

            begin

                    if(C1 == TRP -1)

                            begin

                                    i <= i + 1'b1;

                                    C1 <= 14'd0;

                            end

                else

                        begin

                                C1 <= C1 + 1'b1;

                                rCMD  <= _NOP;

                        end

            end

            

            3://Set Auto Refresh command

            begin

                    rCMD  <= _AR;

                    i <= i + 1'b1;

            end

            

            4://delay tRRC 63ns

            begin

                     if(C1 == TRRC -1)

                            begin

                                    i <= i + 1'b1;

                                    C1 <= 14'd0;

                            end

                    else

                            begin

                                    C1 <= C1 + 1'b1;

                                    rCMD  <= _NOP;

                            end

            end

            

            5://Set Auto Refresh Command

            begin

                    rCMD  <= _AR;

                    i <= i + 1'b1;

            end

            

            6://delay tRRC 63ns

            begin

                     if(C1 == TRRC -1)

                            begin

                                    i <= i + 1'b1;

                                    C1 <= 14'd0;

                            end

                   else

                            begin

                                    C1 <= C1 + 1'b1;

                                    rCMD  <= _NOP;

                            end

            end

            

            7://Set LMR Command:burst Read and Write, A6A5A4=011 means CAS latecy = 3, Sequential, 1 burst length

             begin

                    rCMD  <= _LMR;

                    rBA <= 2'b11;

                    rA <= {3'd0, 1'b0, 2'd0, 3'b011, 1'b0, 3'b000};

                    i <= i + 1'b1;

            end

            

            8://Set 2 nop CLK for tMRD

            begin

                    if(C1 == TMRD -1)

                            begin

                                  i <= i + 1'b1;

                                  C1 <= 14'd0;

                            end

                    else

                            begin

                                 C1 <= C1 + 1'b1;

                                rCMD  <= _NOP;

                            end

            end

            

            9://Generate done signal

            begin

                    isDone = 1'b1;

                    i <= i + 1'b1;

            end

            

            10:

            begin

                    isDone = 1'b0;

                    i <= 4'd0;

            end

            

         endcase

(二)自刷新:

       SDRAM需要不断刷新才能保留住数据,目前公认的标准是存储体数据有效保存期上限是64ms,即每一行刷新的循环周期是64ms。对于整个SDRAM,需要每隔行数量/64ms就要进行一次刷新。发送AR(自刷新)命令时不需要外部提供行地址信息,行地址由SDRAM的内部行地址生成器自动依次生成。刷新是针对一行中所有的存储体进行,所以无需进行列寻址。自刷新的具体流程如下(操作相当于简化后的初始化):

1、发送PR(预充电)命令。

2、延时TRP。

3、进行自刷新,发送AR(自刷新)命令。

4、延时TRRC。

5、重复步骤3和4。

具体代码如下(参考:Verilog 那些事儿,驱动篇I):

 

 //Auto Refresh

            case(i)

            0: //Set Precharg Command

            begin

                    rCMD  <= _PR;

                    i <= i + 1'b1;

            end

            

            1://Delay TRP 20ns

            begin

                    if(C1 == TRP -1)

                            begin

                                    i <= i + 1'b1;

                                    C1 <= 14'd0;

                            end

                else

                            begin

                                    C1 <= C1 + 1'b1;

                                    rCMD  <= _NOP;

                            end

                end

                    

            2://Set Auto Refresh Command

            begin

                   rCMD  <= _AR;

                   i <= i + 1'b1;

            end

            

            3://delay tRRC 63ns

            begin

                     if(C1 == TRRC -1)

                            begin

                                    i <= i + 1'b1;

                                    C1 <= 14'd0;

                            end

                    else

                            begin

                                    C1 <= C1 + 1'b1;

                                    rCMD  <= _NOP;

                            end

            end

            

            4://Set Auto Refresh Command

            begin

                    rCMD  <= _AR;

                    i <= i + 1'b1;

            end

            

            5://delay tRRC 63ns

            begin

                     if(C1 == TRRC -1)

                            begin

                                    i <= i + 1'b1;

                                    C1 <= 14'd0;

                            end

                    else

                            begin

                                    C1 <= C1 + 1'b1;

                                    rCMD  <= _NOP;

                            end

            end

            

            6://Generate done signal

            begin

                    isDone = 1'b1;

                    i <= i + 1'b1;

            end

            

            7:

            begin

                    isDone = 1'b0;

                    i <= 4'd0;

            end

            endcase


(三)数据写(单字节):

        SDRAM数据读写按照L-BANK->行->列寻址。在写入数据后,还要执行预充电命令。预充电的目的是释放L-BANK地址,行地址,列地址。方便对同一个L-BANK的其他行地址进行操作。数据写的具体流程为:

image.png

图二

image.png

图三

1、发送ACT(激活)命令,发送L-BANK,行地址。

2、延时TRCD。

3、发送WR(写)命令,发送L-BANK,列地址。同时A10需要拉高进行预充电。写数据。

4、延时TWR。

5、延时TRP。

具体代码如下(参考:Verilog 那些事儿,驱动篇I):


//Data Write

            case(i)

            0://Set IO to Output State

            begin

                    IsOut = 1;

                    i <= i + 1'b1;

            end

            

            1: //Send Active Command with Bank and Row address

            begin

                    rCMD  <= _ACT;

                    rBA <= iAddr[23:22];

                    rA <= iAddr[21:9];

                    i <= i + 1'b1;

            end

            

            2: //Wait TRCD 20ns

            begin

                    if(C1 == TRCD - 1)

                            begin

                                    i <= i + 1'b1;

                                    C1 <= 14'd0;

                            end

                else

                            begin

                                    C1 <= C1 + 1'b1;

                                    rCMD  <= _NOP;

                            end

            end

            

            3: // Send Write cmd with row address, pull up A10 1 clk to PR

            begin

                    rCMD <= _WR;

                    rBA <= iAddr[23:22];

                    rA <= {4'b0010, iAddr[8:0] };

                    i <= i + 1'b1;  

                    rDA  <= rData;     //Write data

            end

            

            4: //Wait TWR 2 CLK

             begin

                    if(C1 == TWR - 1)

                            begin

                                    i <= i + 1'b1;

                                    C1 <= 14'd0;

                            end

             else

                    begin

                            C1 <= C1 + 1'b1;

                            rCMD  <= _NOP;

                    end

            end

            

            5://Delay TRP 20ns

            begin

                    if(C1 == TRP -1)

                            begin

                                    i <= i + 1'b1;

                                    C1 <= 14'd0;

                            end

                    else

                            begin

                                   C1 <= C1 + 1'b1;

                                    rCMD  <= _NOP;

                            end

                end

                    

            6://Generate done signal

            begin

                    isDone = 1'b1;

                    i <= i + 1'b1;

            end

            

            7:

            begin

                    isDone = 1'b0;

                    i <= 4'd0;

            end      

            endcase


数据写(多字节):

      以BL=4为例,需要在模式寄存器中设置BL=4,即A2~A0 = 3‘b010。具体流程为:

1、发送ACT(激活)命令,发送L-BANK,行地址。

2、延时TRCD。

3、发送WR(写)命令,发送L-BANK,列地址。同时A10需要拉高进行预充电。写第一字节数据。

4、写第一字节数据。

5、写第二字节数据。

6、写第三字节数据。

7、写第四字节数据。

8、延时TWR。

9、延时TRP。

具体代码如下(参考:Verilog 那些事儿,驱动篇I):


         //Data Write   

             case(i)

            0://Set IO to Output State

            begin

                    IsOut = 1;

                    i <= i + 1'b1;

            end

            

            1: //Send Active Command with Bank and Row address

            begin

                    rCMD  <= _ACT;

                    rBA <= iAddr[23:22];

                    rA <= iAddr[21:9];

                    i <= i + 1'b1;

            end

            

            2: //Wait TRCD 20ns

            begin

                    if(C1 == TRCD - 1)

                            begin

                                    i <= i + 1'b1;

                                    C1 <= 14'd0;

                            end

                    else

                            begin

                                C1 <= C1 + 1'b1;

                                rCMD  <= _NOP;

                    end

            end

            

            3: // Send Write cmd with row address, pull up A10 1 clk to PR

            begin

                    rCMD <= _WR;

                    rBA <= iAddr[23:22];

                    rA <= {4'b0010, iAddr[8:0] };

                     D1 <= iData[63:48];

                    i <= i + 1'b1;  

            end

            

             4:

             begin

                     rCMD <= _NOP;

                     D1 <= iData[47:32];

                     i <= i + 1'b1;

             end

            

             5:

             begin

                     rCMD <= _NOP;

                     D1 <= iData[31:16];

                     i <= i + 1'b1;

             end

            

             6:

             begin

                     rCMD <= _NOP;

                     D1 <= iData[15:0];

                     i <= i + 1'b1;

             end


            7: //Wait TWR 2 CLK

             begin

                    if(C1 == TWR - 1)

                            begin

                                    i <= i + 1'b1;

                                    C1 <= 14'd0;

                            end

                else

                            begin

                                    C1 <= C1 + 1'b1;

                                    rCMD  <= _NOP;

                            end

            end

            

            8://Delay TRP 20ns

            begin

                    if(C1 == TRP -1)

                            begin

                                    i <= i + 1'b1;

                                    C1 <= 14'd0;

                            end

                    else

                            begin

                                    C1 <= C1 + 1'b1;

                                    rCMD  <= _NOP;

                            end

            end

                    

            9://Generate done signal

            begin

                    isDone = 1'b1;

                    i <= i + 1'b1;

            end

            

            10:

            begin

                    isDone = 1'b0;

                    i <= 4'd0;

            end

         

         endcase

 

 

(四)数据读(单字节):

       SDRAM数据读取与数据写入大同小异。数据读写按照L-BANK->行->列寻址。在读入数据后,还要执行预充电命令。发出数据读取命令后需要满足CAS延时。具体流程为:

image.png

图四

1、发送ACT(激活)命令,发送L-BANK,行地址。

2、延时TRCD。

3、发送RD(读)命令,发送L-BANK,列地址。同时A10需要拉高进行预充电。

4、延时,满足CAS Latency。

5、读取数据。

6、延时TRP。

具体代码如下(参考:Verilog 那些事儿,驱动篇I):

 

            //Data Read    

         case(i)

            0://Set IO to Input State

            begin

                    IsOut = 0;

                    i <= i + 1'b1;

            end

            

            1: //Send Active Command with Bank and Row address

            begin

                    rCMD  <= _ACT;

                    rBA <= iAddr[23:22];

                    rA <= iAddr[21:9];

                    i <= i + 1'b1;

            end

            

            2: //Wait TRCD 20ns

            begin

                    if(C1 == TRCD - 1)

                           begin

                                    i <= i + 1'b1;

                                    C1 <= 14'd0;

                            end

                    else

                            begin

                                    C1 <= C1 + 1'b1;

                                    rCMD  <= _NOP;

                            end

            end

            

            3: // Send Read cmd with row address, pull up A10 1 clk to PR

            begin

                    rCMD <= _RD;

                    rBA <= iAddr[23:22];

                    rA <= {4'b0010,iAddr[8:0] };

                    i <= i + 1'b1;        

            end

            

             4: //Wait CL 3 CLK

             begin

                    if(C1 == CL - 1)

                            begin

                                    i <= i + 1'b1;

                                    C1 <= 14'd0;

                            end

                    else

                            begin

                                    C1 <= C1 + 1'b1;

                                    rCMD  <= _NOP;

                            end

            end

            

            

            5: //Read data

            begin

                    D1 <= S_DQ;

                    i <= i + 1'b1;

            end

            

            6://Delay TRP 20ns

            begin

                    if(C1 == TRP -1)

                            begin

                                    i <= i + 1'b1;

                                    C1 <= 14'd0;

                            end

                else

                            begin

                                    C1 <= C1 + 1'b1;

                                    rCMD  <= _NOP;

                            end

             end

                    

            7://Generate done signal

            begin

                    isDone = 1'b1;

                    i <= i + 1'b1;

            end

            

            8:

            begin

                    isDone = 1'b0;

                    i <= 4'd0;

            end

endcase

(四)数据读(多字节):

      以BL=4为例,需要在模式寄存器中设置BL=4,即A2~A0 = 3‘b010。具体流程为:

1、发送ACT(激活)命令,发送L-BANK,行地址。

2、延时TRCD。

3、发送RD(读)命令,发送L-BANK,列地址。同时A10需要拉高进行预充电。

4、延时,满足CAS Latency。

5、读取第一个字节。

6、读取第二个字节。

7、读取第三个字节。

8、读取第四个字节。

9、延时TRP。

具体代码如下(参考:Verilog 那些事儿,驱动篇I):


            //Data Read

            case(i)

            0://Set IO to Input State

            begin

                    IsOut = 0;

                    i <= i + 1'b1;

                    D1 <= 16'd0;

            end

            

            1: //Send Active Command with Bank and Row address

            begin

                    rCMD  <= _ACT;

                    rBA <= iAddr[23:22];

                    rA <= iAddr[21:9];

                    i <= i + 1'b1;

            end

            

            2: //Wait TRCD 20ns

            begin

                    if(C1 == TRCD - 1)

                            begin

                                    i <= i + 1'b1;

                                    C1 <= 14'd0;

                            end

                    else

                            begin

                                    C1 <= C1 + 1'b1;

                                    rCMD  <= _NOP;

                            end

            end

            

            3: // Send Read cmd with row address, pull up A10 1 clk to PR

            begin

                    rCMD <= _RD;

                    rBA <= iAddr[23:22];

                    rA <= {4'b0010,iAddr[8:0] };

                    i <= i + 1'b1;        

            end

            

            4: //Wait CL 3 CLK

             begin

                    if(C1 == CL - 1)

                            begin

                                    i <= i + 1'b1;

                                    C1 <= 14'd0;

                            end

                    else

                            begin

                                    C1 <= C1 + 1'b1;

                                    rCMD  <= _NOP;

                            end

            end

            

            

            5: //Read data

            begin

                    T[63:48] <= S_DQ;

                    i <= i + 1'b1;

            end


            6: //Read data

            begin

                    T[47:32] <= S_DQ;

                    i <= i + 1'b1;

            end


            7: //Read data

            begin

                    T[31:16] <= S_DQ;

                    i <= i + 1'b1;

            end

            

            8: //Read data

            begin

                    T[15:0] <= S_DQ;

                    i <= i + 1'b1;

            end

                    

            9:

            begin

                    rCMD  <= _NOP;

                    isDone = 1'b1;

                    i <= i + 1'b1;

            end

            

            10:

            begin

                    isDone = 1'b0;

                    i <= 4'd0;

            end

endcase

 

SDRAM模式寄存器控制

       在前文说过,在SDRAM初始化时,需要设置模式寄存器。模式寄存器的参数设置是通过设置地址线的0/1信号实现的。地址线各个位对应的寄存器设置加下图:

image.png

 图五    

       BA1~BA0,A11~A7:设置操作模式。

       A6~A4:CAS潜伏期,读操作中的CL参数,发出读命令后存储芯片到IO口输出真正数据需要的延时。

       A3:突发传输方式。1—顺序传输,按照地址依次进行数据寻址。每次数据读写需要发送读写命令和读写地址。0—突发传输,数据读写前只需要指定首地址和突发长度,发送一次读写命令后便可以进行连续数据读写。

      A2~A0:连续数据读写长度设置。设置BL的值后,可以在sdram读写程序中读写相应的长度。每次数据读写各需要一个时钟周期。