为什么我的 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
你的头像不好,所以只能跑100MHz cmos2345 发表于 2014-2-2 13:39
你的头像不好,所以只能跑100MHz
{:sweat:} ,要是换成你那样的头像就能跑1GHz呢? 这个应该做一下时序约束,100M以上的时序还是很有必要的;
另外,速度和你的板子和FPGA也有关系的 本帖最后由 sky5566 于 2014-2-4 02:32 编辑
你查一下 SDRAM_CLK 相位调整一下.
约束可防止每次编辑偏离时序.
另外你使用那个等级的 FPGA?EP2C8理想最快也才150MHZ 我用的是EP4CGX30CF23C8N ,最奇怪的就是162mhz交错读写时可以看到是读取错误,因为在下5秒时读取的数据显示图像正常,可它也意味着只进行读取时能工作在162mhz上,真是纳闷。另外我看到前面有人发贴说,sdram和fpga之间要串33欧姆电阻,我没串,和这有关系么?
关注一下!我也想学一下这方面。 SDRAM能跑多快取决于它本身,一般是100、133、167M
另外SDRAM控制器和SDRAM器件时钟之间要有一定偏移
你试过100、133、162M,那相移肯定也要设置不一样的
FPGA接SDRAM可以跑到160M,我跑过的,读写都正常。
系统用的是100M晶振,然后用DLL倍频到160M提供给SDRAM的CLK。
我估计是你的SDRAM时序有问题,你可以参考sdr_sdram代码 我用EPM570做的也是到100M,原因也没搞清楚 郁闷
页:
[1]