grantlu 发表于 2014-2-2 13:35:27

为什么我的 SDRAM 控制器只能运行在 100MHz?请高手支招。

    我写了一个 SDRAM 控制器,
又写了了一个测试,SDRAM用于图像帧存,前5秒图像数据读写交错进行,后 5 秒输出的图像只从SDRAM中读取,
期间不再往SDRAM中写入数据,如此反复。通过观察输出的图像发现,当运行在 162MHz、133MHz时图像数据交
错进行时,输出的图像有错误数据,即图像有干扰,而且可以肯定错误的数据是出现在读和写转换的位置上,
在后5秒钟时,图像数据读取正常。但是将运行频率将到 100MHz 时,输出的图像数据都正常。

   我没写时序约束,由于我的知识都是自学的,没有很系统的学过,所以不知道怎么书写时序约束,如果是针
对这个SDRAM控制器,应该要怎么写时序约束?

module sdram_control (
        input                                mainclk,
        input                                sd_res,
   // device interface
        inout                        sddq,
        output                        sdadd,
        output                        sddqm,
        output                        sdba,
        output                                sdclk,
        output                                sdcke,
        output                                sdcas,
        output                                sdras,
        output                                sdwe,
        output                                sdcs,

        // user interface
        input                        sd_radd,
        input                        sd_wadd,
        input                                sd_rq,
        input                                sd_wq,
        output                        sd_q,
        input                        sd_data,
        output                                sd_we,
        output                                sd_re,
        output                                sd_wack,
        output                                sd_rack,
       
        output                                test2,
        output                                test3

);


// Address 4 Blank * 512K * 32 Bit
// , Blank,

parameter CMD_DS = 4'b1000;
parameter CMD_NOP = 4'b0111;
parameter CMD_ACTIVE = 4'b0011;
parameter CMD_READ = 4'b0101;
parameter CMD_WRITE = 4'b0100;
parameter CMD_STR = 4'b0110;
parameter CMD_PRE = 4'b0010;
parameter CMD_AF = 4'b0001;
parameter CMD_ML = 4'b0000;

reg                                sd_status;
reg                                res_count1;
reg                                sd_cmd;
reg                                af_count;
reg                                        af_rq2, af_rq1;
reg                                Column_add;
reg                                ac_add;
wire                                        sd_rfq;
reg                                        r_outen, r_inen;
reg                                r_sdba;
reg                                r_sdadd;
reg                                        r_wack, r_rack;
reg                                        r_read_d1, r_read_d2, r_read_d3;
reg                                write_buf, read_buf;

reg                                res_afc;

reg                                        r_test, r_first;


initial
begin
   sd_status <= 0;
   res_count1 <= 16'b0;
end



// 162 MHz 15.6uS6.17 nS

assign sddqm = 4'b0000;
assign sd_rfq = (af_rq2 ^ af_rq1);

assign sdclk = mainclk;
assign sdcke = 1'b1;

assign sdcs= sd_cmd;
assign sdras = sd_cmd;
assign sdcas = sd_cmd;
assign sdwe= sd_cmd;
// assign sdadd = (r_rack) ? {4'd0, Column_add} : r_sdadd;
assign sdadd = r_sdadd;
assign sdba= r_sdba;

assign sd_q = sddq;

assign test2 = r_test;
assign test3 = af_rq1;

assign sddq = (sd_we) ? write_buf : 32'bz;

assign sd_wack = r_wack;
assign sd_we = r_wack;

assign sd_rack = r_rack;
assign sd_re = r_read_d3;

always @(posedge mainclk)
begin
   write_buf <= sd_data;

   // mainclk = 162 MHz 15.6uS
//   if (af_count < 2528) af_count <= af_count + 1;
   if (af_count < 2109) af_count <= af_count + 1;
   else
    begin
   af_count <= 0;
        af_rq1 <= ~af_rq1;
    end
   
   r_read_d1 <= r_rack;
   r_read_d2 <= r_read_d1;
   r_read_d3 <= r_read_d2;
   
   case (sd_status)
    0:                // reset
   begin
       if (sd_res)
          begin
              sd_cmd <= CMD_DS;
           r_sdadd <= 0;
           r_sdba <= 0;
           res_count1 <= 16'b0;
          end
       else sd_status <= 7;
        end
    1:                // 复位,所有块预充电
   begin
          sd_cmd <= CMD_PRE;
       r_sdadd <= 12'b0100_0000_0000;
      sd_status <= 2;
        end
    2:
   begin
       sd_cmd <= CMD_DS;
       sd_status <= 3;
        end
    3:
   begin
       sd_cmd <=CMD_DS;
       sd_status <= 4;
       res_afc <= 0;
        end
    4:                // 8 个刷新周期
   begin
       res_afc <= res_afc + 1;
       if (res_afc == 4'd8) sd_status <= 8;
       else sd_status <= 5;
        end
    5:
   begin
       sd_status <= 6;       
       sd_cmd <= CMD_AF;
       af_count <= 0;
   end
    6:
   begin
       sd_cmd <= CMD_DS;
       af_count <= af_count + 1;
       if (af_count > 11) sd_status <= 4;
        end
    7:
   begin        // 200uS = 29850 clk
       if (res_count1 > 30000) sd_status <= 1;
       res_count1 <= res_count1 + 1;
        end
    8:                // 设置模式寄存器        CAS = 3,
   begin
       sd_cmd <= CMD_ML;
       r_sdadd <= 12'b00000_011_0000;
       r_sdba <= 2'b00;
       sd_status <= 9;
        end
    9:
   begin
       sd_cmd <= CMD_DS;
       sd_status <= 10;
        end
        10:                // 空闲
   begin
       sd_cmd <= CMD_DS;
       if (sd_rfq) sd_status <= 40;
      else if (sd_rq) sd_status <= 20;
       else if (sd_wq) sd_status <= 30;
   end
    20:                // read
   begin
       sd_cmd <= CMD_ACTIVE;
       r_sdadd <= sd_radd;
       r_sdba <= sd_radd;
       sd_status <= 21;
       ac_add <= sd_radd;
   end
   21:
       begin
          sd_cmd <= CMD_DS;
          sd_status <= 22;
       end
    22:
        begin
       sd_cmd <= CMD_DS;
       sd_status <= 23;
       r_rack <= 1'b0;
   end
    23:
   begin
       if (sd_rfq | ~sd_rq | (sd_radd != ac_add))
       begin
           sd_cmd <= CMD_PRE;
              r_rack <= 1'b0;
           sd_status <= 24;
       end
       else
          begin
           sd_cmd <= CMD_READ;
           r_rack <= 1'b1;
           r_sdadd <= {4'b0000, sd_radd};
           sd_status <= 22;
          end
        end
    24:
   begin
       sd_cmd <= CMD_DS;
       sd_status <= 25;
   end       
    25:
   begin
      sd_cmd <= CMD_DS;
      if (sd_rfq) sd_status <= 40;
       else sd_status <= 10;
   end       

    30:                // write
   begin
       sd_cmd <= CMD_ACTIVE;
       r_sdadd <= sd_wadd;
       r_sdba <= sd_wadd;
       sd_status <= 31;
       ac_add <= sd_wadd;
   end
   31:
       begin
          sd_cmd <= CMD_DS;
          sd_status <= 32;
       end
    32:
        begin
       sd_cmd <= CMD_DS;
       sd_status <= 33;
       r_wack <= 1'b0;
        end
    33:
   begin
       if (sd_rfq | ~sd_wq | (sd_wadd != ac_add))
       begin
           sd_cmd <= CMD_DS;
           r_wack <= 1'b0;
           sd_status <= 34;
       end
      else
          begin
           sd_cmd <= CMD_WRITE;
           r_wack <= 1'b1;
           r_sdadd <= {4'b0000, sd_wadd};
           sd_status <= 32;
          end
   end       
    34:
   begin
      sd_cmd <= CMD_PRE;
      sd_status <= 24;
   end

    40:                // automatic refresh
   begin
       af_rq2 <= ~af_rq2;
      sd_status <= 41;
       sd_cmd <= CMD_AF;
       af_count <= 0;
   end
    41:
   begin
       sd_cmd <= CMD_DS;
       af_count <= af_count + 1;
       if (af_count > 11) sd_status <= 10;
        end
    default sd_status <= 0;
   endcase

end


endmodule


cmos2345 发表于 2014-2-2 13:39:01

你的头像不好,所以只能跑100MHz

grantlu 发表于 2014-2-2 13:59:58

cmos2345 发表于 2014-2-2 13:39
你的头像不好,所以只能跑100MHz

{:sweat:} ,要是换成你那样的头像就能跑1GHz呢?

jm2011 发表于 2014-2-2 16:58:06

这个应该做一下时序约束,100M以上的时序还是很有必要的;
另外,速度和你的板子和FPGA也有关系的

sky5566 发表于 2014-2-4 02:29:06

本帖最后由 sky5566 于 2014-2-4 02:32 编辑

你查一下 SDRAM_CLK 相位调整一下.
约束可防止每次编辑偏离时序.
另外你使用那个等级的 FPGA?EP2C8理想最快也才150MHZ

grantlu 发表于 2014-2-4 02:52:16

我用的是EP4CGX30CF23C8N ,最奇怪的就是162mhz交错读写时可以看到是读取错误,因为在下5秒时读取的数据显示图像正常,可它也意味着只进行读取时能工作在162mhz上,真是纳闷。另外我看到前面有人发贴说,sdram和fpga之间要串33欧姆电阻,我没串,和这有关系么?


codefish 发表于 2014-2-4 16:27:01

关注一下!我也想学一下这方面。

蓝色风暴@FPGA 发表于 2014-2-7 20:23:50

SDRAM能跑多快取决于它本身,一般是100、133、167M
另外SDRAM控制器和SDRAM器件时钟之间要有一定偏移
你试过100、133、162M,那相移肯定也要设置不一样的

ximuyi 发表于 2014-2-8 16:57:22

FPGA接SDRAM可以跑到160M,我跑过的,读写都正常。
系统用的是100M晶振,然后用DLL倍频到160M提供给SDRAM的CLK。
我估计是你的SDRAM时序有问题,你可以参考sdr_sdram代码

xiaohe669 发表于 2014-2-9 13:12:20

我用EPM570做的也是到100M,原因也没搞清楚    郁闷
页: [1]
查看完整版本: 为什么我的 SDRAM 控制器只能运行在 100MHz?请高手支招。