修改example工程代码
由于官方产生的MIG控制核示例仿真工程太过复杂,不利于新手学习,所以对示例工程进行修改,使之适合学习以及仿真测试.
该项目完成的是先对DDR3中8个banks的前800个地址执行写操作,8个banks的前800个地址写满之后再对其中数据进行读操作.
这里需要注意的是app_wdf_data和app_rd_data的位宽,因为Burst Length为8所以这里app_wdf_data和app_rd_data的位宽为16*8=128bits.所以在ui_clk为200MHz下一次时钟上升沿向MIG控制器传输或得到128bits的数据.
下面给出读写状态控制的代码,完整工程在百度云中,链接:https://pan.baidu.com/s/1sWY0wa-pUvom76pLenC9Ow 提取码:6kab
reg [4:0] cstate,nstate; //state machine变量
//写标志
wire wr1_done;
wire wr2_done;
wire wr3_done;
wire wr4_done;
wire wr5_done;
wire wr6_done;
wire wr7_done;
wire wr8_done;
//读标志
wire rd1_done;
wire rd2_done;
wire rd3_done;
wire rd4_done;
wire rd5_done;
wire rd6_done;
wire rd7_done;
wire rd8_done;
localparam IDLE = 5'd0,
WR1 = 5'd1,
WR2 = 5'd2,
WR3 = 5'd3,
WR4 = 5'd4,
WR5 = 5'd5,
WR6 = 5'd6,
WR7 = 5'd7,
WR8 = 5'd8,
RD1 = 5'd9,
RD2 = 5'd10,
RD3 = 5'd11,
RD4 = 5'd12,
RD5 = 5'd13,
RD6 = 5'd14,
RD7 = 5'd15,
RD8 = 5'd16,
DONE = 5'd17;
//地址变量
reg [2:0] bank;
reg [24:0] addr;
//写数据变量
reg [15:0] cout16_1;
reg [15:0] cout16_2;
reg [15:0] cout16_3;
reg [15:0] cout16_4;
reg [15:0] cout16_5;
reg [15:0] cout16_6;
reg [15:0] cout16_7;
reg [15:0] cout16_8;
//MIG不需要的引脚置0
assign app_addr ={1'b0,bank,addr};
assign app_sr_req = 1'b0;
assign app_ref_req = 1'b0;
assign app_zq_req = 1'b0;
assign app_wdf_mask = 16'h0000;
assign app_wdf_end = app_wdf_wren;
//写标志置位
assign wr1_done = (app_cmd ==`CMD_WR && addr == 28'd800 && bank == 3'b000) ? 1'b1:1'b0;
assign wr2_done = (app_cmd ==`CMD_WR && addr == 28'd800 && bank == 3'b001) ? 1'b1:1'b0;
assign wr3_done = (app_cmd ==`CMD_WR && addr == 28'd800 && bank == 3'b010) ? 1'b1:1'b0;
assign wr4_done = (app_cmd ==`CMD_WR && addr == 28'd800 && bank == 3'b011) ? 1'b1:1'b0;
assign wr5_done = (app_cmd ==`CMD_WR && addr == 28'd800 && bank == 3'b100) ? 1'b1:1'b0;
assign wr6_done = (app_cmd ==`CMD_WR && addr == 28'd800 && bank == 3'b101) ? 1'b1:1'b0;
assign wr7_done = (app_cmd ==`CMD_WR && addr == 28'd800 && bank == 3'b110) ? 1'b1:1'b0;
assign wr8_done = (app_cmd ==`CMD_WR && addr == 28'd800 && bank == 3'b111) ? 1'b1:1'b0;
//读标志置位
assign rd1_done = (cstate == RD1 && app_cmd ==`CMD_RD && addr == 28'd800) ? 1'b1:1'b0;
assign rd2_done = (cstate == RD2 && app_cmd ==`CMD_RD && addr == 28'd800) ? 1'b1:1'b0;
assign rd3_done = (cstate == RD3 && app_cmd ==`CMD_RD && addr == 28'd800) ? 1'b1:1'b0;
assign rd4_done = (cstate == RD4 && app_cmd ==`CMD_RD && addr == 28'd800) ? 1'b1:1'b0;
assign rd5_done = (cstate == RD5 && app_cmd ==`CMD_RD && addr == 28'd800) ? 1'b1:1'b0;
assign rd6_done = (cstate == RD6 && app_cmd ==`CMD_RD && addr == 28'd800) ? 1'b1:1'b0;
assign rd7_done = (cstate == RD7 && app_cmd ==`CMD_RD && addr == 28'd800) ? 1'b1:1'b0;
assign rd8_done = (cstate == RD8 && app_cmd ==`CMD_RD && addr == 28'd800) ? 1'b1:1'b0;
assign app_wdf_data = {cout16_1,cout16_2,cout16_3,cout16_4,cout16_5,cout16_6,cout16_7,cout16_8};
assign app_en =(((cstate == WR1 ||cstate == WR2 ||cstate == WR3 ||cstate == WR4 ||cstate == WR5 ||cstate == WR6 ||cstate == WR7 ||cstate == WR8)&& app_wdf_rdy == 1'b1&&app_rdy == 1'b1)
||((cstate == RD1 ||cstate == RD2 ||cstate == RD3 ||cstate == RD4 ||cstate == RD5 ||cstate == RD6 ||cstate == RD7 ||cstate == RD8)&& app_rdy == 1'b1)
&&((!wr1_done)||(!wr2_done)||(!wr3_done)||(!wr4_done)||(!wr5_done)||(!wr6_done)||(!wr7_done)||(!wr8_done)||(!rd1_done)||(!rd2_done)||(!rd3_done)||(!rd4_done)||(!rd5_done)||(!rd6_done)||(!rd7_done)||(!rd8_done)))?1'b1:1'b0;
assign app_wdf_wren =(((cstate == WR1 ||cstate == WR2 ||cstate == WR3 ||cstate == WR4 ||cstate == WR5 ||cstate == WR6 ||cstate == WR7 ||cstate == WR8) && app_wdf_rdy == 1'b1&&app_rdy == 1'b1)
&&((!wr1_done)||(!wr2_done)||(!wr3_done)||(!wr4_done)||(!wr5_done)||(!wr6_done)||(!wr7_done)||(!wr8_done)))?1'b1:1'b0;
always@(posedge ui_clk or negedge ui_clk_sync_rst)begin
if(ui_clk_sync_rst == 1'b1)
cstate <= IDLE;
else
cstate <= nstate;
end
always @(*) begin
nstate = IDLE;
case(cstate)
IDLE:begin
if(init_calib_complete == 1'b1)
nstate = WR1;
else
nstate = IDLE;
end
WR1:begin
if(wr1_done == 1'b1)
nstate = WR2;
else
nstate = WR1;
end
WR2:begin
if(wr2_done == 1'b1)
nstate = WR3;
else
nstate = WR2;
end
WR3:begin
if(wr3_done == 1'b1)
nstate = WR4;
else
nstate = WR3;
end
WR4:begin
if(wr4_done == 1'b1)
nstate = WR5;
else
nstate = WR4;
end
WR5:begin
if(wr5_done == 1'b1)
nstate = WR6;
else
nstate = WR5;
end
WR6:begin
if(wr6_done == 1'b1)
nstate = WR7;
else
nstate = WR6;
end
WR7:begin
if(wr7_done == 1'b1)
nstate = WR8;
else
nstate = WR7;
end
WR8:begin
if(wr8_done == 1'b1)
nstate = RD1;
else
nstate = WR8;
end
RD1:begin
if(rd1_done == 1'b1)
nstate = RD2;
else
nstate = RD1;
end
RD2:begin
if(rd2_done == 1'b1)
nstate = RD3;
else
nstate = RD2;
end
RD3:begin
if(rd3_done == 1'b1)
nstate = RD4;
else
nstate = RD3;
end
RD4:begin
if(rd4_done == 1'b1)
nstate = RD5;
else
nstate = RD4;
end
RD5:begin
if(rd5_done == 1'b1)
nstate = RD6;
else
nstate = RD5;
end
RD6:begin
if(rd6_done == 1'b1)
nstate = RD7;
else
nstate = RD6;
end
RD7:begin
if(rd7_done == 1'b1)
nstate = RD8;
else
nstate = RD7;
end
RD8:begin
if(rd8_done == 1'b1)
nstate = DONE;
else
nstate = RD8;
end
DONE:begin
nstate = WR1;
end
endcase
end
always @(posedge ui_clk or posedge ui_clk_sync_rst) begin
if(ui_clk_sync_rst == 1'b1) begin
app_cmd <= `CMD_WR;
cout16_1 <= 16'd0; cout16_2 <= 16'd1; cout16_3 <= 16'd2; cout16_4 <= 16'd3;
cout16_5 <= 16'd4; cout16_6 <= 16'd5; cout16_7 <= 16'd6; cout16_8 <= 16'd7;
bank <= 3'b000;
addr <=25'b0;
end
else
case(cstate)
WR1:begin
app_cmd <= `CMD_WR;
bank <= 3'b000;
if(wr1_done == 1'b1) begin
addr <=25'b0;
cout16_1 <= 16'd0; cout16_2 <= 16'd1; cout16_3 <= 16'd2; cout16_4 <= 16'd3;
cout16_5 <= 16'd4; cout16_6 <= 16'd5; cout16_7 <= 16'd6; cout16_8 <= 16'd7;
end
else if(app_wdf_rdy == 1'b1&&app_rdy == 1'b1) begin
addr <= addr +8;
cout16_1 <= cout16_1+1; cout16_2 <= cout16_2+1; cout16_3 <= cout16_3+1; cout16_4 <= cout16_4+1;
cout16_5 <= cout16_5+1; cout16_6 <= cout16_6+1; cout16_7 <= cout16_7+1; cout16_8 <= cout16_8+1;
end
else begin
addr <= addr;
cout16_1 <= cout16_1; cout16_2 <= cout16_2; cout16_3 <= cout16_3; cout16_4 <= cout16_4;
cout16_5 <= cout16_5; cout16_6 <= cout16_6; cout16_7 <= cout16_7; cout16_8 <= cout16_8;
end
end
WR2:begin
app_cmd <= `CMD_WR;
bank <= 3'b001;
if(wr2_done == 1'b1) begin
addr <=25'b0;
cout16_1 <= 16'd0; cout16_2 <= 16'd1; cout16_3 <= 16'd2; cout16_4 <= 16'd3;
cout16_5 <= 16'd4; cout16_6 <= 16'd5; cout16_7 <= 16'd6; cout16_8 <= 16'd7;
end
else if(app_wdf_rdy == 1'b1&&app_rdy == 1'b1) begin
addr <= addr +8;
cout16_1 <= cout16_1+1; cout16_2 <= cout16_2+1; cout16_3 <= cout16_3+1; cout16_4 <= cout16_4+1;
cout16_5 <= cout16_5+1; cout16_6 <= cout16_6+1; cout16_7 <= cout16_7+1; cout16_8 <= cout16_8+1;
end
else begin
addr <= addr;
cout16_1 <= cout16_1; cout16_2 <= cout16_2; cout16_3 <= cout16_3; cout16_4 <= cout16_4;
cout16_5 <= cout16_5; cout16_6 <= cout16_6; cout16_7 <= cout16_7; cout16_8 <= cout16_8;
end
end
WR3:begin
app_cmd <= `CMD_WR;
bank <= 3'b010;
if(wr3_done == 1'b1) begin
addr <=25'b0;
cout16_1 <= 16'd0; cout16_2 <= 16'd1; cout16_3 <= 16'd2; cout16_4 <= 16'd3;
cout16_5 <= 16'd4; cout16_6 <= 16'd5; cout16_7 <= 16'd6; cout16_8 <= 16'd7;
end
else if(app_wdf_rdy == 1'b1&&app_rdy == 1'b1) begin
addr <= addr +8;
cout16_1 <= cout16_1+1; cout16_2 <= cout16_2+1; cout16_3 <= cout16_3+1; cout16_4 <= cout16_4+1;
cout16_5 <= cout16_5+1; cout16_6 <= cout16_6+1; cout16_7 <= cout16_7+1; cout16_8 <= cout16_8+1;
end
else begin
addr <= addr;
cout16_1 <= cout16_1; cout16_2 <= cout16_2; cout16_3 <= cout16_3; cout16_4 <= cout16_4;
cout16_5 <= cout16_5; cout16_6 <= cout16_6; cout16_7 <= cout16_7; cout16_8 <= cout16_8;
end
end
WR4:begin
app_cmd <= `CMD_WR;
bank <= 3'b011;
if(wr4_done == 1'b1) begin
addr <=25'b0;
cout16_1 <= 16'd0; cout16_2 <= 16'd1; cout16_3 <= 16'd2; cout16_4 <= 16'd3;
cout16_5 <= 16'd4; cout16_6 <= 16'd5; cout16_7 <= 16'd6; cout16_8 <= 16'd7;
end
else if(app_wdf_rdy == 1'b1&&app_rdy == 1'b1) begin
addr <= addr +8;
cout16_1 <= cout16_1+1; cout16_2 <= cout16_2+1; cout16_3 <= cout16_3+1; cout16_4 <= cout16_4+1;
cout16_5 <= cout16_5+1; cout16_6 <= cout16_6+1; cout16_7 <= cout16_7+1; cout16_8 <= cout16_8+1;
end
else begin
addr <= addr;
cout16_1 <= cout16_1; cout16_2 <= cout16_2; cout16_3 <= cout16_3; cout16_4 <= cout16_4;
cout16_5 <= cout16_5; cout16_6 <= cout16_6; cout16_7 <= cout16_7; cout16_8 <= cout16_8;
end
end
WR5:begin
app_cmd <= `CMD_WR;
bank <= 3'b100;
if(wr5_done == 1'b1) begin
addr <=25'b0;
cout16_1 <= 16'd0; cout16_2 <= 16'd1; cout16_3 <= 16'd2; cout16_4 <= 16'd3;
cout16_5 <= 16'd4; cout16_6 <= 16'd5; cout16_7 <= 16'd6; cout16_8 <= 16'd7;
end
else if(app_wdf_rdy == 1'b1&&app_rdy == 1'b1) begin
addr <= addr +8;
cout16_1 <= cout16_1+1; cout16_2 <= cout16_2+1; cout16_3 <= cout16_3+1; cout16_4 <= cout16_4+1;
cout16_5 <= cout16_5+1; cout16_6 <= cout16_6+1; cout16_7 <= cout16_7+1; cout16_8 <= cout16_8+1;
end
else begin
addr <= addr;
cout16_1 <= cout16_1; cout16_2 <= cout16_2; cout16_3 <= cout16_3; cout16_4 <= cout16_4;
cout16_5 <= cout16_5; cout16_6 <= cout16_6; cout16_7 <= cout16_7; cout16_8 <= cout16_8;
end
end
WR6:begin
app_cmd <= `CMD_WR;
bank <= 3'b101;
if(wr6_done == 1'b1) begin
addr <=25'b0;
cout16_1 <= 16'd0; cout16_2 <= 16'd1; cout16_3 <= 16'd2; cout16_4 <= 16'd3;
cout16_5 <= 16'd4; cout16_6 <= 16'd5; cout16_7 <= 16'd6; cout16_8 <= 16'd7;
end
else if(app_wdf_rdy == 1'b1&&app_rdy == 1'b1) begin
addr <= addr +8;
cout16_1 <= cout16_1+1; cout16_2 <= cout16_2+1; cout16_3 <= cout16_3+1; cout16_4 <= cout16_4+1;
cout16_5 <= cout16_5+1; cout16_6 <= cout16_6+1; cout16_7 <= cout16_7+1; cout16_8 <= cout16_8+1;
end
else begin
addr <= addr;
cout16_1 <= cout16_1; cout16_2 <= cout16_2; cout16_3 <= cout16_3; cout16_4 <= cout16_4;
cout16_5 <= cout16_5; cout16_6 <= cout16_6; cout16_7 <= cout16_7; cout16_8 <= cout16_8;
end
end
WR7:begin
app_cmd <= `CMD_WR;
bank <= 3'b110;
if(wr7_done == 1'b1) begin
addr <=25'b0;
cout16_1 <= 16'd0; cout16_2 <= 16'd1; cout16_3 <= 16'd2; cout16_4 <= 16'd3;
cout16_5 <= 16'd4; cout16_6 <= 16'd5; cout16_7 <= 16'd6; cout16_8 <= 16'd7;
end
else if(app_wdf_rdy == 1'b1&&app_rdy == 1'b1) begin
addr <= addr +8;
cout16_1 <= cout16_1+1; cout16_2 <= cout16_2+1; cout16_3 <= cout16_3+1; cout16_4 <= cout16_4+1;
cout16_5 <= cout16_5+1; cout16_6 <= cout16_6+1; cout16_7 <= cout16_7+1; cout16_8 <= cout16_8+1;
end
else begin
addr <= addr;
cout16_1 <= cout16_1; cout16_2 <= cout16_2; cout16_3 <= cout16_3; cout16_4 <= cout16_4;
cout16_5 <= cout16_5; cout16_6 <= cout16_6; cout16_7 <= cout16_7; cout16_8 <= cout16_8;
end
end
WR8:begin
app_cmd <= `CMD_WR;
bank <= 3'b111;
if(wr8_done == 1'b1) begin
addr <=25'b0;
cout16_1 <= 16'd0; cout16_2 <= 16'd1; cout16_3 <= 16'd2; cout16_4 <= 16'd3;
cout16_5 <= 16'd4; cout16_6 <= 16'd5; cout16_7 <= 16'd6; cout16_8 <= 16'd7;
end
else if(app_wdf_rdy == 1'b1&&app_rdy == 1'b1) begin
addr <= addr +8;
cout16_1 <= cout16_1+1; cout16_2 <= cout16_2+1; cout16_3 <= cout16_3+1; cout16_4 <= cout16_4+1;
cout16_5 <= cout16_5+1; cout16_6 <= cout16_6+1; cout16_7 <= cout16_7+1; cout16_8 <= cout16_8+1;
end
else begin
addr <= addr;
cout16_1 <= cout16_1; cout16_2 <= cout16_2; cout16_3 <= cout16_3; cout16_4 <= cout16_4;
cout16_5 <= cout16_5; cout16_6 <= cout16_6; cout16_7 <= cout16_7; cout16_8 <= cout16_8;
end
end
RD1:begin
app_cmd <= `CMD_RD;
bank <= 3'b000;
if(rd1_done == 1'b1) begin
addr <= 25'b0;
end
else if(app_rdy == 1'b1)begin
addr <= addr+8;
end
else begin
addr <= addr;
end
end
RD2:begin
app_cmd <= `CMD_RD;
bank <= 3'b001;
if(rd2_done == 1'b1) begin
addr <= 25'b0;
end
else if(app_rdy == 1'b1)begin
addr <= addr+8;
end
else begin
addr <= addr;
end
end
RD3:begin
app_cmd <= `CMD_RD;
bank <= 3'b010;
if(rd3_done == 1'b1) begin
addr <= 25'b0;
end
else if(app_rdy == 1'b1)begin
addr <= addr+8;
end
else begin
addr <= addr;
end
end
RD4:begin
app_cmd <= `CMD_RD;
bank <= 3'b011;
if(rd4_done == 1'b1) begin
addr <= 25'b0;
end
else if(app_rdy == 1'b1)begin
addr <= addr+8;
end
else begin
addr <= addr;
end
end
RD5:begin
app_cmd <= `CMD_RD;
bank <= 3'b100;
if(rd5_done == 1'b1) begin
addr <= 25'b0;
end
else if(app_rdy == 1'b1)begin
addr <= addr+8;
end
else begin
addr <= addr;
end
end
RD6:begin
app_cmd <= `CMD_RD;
bank <= 3'b101;
if(rd6_done == 1'b1) begin
addr <= 25'b0;
end
else if(app_rdy == 1'b1)begin
addr <= addr+8;
end
else begin
addr <= addr;
end
end
RD7:begin
app_cmd <= `CMD_RD;
bank <= 3'b110;
if(rd7_done == 1'b1) begin
addr <= 25'b0;
end
else if(app_rdy == 1'b1)begin
addr <= addr+8;
end
else begin
addr <= addr;
end
end
RD8:begin
app_cmd <= `CMD_RD;
bank <= 3'b111;
if(rd8_done == 1'b1) begin
addr <= 25'b0;
end
else if(app_rdy == 1'b1)begin
addr <= addr+8;
end
else begin
addr <= addr;
end
end
DONE:begin
bank <= 3'b000;
addr <=25'b0;
app_cmd <= `CMD_WR;
cout16_1 <= 16'd0; cout16_2 <= 16'd1; cout16_3 <= 16'd2; cout16_4 <= 16'd3;
cout16_5 <= 16'd4; cout16_6 <= 16'd5; cout16_7 <= 16'd6; cout16_8 <= 16'd7;
end
endcase
end
仿真测试
在用modelsim做软仿的时候需要注意,testbench最好用官方给的代码,或者就在官方生成的项目上直接改example_top.自己写testbench很容易出错.一开始我是自己写的tesetbench做仿真,测试时总是有问题,后来才发现要用官方生成的testbench做仿真,才不会出错.
modelsim仿真结果如下:
DDR3读写仿真结果:
读操作
写操作
存在问题
app_rdy和app_rd_data_valid是MIG控制核User Interface上的输出信号,我还不太清楚这两个信号什么时候置位,什么时候复位?到底是哪些因素影响了这两个信号的置位与复位?如果有看到这里的大神可以在评论区里帮忙解答一下~~