|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?注册
x
小弟毕业设计就要做DDR2控制,芯片是sp6,用的ise13.2,以前也只用FPGA做过一些小玩意儿,没有做过DDR2这种复杂控制,所以没经验,总的来说,我就是个菜鸟,到现在还没仿真出基本读写时序,中英文资料也看了好多了,什么ug388,什么什么。。。半懂半不懂的,时间比较紧了,求大神指点我一下,能弄出基本读写就行了。由于时间关系,我就没去仔细读DDR2协议了,直接看的xilinx的MCB控制器文档,目前我知道的,就是操作命令端、用户端的FIFO,至于后面的DDR2接口,肯定是接硬件的,内部时序也由MCB自动完成,我只需要按照MCB的读写时序操作就行了,不知道是不是?
我用的MT开头的RAM,位宽16bit,128M。
在MIG工具里,我用port2做写端(只写),用port3做读端(只读),时间参数就是默认(小弟也不懂啊,没有按照RAM的真实参数设置,不会影响仿真吧?),然后就生成了一个MCB核。
我就用传统观的调用ipcore的方式,写一个“外套”,里面例华一个MCB核,然后把各输入输出接口对应上(下面是代码,不知道对不对,mcb_tst就是我自己起的MCB核名字)
/**************************************************************************************/
module mcb(
inout [15:0]
mcb3_dram_dq,
output [13:0]
mcb3_dram_a,
output [2:0]
mcb3_dram_ba,
output mcb3_dram_ras_n,
output mcb3_dram_cas_n,
output mcb3_dram_we_n,
output mcb3_dram_odt,
output mcb3_dram_cke,
output mcb3_dram_dm,
inout mcb3_dram_udqs,
inout mcb3_dram_udqs_n,
inout mcb3_rzq,
inout mcb3_zio,
output mcb3_dram_udm,
input c3_sys_clk,
input c3_sys_rst_i,
output c3_calib_done,
output c3_clk0,
output c3_rst0,
inout mcb3_dram_dqs,
inout mcb3_dram_dqs_n,
output mcb3_dram_ck,
output mcb3_dram_ck_n,
input
c3_p2_cmd_clk,
input
c3_p2_cmd_en,
input [2:0]
c3_p2_cmd_instr,
input [5:0]
c3_p2_cmd_bl,
input [29:0]
c3_p2_cmd_byte_addr,
output
c3_p2_cmd_empty,
output
c3_p2_cmd_full,
input
c3_p2_wr_clk,
input
c3_p2_wr_en,
input [3:0]
c3_p2_wr_mask,
input [31:0]
c3_p2_wr_data,
output
c3_p2_wr_full,
output
c3_p2_wr_empty,
output [6:0]
c3_p2_wr_count,
output
c3_p2_wr_underrun,
output
c3_p2_wr_error,
input
c3_p3_cmd_clk,
input
c3_p3_cmd_en,
input [2:0]
c3_p3_cmd_instr,
input [5:0]
c3_p3_cmd_bl,
input [29:0]
c3_p3_cmd_byte_addr,
output
c3_p3_cmd_empty,
output
c3_p3_cmd_full,
input
c3_p3_rd_clk,
input
c3_p3_rd_en,
output [31:0]
c3_p3_rd_data,
output
c3_p3_rd_full,
output
c3_p3_rd_empty,
output [6:0]
c3_p3_rd_count,
output
c3_p3_rd_overflow,
output
c3_p3_rd_error
);
//例化MCB核:
mcb_tst mcb1(
.mcb3_dram_dq(mcb3_dram_dq),
.mcb3_dram_a(mcb3_dram_a),
.mcb3_dram_ba(mcb3_dram_ba),
.mcb3_dram_ras_n(mcb3_dram_ras_n),
.mcb3_dram_cas_n(mcb3_dram_cas_n),
.mcb3_dram_we_n(mcb3_dram_we_n),
.mcb3_dram_odt(mcb3_dram_odt),
.mcb3_dram_cke(mcb3_dram_cke),
.mcb3_dram_dm(mcb3_dram_dm),
.mcb3_dram_udqs(mcb3_dram_udqs),
.mcb3_dram_udqs_n(mcb3_dram_udqs_n),
.mcb3_rzq(mcb3_rzq),
.mcb3_zio(mcb3_zio),
.mcb3_dram_udm(mcb3_dram_udm),
.c3_sys_clk(c3_sys_clk),
.c3_sys_rst_i(c3_sys_rst_i),
.c3_calib_done(c3_calib_done),
.c3_clk0(c3_clk0),
.c3_rst0(c3_rst0),
.mcb3_dram_dqs(mcb3_dram_dqs),
.mcb3_dram_dqs_n(mcb3_dram_dqs_n),
.mcb3_dram_ck(mcb3_dram_ck),
.mcb3_dram_ck_n(mcb3_dram_ck_n),
.c3_p2_cmd_clk(c3_p2_cmd_clk),
.c3_p2_cmd_en(c3_p2_cmd_en),
.c3_p2_cmd_instr(c3_p2_cmd_instr),
.c3_p2_cmd_bl(c3_p2_cmd_bl),
.c3_p2_cmd_byte_addr(c3_p2_cmd_byte_addr),
.c3_p2_cmd_empty(c3_p2_cmd_empty),
.c3_p2_cmd_full(c3_p2_cmd_full),
.c3_p2_wr_clk(c3_p2_wr_clk),
.c3_p2_wr_en(c3_p2_wr_en),
.c3_p2_wr_mask(c3_p2_wr_mask),
.c3_p2_wr_data(c3_p2_wr_data),
.c3_p2_wr_full(c3_p2_wr_full),
.c3_p2_wr_empty(c3_p2_wr_empty),
.c3_p2_wr_count(c3_p2_wr_count),
.c3_p2_wr_underrun(c3_p2_wr_underrun),
.c3_p2_wr_error(c3_p2_wr_error),
.c3_p3_cmd_clk(c3_p3_cmd_clk),
.c3_p3_cmd_en(c3_p3_cmd_en),
.c3_p3_cmd_instr(c3_p3_cmd_instr),
.c3_p3_cmd_bl(c3_p3_cmd_bl),
.c3_p3_cmd_byte_addr(c3_p3_cmd_byte_addr),
.c3_p3_cmd_empty(c3_p3_cmd_empty),
.c3_p3_cmd_full(c3_p3_cmd_full),
.c3_p3_rd_clk(c3_p3_rd_clk),
.c3_p3_rd_en(c3_p3_rd_en),
.c3_p3_rd_data(c3_p3_rd_data),
.c3_p3_rd_full(c3_p3_rd_full),
.c3_p3_rd_empty(c3_p3_rd_empty),
.c3_p3_rd_count(c3_p3_rd_count),
.c3_p3_rd_overflow(c3_p3_rd_overflow),
.c3_p3_rd_error(c3_p3_rd_error)
);
endmodule
/**************************************************************************/
然后就写了个简单的testbench,想写一个32位的数到MCB里去,用ise自带的仿真工具仿真(因为最近更换ise,所以绑一起的modelsim给卸载了,只好暂时用ise自带的仿真工具)
我的testbech思路是这样的:
1、复位
2、向port2的写端fifo写入一个数据(写fifo时钟有效--->准备数据--->写使能)
3、向port2的命令端发送写入命令(命令端fifo时钟有效--->准备地址、突发长度、写入命令--->写命令使能)
下面是testbench代码:
/**************************************************************************/
module rx_tb;
// Inputs
reg c3_sys_clk;
reg c3_sys_rst_i;
reg c3_p2_cmd_clk;
reg c3_p2_cmd_en;
reg [2:0] c3_p2_cmd_instr;
reg [5:0] c3_p2_cmd_bl;
reg [29:0] c3_p2_cmd_byte_addr;
reg c3_p2_wr_clk;
reg c3_p2_wr_en;
reg [3:0] c3_p2_wr_mask;
reg [31:0] c3_p2_wr_data;
reg c3_p3_cmd_clk;
reg c3_p3_cmd_en;
reg [2:0] c3_p3_cmd_instr;
reg [5:0] c3_p3_cmd_bl;
reg [29:0] c3_p3_cmd_byte_addr;
reg c3_p3_rd_clk;
reg c3_p3_rd_en;
// Outputs
wire [13:0] mcb3_dram_a;
wire [2:0] mcb3_dram_ba;
wire mcb3_dram_ras_n;
wire mcb3_dram_cas_n;
wire mcb3_dram_we_n;
wire mcb3_dram_odt;
wire mcb3_dram_cke;
wire mcb3_dram_dm;
wire mcb3_dram_udm;
wire c3_calib_done;
wire c3_clk0;
wire c3_rst0;
wire mcb3_dram_ck;
wire mcb3_dram_ck_n;
wire c3_p2_cmd_empty;
wire c3_p2_cmd_full;
wire c3_p2_wr_full;
wire c3_p2_wr_empty;
wire [6:0] c3_p2_wr_count;
wire c3_p2_wr_underrun;
wire c3_p2_wr_error;
wire c3_p3_cmd_empty;
wire c3_p3_cmd_full;
wire [31:0] c3_p3_rd_data;
wire c3_p3_rd_full;
wire c3_p3_rd_empty;
wire [6:0] c3_p3_rd_count;
wire c3_p3_rd_overflow;
wire c3_p3_rd_error;
// Bidirs
wire [15:0] mcb3_dram_dq;
wire mcb3_dram_udqs;
wire mcb3_dram_udqs_n;
wire mcb3_rzq;
wire mcb3_zio;
wire mcb3_dram_dqs;
wire mcb3_dram_dqs_n;
// Instantiate the Unit Under Test (UUT)
mcb uut (
.mcb3_dram_dq(mcb3_dram_dq),
.mcb3_dram_a(mcb3_dram_a),
.mcb3_dram_ba(mcb3_dram_ba),
.mcb3_dram_ras_n(mcb3_dram_ras_n),
.mcb3_dram_cas_n(mcb3_dram_cas_n),
.mcb3_dram_we_n(mcb3_dram_we_n),
.mcb3_dram_odt(mcb3_dram_odt),
.mcb3_dram_cke(mcb3_dram_cke),
.mcb3_dram_dm(mcb3_dram_dm),
.mcb3_dram_udqs(mcb3_dram_udqs),
.mcb3_dram_udqs_n(mcb3_dram_udqs_n),
.mcb3_rzq(mcb3_rzq),
.mcb3_zio(mcb3_zio),
.mcb3_dram_udm(mcb3_dram_udm),
.c3_sys_clk(c3_sys_clk),
.c3_sys_rst_i(c3_sys_rst_i),
.c3_calib_done(c3_calib_done),
.c3_clk0(c3_clk0),
.c3_rst0(c3_rst0),
.mcb3_dram_dqs(mcb3_dram_dqs),
.mcb3_dram_dqs_n(mcb3_dram_dqs_n),
.mcb3_dram_ck(mcb3_dram_ck),
.mcb3_dram_ck_n(mcb3_dram_ck_n),
.c3_p2_cmd_clk(c3_p2_cmd_clk),
.c3_p2_cmd_en(c3_p2_cmd_en),
.c3_p2_cmd_instr(c3_p2_cmd_instr),
.c3_p2_cmd_bl(c3_p2_cmd_bl),
.c3_p2_cmd_byte_addr(c3_p2_cmd_byte_addr),
.c3_p2_cmd_empty(c3_p2_cmd_empty),
.c3_p2_cmd_full(c3_p2_cmd_full),
.c3_p2_wr_clk(c3_p2_wr_clk),
.c3_p2_wr_en(c3_p2_wr_en),
.c3_p2_wr_mask(c3_p2_wr_mask),
.c3_p2_wr_data(c3_p2_wr_data),
.c3_p2_wr_full(c3_p2_wr_full),
.c3_p2_wr_empty(c3_p2_wr_empty),
.c3_p2_wr_count(c3_p2_wr_count),
.c3_p2_wr_underrun(c3_p2_wr_underrun),
.c3_p2_wr_error(c3_p2_wr_error),
.c3_p3_cmd_clk(c3_p3_cmd_clk),
.c3_p3_cmd_en(c3_p3_cmd_en),
.c3_p3_cmd_instr(c3_p3_cmd_instr),
.c3_p3_cmd_bl(c3_p3_cmd_bl),
.c3_p3_cmd_byte_addr(c3_p3_cmd_byte_addr),
.c3_p3_cmd_empty(c3_p3_cmd_empty),
.c3_p3_cmd_full(c3_p3_cmd_full),
.c3_p3_rd_clk(c3_p3_rd_clk),
.c3_p3_rd_en(c3_p3_rd_en),
.c3_p3_rd_data(c3_p3_rd_data),
.c3_p3_rd_full(c3_p3_rd_full),
.c3_p3_rd_empty(c3_p3_rd_empty),
.c3_p3_rd_count(c3_p3_rd_count),
.c3_p3_rd_overflow(c3_p3_rd_overflow),
.c3_p3_rd_error(c3_p3_rd_error)
);
//testbench的逻辑代码:
initial begin
// Initialize Inputs
c3_sys_clk = 0;
c3_sys_rst_i = 0;
c3_p2_cmd_clk = 0;
c3_p2_cmd_en = 0;
c3_p2_cmd_instr = 0;
c3_p2_cmd_bl = 0;
c3_p2_cmd_byte_addr = 0;
c3_p2_wr_clk = 0;
c3_p2_wr_en = 0;
c3_p2_wr_mask = 0;
c3_p2_wr_data = 0;
c3_p3_cmd_clk = 0;
c3_p3_cmd_en = 0;
c3_p3_cmd_instr = 0;
c3_p3_cmd_bl = 0;
c3_p3_cmd_byte_addr = 0;
c3_p3_rd_clk = 0;
c3_p3_rd_en = 0;
// Wait 100 ns for global reset to finish
forever begin
#1 c3_sys_clk = ~c3_sys_clk; //系统时钟,单时钟
c3_p2_wr_clk = ~c3_p2_wr_clk; //port2写端fifo时钟
c3_p2_cmd_clk = ~c3_p2_cmd_clk; //port2命令端fifo时钟
end
// Add stimulus here
end
initial begin
#5 c3_sys_rst_i = 1;
#5 c3_sys_rst_i = 0; //复位
#200 c3_p2_wr_data = 32'b10101010101010101010101010101010; //准备数据
#2 c3_p2_wr_en = 1;
//使能写端fifo
#2 c3_p2_wr_en = 0;
#5 c3_p2_cmd_byte_addr = 0; //送地址
c3_p2_cmd_bl = 0; //送突发长度0,代表写入32位?
c3_p2_cmd_instr = 0;
//发送写入命令000
#2 c3_p2_cmd_en = 1; //使能命令端fifo
#2 c3_p2_cmd_en = 0;
end
endmodule
/*******************************************************************************/
仿真后完全就和ug388上的时序不对啊,而且为什么port2写端fifo的full和empty同时为1 ? 也不知道究竟数据写入了fifo没有,下面给仿真图:
求大神交我简单的MCB操作步骤吧,我都要崩溃了。。 |
|