DDR3 调试
DDR3配置:时钟输入400M ,芯片V6 lx240t -2 ff1156 ,突发模式为BL=8,长度为64。
仿真:新建工程,添加用xilinx 生成DDR3核的sim_tb_top 等文件。进行仿真。
traffic_gen 是xilinx 自带的一个测试DDR 的模块随机的读写DDR ,然后校验读取和写入的数值是不是一样。如果有错,会拉高tg_compare_error 来报警。而我们要做的就是自己看懂traffic_gen 向DDR 模块发送的时序,然后去重新编写一个模块来代替traffic_gen 。
traffic_gen 写数据时序图:
traffic_gen 读数据时序图:
设计读写模块:
由于需要代替traffic_gen 模块,所以需要设计数据发送模块(cad_gen_1),命令时序模块(cad_gen_2)和数据校验模块(data_compare ),另外增加异步读写FIFO 来保证读写稳定不出错。系统模块间信号连接图如下:
Example_top
DDR3_CORE
wr_fifo
Cad_gen_1
Wr_en
din
dout Cad_gen_2
App_en App_wdf_wren App_wdf_end App_cmd
App_addr
Phy_init_done App_rdy App_wdf_rdy
Rd_en
rd_fifo
din Wr_en
Rd_en
Data_co mpare
data
Rd_en
子模块功能
cad_gen_1模块负责产要写入DDR3的数据。先将数据存入写FIFO中。
cad_gen_2模块负责产生命令(app_com),地址(app_addr),控制器写数据有效使能(app_en),写数据使能(app_wdf_wren),写数据结束信号(app_wdf_end)。
data_compare模块负责将从的DDR3核中读出的数据与写入的数据相比较。从而得出误码率。
子模块接口
Cad_gen_1模块
信号位宽方向描述
Clk 1 Input 外部时钟
rst 1 input 复位信号
app_rdy 1 Input 由DDR3核输出的核ready信号
app_wdf_rdy 1 Input 由DDR3核输出的接收数据ready信号phy_init_done 1 Input 核初始化成功时置1,只有初始化完成
以后才能进行相应的读写操作。
fifo_wr_data 256 Output 写入DDR的数据,当FIFO的使能
wr_fifo_wren为高时+1计数
wr_fifo_wren 1 Output 数据存入fifo的使能,每次拉高两个
时钟周期。
Cad_gen_2模块
信号位宽方向描述
clk 1 Input 与DDR核的时钟一直
rst 1 Input 复位
app_rdy 1 Input 由DDR3核输出的核ready信号
phy_init_done 1 Input 核初始化成功时置1,只有初始化完成
以后才能进行相应的读写操作。
app_wdf_rdy 1 Input 由DDR3核输出的接收数据ready信号app_cmd 3 Output 读写命令信号,1为读,0为写
app_en 1 Output 操作地址app_addr的是能,只又它拉
高的时候,命令和地址才有效。(注意,
当写入时,如果app_en为高,且
app_rdy为低,则app_en保持高直到
app_rdy为高时,app_en拉低)
app_wdf_wren 1 Output 写数据使能,拉高时,写入数据有效。
在app_en有效的下一个时钟上升沿,
数据使能拉高保持两个时钟周期后,拉
低。(准确的说,只能每个地址写入数
据时,此信号要在app_en拉高后也拉
高,持续两个时钟周期)
app_addr 28 Output 读写的地址(注意:因为突发长度为8,
所以地址应该以8递增。)
app_wdf_end
1
output
写结束接口,在写使能有效的下一个时钟上升沿拉高,持续一个时钟周期。
Data_conpare 模块
信号
位宽
方向 描述
Clk 1 Input 时钟,与核一致
Rst 1 Input 复位
Data 256 Input DDR3核中读出的数据
Rd_en 1 Input 读数据时,DDR3核反馈的读数据有效信号,拉高,则数据有效。 Error 1 Output 数据错误 Error_cnt
32 Output
错误计数
读写时序图
写入数据时序:
Clk 8
app_cmd 0
app_addr app_en app_rdy app_wdf_rdy 12
app_wdf_data app_wdf_wren app_wdf_end
写数据时序图
在保证app_wdf_rdy 和app_rdy 为高的情况下,写数据时,写命令app_cmd 为3’b000,地址每次计数+8。当地址变化时,将app_en 置高一个时钟周期就置0,如果app_en 置高时,app_rdy 为低,则app_en 要保持拉高到app_rdy 置1后一个周期拉低,在此期间地址数据使能都不变。在app_en 拉高的一个周期后,将app_wdf_wren 拉高2个时钟周期,并对应发送两个256位的数据,发送第二个数据时,拉高app_wdf_end 信号,表明,当前地址要发送的数据传输完成。app_rdy 在app_rdy 为高的情况下,拉高一个周期表明当前地址数据有效。否则数据地址均无效。
读出数据时序:
Clk 8
app_cmd 0
1
app_addr app_en app_rdy 12
app_rd_data app_rd_data_wren app_rd_data_end
读数据时序图
读数据和写数据类似,读数据命令app_cmd 为3’b001,同样在地址变化的同时拉高app_en 信号,同样要求app_rdy 为高,否则app_en 与地址保持到app_rdy 为高的下个时钟周期。读使能app_rd_data_valid 与读数据app_rd_data 读结束app_rd_data_end 在地址给定后一段时间会从控制器中反馈出来。
对应的在软件中读写数据的时序图为:(其中data_valid_o 就是数据给DDR3的app_wdf_wren ,cmd_en_o 就是输出给DDR3的app_en ,data_wr_end_o 就是输出的app_wdf_end ,addr_o 是输出的写入或者读出的地址,具体由所对应的cmd 决定。Data_o 为写入的数据,可写一个计数器,作为数据。cmd_o 为读写命令。) 软件写数据时序图:
软件读数据时序图:
DDR3总体工作状态机如下图:
IDEL
WRITE_ADDRESS
WRITE_DATA
READ_ADDRESS
READ_DELAY
FINISH
每次地址+8转入WRITE_DATA 状态,当地址计数到65536时,转入READ_ADDRESS 状态做一个计数器,让每个地址维持至少3个时钟周期,当计数
器计到2时,跳转到WRITE_ADDRESS 状态每次当DDR3的fifo 可写,并且控制器有效时,读地址+8后挑转到READ_DELAY ,当地址计数器计到写地址挑战状态时就
挑战到FINISH 状态做一个计数器,让每个地址维持至少3个时钟周期,当计数
器计到1时,跳转到READ_ADDRESS 状态
状态机停止运行
控制器内部使用MMCM 产生的200M 时钟,用户接口使用系统顶层锁相环锁出的200M 时钟。(会有相位差)
FIFO 分为写数据FIFO 和读数据FIFO 。 写数据FIFO :
● 写时钟:用户200M 时钟 ● 读时钟:控制器200M 时钟 ● 复位:控制器复位(高有效)
● 写数据 (fifo_wr_data) :用户给的数据(计数器,在写使能为高,
并且不满时计数)
● 读数据 (app_wdf_data) :在控制器反馈的读使能时,读出数据。 ● 写使能 (wrfifo_wren) :每次拉高2个时钟,保证每次写入2个数
据。
● 读使能:将发送给DDR3核的写使能作为FIFO 的读使能。将数据写
入核中。
读数据FIFO :
● 写时钟:控制器200M 时钟 ● 读时钟:用户200M 时钟
● 复位:控制器复位(高有效)
●写数据:从控制器中按所给地址读出的数据
●写使能:给控制器后,控制器反馈的读数据有效信号
app_rd_data_valid
●读使能:因为读出的数据是在地址给定核一段时间后才会读出。在
检测到FIFO为非空的情况下,并且地址变化时,每次给2个时钟周
期的使能,当命令app_cmd变为0时,则保持读使能为高,直到FIFO
被读空。
FIFO的读写使能不能一直为高,否则会导致FIFO为满状态,这样会导致数据出错。或者导致FIFO被读空。在写数据时,fifo的使能与写入DDR3核的使能保持一致,每个地址拉高两个时钟周期,取出FIFO中的2个256位数据写入DDR3核。读数据时,将给定有效地址后核反馈的读使能作为FIFO的写入使能,将读出数据写入FIFO。这样读FIFO不会空,写FIFO也不会满,保证数据传输在异步FIFO中能正确传输。