基于K7-325T的DDR3读写仿真实验

1、 IP核设置注意事项
在这里插入图片描述
⭐时钟选500MHz-即DQS频率为500MHz。
⭐Phy to controller clock ratio选择4:1-此处4代表的是DQS时钟,1代表逻辑收发时钟,此处为4:1的关系,即逻辑收发时钟为500/4=125MHz。此设置也会影响数据端口的位宽,如下分别为4:1和2:1时的UI数据位宽和DDR数据位宽的关系,本实验DDR数据位宽为32位,由于时上下沿采样,所以4:1的关系实际为8:1,所以对应的UI数据位宽位32*8=256bit。
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
⭐此处注意Input Clock Period 此时钟为输入FPGA的主时钟,也就是system clock,此处有很多值可以选择,本实验选择200MHz,选择这个时钟频率的好处是Reference clock可以直接选择使用system clock。
在这里插入图片描述
IP核设置的注意事项到此完毕。
2.读写时序分别如下图所示,此处注意DDR3的burst length 只能为8在这里插入图片描述
在这里插入图片描述
下面是读写状态机:

module DDR_TEST(
    output reg[255:0]       read_data,

	input					sys_clk_p,
	input					sys_clk_n,
    input 					sys_rst,
	output [14:0]	   		ddr3_addr,  			// output [14:0]	ddr3_addr
	output [2:0]		   	ddr3_ba,  				// output [2:0]		ddr3_ba
	output			   		ddr3_cas_n,  			// output			ddr3_cas_n
	output [0:0]		   	ddr3_ck_n,  			// output [0:0]		ddr3_ck_n
	output [0:0]		   	ddr3_ck_p,  			// output [0:0]		ddr3_ck_p
	output [0:0]		   	ddr3_cke,  				// output [0:0]		ddr3_cke
	output			   		ddr3_ras_n,  			// output			ddr3_ras_n	
	output		   			ddr3_reset_n,  			// output			ddr3_reset_n
	output			   		ddr3_we_n,  			// output			ddr3_we_n
	inout  [31:0]		   	ddr3_dq,  				// inout  [31:0]	ddr3_dq
	inout  [3:0]		   	ddr3_dqs_n,  			// inout  [3:0]		ddr3_dqs_n
	inout  [3:0]		   	ddr3_dqs_p,  			// inout  [3:0]		ddr3_dqs_p
	output	   				init_calib_complete,  	// output			init_calib_complete	
	output [0:0]		   	ddr3_cs_n, 				// output [0:0]		ddr3_cs_n	
	output [3:0]		   	ddr3_dm,  				// output [3:0]		ddr3_dm	
	output       		   	ddr3_odt 				// output [0:0]		ddr3_odt	
	
);
reg  [28:0]		app_addr;
reg  [2:0]		app_cmd;
reg				app_en;
reg  [255:0]	app_wdf_data;
reg				app_wdf_end;
reg				app_wdf_wren;

wire [255:0]	app_rd_data;
wire			app_rd_data_end;
wire			app_rd_data_valid;
wire			app_rdy;
wire			app_wdf_rdy;

reg [2:0]		state_c;
reg [2:0]		state_n;
reg [28:0]		cnt;
wire add_cnt;
wire end_cnt;
wire rst_h;
wire clk;
wire idl2write_start;
wire write2read_start;
wire read2idle_start;
wire write_vld;
wire read_vld;

assign rst_n = !rst_h;
assign write_vld = app_rdy && app_wdf_rdy;
assign read_vld  = app_rdy;
///
localparam IDLE     = 3'b001;
localparam READ     = 3'b010;
localparam WRITE    = 3'b100;
///
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt <= 0;
    end
    else if(add_cnt)begin
        if(end_cnt)
            cnt <= 0;
        else
            cnt <= cnt + 8;
    end
end

assign add_cnt = (state_c==WRITE && write_vld)||(state_c==READ && read_vld && app_rd_data_valid);       
assign end_cnt = add_cnt && cnt== 64-8;   
//第一段:
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        state_c <= IDLE;
    end
    else begin
        state_c <= state_n;
    end
end

//第二段:
always@(*)begin
    case(state_c)
        IDLE:begin
            if(idl2write_start)begin
                state_n = WRITE;
            end
            else begin
                state_n = state_c;
            end
        end
        WRITE:begin
            if(write2read_start)begin
                state_n = READ;
            end
            else begin
                state_n = state_c;
            end
        end
        READ:begin
            if(read2idle_start)begin
                state_n = IDLE;
            end
            else begin
                state_n = state_c;
            end
        end
        default:begin
            state_n = IDLE;
        end
    endcase
end
//第三段:
assign idl2write_start  = state_c==IDLE  && init_calib_complete && write_vld;
assign write2read_start = state_c==WRITE && end_cnt && read_vld;
assign read2idle_start  = state_c==READ  && end_cnt;

//--app_addr
 always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        app_addr <= 29'h0;
    end
    else if(state_c!=IDLE && (write_vld ||read_vld)) begin
        app_addr <= cnt;
    end
end 
//--app_cmd
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
		app_cmd<=3'h0;
    end
    else if (state_c==WRITE && write_vld)begin
        app_cmd<=3'h0;
    end
    else if (state_c==READ && read_vld)begin
        app_cmd<=3'h1;
    end
end
//--app_en
 always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        app_en <=1'b0;
    end
    else if(state_c!=IDLE && (write_vld ||read_vld))begin
        app_en <=1'b1;
    end
    else if(state_c == IDLE)begin
        app_en <=1'b0;//app_en need to hold, in case the  app_rdy pull down suddenly
    end
end 
//--app_wdf_data
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
            app_wdf_data<=256'd0;
    end
    else if (state_c==WRITE && write_vld)begin
        case(cnt)
            29'd0:app_wdf_data<=256'd1;
            29'd8:app_wdf_data<=256'd2;
            29'd16:app_wdf_data<=256'd3;
            29'd24:app_wdf_data<=256'd4;
            29'd32:app_wdf_data<=256'd5;
            29'd40:app_wdf_data<=256'd6;
            29'd48:app_wdf_data<=256'd7;
            29'd56:app_wdf_data<=256'd8;
        default: app_wdf_data<=256'd0;
        endcase
    end
end
//--app_wdf_end
 always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        app_wdf_end <=1'b0;
    end
    else if(state_c==WRITE)begin
        app_wdf_end <=1'b1;
    end
    else begin
        app_wdf_end <=1'b0;
    end
end 
//--app_wdf_wren
 always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        app_wdf_wren <=1'b0;
    end
    else if(state_c==WRITE && write_vld)begin
        app_wdf_wren <=1'b1;
    end
    else begin
        app_wdf_wren <=1'b0;
    end
end 
//--read_data
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        read_data <=1'b0;
    end
    else if(app_rd_data_valid)begin
        read_data <=app_rd_data;
    end
end
	
mig_7series_0 u_mig_7series_0 (
	// Memory interface ports
	.ddr3_addr                      (ddr3_addr			),  // output [14:0]	ddr3_addr
	.ddr3_ba                        (ddr3_ba			),  // output [2:0]		ddr3_ba
	.ddr3_cas_n                     (ddr3_cas_n			),  // output			ddr3_cas_n
	.ddr3_ck_n                      (ddr3_ck_n			),  // output [0:0]		ddr3_ck_n
	.ddr3_ck_p                      (ddr3_ck_p			),  // output [0:0]		ddr3_ck_p
	.ddr3_cke                       (ddr3_cke			),  // output [0:0]		ddr3_cke
	.ddr3_ras_n                     (ddr3_ras_n			),  // output			ddr3_ras_n
	.ddr3_reset_n                   (ddr3_reset_n		),  // output			ddr3_reset_n
	.ddr3_we_n                      (ddr3_we_n			),  // output			ddr3_we_n
	.ddr3_dq                        (ddr3_dq			),  // inout [31:0]		ddr3_dq
	.ddr3_dqs_n                     (ddr3_dqs_n			),  // inout [3:0]		ddr3_dqs_n
	.ddr3_dqs_p                     (ddr3_dqs_p			),  // inout [3:0]		ddr3_dqs_p
	.init_calib_complete            (init_calib_complete),  // output			init_calib_complete
	.ddr3_cs_n                      (ddr3_cs_n			),  // output [0:0]		ddr3_cs_n
	.ddr3_dm                        (ddr3_dm			),  // output [3:0]		ddr3_dm
	.ddr3_odt                       (ddr3_odt			),  // output [0:0]		ddr3_odt
	// Application interface ports
	.app_addr                       (app_addr			),  // input [28:0]		app_addr
	.app_cmd                        (app_cmd			),  // input [2:0]		app_cmd
	.app_en                         (app_en				),  // input			app_en
	.app_wdf_data                   (app_wdf_data		),  // input [255:0]	app_wdf_data
	.app_wdf_end                    (app_wdf_end		),  // input			app_wdf_end
	.app_wdf_wren                   (app_wdf_wren		),  // input			app_wdf_wren
	.app_rd_data                    (app_rd_data		),  // output [255:0]	app_rd_data
	.app_rd_data_end                (app_rd_data_end	),  // output			app_rd_data_end
	.app_rd_data_valid              (app_rd_data_valid	),  // output			app_rd_data_valid
	.app_rdy                        (app_rdy			),  // output			app_rdy,This output indicates that the UI is ready to accept commands
	.app_wdf_rdy                    (app_wdf_rdy		),  // output			app_wdf_rdy,This output indicates that the write data FIFO is ready to receive data
	.app_sr_req                     (1'b0				),  // input			app_sr_req
	.app_ref_req                    (1'b0				),  // input			app_ref_req
	.app_zq_req                     (1'b0				),  // input			app_zq_req
	.app_sr_active                  (					),  // output			app_sr_active
	.app_ref_ack                    (					),  // output			app_ref_ack
	.app_zq_ack                     (					),  // output			app_zq_ack
	.ui_clk                         (clk		        ),  // output			ui_clk 			500M/4=125M
	.ui_clk_sync_rst                (rst_h				),  // output			ui_clk_sync_rst
	.app_wdf_mask                   (32'b0 				),  // input [31:0]		app_wdf_mask
	// System Clock Ports
	.sys_clk_p                      (sys_clk_p			),  // input			sys_clk_p  200M
	.sys_clk_n                      (sys_clk_n			),  // input			sys_clk_n
	.sys_rst                        (sys_rst			)   // input 			sys_rst
);
endmodule

状态机对从0开始的连续8个地址分别写入1-8的数字,写完成后再读出。
3、仿真
DDR的仿真需要DDR的Module,模型可以通过example design获得,但直接拿过来并不能用,需要进行修改,后面会给出包括TB的完整工程链接,这里就不做过多阐述,下面是仿真结果:读写时序如图所示可以看到结果完全符合预期。
包括仿真文件的完整工程见下面链接:
https://download.csdn.net/download/weixin_45002573/11998076

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值