上一节中,记录到了ddr控制器的整体架构,在本节中,准备把ddr控制器的各个模块完善一下。

可以看到上一节中介绍了DDR控制器的整体架构,因为这几周事情多,又要课设什么的麻烦,今天抽点时间把这个记录完了,不然以后都忘了DDR该咋去控制了。

从本次实验的整体功能模块可以看出,最终我们只需要用户操作的信号为用户写入的256bit数据wr_ddr_data,写开始信号wr_start,数据请求信号data_req,读开始信号rd_start,读出的数据rd_ddr_data,读数据有效信号rd_data_vld,读结束和写结束信号rd_done、wr_done,ddr忙碌信号ddr_busy;

接下来我们将从顶层模块开始介绍各个模块实现的功能。

1) 顶层模块:

在顶层模块中,我们主要介绍用户相关的接口,在DDR3 存储器一侧的信号不做过多介绍

端口名称

I/O

位宽

备注

wr_ddr_data

I

256

用户写入的256bit数据

data_req

O

1

向上游模块请求数据信号

wr_start

I

1

一次写ddr开始信号

wr_done

O

1

一次写ddr结束信号

rd_start

I

1

读开始信号

rd_data_vld

O

1

读出数据有效信号

rd_ddr_data

O

256

读出的有效数据

rd_done

O

1

一次突发读数据结束信号

ddr_busy

O

1

当前控制器处于忙碌状态

用户通过这些信号,能够较为简单地实现对DDR的访问。

2) 用户写控制模块

该模块的主要作用是,在接收到上游模块发送过来的写开始信号后,从上游模块将要写入DDR的数据请求而来,并将数据写入到DDR中。本模块的结构如下:

各个信号的作用如下表所示:

端口名称

I/O

位宽

备注

ui_clk

I

1

系统时钟100M

rst

I

1

系统复位,同步复位

wr_start

I

1

写开始信号

wr_ddr_data

I

256

用户写入的256bit数据

dta_req

O

1

向上游模块请求数据信号

wr_busy

O

1

当前模块正处于写忙碌状态

wr_done

O

1

一次写结束信号

wr_req

O

1

写请求信号,给到仲裁模块做总裁

wr_ack

I

1

写响应信号,仲裁模块给回的写响应

app_wdf_mask

O

32

32bit写入数据掩码

app_wdf_data

O

256

写入到DDR的数据

app_wdf_wren

O

当前写入数据有效信号

app_wdf_end

O

1

当前数据是ddr一次8突发的最后一个数据

app_wdf_rdy

I

1

当前MIG IP写数据通道处于空闲状态

app_rdy

I

1

当前MIG IP命令通道处于空闲状态

app_cmd

O

3

写数据命令3’b000

app_en

O

1

命令使能信号

app_addr

O

29

要访问的内存地址

关于本模块的代码设计,可以参考本模块的时序波形图,本模块状态跳转图如下,在IDLE状态下,若接收到写开始信号wr_start,则进入写请求状态,同时产生写请求wr_req给到仲裁模块,若当前可以进行写操作,则仲裁模块将会给出一个写响应信号wr_ack,接收到响应过后将跳转如写数据状态,从上游模块请求数据并给出写命令和地址,把数据写入到DDR中。

时序设计图如下:

对时序图做简单说明:进入写状态后,将使能app_wdf_wren信号,于此同时data_req信号在app_wdf_wren和app_wdf_rdy同时有效时才为有效,从而向上游模块请求数据,在写模块中,一次写操作需要向上游模块请求64个256bit数据。app_en在app_wdf_wren一个周期后拉高,然后再app_rdy和app_en同时有效的时候,需要给出写入ddr的地址,写入ddr的地址每次需要增加8,这是因为我们写入的数据是256bit,而ddr内存一个地址的容量是32bit,一次写入256bit地址正好增加8。当全部64个数据写入完成后,将产生一个写结束信号,指示本次写操作已经完成。在写状态时,拉高wr_busy指示当前模块正处于写忙碌的状态。

 /*=============================================================================
#
# Author: weichaochen - 1530604142@qq.com
#
# QQ : 1530604142
#
# Last modified: 2019-12-29 19:28
#
# Filename: ddr_wr_ctrl.v
#
# Description:
#
=============================================================================*/
`timescale 1ns / 1ps module ddr_wr_ctrl(
input wire ui_clk ,//ddr3工作时钟
input wire rst ,//系统复位
input wire wr_start ,//写开始信号
output wire data_req ,//请求写数据信号
input wire [:] wr_ddr_data ,//将要写入的数据 output wire wr_req ,//写数据请求
input wire wr_ack ,//写响应
output wire wr_done ,//一次写结束
output wire wr_busy ,//当前处于忙碌状态 input wire app_rdy ,//命令通道空闲
output wire [:] app_cmd ,//输出的控制命令
output wire app_en ,//命令使能
output wire [:] app_addr ,//输出的地址 input wire app_wdf_rdy ,//写数据通道空闲信号
output wire [:] app_wdf_data,//写入的数据
output wire app_wdf_wren,//写入数据使能
output wire app_wdf_end ,//当前数据是DDR一次突发的最后一个数据
output wire [:] app_wdf_mask //写入数据掩码
); //=============================================
//parameter define
//=============================================
parameter IDLE = 'b001;
parameter WR_REQ = 'b010;
parameter WRITE = 'b100; parameter TOTAL_PIXEL = * - ;
parameter BURST_LEN = - ; //=============================================
//internal siganl
//=============================================
reg [:] state ;//状态寄存器 reg [:] cnt_data ;//计数当前写入的数据
wire add_cnt_data ;
wire end_cnt_data ; reg [:] cnt_cmd ;//计数当前已经给出的命令
wire add_cnt_cmd ;
wire end_cnt_cmd ; reg app_wdf_wren_r ;//写入数据有效
reg app_en_r ;//命令有效信号
reg [:] app_addr_r ;//写入的地址 reg wr_done_r ;//一次写完成
reg wr_req_r ;//写请求 assign app_cmd = 'b000; //写命令
assign app_wdf_mask = 'd0; //写数据掩码
assign app_wdf_wren = app_wdf_wren_r;
assign app_en = app_en_r ;
assign app_addr= app_addr_r;
assign app_wdf_data = wr_ddr_data;
assign wr_done = wr_done_r;
assign wr_busy = state==WRITE;
assign wr_req = wr_req_r;
assign app_wdf_end = app_wdf_wren_r; assign data_req = app_wdf_wren_r & app_wdf_rdy;//向上游模块请求数据 //--------------------state machine describe--------------------
always @(posedge ui_clk)begin
if(rst == 'b1)begin
state <= IDLE;
end
else begin
case(state)
IDLE:begin
if(wr_start=='b1)
state <= WR_REQ;
else
state <= IDLE;
end WR_REQ:begin
if(wr_ack)
state <= WRITE;
else
state <= WR_REQ;
end WRITE:begin
if(end_cnt_cmd)
state <= IDLE;
else
state <= WRITE;
end default:begin
state <= IDLE;
end
endcase
end
end //--------------------app_wdf_wren_r--------------------
always @(posedge ui_clk)begin
if(rst == 'b1)begin
app_wdf_wren_r <= 'b0;
end
else if(end_cnt_data)begin
app_wdf_wren_r <= 'b0;
end
else if(state==WR_REQ && wr_ack=='b1)begin
app_wdf_wren_r <= 'b1;
end
end //--------------------cnt_data--------------------
always @(posedge ui_clk)begin
if(rst=='b1)begin
cnt_data <= ;
end
else if(add_cnt_data)begin
if(end_cnt_data)
cnt_data <= ;
else
cnt_data <= cnt_data + 'b1;
end
end assign add_cnt_data = data_req;
assign end_cnt_data = add_cnt_data && cnt_data== BURST_LEN; //--------------------app_en_r--------------------
always @(posedge ui_clk)begin
if(rst == 'b1)begin
app_en_r <= 'b0;
end
else if(end_cnt_cmd)begin
app_en_r <= 'b0;
end
else if(app_wdf_wren_r=='b1)begin
app_en_r <= 'b1;
end
end //--------------------cnt_cmd--------------------
always @(posedge ui_clk)begin
if(rst=='b1)begin
cnt_cmd <= ;
end
else if(add_cnt_cmd)begin
if(end_cnt_cmd)
cnt_cmd <= ;
else
cnt_cmd <= cnt_cmd + 'b1;
end
end assign add_cnt_cmd = app_rdy & app_en_r;
assign end_cnt_cmd = add_cnt_cmd && cnt_cmd== BURST_LEN; //--------------------app_addr_r--------------------
always @(posedge ui_clk)begin
if(rst == 'b1)begin
app_addr_r <= 'd0;
end
else if(app_addr_r == TOTAL_PIXEL && app_en_r=='b1 && app_rdy==1'b1)begin
app_addr_r <= 'd0;
end
else if(app_en_r=='b1 && app_rdy==1'b1)begin
app_addr_r <= app_addr_r + 'd8;
end
end //--------------------wr_done_r--------------------
always @(posedge ui_clk)begin
if(rst == 'b1)begin
wr_done_r <= 'b0;
end
else if(end_cnt_cmd=='b1)begin
wr_done_r <= 'b1;
end
else begin
wr_done_r <= 'b0;
end
end //--------------------wr_req_r--------------------
always @(posedge ui_clk)begin
if(rst == 'b1)begin
wr_req_r <= 'b0;
end
else if(wr_ack=='b1)begin
wr_req_r <= 'b0;
end
else if(state==IDLE && wr_start=='b1)begin
wr_req_r <= 'b1;
end
end endmodule

3) 用户读控制模块

本模块的作用是,当接收到读开始信号rd_start后,本模块产生读命令将数据从ddr中读出来,并将数据给到下游模块,本模块的结构图如下:

各个信号的作用如下表所示:

端口名称

I/O

位宽

备注

ui_clk

I

1

系统时钟100M

rst

I

1

系统复位,同步复位

rd_start

I

1

读开始信号

rd_ddra_data

O

256

从DDR中读出的数据

rd_data_vld

O

1

读出数据有效信号

rd_req

O

1

读请求信号,给到仲裁模块做判断

rd_ack

I

1

读响应信号,仲裁模块对读请求的响应

rd_done

O

1

一次读操作完成信号

rd_busy

O

1

当前模块正处于读忙碌状态

app_rdy

I

1

当前命令通道处于空闲状态

app_addr

O

29

读DDR的内存地址

app_en

O

1

读命令有效信号

app_cmd

O

3

读DDR的命令3’b001

app_rd_data

I

256

从DDR中读出的数据

app_rd_data_vld

I

1

从DDR中读出数据有效信号

app_rd_data_end

I

1

当前数据是DDR8突发的最后一个数据

本模块功能设计,可以参考用户读控制波形图,本模块的状态跳转图如下:若在空闲状态下接收到写开始信号rd_start则状态跳转到写请求状态,并给出写读请求信号rd_req,若接收到仲裁模块给出的读响应信号rd_ack,则跳转入读数据状态,将数据从ddr中读出。当读完64个数据后跳转回空闲状态。

本模块的时序设计如下:

在读状态下,将使能app_en信号,同时开始计数当前给出了多少个命令,在读模块中,一次读操作同样对应了64个数据,这样就与前面的写模块具有相同的长度,能够在读写速度上匹配,避免读写的冲突。当读完全部64个数据后,将给出读结束信号rd_done指示本次读操作已经完成,本模块处于读状态时,将使能rd_busy信号,指示本模块当前正忙碌。

 /*=============================================================================
#
# Author: weichaochen - 1530604142@qq.com
#
# QQ : 1530604142
#
# Last modified: 2019-12-29 19:32
#
# Filename: ddr_rd_ctrl.v
#
# Description:
#
=============================================================================*/ `timescale 1ns / 1ps
module ddr_rd_ctrl(
input wire ui_clk ,//系统时钟
input wire rst ,//系统复位
input wire rd_start ,//读开始 output wire rd_req ,//读请求
input wire rd_ack ,//读响应
output wire rd_done ,//读完成
output wire rd_busy ,//读忙碌 output wire [:] app_cmd ,//读ddr命令
output wire app_en ,//读ddr命令使能
output wire [:] app_addr ,//读ddr地址
input wire app_rdy ,//ddr命令通道空闲 input wire app_rd_data_vld ,//ddr读出数据有效
input wire [:] app_rd_data ,//从ddr中读出的数据
output wire rd_ddr_data_vld ,//用户读出数据有效
output wire [:] rd_ddr_data //用户读出的数据
); //=============================================
//parameter define
//=============================================
parameter IDLE = 'b001;
parameter RD_REQ = 'b010;
parameter READ = 'b100; parameter TOTAL_PIXEL = * - ;
parameter BURST_LEN = - ; //=============================================
//internal siganl
//=============================================
reg [:] state ;//状态寄存器 reg [:] cnt_data ;//计数当读出的数据
wire add_cnt_data ;
wire end_cnt_data ; reg [:] cnt_cmd ;//计数当前已经给出的命令
wire add_cnt_cmd ;
wire end_cnt_cmd ; reg app_en_r ;//命令有效信号
reg [:] app_addr_r ;//写入的地址 reg rd_done_r ;//一次读完成
reg rd_req_r ;//读请求
reg rd_ddr_data_vld_r ;//读出数据有效
reg [:] rd_ddr_data_r ;//读出的数据 assign app_cmd = 'b001; //读命令
assign app_en = app_en_r ;
assign app_addr= app_addr_r;
assign rd_done = rd_done_r;
assign rd_busy = state==READ;
assign rd_req = rd_req_r;
assign rd_ddr_data = rd_ddr_data_r;
assign rd_ddr_data_vld = rd_ddr_data_vld_r; //--------------------state machine describe--------------------
always @(posedge ui_clk)begin
if(rst == 'b1)begin
state <= IDLE;
end
else begin
case(state)
IDLE:begin
if(rd_start=='b1)
state <= RD_REQ;
else
state <= IDLE;
end RD_REQ:begin
if(rd_ack)
state <= READ;
else
state <= RD_REQ;
end READ:begin
if(end_cnt_cmd)
state <= IDLE;
else
state <= READ;
end default:begin
state <= IDLE;
end
endcase
end
end //--------------------cnt_data--------------------
always @(posedge ui_clk)begin
if(rst=='b1)begin
cnt_data <= ;
end
else if(add_cnt_data)begin
if(end_cnt_data)
cnt_data <= ;
else
cnt_data <= cnt_data + 'b1;
end
end assign add_cnt_data = app_rd_data_vld;
assign end_cnt_data = add_cnt_data && cnt_data== BURST_LEN; //--------------------app_en_r--------------------
always @(posedge ui_clk)begin
if(rst == 'b1)begin
app_en_r <= 'b0;
end
else if(end_cnt_cmd)begin
app_en_r <= 'b0;
end
else if(state==RD_REQ && rd_ack=='b1)begin
app_en_r <= 'b1;
end
end //--------------------cnt_cmd--------------------
always @(posedge ui_clk)begin
if(rst=='b1)begin
cnt_cmd <= ;
end
else if(add_cnt_cmd)begin
if(end_cnt_cmd)
cnt_cmd <= ;
else
cnt_cmd <= cnt_cmd + 'b1;
end
end assign add_cnt_cmd = app_rdy & app_en_r;
assign end_cnt_cmd = add_cnt_cmd && cnt_cmd== BURST_LEN; //--------------------app_addr_r--------------------
always @(posedge ui_clk)begin
if(rst == 'b1)begin
app_addr_r <= 'd0;
end
else if(app_addr_r == TOTAL_PIXEL && app_en_r=='b1 && app_rdy==1'b1)begin
app_addr_r <= 'd0;
end
else if(app_en_r=='b1 && app_rdy==1'b1)begin
app_addr_r <= app_addr_r + 'd8;
end
end //--------------------rd_done_r--------------------
always @(posedge ui_clk)begin
if(rst == 'b1)begin
rd_done_r <= 'b0;
end
else if(end_cnt_data=='b1)begin
rd_done_r <= 'b1;
end
else begin
rd_done_r <= 'b0;
end
end //--------------------rd_req_r--------------------
always @(posedge ui_clk)begin
if(rst == 'b1)begin
rd_req_r <= 'b0;
end
else if(rd_ack=='b1)begin
rd_req_r <= 'b0;
end
else if(state==IDLE && rd_start=='b1)begin
rd_req_r <= 'b1;
end
end //--------------------rd_ddr_data_r, rd_ddr_data_vld_r--------------------
always @(posedge ui_clk)begin
if(rst == 'b1)begin
rd_ddr_data_r <= 'd0;
rd_ddr_data_vld_r <= 'b0;
end
else begin
rd_ddr_data_r <= app_rd_data;
rd_ddr_data_vld_r <= app_rd_data_vld;
end
end
endmodule

4) 读写仲裁模块

本模块的目的是为了来避免读写冲突的,在ddr进行写操作的同时,也有可能有读操作需要处理,这时候就会发生读写冲突,为了避免读写操作同时发生创建一个仲裁模块,模块的结构和信号列表如下:

端口名称

I/O

位宽

备注

wr_req

I

1

写数据请求,写控制模块给出的写请求

rd_req

I

1

读数据请求,读控制模块给出的读请求

ui_clk

I

1

系统时钟

rst

I

1

系统同步复位

wr_ack

O

1

写响应,用来响应本次写操作

wr_done

I

1

一次写操作完成

rd_ack

O

1

读响应,用来响应读操作

rd_done

I

1

一次读操作完成。

本模块的功能设计可以参考时序图,这里简单介绍以下本模块的工作方式,本模块的状态跳转入下图所示,在仲裁状态ARBIT下若接收到读请求,则进入读状态,若接收到写请求,则进入写状态,若读写请求同时出现则优先响应写请求进入写状态,当在读写状态中接收到读写结束信号wr_done或者rd_done时,状态将回到仲裁状态。

本模块的工作的时序设计如下:

本模块实现的功能比较简单,通过时序图能够很直观地就看出其功能,在这里不再赘述。至此我们完成了这些基础模块地创建,有了这些时序设计波形图,去设计代码就是十分简单地事情了。

/*=============================================================================
#
# Author: weichaochen - 1530604142@qq.com
#
# QQ : 1530604142
#
# Last modified: 2019-12-29 19:35
#
# Filename: ddr_arbit.v
#
# Description:
#
=============================================================================*/ `timescale 1ns / 1ps
module ddr_arbit(
input wire ui_clk ,//系统时钟
input wire rst ,//系统复位
input wire wr_req ,//写请求
output wire wr_ack ,//写响应
input wire wr_done ,//写完成 input wire rd_req ,//读请求
output wire rd_ack ,//读响应
input wire rd_done //读完成
); //==================================================
//parameter define
//==================================================
parameter IDLE = 'b0001;
parameter ARBIT = 'b0010;
parameter WRITE = 'b0100;
parameter READ = 'b1000; //==================================================
//internal siganls
//==================================================
reg wr_ack_r ;
reg rd_ack_r ;
reg [:] state ; assign wr_ack = wr_ack_r ;
assign rd_ack = rd_ack_r ; //--------------------state machine describe--------------------
always @(posedge ui_clk)begin
if(rst == 'b1)begin
state <= IDLE;
end
else begin
case(state)
IDLE:begin
state <= ARBIT;
end ARBIT:begin
if(wr_req=='b1)//写的优先级高于读
state <= WRITE;
else if(wr_req=='b0 && rd_req==1'b1)
state <= READ;
end WRITE:begin
if(wr_done)
state <= ARBIT;
else
state <= WRITE;
end READ:begin
if(rd_done)
state <= ARBIT;
else
state <= READ;
end default:begin
state <= IDLE;
end
endcase
end
end //--------------------wr_ack_r--------------------
always @(posedge ui_clk)begin
if(rst == 'b1)begin
wr_ack_r <= 'b0;
end
else if(state==ARBIT && wr_req=='b1)begin
wr_ack_r <= 'b1;
end
else begin
wr_ack_r <= 'b0;
end
end //--------------------rd_ack_r--------------------
always @(posedge ui_clk)begin
if(rst == 'b1)begin
rd_ack_r <= 'b0;
end
else if(state==ARBIT && wr_req=='b0 && rd_req==1'b1)begin
rd_ack_r <= 'b1;
end
else begin
rd_ack_r <= 'b0;
end
end endmodule

在有了这些模块后,接下来我们要进行对这些模块的功能测试,我们将对ddr3进行循环读写测试来验证其功能。接下来,我们就编写一个测试模块。

该模块负责对DDR进行循环读写,每次读写64个256bit数据,通过比较写入和读出的数据是否相同来判断ddr控制器是否正常工作.

该模块的状态跳转如下图所示,在arbit状态下判断当前是该进行写还是读,应该注意本次实验的读写是交替进行的.

 /*=============================================================================
#
# Author: weichaochen - 1530604142@qq.com
#
# QQ : 1530604142
#
# Last modified: 2019-12-29 19:41
#
# Filename: gen_test_data.v
#
# Description:
#
=============================================================================*/ `timescale 1ns / 1ps
module gen_test_data(
input wire ui_clk ,//系统时钟
input wire rst ,//系统复位
input wire ddr_busy ,//ddr控制器当前处于忙碌状态 output wire wr_start ,//写开始信号
input wire data_req ,//数据请求信号
output wire [:] wr_ddr_data ,//将要写入ddr的数据
input wire wr_done ,//一次写操作完成信号 output wire rd_start ,//读开始信号
input wire rd_data_vld ,//读出数据有效信号
input wire [:] rd_ddr_data ,//读出的有效数据
input wire rd_done ,//一次读完成信号 output wire error //读写错误信号
); //==================================================
//parameter define
//==================================================
parameter IDLE = 'b0001;
parameter ARBIT = 'b0010;
parameter WRITE = 'b0100;
parameter READ = 'b1000; parameter CNT_MAX = - ; //==================================================
//internal siganls
//==================================================
reg [:] state ;//状态寄存器
reg [:] cnt_data ;//数据计数
reg wr_start_r ;//写开始信号
reg rd_start_r ;//读开始信号
reg error_r ;//错误指示信号
reg wr_rd_flag ;//读写指示信号 assign wr_ddr_data = (wr_rd_flag=='b0)?{32{cnt_data}}:256'd0;
assign wr_start = wr_start_r;
assign rd_start = rd_start_r;
assign error = error_r;
//--------------------state machine describe--------------------
always @(posedge ui_clk)begin
if(rst == 'b1)begin
state <= IDLE;
end
else begin
case(state)
IDLE:begin
state <= ARBIT;
end ARBIT:begin
if(wr_start_r)//当前需要进行写操作
state <= WRITE;
else if(rd_start_r)//当前需要进行读操作
state <= READ;
end WRITE:begin
if(wr_done)
state <= ARBIT;
else
state <= WRITE;
end READ:begin
if(rd_done)
state <= ARBIT;
else
state <= READ;
end default:begin
state <= IDLE;
end
endcase
end
end //--------------------wr_rd_flag--------------------
always @(posedge ui_clk)begin
if(rst == 'b1)begin
wr_rd_flag <= 'b0;
end
else if(wr_done=='b1)begin
wr_rd_flag <= 'b1;
end
else if(rd_done=='b1)begin
wr_rd_flag <= 'b0;
end
end //--------------------wr_start_r,rd_start_r--------------------
always @(posedge ui_clk)begin
if(rst == 'b1)begin
wr_start_r <= 'b0;
rd_start_r <= 'b0;
end
else if(state==ARBIT && ddr_busy=='b0 && wr_rd_flag==1'b0)begin
wr_start_r <= 'b1;
end
else if(state==ARBIT && ddr_busy=='b0 && wr_rd_flag==1'b1)begin
rd_start_r <= 'b1;
end
else begin
rd_start_r <= 'b0;
wr_start_r <= 'b0;
end
end //--------------------cnt_data--------------------
always @(posedge ui_clk)begin
if(rst == 'b1)begin
cnt_data <= 'd0;
end
else if(data_req=='b1)begin
if(cnt_data==CNT_MAX)
cnt_data <= 'd0;
else
cnt_data <= cnt_data + 'b1;
end
else if(rd_data_vld=='b1)begin
if(cnt_data==CNT_MAX)
cnt_data <= 'd0;
else
cnt_data <= cnt_data + 'b1;
end
end //--------------------error--------------------
always @(posedge ui_clk)begin
if(rst == 'b1)begin
error_r <= 'b0;
end
else if(rd_data_vld=='b1 && (rd_ddr_data !={32{cnt_data}}))begin
error_r <= 'b1;
end
end endmodule

在接下来可以对对将整个工程进行仿真,通过仿真的结果来判断结构是否正确.

在产生循环读写的模块中,我们可以看到error信号一直保持为低,并且用户的确向DDR中写入了数据,并且也从DDR中读出了数据,说明我们的设计的控制器已经正常工作了。

基于MIG IP核的DDR3控制器(二)的更多相关文章

  1. 基于MIG IP核的DDR3控制器(一)

    最近学习了DDR3控制器的使用,也用着DDR完成了一些简单工作,想着以后一段可能只用封装过后的IP核,可能会忘记DDR3控制器的一些内容,想着把这个DDR控制器的编写过程记录下来,便于我自己以后查看吧 ...

  2. MIG IP控制DDR3读写测试

    本文设计思想采用明德扬至简设计法.在高速信号处理场合下,很短时间内就要缓存大量的数据,这时片内存储资源已经远远不够了.DDR SDRAM因其极高的性价比几乎是每一款中高档FPGA开发板的首选外部存储芯 ...

  3. FPGA上外挂DDR2&DDR3&MIG IP的使用记录

    前言 当需要大容量数据存储及处理的时候,FPGA内部自带的存储资源是远远不够的,所以问题来了,怎么使用外带的DDR3? 首要问题在于DDR3是什么?有没有协议?当然只是需要用Xilinx MIG IP ...

  4. Vivado设计二:zynq的PS访问PL中的自带IP核(基于zybo)

    1.建立工程 首先和Vivado设计一中一样,先建立工程(这部分就忽略了) 2.create block design 同样,Add IP 同样,也添加配置文件,这些都和设计一是一样的,没什么区别. ...

  5. DDR3(1):IP核调取

    本系列整理一下基于 Xilinx A7 芯片的 DDR3 的使用,此处采用的 DDR3 IP核为软核,即采用 FPGA 逻辑单元.寄存器.查找表等搭建出来 IP核.从 IP 核的调取开始,接着读写测试 ...

  6. Xilinx 7系列例化MIG IP core DDR3读写

    昨晚找了一下,发现DDR3读写在工程上多是通过例化MIG,调用生成IPcore的HDL Functional Model.我说嘛,自己哪能写出那么繁琐的,不过DDR读写数据可以用到状态机,后期再添砖加 ...

  7. 基于AXI4总线卷积FPGA加速IP核的尝试

    本文先总结不同AXI IP核的实现的方法,性能的对比,性能差异的分析,可能改进的方面.使用的硬件平台是Zedboard. 不同的AXI总线卷积加速模块的概况 这次实现并逐渐优化了三个版本的卷积加速模块 ...

  8. Xilinx DDR3 IP核使用问题汇总(持续更新)和感悟

    一度因为DDR3的IP核使用而发狂. 后来因为解决问题,得一感悟.后面此贴会完整讲述ddr3 ip的使用.(XILINX K7) 感悟:对于有供应商支持的产品,遇到问题找官方的流程.按照官方的指导进行 ...

  9. 基于Virtext6平台的GTX IP核基本设置说明

    本工程基于以下条件使用: 板卡:DBF板v3.0 芯片型号:Virtex6 315T ISE版本:14.7 IP核版本: v6_gtxwizard : 1.12 一.IP核配置进行流程 第一页配置:线 ...

随机推荐

  1. 洛谷2387 BZOJ3669魔法森林题解

    题目链接 BZ链接 这道题被很多人用spfa水了过去,表示很... 其实spfa很好卡,这组数据可以卡掉大多数spfa 链接:密码:rjvk 这里讲一下LCT的做法 我们按照a将边排序,然后依次添加 ...

  2. Lib1vent:10链接监听器接受TCP链接

    evconnlistener机制提供了监听并接受TCP链接的方法.除非特别注明,本章的所有函数和类型都在event2/listener.h中声明. 一:创建或释放evconnlistener stru ...

  3. MaxCompute 图计算开发指南

    快速入门step by step MaxCompute Studio 创建完成 MaxCompute Java Module后,即可以开始开发Graph了. 代码示例 在examples目录下有gra ...

  4. importError: DLL load failed when import matplotlib.pyplot as plt

    importError: DLL load failed when import matplotlib.pyplot as plt 出现这种情况的原因, 大多是matplotlib的版本与python ...

  5. GIT 公钥配置

    1.下载git 2.ssh-keygen -t rsa -C "xxx@xxx.com" 3.cd ~/.ssh 4.ls 5.cat id_rsa.pub 或者C:\User\x ...

  6. 模板—tarjan求割边

    int dfn[MAXN],low[MAXN],cnt; void tarjan(int x,int edg) { low[x]=dfn[x]=++cnt; for(int i=f(x);i;i=n( ...

  7. 解锁当前XXX用户

    pam_tally2 查看当前锁账户 pam_tally2 --user=XXX用户 --reset 解锁当前XXX用户

  8. 通过GDB重新获得进程的输出

    有时通过SecureCRT或者Putty远程ssh到主机上执行某个进程,因长时间没有交互导致ssh断链,此时该进程由init进程收留.该进程的输出也就无法获得了. 这种情况下,可以利用gdb重新获得该 ...

  9. 31页PPT:基于Spark的移动大数据挖掘

    31页PPT:基于Spark的移动大数据挖掘 数盟11.16 Data Science Meetup(DSM北京)分享:基于Spark的移动大数据挖掘分享嘉宾:张夏天(TalkingData首席数据科 ...

  10. 微信小程序下拉刷新 并重新加载数据

    1.在json页面配置: { "enablePullDownRefresh": true } 2.调用刷新函数 onPullDownRefresh: function() { wx ...