搜索
bottom↓
回复: 9

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

[复制链接]

出0入0汤圆

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

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

module sdram_control (
        input                                mainclk,
        input                                sd_res,
     // device interface
        inout        [31:0]                sddq,
        output        [11:0]                sdadd,
        output        [3:0]                sddqm,
        output        [1:0]                sdba,
        output                                sdclk,
        output                                sdcke,
        output                                sdcas,
        output                                sdras,
        output                                sdwe,
        output                                sdcs,

        // user interface
        input        [21:0]                sd_radd,
        input        [21:0]                sd_wadd,
        input                                sd_rq,
        input                                sd_wq,
        output        [31:0]                sd_q,
        input        [31:0]                sd_data,
        output                                sd_we,
        output                                sd_re,
        output                                sd_wack,
        output                                sd_rack,
       
        output                                test2,
        output                                test3

);


// Address 4 Blank * 512K * 32 Bit
// [L10:0], Blank[1:0], [C7:0]

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                [7:0]                 sd_status;
reg                [15:0]                res_count1;
reg                [3:0]                sd_cmd;
reg                [11:0]                af_count;
reg                                        af_rq2, af_rq1;
reg                [7:0]                Column_add;
reg                [13:0]                ac_add;
wire                                        sd_rfq;
reg                                        r_outen, r_inen;
reg                [1:0]                r_sdba;
reg                [11:0]                r_sdadd;
reg                                        r_wack, r_rack;
reg                                        r_read_d1, r_read_d2, r_read_d3;
reg                [31:0]                write_buf, read_buf;

reg                [3:0]                res_afc;

reg                                        r_test, r_first;


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



// 162 MHz 15.6uS  6.17 nS

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

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

assign sdcs  = sd_cmd[3];
assign sdras = sd_cmd[2];
assign sdcas = sd_cmd[1];
assign sdwe  = sd_cmd[0];
// 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[21:10];
         r_sdba <= sd_radd[9:8];
         sd_status <= 21;
         ac_add <= sd_radd[21:8];
     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[21:8] != 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[7:0]};
           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[21:10];
         r_sdba <= sd_wadd[9:8];
         sd_status <= 31;
         ac_add <= sd_wadd[21:8];
     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[21:8] != 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[7:0]};
           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


阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2014-2-2 13:39:01 | 显示全部楼层
你的头像不好,所以只能跑100MHz

出0入0汤圆

 楼主| 发表于 2014-2-2 13:59:58 | 显示全部楼层
cmos2345 发表于 2014-2-2 13:39
你的头像不好,所以只能跑100MHz

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

出0入0汤圆

发表于 2014-2-2 16:58:06 | 显示全部楼层
这个应该做一下时序约束,100M以上的时序还是很有必要的;
另外,速度和你的板子和FPGA也有关系的

出0入0汤圆

发表于 2014-2-4 02:29:06 | 显示全部楼层
本帖最后由 sky5566 于 2014-2-4 02:32 编辑

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

出0入0汤圆

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


出0入0汤圆

发表于 2014-2-4 16:27:01 | 显示全部楼层
关注一下!我也想学一下这方面。

出0入0汤圆

发表于 2014-2-7 20:23:50 | 显示全部楼层
SDRAM能跑多快取决于它本身,一般是100、133、167M
另外SDRAM控制器和SDRAM器件时钟之间要有一定偏移
你试过100、133、162M,那相移肯定也要设置不一样的

出0入0汤圆

发表于 2014-2-8 16:57:22 | 显示全部楼层
FPGA接SDRAM可以跑到160M,我跑过的,读写都正常。
系统用的是100M晶振,然后用DLL倍频到160M提供给SDRAM的CLK。
我估计是你的SDRAM时序有问题,你可以参考sdr_sdram代码

出0入0汤圆

发表于 2014-2-9 13:12:20 | 显示全部楼层
我用EPM570做的也是到100M,原因也没搞清楚    郁闷
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-27 06:00

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表