|
我写了一个 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周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|