2020-11-06

秦韵FPGA 转载或原创(八)

基于高云fpga ------ GW2A18

1.DDR3控制器介绍

1.1 DDR3简介

DDR3 SDRAM:ddr3(转载),关于这部分的理论知识,直接在百度上搜索即可,想要了解具体的内存芯片,可以去自己板卡上使用的芯片官网去下载数据手册,上面会详细讲解操作…sdram的时序。

1.2 。。。

2.DDR3控制逻辑思路简单介绍

关于这部分的思路,相对来说比较简单,参考高云官网的ddr3 控制手册,(比较喜人的一点是完全中文的手册),参照时序图写代码,比较轻松了。
主要的控制逻辑是基于init_calib_complete为高的情况下来做的,否则没有意义。简单点的介绍就类似于valid ,ready总线。有ready拉高的情况下,我才可以给出valid信号。因此,在ddr3控制器的控制逻辑部分,简单可以分为三个通道:
命令地址通道
写数据通道
读数据通道
清楚了这部分,代码就好写了,直接用一个状态机(不论三段式还是一段式,哪个熟用哪个),分别将命令的数据写进ddr3就行了,其他的代码高云已经帮我们做完了。注:多看手册(中文的)。
做完这部分,你的外部控制逻辑的接口就出来了,后面的业务部分代码就需要你来添加了,不论是存储图像数据,adc数据,还是音频数据,都ok。

3.DDR3控制逻辑代码代码解释

简单的贴一些代码:(贴一个测试代码的顶层文件,可以做为参考)

 WMP0015_V_DDR3_V001_D35(
	input	 					clk,
	input 						rst_n,
    output [14-1:0]             DDR3_addr,       
    output [3-1:0]              DDR3_bank,       

    output                      DDR3_cs,
    output                      DDR3_ras,
    output                      DDR3_cas,
    output                      DDR3_we,
    output                      DDR3_ck,
    output                      DDR3_ck_n,
    output                      DDR3_cke,
    output                      DDR3_odt,
    output                      DDR3_reset_n,
    output [2-1:0]              DDR3_dm,        
    inout [16-1:0]              DDR3_dq,        
    inout [2-1:0]               DDR3_dqs,        
    inout [2-1:0]               DDR3_dqs_n,      
    output                      init_calib_complete,
	output 						led

);

assign ddr_cs = 1'b0;

wire 						clk_ddr;
wire 						ddr_rst;
wire                        usr_wr_wren;
wire  [16-1:0]              usr_wr_mask;    
wire                        usr_wr_end; 
wire [128-1:0]              usr_wr_data;    

wire                        usr_en/* synthesis syn_keep=1 */;
wire [2:0]                  usr_cmd/* synthesis syn_keep=1 */;
wire [28-1:0]               usr_addr/* synthesis syn_keep=1 */;        
wire                        usr_sre_req;
wire                        usr_ref_req;
wire                        usr_burst;
wire                        usr_sre_act;
wire                        usr_ref_ack;
wire                        usr_wr_rdy/* synthesis syn_keep=1 */;
wire                        usr_rdy;
wire                        usr_rd_data_valid/* synthesis syn_keep=1 */; 
wire                        usr_rd_data_end/* synthesis syn_keep=1 */;
wire [128-1:0]              usr_rd_data/* synthesis syn_keep=1 */;     
wire [5:0]                  usr_burst_number;

assign led = !init_calib_complete;

DDR3_Memory_Control#(
    .ADDR_WIDTH			(28),
    .APP_DATA_WIDTH		(128),
    .APP_MASK_WIDTH		(16)
)
(
	.clk				(clk_ddr 	),
	.rst				(ddr_rst 	),
	.usr_rdy			(usr_rdy), 
	.usr_rd_data_valid	(usr_rd_data_valid), 
	.wr_data_rdy		(usr_wr_rdy),
    .usr_rd_data		(usr_rd_data),
    .init_calib_complete(init_calib_complete),
    .usr_en				(usr_en),
    .usr_cmd			(usr_cmd),
    .usr_addr 			(usr_addr),
    .usr_wr_data 		(usr_wr_data),
    .usr_wr_wren		(usr_wr_wren),
    .usr_wr_end		    (usr_wr_end),		
    .usr_wr_mask 		(usr_wr_mask),
    .usr_burst			(usr_burst),
    .sr_req				(usr_sre_req),
    .ref_req			(usr_ref_req),
    .usr_burst_number	(usr_burst_number)
);


//添加一部分控制逻辑代码,仅作为参考,这部分代码
//数据位宽64bit
//数据掩码8bit
//
always@(posedge clk or posedge rst)
if(rst)
	arbi_rw_cnt <= 3'd0;
else if( ((state_cs == ARBI_WRITE) | (state_cs == ARBI_READ)) && wr_data_rdy && init_calib_complete )
	arbi_rw_cnt <= arbi_rw_cnt + 1;
else 
	arbi_rw_cnt <= 3'd0;

always@(posedge clk or posedge rst)
if(rst) begin 
	usr_en <= 1'b0;
	usr_cmd <= 3'b000;
	usr_addr <= 24'h0;
end
else if(state_cs == ARBI_WCMD) begin 
	usr_en <= 1'b1;
	usr_cmd <= 3'b000;
	usr_addr <= usr_wdf_addr;
end
else if(state_cs == ARBI_RCMD) begin 
	usr_en <= 1'b1;
	usr_cmd <= 3'b001;
	usr_addr <= usr_rdf_addr;
end
else begin 
	usr_en <= 1'b0;
	usr_cmd <= 3'b000;
	usr_addr <= 24'h0;
end

always@(posedge clk or posedge rst)
if(rst) begin 
	usr_wr_wren <= 1'b0;
	usr_wr_mask <= 8'b00000000;
	usr_wr_data <= 64'h0;
	usr_wr_end <= 1'b0;
end
else if( (state_cs == ARBI_WRITE) && wr_data_rdy && init_calib_complete) begin 
	usr_wr_wren <= 1'b1;
	usr_wr_mask <= 8'b00000000;
	usr_wr_data <= usr_wdf_data;
	if(&arbi_rw_cnt)
		usr_wr_end <= 1'b1;
	else 
		usr_wr_end <= 1'b0;
end
else begin 
	usr_wr_wren <= 1'b0;
	usr_wr_mask <= 8'b00000000;
	usr_wr_data <= 64'h0;
	usr_wr_end <= 1'b0;
end
	

4.代码扩展(逻辑扩展)

这部分做为整体项目规划的来处理的,主要实现的是除了ddr3驱动部分以外的逻辑,包括数据的存储,怎样存储?封包还是单纯数据存储,是添加其他协议还是经过业务层的处理过后再存储?这边简单的画一个框图,有兴趣的可以写来测试一下。
在这里插入图片描述简单的8路百兆数据写入,千兆吐出,不要求时时数据,每3s出1s的数据(1s中的1/n),具体业务处理方式就不做介绍了。写入ddr3之前,需要做分包处理,在写入ddr3之前添加缓存,写个简单的仲裁器。
贴个简单的图吧:
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值