quartus qsys sdram ip时序问题
一个关于qsys sdram的时序问题,希望各位有经验的大佬给予一些解决方法
将时序进行约束后,其他违规的我都已经改好了
就剩下这一个qsys sdram ip内部的违规我不知道该怎么修改好,
首先我把这个模块里面把我自己认为该改的都改好了,其他模块也优化了大概2k LE出来,但对这个违规并没什么改善
用signaltap ii看读写数据时,写进去数据全为0,但出来同一个地址,数据变化乱跳
时而有数据时而为0,当程序才烧入FPGA时还好,但是跑了一段时间后,现在就严重了
困惑了好久,请各位给出一个解决方案,指出指出代码编写中存在的问问,谢谢大佬
module qsys_sdram_ctrl
(
clk ,
rst_n ,
sync ,
sdram_rd_en ,
rd_done_sig ,
MOD_HALF ,
RD_LEN ,
mod_h ,
mod_v ,
mod_l ,
mod_c ,
mod_p ,
mod_g ,
port0_init ,
port1_init ,
port2_init ,
port3_init ,
port4_init ,
port5_init ,
port6_init ,
port7_init ,
port8_init ,
port9_init ,
port10_init ,
port11_init ,
wr_ram_wrreq ,
wr_ram_wraddress ,
sdram_ctrl_readdatavalid,
bit_dif ,
bit_select1 ,
bit_select2 ,
frame_init ,
sdram_datain ,
sdram_ctrl_chipselect ,
sdram_ctrl_byteenable_n ,
sdram_ctrl_address ,
sdram_ctrl_writedata ,
sdram_ctrl_read ,
sdram_ctrl_write ,
sdram_ctrl_waitrequest ,
ram_rd_en ,
ram_rdaddress ,
sdram_read_en ,
rd_flag
);
input clk ;
input rst_n ;
input rd_done_sig ;
input sdram_rd_en /* synthesis keep */;
input wr_ram_wrreq /* synthesis keep */;
input [ 7:0] wr_ram_wraddress ;
input [ 3:0] bit_dif ;
input [ 3:0] bit_select1 ;
input [ 3:0] bit_select2 ;
input [31:0] sdram_datain ;
input sdram_ctrl_readdatavalid;
input sync ;
input [13:0] MOD_HALF ;
input [ 7:0] RD_LEN ;
input [ 5:0] mod_h ;
input [ 8:0] mod_v ;
input [ 4:0] mod_l ;
input [ 3:0] mod_c ;
input [ 6:0] mod_p ;
input [ 6:0] mod_g ;
input [14:0] port0_init ;
input [14:0] port1_init ;
input [14:0] port2_init ;
input [14:0] port3_init ;
input [14:0] port4_init ;
input [14:0] port5_init ;
input [14:0] port6_init ;
input [14:0] port7_init ;
input [14:0] port8_init ;
input [14:0] port9_init ;
input [14:0] port10_init ;
input [14:0] port11_init ;
output reg frame_init ;
output reg [16:0] ram_rd_en ;
output reg [ 7:0] ram_rdaddress ;
output sdram_ctrl_chipselect;
output [ 3:0] sdram_ctrl_byteenable_n;
output reg [20:0] sdram_ctrl_address;
output reg [31:0] sdram_ctrl_writedata;
output reg sdram_ctrl_read;
output reg sdram_ctrl_write;
output reg rd_flag;
output reg sdram_read_en;
input sdram_ctrl_waitrequest;
localparam EN_READ = 1'b0 ;
localparam DIS_READ = 1'b1 ;
localparam EN_WRITE = 1'b0 ;
localparam DIS_WRITE = 1'b1 ;
localparam SYNC = 4'd0 ;
localparam INIT = 4'd1 ;
localparam WRITE_INIT = 4'd2 ;
localparam WRITE_INIT2 = 4'd3 ;
localparam WRITE = 4'd4 ;
localparam WRITE1 = 4'd5 ;
localparam WRITE_DONE = 4'd6 ;
localparam READ_INIT = 4'd7 ;
localparam READ = 4'd8 ;
localparam READ_DONE = 4'd9 ;
parameter BIT0_INIT = 21'd0;
parameter BIT1_INIT = 21'd18432;
parameter BIT2_INIT = 21'd36864;
parameter BIT3_INIT = 21'd55296;
parameter BIT4_INIT = 21'd73728;
parameter BIT5_INIT = 21'd92160;
parameter BIT6_INIT = 21'd110592;
parameter BIT7_INIT = 21'd129024;
parameter BIT8_INIT = 21'd147456;
parameter BIT9_INIT = 21'd165888;
parameter BIT10_INIT = 21'd184320;
parameter BIT11_INIT = 21'd202752;
parameter BIT12_INIT = 21'd221184;
parameter BIT13_INIT = 21'd239616;
parameter BIT14_INIT = 21'd258048;
parameter BIT15_INIT = 21'd276480;
parameter MOD_DONE = 21'd290304;
parameter MOD_DONE2 = 21'd585216;
parameter BIT_DONE = 21'd294912;
parameter BIT_DONE2 = 21'd589824;
parameter BIT_HALF = 21'd9216;
parameter NEXT_DONE = BIT_HALF + BIT_DONE;
parameter INIT_COUNT = 9'd10;
reg [3:0] current_state ;
reg [3:0] next_state /* synthesis keep */;
/////////////////////////////////////////////
reg [20:0] rd_bit_init;
reg [20:0] wr_bit_init;
reg [20:0] write_init;
reg [20:0] rd_rgb_init;
reg [ 3:0] sdram_rd_bit;
reg rd_bit_flag;
reg sync_f1;
reg sync_f2;
wire sync_h2l;
reg wr_flag_f1;
reg wr_flag_f2;
wire wr_flag_h2l;
reg flag;
reg rd_en;
reg write_en;
reg sdram_write_en;
// reg sdram_read_en;
// reg sdram_rd_init;
reg [ 9:0] counter;
reg skip_en;
reg [16:0] ram_rd_en_reg;
reg [13:0] sdram_wraddress;
reg [14:0] sdram_rdaddress;
reg [ 4:0] cnt;
reg read_sig;
reg [10:0] write_cnt;
reg [13:0] read_cnt;
reg rd_done;
reg wr_done;
reg [ 5:0] cnt_h;
reg [ 8:0] cnt_v;
reg [ 4:0] cnt_l;
reg [ 3:0] cnt_c;
reg [ 6:0] cnt_p;
reg [ 6:0] cnt_g;
reg [14:0] port0_addr;
reg [14:0] port1_addr;
reg [14:0] port2_addr;
reg [14:0] port3_addr;
reg [14:0] port4_addr;
reg [14:0] port5_addr;
reg [14:0] port6_addr;
reg [14:0] port7_addr;
reg [14:0] port8_addr;
reg [14:0] port9_addr;
reg [14:0] port10_addr;
reg [14:0] port11_addr;
assign sdram_ctrl_chipselect = 1'b1;
assign sdram_ctrl_byteenable_n = 4'b0;
assign sync_h2l = !sync_f1 & sync_f2;
assign wr_flag_h2l = !wr_flag_f1 & wr_flag_f2;
//帧同步信号下降沿检测
always @(posedge clk) begin
sync_f1 <= sync;
sync_f2 <= sync_f1;
end
//写标志下降沿检测
always @(posedge clk) begin
wr_flag_f1 <= wr_flag;
wr_flag_f2 <= wr_flag_f1;
end
//写地址初地址,16个bit数据分16个区域存储
always @(posedge clk) begin
case(ram_rd_en)
17'd2 : wr_bit_init <= BIT0_INIT;
17'd4 : wr_bit_init <= BIT1_INIT;
17'd8 : wr_bit_init <= BIT2_INIT;
17'd16 : wr_bit_init <= BIT3_INIT;
17'd32 : wr_bit_init <= BIT4_INIT;
17'd64 : wr_bit_init <= BIT5_INIT;
17'd128 : wr_bit_init <= BIT6_INIT;
17'd256 : wr_bit_init <= BIT7_INIT;
17'd512 : wr_bit_init <= BIT8_INIT;
17'd1024 : wr_bit_init <= BIT9_INIT;
17'd2048 : wr_bit_init <= BIT10_INIT;
17'd4096 : wr_bit_init <= BIT11_INIT;
17'd8192 : wr_bit_init <= BIT12_INIT;
17'd16384 : wr_bit_init <= BIT13_INIT;
17'd32768 : wr_bit_init <= BIT14_INIT;
17'd65536 : wr_bit_init <= BIT15_INIT;
default : wr_bit_init <= BIT0_INIT;
endcase
end
//读地址初地址,根据当前哪个bit的数据,便从哪个初地址开始读
always @(posedge clk) begin
case(sdram_rd_bit)
4'd15 : rd_bit_init <= BIT0_INIT;
4'd14 : rd_bit_init <= BIT1_INIT;
4'd13 : rd_bit_init <= BIT2_INIT;
4'd12 : rd_bit_init <= BIT3_INIT;
4'd11 : rd_bit_init <= BIT4_INIT;
4'd10 : rd_bit_init <= BIT5_INIT;
4'd9 : rd_bit_init <= BIT6_INIT;
4'd8 : rd_bit_init <= BIT7_INIT;
4'd7 : rd_bit_init <= BIT8_INIT;
4'd6 : rd_bit_init <= BIT9_INIT;
4'd5 : rd_bit_init <= BIT10_INIT;
4'd4 : rd_bit_init <= BIT11_INIT;
4'd3 : rd_bit_init <= BIT12_INIT;
4'd2 : rd_bit_init <= BIT13_INIT;
4'd1 : rd_bit_init <= BIT14_INIT;
4'd0 : rd_bit_init <= BIT15_INIT;
default : rd_bit_init <= BIT0_INIT;
endcase
end
//写标志,每一个bit分两组数据,标志位为0存第一组数据,反之则存第二组数据
reg wr_flag;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
wr_flag <= 1'b0;
else if(sync)
wr_flag <= 1'b0;
else if(sdram_wraddress == MOD_HALF) //第一组数据存满,标志位变化开始存第二组
wr_flag <= ~wr_flag;
else
wr_flag <= wr_flag;
end
//写地址选择寄存器
reg [ 3:0] wr_select;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
wr_select <= 4'b0;
else if(sync)
wr_select <= 4'b0;
else begin
if(wr_flag_h2l)
wr_select <= wr_select + 1'b1;
else
wr_select <= wr_select;
end
end
//根据写选择寄存器,对当前bit当前数据该写入的初地址进行选择
reg [20:0] wraddress_init;
always @(posedge clk) begin
case(wr_select)
4'd0 : wraddress_init <= 21'b0;
4'd1 : wraddress_init <= 21'd1152;
4'd2 : wraddress_init <= 21'd2304;
4'd3 : wraddress_init <= 21'd3456;
4'd4 : wraddress_init <= 21'd4608;
4'd5 : wraddress_init <= 21'd5760;
4'd6 : wraddress_init <= 21'd6912;
4'd7 : wraddress_init <= 21'd8064;
4'd8 : wraddress_init <= 21'd9216;
4'd9 : wraddress_init <= 21'd10368;
4'd10 : wraddress_init <= 21'd11520;
4'd11 : wraddress_init <= 21'd12672;
default : wraddress_init <= 21'b0;
endcase
end
//前级ram全部写完标志信号
reg ram_rd_en_f1 ;
reg ram_rd_en_f2 ;
wire ram_rd_en_h2l ;
assign ram_rd_en_h2l = !ram_rd_en_f1 & ram_rd_en_f2;
always @(posedge clk) begin
ram_rd_en_f1 <= ram_rd_en[16];
ram_rd_en_f2 <= ram_rd_en_f1;
end
//sdram当前读完毕标志信号
reg read_f1;
reg read_f2;
wire read_sig_h2l;
assign read_sig_h2l = !read_f1 & read_f2;
always @(posedge clk) begin
read_f1 <= read_sig;
read_f2 <= read_f1;
end
//乒乓读sdram信号
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
rd_done <= 1'b0;
else if(rd_done_sig) //当前sdram全部读完,乒乓下一帧读取
rd_done <= ~rd_done;
else
rd_done <= rd_done;
end
//乒乓写sdram信号
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
wr_done <= 1'b0;
else begin
case(next_state)
WRITE_DONE : begin
if(sdram_ctrl_address == MOD_DONE2 - 1'b1)
wr_done <= 1'b0;
else if(sdram_ctrl_address == MOD_DONE - 1'b1)
wr_done <= 1'b1;
else
wr_done <= wr_done;
end
default : wr_done <= wr_done;
endcase
end
end
//sdram写使能
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
write_en <= 1'b0;
else if(sync)
write_en <= 1'b0;
else begin
if(wr_ram_wrreq && (wr_ram_wraddress == 8'd128 || wr_ram_wraddress == 8'd255)) //当前级ram乒乓写满一半
write_en <= 1'b1; //开始读前级ram,并将读出数据存入sdram当中
else if(ram_rd_en_h2l && (ram_rdaddress == 8'd128 || ram_rdaddress == 8'd0)) //当前级ram读完一半后,写使能关闭
write_en <= 1'b0;
else
write_en <= write_en;
end
end
//sdram实际写使能,当前如果有读信号读,则实际写使能清零,实现读优先
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
sdram_write_en <= 1'b0;
else if(sync)
sdram_write_en <= 1'b0;
else begin
if(sdram_read_en && rd_en)
sdram_write_en <= 1'b0;
else
sdram_write_en <= write_en;
end
end
//最后两个ram在读时候,不进行sdram读操作,防止前级ram写数据溢出
always @(posedge clk) begin
if(ram_rd_en[15] || ram_rd_en[14])
rd_en <= 1'b0;
else
rd_en <= 1'b1;
end
//sdram读使能
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
sdram_read_en <= 1'b0;
else if(sync)
sdram_read_en <= 1'b0;
else begin
if(sdram_rd_en) //读信号到,读使能置位
sdram_read_en <= 1'b1;
else if(read_sig_h2l) //读完成信号到,读使能清零
sdram_read_en <= 1'b0;
else
sdram_read_en <= sdram_read_en;
end
end
//三段式状态机
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
current_state <= SYNC;
else if(sync)
current_state <= SYNC;
else
current_state <= next_state;
end
//////////////////////////////////////////////////////
always @(*) begin
next_state = INIT;
case(current_state)
SYNC : begin
if(sync_h2l)
next_state = INIT;
else
next_state = SYNC;
end
INIT : begin
if(sdram_write_en)
if(sdram_read_en && rd_en)
next_state = READ_INIT;
else if(sdram_write_en)
next_state = WRITE_INIT;
else
next_state = INIT;
end
READ_INIT : begin
if(skip_en)
next_state = READ;
else
next_state = READ_INIT;
end
READ : begin
if(skip_en)
next_state = READ_DONE;
else
next_state = READ;
end
READ_DONE : begin
if(skip_en)
next_state = INIT;
else
next_state = READ_DONE;
end
WRITE_INIT : begin
if(skip_en)
next_state = WRITE_INIT2;
else
next_state = WRITE_INIT;
end
WRITE_INIT2 : begin
if(skip_en)
next_state = WRITE;
else
next_state = WRITE_INIT2;
end
WRITE : begin
if(skip_en)
next_state = WRITE1;
else
next_state = WRITE;
end
WRITE1 : begin
if(skip_en)
next_state = WRITE_DONE;
else
next_state = WRITE1;
end
WRITE_DONE : begin
if(skip_en)
next_state = INIT;
else
next_state = WRITE_DONE;
end
default : next_state = SYNC;
endcase
end
//状态跳转
always @(posedge clk) begin
skip_en <= 1'b0;
case(next_state)
READ_INIT : begin
if(counter == 10'd2) //空两个时钟出来,给初始化端口0的地址使用
skip_en <= 1'b1;
end
READ : begin
if(counter == RD_LEN - 1'b1 && !sdram_ctrl_waitrequest) //当计数满且sdram不是忙碌状态
skip_en <= 1'b1;
end
READ_DONE : begin
if(counter == INIT_COUNT) //计满跳转,保证sdram刷新时间
skip_en <= 1'b1;
end
WRITE_INIT : skip_en <= 1'b1; //打一拍
WRITE_INIT2 : begin
if(counter == 10'd1)
skip_en <= 1'b1;
end
WRITE : begin
if(!sdram_ctrl_waitrequest && counter == 10'd126) //写计满且sdram不是忙碌状态
skip_en <= 1'b1;
end
WRITE1 : begin
if(!sdram_ctrl_waitrequest) //非忙碌状态
skip_en <= 1'b1;
end
WRITE_DONE : begin
if(counter == INIT_COUNT) //计满跳转,保证sdram刷新时间
skip_en <= 1'b1;
end
default : skip_en <= 1'b0;
endcase
end
//计数跳转
always @(posedge clk) begin
case(next_state)
READ_INIT : begin
if(counter == 10'd2)
counter <= 10'b0;
else
counter <= counter + 1'b1;
end
READ : begin
if(counter == RD_LEN - 1'b1 && !sdram_ctrl_waitrequest)
counter <= 10'b0;
else if(!sdram_ctrl_waitrequest)
counter <= counter + 1'b1;
end
READ_DONE : begin
if(counter == INIT_COUNT)
counter <= 10'b0;
else
counter <= counter + 1'b1;
end
WRITE_INIT2 : begin
if(counter == 10'd1)
counter <= 10'b0;
else
counter <= counter + 1'b1;
end
WRITE : begin
if(!sdram_ctrl_waitrequest && counter == 10'd126)
counter <= 8'b0;
else if(!sdram_ctrl_waitrequest)
counter <= counter + 1'b1;
end
WRITE_DONE : begin
if(counter == INIT_COUNT)
counter <= 10'd0;
else
counter <= counter + 1'b1;
end
endcase
end
//sdram读使能控制,读长度由RD_LEN控制
always @(posedge clk) begin
case(next_state)
READ_INIT : begin
if(counter == 10'd2)
sdram_ctrl_read <= EN_READ;
else
sdram_ctrl_read <= DIS_READ;
end
READ : begin
sdram_ctrl_read <= EN_READ;
if(counter == RD_LEN - 1'b1 && !sdram_ctrl_waitrequest)
sdram_ctrl_read <= DIS_READ;
end
default : sdram_ctrl_read <= DIS_READ;
endcase
end
//sdram写使能,写长度为128个数据
always @(posedge clk) begin
case(next_state)
WRITE , WRITE1 :
sdram_ctrl_write <= EN_WRITE;
default :
sdram_ctrl_write <= DIS_WRITE;
endcase
end
//当前写sdram初地址
always @(posedge clk)
write_init <= wraddress_init + wr_bit_init;
//sdram读写地址控制
always @(posedge clk) begin
case(next_state)
SYNC :
sdram_ctrl_address <= 21'b0;
READ_INIT : begin
if(!sdram_ctrl_waitrequest) begin
if(!rd_done) begin
if(rd_flag)
sdram_ctrl_address <= rd_bit_init + sdram_rdaddress + BIT_HALF;
else
sdram_ctrl_address <= rd_bit_init + sdram_rdaddress;
end
else begin
if(rd_flag)
sdram_ctrl_address <= rd_bit_init + sdram_rdaddress + NEXT_DONE;
else
sdram_ctrl_address <= rd_bit_init + sdram_rdaddress + BIT_DONE;
end
end
else
sdram_ctrl_address <= sdram_ctrl_address;
end
READ : begin
if(!sdram_ctrl_waitrequest) begin
if(!rd_done) begin
if(rd_flag)
sdram_ctrl_address <= rd_bit_init + sdram_rdaddress + BIT_HALF;
else
sdram_ctrl_address <= rd_bit_init + sdram_rdaddress;
end
else begin
if(rd_flag)
sdram_ctrl_address <= rd_bit_init + sdram_rdaddress + NEXT_DONE;
else
sdram_ctrl_address <= rd_bit_init + sdram_rdaddress + BIT_DONE;
end
end
end
WRITE : begin
if(!sdram_ctrl_waitrequest) begin
if(wr_done) begin
if(wr_flag)
sdram_ctrl_address <= sdram_wraddress + NEXT_DONE;
else
sdram_ctrl_address <= sdram_wraddress + BIT_DONE;
end
else begin
if(wr_flag)
sdram_ctrl_address <= sdram_wraddress + BIT_HALF;
else
sdram_ctrl_address <= sdram_wraddress;
end
end
else
sdram_ctrl_address <= sdram_ctrl_address;
end
WRITE1 : begin
if(!sdram_ctrl_waitrequest) begin
if(wr_done) begin
if(wr_flag)
sdram_ctrl_address <= sdram_wraddress + NEXT_DONE;
else
sdram_ctrl_address <= sdram_wraddress + BIT_DONE;
end
else begin
if(wr_flag)
sdram_ctrl_address <= sdram_wraddress + BIT_HALF;
else
sdram_ctrl_address <= sdram_wraddress;
end
end
else
sdram_ctrl_address <= sdram_ctrl_address;
end
default : sdram_ctrl_address <= sdram_ctrl_address;
endcase
end
//sdram写地址寄存器,当前级ram 16个都读取完毕,则开始存到下一轮地址当中
always @(posedge clk) begin
case(next_state)
SYNC : sdram_wraddress <= 14'b0;
WRITE : begin
if(!sdram_ctrl_waitrequest)
sdram_wraddress <= sdram_wraddress + 1'b1;
end
WRITE1 : begin
if(!sdram_ctrl_waitrequest) begin
if(ram_rd_en[16])
sdram_wraddress <= sdram_wraddress + 1'b1;
else
sdram_wraddress <= sdram_wraddress - 14'd127;
end
end
WRITE_DONE : begin
if(sdram_wraddress == MOD_HALF)
sdram_wraddress <= 14'b0;
else
sdram_wraddress <= sdram_wraddress;
end
default : sdram_wraddress <= sdram_wraddress;
endcase
end
//写sdram数据,非忙碌则正常存,否则便保存数据不变
always @(posedge clk) begin
if(!sdram_ctrl_waitrequest)
sdram_ctrl_writedata <= sdram_datain;
else
sdram_ctrl_writedata <= sdram_ctrl_writedata;
end
//前级sdram读使能信号,没读完128个数据便跳转至下一ram进行使能读取
always @(posedge clk) begin
case(next_state)
SYNC : ram_rd_en <= 17'b1;
WRITE_INIT : ram_rd_en <= {ram_rd_en[15:0] , ram_rd_en[16]};
WRITE_DONE : begin
if(ram_rd_en[16])
ram_rd_en <= 17'd1;
else
ram_rd_en <= ram_rd_en;
end
default : ram_rd_en <= ram_rd_en;
endcase
end
//读前级ram地址
always @(posedge clk) begin
case(next_state)
SYNC : ram_rdaddress <= 8'd0;
WRITE_INIT2 : ram_rdaddress <= ram_rdaddress + 1'b1;
WRITE : begin
if(!sdram_ctrl_waitrequest && counter < 10'd125)
ram_rdaddress <= ram_rdaddress + 1'b1;
if(!sdram_ctrl_waitrequest && counter == 10'd125) begin
if(ram_rd_en[16])
ram_rdaddress <= ram_rdaddress + 1'b1;
else
ram_rdaddress <= ram_rdaddress - 8'd127;
end
end
default : ram_rdaddress <= ram_rdaddress;
endcase
end
//sdram当前读bit控制
always @(posedge clk) begin
if(sync)
sdram_rd_bit <= 4'b0;
else if(sync_h2l)
sdram_rd_bit <= bit_select1 + bit_dif;
else if(rd_bit_flag)
sdram_rd_bit <= bit_select2 + bit_dif;
else
sdram_rd_bit <= bit_select1 + bit_dif;
end
//当前读bit通过此标志读取两组数据
always @(posedge clk) begin
if(sync)
rd_bit_flag <= 1'b0;
else if(read_sig_h2l)
rd_bit_flag <= ~rd_bit_flag;
else
rd_bit_flag <= rd_bit_flag;
end
//读信号,判断当前是否在读状态当中
always @(posedge clk) begin
case(next_state)
SYNC : read_sig <= 1'b0;
READ_INIT : read_sig <= 1'b1;
READ_DONE : begin
if(counter == INIT_COUNT - 10'd2 && rd_flag)
read_sig <= 1'b0;
else
read_sig <= read_sig;
end
default : read_sig <= read_sig;
endcase
end
//读地址寄存器
always @(posedge clk) begin
case(next_state)
SYNC : sdram_rdaddress <= 15'b0;
READ_INIT : sdram_rdaddress <= port0_addr;
READ : begin
if(!sdram_ctrl_waitrequest) begin
case(cnt_c)
4'd0 : sdram_rdaddress <= port0_addr;
4'd1 : sdram_rdaddress <= port1_addr;
4'd2 : sdram_rdaddress <= port2_addr;
4'd3 : sdram_rdaddress <= port3_addr;
4'd4 : sdram_rdaddress <= port4_addr;
4'd5 : sdram_rdaddress <= port5_addr;
4'd6 : sdram_rdaddress <= port6_addr;
4'd7 : sdram_rdaddress <= port7_addr;
4'd8 : sdram_rdaddress <= port8_addr;
4'd9 : sdram_rdaddress <= port9_addr;
4'd10 : sdram_rdaddress <= port10_addr;
4'd11 : sdram_rdaddress <= port11_addr;
default : sdram_rdaddress <= sdram_rdaddress;
endcase
end
else
sdram_rdaddress <= sdram_rdaddress;
end
default : sdram_rdaddress <= 15'b0;
endcase
end
always @(posedge clk) begin
case(next_state)
SYNC : rd_flag <= 1'b0;
READ_DONE : begin
if(counter == INIT_COUNT && frame_init)
rd_flag <= ~rd_flag;
else
rd_flag <= rd_flag;
end
default : rd_flag <= rd_flag;
endcase
end
always @(posedge clk) begin
case(next_state)
SYNC : cnt_g <= 7'b0;
READ_DONE : begin
if(cnt_h == mod_h && cnt_p == mod_p - 1'b1) begin
if(cnt_g == mod_g - 1'b1)
cnt_g <= 7'b0;
else
cnt_g <= cnt_g + 1'b1;
end
end
default : cnt_g <= cnt_g;
endcase
end
always @(posedge clk) begin
case(next_state)
SYNC : cnt_p <= 7'b0;
READ_DONE : begin
if(cnt_h == mod_h) begin
if(cnt_p == mod_p - 1'b1)
cnt_p <= 7'b0;
else
cnt_p <= cnt_p + 1'b1;
end
end
default : cnt_p <= cnt_p;
endcase
end
always @(posedge clk) begin
case(next_state)
SYNC : cnt_h <= 6'b0;
READ : begin
if(!sdram_ctrl_waitrequest && cnt_l == mod_l - 1'b1 && cnt_c == mod_c - 1'b1 && rd_flag && rd_bit_flag)
cnt_h <= cnt_h + 1'b1;
else
cnt_h <= cnt_h;
end
READ_DONE : begin
if(cnt_h == mod_h && counter == INIT_COUNT)
cnt_h <= 6'b0;
else
cnt_h <= cnt_h;
end
default : cnt_h <= cnt_h;
endcase
end
always @(posedge clk) begin
case(next_state)
SYNC : cnt_l <= 5'b0;
READ_INIT : begin
if(counter == 10'd0)
cnt_l <= 5'b0;
else
cnt_l <= cnt_l + 1'b1;
end
READ : begin
if(!sdram_ctrl_waitrequest) begin
if(cnt_l == mod_l - 1'b1)
cnt_l <= 5'b0;
else
cnt_l <= cnt_l + 1'b1;
end
end
default : cnt_l <= 5'b0;
endcase
end
always @(posedge clk) begin
case(next_state)
SYNC : cnt_c <= 4'b0;
READ : begin
if(!sdram_ctrl_waitrequest && cnt_l == mod_l - 1'b1)
cnt_c <= cnt_c + 1'b1;
else
cnt_c <= cnt_c;
end
default : cnt_c <= 4'b0;
endcase
end
always @(posedge clk) begin
case(next_state)
SYNC : port0_addr <= port0_init;
READ_INIT : begin
if(counter == 10'd0)
port0_addr <= port0_addr;
else
port0_addr <= port0_addr + 1'b1;
end
READ : begin
if(!sdram_ctrl_waitrequest && cnt_c == 4'd0) begin
if(cnt_l == mod_l - 1'b1 && rd_flag && rd_bit_flag)
port0_addr <= port0_addr + mod_v;
else if(cnt_l == mod_l - 1'b1)
port0_addr <= port0_addr - mod_l + 1'b1;
else
port0_addr <= port0_addr + 1'b1;
end
else
port0_addr <= port0_addr;
end
READ_DONE : begin
if(cnt_h == mod_h && counter == INIT_COUNT)
port0_addr <= port0_init;
else
port0_addr <= port0_addr;
end
default : port0_addr <= port0_addr;
endcase
end
always @(posedge clk) begin
case(next_state)
SYNC : port1_addr <= port1_init;
READ : begin
if(!sdram_ctrl_waitrequest && cnt_c == 4'd1) begin
if(cnt_l == mod_l - 1'b1 && rd_flag && rd_bit_flag)
port1_addr <= port1_addr + mod_v;
else if(cnt_l == mod_l - 1'b1)
port1_addr <= port1_addr - mod_l + 1'b1;
else
port1_addr <= port1_addr + 1'b1;
end
else
port1_addr <= port1_addr;
end
READ_DONE : begin
if(cnt_h == mod_h && counter == INIT_COUNT)
port1_addr <= port1_init;
else
port1_addr <= port1_addr;
end
default : port1_addr <= port1_addr;
endcase
end
always @(posedge clk) begin
case(next_state)
SYNC : port2_addr <= port2_init;
READ : begin
if(!sdram_ctrl_waitrequest && cnt_c == 4'd2) begin
if(cnt_l == mod_l - 1'b1 && rd_flag && rd_bit_flag)
port2_addr <= port2_addr + mod_v;
else if(cnt_l == mod_l - 1'b1)
port2_addr <= port2_addr - mod_l + 1'b1;
else
port2_addr <= port2_addr + 1'b1;
end
else
port2_addr <= port2_addr;
end
READ_DONE : begin
if(cnt_h == mod_h && counter == INIT_COUNT)
port2_addr <= port2_init;
else
port2_addr <= port2_addr;
end
default : port2_addr <= port2_addr;
endcase
end
always @(posedge clk) begin
case(next_state)
SYNC : port3_addr <= port3_init;
READ : begin
if(!sdram_ctrl_waitrequest && cnt_c == 4'd3) begin
if(cnt_l == mod_l - 1'b1 && rd_flag && rd_bit_flag)
port3_addr <= port3_addr + mod_v;
else if(cnt_l == mod_l - 1'b1)
port3_addr <= port3_addr - mod_l + 1'b1;
else
port3_addr <= port3_addr + 1'b1;
end
else
port3_addr <= port3_addr;
end
READ_DONE : begin
if(cnt_h == mod_h && counter == INIT_COUNT)
port3_addr <= port3_init;
else
port3_addr <= port3_addr;
end
default : port3_addr <= port3_addr;
endcase
end
always @(posedge clk) begin
case(next_state)
SYNC : port4_addr <= port4_init;
READ : begin
if(!sdram_ctrl_waitrequest && cnt_c == 4'd4) begin
if(cnt_l == mod_l - 1'b1 && rd_flag && rd_bit_flag)
port4_addr <= port4_addr + mod_v;
else if(cnt_l == mod_l - 1'b1)
port4_addr <= port4_addr - mod_l + 1'b1;
else
port4_addr <= port4_addr + 1'b1;
end
else
port4_addr <= port4_addr;
end
READ_DONE : begin
if(cnt_h == mod_h && counter == INIT_COUNT)
port4_addr <= port4_init;
else
port4_addr <= port4_addr;
end
default : port4_addr <= port4_addr;
endcase
end
always @(posedge clk) begin
case(next_state)
SYNC : port5_addr <= port5_init;
READ : begin
if(!sdram_ctrl_waitrequest && cnt_c == 4'd5) begin
if(cnt_l == mod_l - 1'b1 && rd_flag && rd_bit_flag)
port5_addr <= port5_addr + mod_v;
else if(cnt_l == mod_l - 1'b1)
port5_addr <= port5_addr - mod_l + 1'b1;
else
port5_addr <= port5_addr + 1'b1;
end
else
port5_addr <= port5_addr;
end
READ_DONE : begin
if(cnt_h == mod_h && counter == INIT_COUNT)
port5_addr <= port5_init;
else
port5_addr <= port5_addr;
end
default : port5_addr <= port5_addr;
endcase
end
always @(posedge clk) begin
case(next_state)
SYNC : port6_addr <= port6_init;
READ : begin
if(!sdram_ctrl_waitrequest && cnt_c == 4'd6) begin
if(cnt_l == mod_l - 1'b1 && rd_flag && rd_bit_flag)
port6_addr <= port6_addr + mod_v;
else if(cnt_l == mod_l - 1'b1)
port6_addr <= port6_addr - mod_l + 1'b1;
else
port6_addr <= port6_addr + 1'b1;
end
else
port6_addr <= port6_addr;
end
READ_DONE : begin
if(cnt_h == mod_h && counter == INIT_COUNT)
port6_addr <= port6_init;
else
port6_addr <= port6_addr;
end
default : port6_addr <= port6_addr;
endcase
end
always @(posedge clk) begin
case(next_state)
SYNC : port7_addr <= port7_init;
READ : begin
if(!sdram_ctrl_waitrequest && cnt_c == 4'd7) begin
if(cnt_l == mod_l - 1'b1 && rd_flag && rd_bit_flag)
port7_addr <= port7_addr + mod_v;
else if(cnt_l == mod_l - 1'b1)
port7_addr <= port7_addr - mod_l + 1'b1;
else
port7_addr <= port7_addr + 1'b1;
end
else
port7_addr <= port7_addr;
end
READ_DONE : begin
if(cnt_h == mod_h && counter == INIT_COUNT)
port7_addr <= port7_init;
else
port7_addr <= port7_addr;
end
default : port7_addr <= port7_addr;
endcase
end
always @(posedge clk) begin
case(next_state)
SYNC : port8_addr <= port8_init;
READ : begin
if(!sdram_ctrl_waitrequest && cnt_c == 4'd8) begin
if(cnt_l == mod_l - 1'b1 && rd_flag && rd_bit_flag)
port8_addr <= port8_addr + mod_v;
else if(cnt_l == mod_l - 1'b1)
port8_addr <= port8_addr - mod_l + 1'b1;
else
port8_addr <= port8_addr + 1'b1;
end
else
port8_addr <= port8_addr;
end
READ_DONE : begin
if(cnt_h == mod_h && counter == INIT_COUNT)
port8_addr <= port8_init;
else
port8_addr <= port8_addr;
end
default : port8_addr <= port8_addr;
endcase
end
always @(posedge clk) begin
case(next_state)
SYNC : port9_addr <= port9_init;
READ : begin
if(!sdram_ctrl_waitrequest && cnt_c == 4'd9) begin
if(cnt_l == mod_l - 1'b1 && rd_flag && rd_bit_flag)
port9_addr <= port9_addr + mod_v;
else if(cnt_l == mod_l - 1'b1)
port9_addr <= port9_addr - mod_l + 1'b1;
else
port9_addr <= port9_addr + 1'b1;
end
else
port9_addr <= port9_addr;
end
READ_DONE : begin
if(cnt_h == mod_h && counter == INIT_COUNT)
port9_addr <= port9_init;
else
port9_addr <= port9_addr;
end
default : port9_addr <= port9_addr;
endcase
end
always @(posedge clk) begin
case(next_state)
SYNC : port10_addr <= port10_init;
READ : begin
if(!sdram_ctrl_waitrequest && cnt_c == 4'd10) begin
if(cnt_l == mod_l - 1'b1 && rd_flag && rd_bit_flag)
port10_addr <= port10_addr + mod_v;
else if(cnt_l == mod_l - 1'b1)
port10_addr <= port10_addr - mod_l + 1'b1;
else
port10_addr <= port10_addr + 1'b1;
end
else
port10_addr <= port10_addr;
end
READ_DONE : begin
if(cnt_h == mod_h && counter == INIT_COUNT)
port10_addr <= port10_init;
else
port10_addr <= port10_addr;
end
default : port10_addr <= port10_addr;
endcase
end
always @(posedge clk) begin
case(next_state)
SYNC : port11_addr <= port11_init;
READ : begin
if(!sdram_ctrl_waitrequest && cnt_c == 4'd11) begin
if(cnt_l == mod_l - 1'b1 && rd_flag && rd_bit_flag)
port11_addr <= port11_addr + mod_v;
else if(cnt_l == mod_l - 1'b1)
port11_addr <= port11_addr - mod_l + 1'b1;
else
port11_addr <= port11_addr + 1'b1;
end
else
port11_addr <= port11_addr;
end
READ_DONE : begin
if(cnt_h == mod_h && counter == INIT_COUNT)
port11_addr <= port11_init;
else
port11_addr <= port11_addr;
end
default : port11_addr <= port11_addr;
endcase
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
frame_init <= 1'b0;
else begin
if(sdram_ctrl_address == MOD_DONE - 1'b1)
frame_init <= 1'b1;
end
end
endmodule
刚从这上面看到这条路径非常长,是这个的问题吗?
出错提示语句发出来
如果可以把出错代码发出来
还在为quartus 自带的IP catlog中搜不到sdram IP而烦恼吗?那么请接着看。
虽然在普通的IP和生成界面没有sdram ip,但是在qsys界面是有的,这说明了什么。。
打开qsys ->
然后跳到如下界面,搜索sdram ,然后双击SDRAM controller ,紧接着如下图所示:
接着切换到timing选项卡,配置一下参数,我这里比较关心的是CAS,可以根据手册查,根据需要跑的频率选择即可:
最后点击finish即可,还可以添加pll,双击红色框可以导出接口,添加完毕后的图如下:
最后点击产生选项产生定制的IP:
备注:在用这个IP的过程中,需要单独产生一路时钟送给sdram的引脚,在手册中有如下一段话:
相同的时钟频率,注意时钟偏移。
读写时序说明:
总结:waitquest为高时,表示等待,此时读写未有效,当该信号为低时,可正常发出读写请求。
signal tap截图:
1.写时序
2.读时序