VIVADO 中基于mig IP、USB3.0完成图片的上位机显示
项目简述
我们前面的两篇文章已经介绍了VIVADO中MIG IP的调用、用户接口、读写时序,相信大家从前面两篇文章的学习中已经可以掌握MIG的使用。那么为了巩固MIG的使用,我们将介绍一个DDR3的典型应用。
该项目的简述是:
1、FPGA产生图像数据,存储到DDR3中
2、从DDR3中读取数据,经过USB3.0接口发送到上位机,并在上位机显示
本来该实验使用OV5640摄像头的效果最好,但是因为在家,硬件不够,所以实行了该策略
本次实验所用到的软硬件环境,如下:
软件环境:VIVADO2019.1软件、Modelsim10.7仿真环境
硬件环境:米联客MA7035FA(100T)开发板
上位机:米联客自带的USB3.0上位机
项目流程框图
我们首先将vivado的MIG IP封装成ISE中MIG的形式,系统框图如上图。这样做的原因是,ISE中MIG的操作比较方便,用命令FIFO与数据FIFO,而vivado的MIG用户接口没有那么方便,所以这里我们先将MIG进行进一步的封装。整个项目的流程图如下:
模块读写控制时序图
上面整个DDR封装包括如下:
写DDR3模块的封装图形如下:
对应上述写模块的时序图如下:
读DDR3模块的封装图形如下:
上述读模块的时序图如下:
仲裁模块的状态机如下:
仲裁模块的时序图如下:
DDR3封装模块代码
我们将vivdado得MIG封装成了4个接口,前两个是写接口,后两个是读接口,代码如下,供大家学习:
ddr3_top模块
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website :
// Module Name : ddr3_top.v
// Create Time : 2020-02-27 23:16:16
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module ddr3_top(
//System Interfaces
input rst_n ,
input locked ,
input clk_200m ,
//DDR3 Interfaces
output wire [13:0] ddr3_addr ,
output wire [ 2:0] ddr3_ba ,
output wire ddr3_cas_n ,
output wire ddr3_ck_n ,
output wire ddr3_ck_p ,
output wire ddr3_cke ,
output wire ddr3_ras_n ,
output wire ddr3_reset_n ,
output wire ddr3_we_n ,
inout [31:0] ddr3_dq ,
inout [ 3:0] ddr3_dqs_n ,
inout [ 3:0] ddr3_dqs_p ,
output wire [ 0:0] ddr3_cs_n ,
output wire [ 3:0] ddr3_dm ,
output wire [ 0:0] ddr3_odt ,
//User Interfaces
input c3_p0_cmd_clk ,
input c3_p0_cmd_en ,
input [ 6:0] c3_p0_cmd_bl ,
input [27:0] c3_p0_cmd_byte_addr ,
output wire c3_p0_cmd_empty ,
output wire c3_p0_cmd_full ,
input c3_p0_wr_clk ,
input c3_p0_wr_en ,
input [31:0] c3_p0_wr_mask ,
input [255:0] c3_p0_wr_data ,
output wire c3_p0_wr_full ,
output wire c3_p0_wr_empty ,
output wire [10:0] c3_p0_wr_count ,
input c3_p1_cmd_clk ,
input c3_p1_cmd_en ,
input [ 6:0] c3_p1_cmd_bl ,
input [27:0] c3_p1_cmd_byte_addr ,
output wire c3_p1_cmd_empty ,
output wire c3_p1_cmd_full ,
input c3_p1_wr_clk ,
input c3_p1_wr_en ,
input [31:0] c3_p1_wr_mask ,
input [255:0] c3_p1_wr_data ,
output wire c3_p1_wr_full ,
output wire c3_p1_wr_empty ,
output wire [10:0] c3_p1_wr_count ,
input c3_p2_cmd_clk ,
input c3_p2_cmd_en ,
input [ 6:0] c3_p2_cmd_bl ,
input [27:0] c3_p2_cmd_byte_addr ,
output wire c3_p2_cmd_empty ,
output wire c3_p2_cmd_full ,
input c3_p2_rd_clk ,
input c3_p2_rd_en ,
output wire [255:0] c3_p2_rd_data ,
output wire c3_p2_rd_full ,
output wire c3_p2_rd_empty ,
output wire [10:0] c3_p2_rd_count ,
input c3_p3_cmd_clk ,
input c3_p3_cmd_en ,
input [ 6:0] c3_p3_cmd_bl ,
input [27:0] c3_p3_cmd_byte_addr ,
output wire c3_p3_cmd_empty ,
output wire c3_p3_cmd_full ,
input c3_p3_rd_clk ,
input c3_p3_rd_en ,
output wire [255:0] c3_p3_rd_data ,
output wire c3_p3_rd_full ,
output wire c3_p3_rd_empty ,
output wire [10:0] c3_p3_rd_count
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
//mig_7series_0_inst
wire init_calib_complete ;
wire [27:0] app_addr ;
wire [ 2:0] app_cmd ;
wire app_en ;
wire [255:0] app_wdf_data ;
wire app_wdf_end ;
wire 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 ;
wire [31:0] app_wdf_mask ;
wire ui_clk ;
wire ui_clk_sync_rst ;
//a7_wr_ctrl_inst1
wire app_en_wr1 ;
wire [ 3:0] app_cmd_wr1 ;
wire [27:0] app_addr_wr1 ;
wire app_wdf_wren_wr1 ;
wire [255:0] app_wdf_data_wr1 ;
wire [31:0] app_wdf_mask_wr1 ;
wire app_wdf_end_wr1 ;
wire a7_wr_start_wr1 ;
wire [ 6:0] a7_wr_bl_wr1 ;
wire [27:0] a7_wr_init_addr_wr1 ;
wire [255:0] a7_wr_data_wr1 ;
wire [31:0] a7_wr_mask_wr1 ;
wire a7_wr_end_wr1 ;
wire a7_wr_req_wr1 ;
//a7_wr_ctrl_inst2
wire app_en_wr2 ;
wire [ 3:0] app_cmd_wr2 ;
wire [27:0] app_addr_wr2 ;
wire app_wdf_wren_wr2 ;
wire [255:0] app_wdf_data_wr2 ;
wire [31:0] app_wdf_mask_wr2 ;
wire app_wdf_end_wr2 ;
wire a7_wr_start_wr2 ;
wire [ 6:0] a7_wr_bl_wr2 ;
wire [27:0] a7_wr_init_addr_wr2 ;
wire [255:0] a7_wr_data_wr2 ;
wire [31:0] a7_wr_mask_wr2 ;
wire a7_wr_end_wr2 ;
wire a7_wr_req_wr2 ;
//a7_rd_ctrl_inst1
wire app_en_rd1 ;
wire [ 3:0] app_cmd_rd1 ;
wire [27:0] app_addr_rd1 ;
wire app_rd_data_valid_rd1 ;
wire a7_rd_start_rd1 ;
wire [ 6:0] a7_rd_bl_rd1 ;
wire [27:0] a7_rd_init_addr_rd1 ;
wire [255:0] a7_rd_data_rd1 ;
wire a7_rd_data_valid_rd1 ;
wire a7_rd_end_rd1 ;
//a7_rd_ctrl_inst2
wire app_en_rd2 ;
wire [ 3:0] app_cmd_rd2 ;
wire [27:0] app_addr_rd2 ;
wire app_rd_data_valid_rd2 ;
wire a7_rd_start_rd2 ;
wire [ 6:0] a7_rd_bl_rd2 ;
wire [27:0] a7_rd_init_addr_rd2 ;
wire [255:0] a7_rd_data_rd2 ;
wire a7_rd_data_valid_rd2 ;
wire a7_rd_end_rd2 ;
//arbit_inst
//wire c3_p0_cmd_empty ;
//wire c3_p1_cmd_empty ;
//wire c3_p2_cmd_empty ;
//wire c3_p3_cmd_empty ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
mig_7series_0 mig_7series_0_inst (
// Memory interface ports
.ddr3_addr (ddr3_addr ), // output [13: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 [27: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
.app_wdf_rdy (app_wdf_rdy ), // output app_wdf_rdy
.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 (ui_clk ), // output ui_clk
.ui_clk_sync_rst (ui_clk_sync_rst ), // output ui_clk_sync_rst
.app_wdf_mask (app_wdf_mask ), // input [31:0] app_wdf_mask
// System Clock Ports
.sys_clk_i (clk_200m ),
.sys_rst (locked ) // input sys_rst
);
arbit arbit_inst(
//System Interfaces
.rst_n (init_calib_complete ),
//DDR3 Interfaces
.ui_clk (ui_clk ),
.app_addr (app_addr ),
.app_cmd (app_cmd ),
.app_en (app_en ),
.app_wdf_data (app_wdf_data ),
.app_wdf_end (app_wdf_end ),
.app_wdf_wren (app_wdf_wren ),
.app_rd_data_valid (app_rd_data_valid ),
.app_wdf_mask (app_wdf_mask ),
//a7_wr_ctrl_inst1
.app_en_wr1 (app_en_wr1 ),
.app_cmd_wr1 (app_cmd_wr1 ),
.app_addr_wr1 (app_addr_wr1 ),
.app_wdf_wren_wr1 (app_wdf_wren_wr1 ),
.app_wdf_data_wr1 (app_wdf_data_wr1 ),
.app_wdf_mask_wr1 (app_wdf_mask_wr1 ),
.app_wdf_end_wr1 (app_wdf_end_wr1 ),
.a7_wr_start_w1 (a7_wr_start_wr1 ),
.a7_wr_end_wr1 (a7_wr_end_wr1 ),
.c3_p0_cmd_empty (c3_p0_cmd_empty ),
//a7_wr_ctrl_inst1
.app_en_wr2 (app_en_wr2 ),
.app_cmd_wr2 (app_cmd_wr2 ),
.app_addr_wr2 (app_addr_wr2 ),
.app_wdf_wren_wr2 (app_wdf_wren_wr2 ),
.app_wdf_data_wr2 (app_wdf_data_wr2 ),
.app_wdf_mask_wr2 (app_wdf_mask_wr2 ),
.app_wdf_end_wr2 (app_wdf_end_wr2 ),
.a7_wr_start_w2 (a7_wr_start_wr2 ),
.a7_wr_end_wr2 (a7_wr_end_wr2 ),
.c3_p1_cmd_empty (c3_p1_cmd_empty ),
//a7_rd_ctrl_inst1
.app_en_rd1 (app_en_rd1 ),
.app_cmd_rd1 (app_cmd_rd1 ),
.app_addr_rd1 (app_addr_rd1 ),
.app_rd_data_valid_rd1 (app_rd_data_valid_rd1 ),
.a7_rd_start_rd1 (a7_rd_start_rd1 ),
.a7_rd_end_rd1 (a7_rd_end_rd1 ),
.c3_p2_cmd_empty (c3_p2_cmd_empty ),
//a7_rd_ctrl_inst2
.app_en_rd2 (app_en_rd2 ),
.app_cmd_rd2 (app_cmd_rd2 ),
.app_addr_rd2 (app_addr_rd2 ),
.app_rd_data_valid_rd2 (app_rd_data_valid_rd2 ),
.a7_rd_start_rd2 (a7_rd_start_rd2 ),
.a7_rd_end_rd2 (a7_rd_end_rd2 ),
.c3_p3_cmd_empty (c3_p3_cmd_empty )
);
a7_wr_ctrl a7_wr_ctrl_inst1(
//System Interfaces
.rst_n (init_calib_complete ),
//DDR3 Interfaces
.ui_clk (ui_clk ),
.app_rdy (app_rdy ),
.app_wdf_rdy (app_wdf_rdy ),
.app_en (app_en_wr1 ),
.app_cmd (app_cmd_wr1 ),
.app_addr (app_addr_wr1 ),
.app_wdf_wren (app_wdf_wren_wr1 ),
.app_wdf_data (app_wdf_data_wr1 ),
.app_wdf_mask (app_wdf_mask_wr1 ),
.app_wdf_end (app_wdf_end_wr1 ),
//Communication Interfaces
.a7_wr_start (a7_wr_start_wr1 ),
.a7_wr_bl (a7_wr_bl_wr1 ),
.a7_wr_init_addr (a7_wr_init_addr_wr1 ),
.a7_wr_data (a7_wr_data_wr1 ),
.a7_wr_mask (a7_wr_mask_wr1 ),
.a7_wr_end (a7_wr_end_wr1 ),
.a7_wr_req (a7_wr_req_wr1 )
);
fifo_generator_0 cmd_wr1_fifo (
.rst (~init_calib_complete ), // input wire rst
.wr_clk (c3_p0_cmd_clk ), // input wire wr_clk
.rd_clk (ui_clk ), // input wire rd_clk
.din ({c3_p0_cmd_bl,c3_p0_cmd_byte_addr}), // input wire [38 : 0] din
.wr_en (c3_p0_cmd_en ), // input wire wr_en
.rd_en (a7_wr_start_wr1 ), // input wire rd_en
.dout ({a7_wr_bl_wr1,a7_wr_init_addr_wr1}), // output wire [38 : 0] dout
.full (c3_p0_cmd_full ), // output wire full
.empty (c3_p0_cmd_empty )
);
fifo_generator_1 data_wr1_fifo (
.rst (~init_calib_complete ), // input wire rst
.wr_clk (c3_p0_wr_clk ), // input wire wr_clk
.rd_clk (ui_clk ), // input wire rd_clk
.din ({c3_p0_wr_mask,c3_p0_wr_data} ), // input wire [287 : 0] din
.wr_en (c3_p0_wr_en ), // input wire wr_en
.rd_en (a7_wr_req_wr1 ), // input wire rd_en
.dout ({a7_wr_mask_wr1,a7_wr_data_wr1}), // output wire [287 : 0] dout
.full (c3_p0_wr_full ), // output wire full
.empty (c3_p0_wr_empty ), // output wire empty
.wr_data_count (c3_p0_wr_count ) // output wire [10 : 0] wr_data_count
);
a7_wr_ctrl a7_wr_ctrl_inst2(
//System Interfaces
.rst_n (init_calib_complete ),
//DDR3 Interfaces
.ui_clk (ui_clk ),
.app_rdy (app_rdy ),
.app_wdf_rdy (app_wdf_rdy ),
.app_en (app_en_wr2 ),
.app_cmd (app_cmd_wr2 ),
.app_addr (app_addr_wr2 ),
.app_wdf_wren (app_wdf_wren_wr2 ),
.app_wdf_data (app_wdf_data_wr2 ),
.app_wdf_mask (app_wdf_mask_wr2 ),
.app_wdf_end (app_wdf_end_wr2 ),
//Communication Interfaces
.a7_wr_start (a7_wr_start_wr2 ),
.a7_wr_bl (a7_wr_bl_wr2 ),
.a7_wr_init_addr (a7_wr_init_addr_wr2 ),
.a7_wr_data (a7_wr_data_wr2 ),
.a7_wr_mask (a7_wr_mask_wr2 ),
.a7_wr_end (a7_wr_end_wr2 ),
.a7_wr_req (a7_wr_req_wr2 )
);
fifo_generator_0 cmd_wr2_fifo (
.rst (~init_calib_complete ), // input wire rst
.wr_clk (c3_p1_cmd_clk ), // input wire wr_clk
.rd_clk (ui_clk ), // input wire rd_clk
.din ({c3_p1_cmd_bl,c3_p1_cmd_byte_addr}), // input wire [38 : 0] din
.wr_en (c3_p1_cmd_en ), // input wire wr_en
.rd_en (a7_wr_start_wr2 ), // input wire rd_en
.dout ({a7_wr_bl_wr2,a7_wr_init_addr_wr2}), // output wire [38 : 0] dout
.full (c3_p1_cmd_full ), // output wire full
.empty (c3_p1_cmd_empty )
);
fifo_generator_1 data_wr2_fifo (
.rst (~init_calib_complete ), // input wire rst
.wr_clk (c3_p1_wr_clk ), // input wire wr_clk
.rd_clk (ui_clk ), // input wire rd_clk
.din ({c3_p1_wr_mask,c3_p1_wr_data} ), // input wire [287 : 0] din
.wr_en (c3_p1_wr_en ), // input wire wr_en
.rd_en (a7_wr_req_wr2 ), // input wire rd_en
.dout ({a7_wr_mask_wr2,a7_wr_data_wr2}), // output wire [287 : 0] dout
.full (c3_p1_wr_full ), // output wire full
.empty (c3_p1_wr_empty ), // output wire empty
.wr_data_count (c3_p1_wr_count ) // output wire [10 : 0] wr_data_count
);
a7_rd_ctrl a7_rd_ctrl_inst1(
//System Interfaces
.rst_n (init_calib_complete ),
//DDR3 Interfaces
.ui_clk (ui_clk ),
.app_en (app_en_rd1 ),
.app_cmd (app_cmd_rd1 ),
.app_addr (app_addr_rd1 ),
.app_rd_data (app_rd_data ),
.app_rd_data_valid (app_rd_data_valid_rd1 ),
.app_rdy (app_rdy ),
//Communication Interfaces
.a7_rd_start (a7_rd_start_rd1 ),
.a7_rd_bl (a7_rd_bl_rd1 ),
.a7_rd_init_addr (a7_rd_init_addr_rd1 ),
.a7_rd_data (a7_rd_data_rd1 ),
.a7_rd_data_valid (a7_rd_data_valid_rd1 ),
.a7_rd_end (a7_rd_end_rd1 )
);
fifo_generator_0 cmd_rd1_fifo (
.rst (~init_calib_complete ), // input wire rst
.wr_clk (c3_p2_cmd_clk ), // input wire wr_clk
.rd_clk (ui_clk ), // input wire rd_clk
.din ({c3_p2_cmd_bl,c3_p2_cmd_byte_addr}), // input wire [38 : 0] din
.wr_en (c3_p2_cmd_en ), // input wire wr_en
.rd_en (a7_rd_start_rd1 ), // input wire rd_en
.dout ({a7_rd_bl_rd1,a7_rd_init_addr_rd1}), // output wire [38 : 0] dout
.full (c3_p2_cmd_full ), // output wire full
.empty (c3_p2_cmd_empty )
);
fifo_generator_2 data_rd1_fifo (
.rst (~init_calib_complete ), // input wire rst
.wr_clk (ui_clk ), // input wire wr_clk
.rd_clk (c3_p2_rd_clk ), // input wire rd_clk
.din (a7_rd_data_rd1 ), // input wire [255 : 0] din
.wr_en (a7_rd_data_valid_rd1 ), // input wire wr_en
.rd_en (c3_p2_rd_en ), // input wire rd_en
.dout (c3_p2_rd_data ), // output wire [255 : 0] dout
.full (c3_p2_rd_full ), // output wire full
.empty (c3_p2_rd_empty ), // output wire empty
.rd_data_count (c3_p2_rd_count ) // output wire [10 : 0] rd_data_count
);
a7_rd_ctrl a7_rd_ctrl_inst2(
//System Interfaces
.rst_n (init_calib_complete ),
//DDR3 Interfaces
.ui_clk (ui_clk ),
.app_en (app_en_rd2 ),
.app_cmd (app_cmd_rd2 ),
.app_addr (app_addr_rd2 ),
.app_rd_data (app_rd_data ),
.app_rd_data_valid (app_rd_data_valid_rd2 ),
.app_rdy (app_rdy ),
//Communication Interfaces
.a7_rd_start (a7_rd_start_rd2 ),
.a7_rd_bl (a7_rd_bl_rd2 ),
.a7_rd_init_addr (a7_rd_init_addr_rd2 ),
.a7_rd_data (a7_rd_data_rd2 ),
.a7_rd_data_valid (a7_rd_data_valid_rd2 ),
.a7_rd_end (a7_rd_end_rd2 )
);
fifo_generator_0 cmd_rd2_fifo (
.rst (~init_calib_complete ), // input wire rst
.wr_clk (c3_p3_cmd_clk ), // input wire wr_clk
.rd_clk (ui_clk ), // input wire rd_clk
.din ({c3_p3_cmd_bl,c3_p3_cmd_byte_addr}), // input wire [38 : 0] din
.wr_en (c3_p3_cmd_en ), // input wire wr_en
.rd_en (a7_rd_start_rd2 ), // input wire rd_en
.dout ({a7_rd_bl_rd2,a7_rd_init_addr_rd2}), // output wire [38 : 0] dout
.full (c3_p3_cmd_full ), // output wire full
.empty (c3_p3_cmd_empty )
);
fifo_generator_2 data_rd2_fifo (
.rst (~init_calib_complete ), // input wire rst
.wr_clk (ui_clk ), // input wire wr_clk
.rd_clk (c3_p3_rd_clk ), // input wire rd_clk
.din (a7_rd_data_rd2 ), // input wire [255 : 0] din
.wr_en (a7_rd_data_valid_rd2 ), // input wire wr_en
.rd_en (c3_p3_rd_en ), // input wire rd_en
.dout (c3_p3_rd_data ), // output wire [255 : 0] dout
.full (c3_p3_rd_full ), // output wire full
.empty (c3_p3_rd_empty ), // output wire empty
.rd_data_count (c3_p3_rd_count ) // output wire [10 : 0] rd_data_count
);
endmodule
a7_wr_ctrl模块:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website :
// Module Name : a7_wr_ctrl.v
// Create Time : 2020-02-29 22:19:50
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module a7_wr_ctrl(
//System Interfaces
input rst_n ,
//DDR3 Interfaces
input ui_clk ,
input app_rdy ,
input app_wdf_rdy ,
output wire app_en ,
output wire [ 3:0] app_cmd ,
output reg [27:0] app_addr ,
output wire app_wdf_wren ,
output wire [255:0] app_wdf_data ,
output wire [31:0] app_wdf_mask ,
output wire app_wdf_end ,
//Communication Interfaces
input a7_wr_start ,
input [ 6:0] a7_wr_bl ,
input [27:0] a7_wr_init_addr ,
input [255:0] a7_wr_data ,
input [31:0] a7_wr_mask ,
output reg a7_wr_end ,
output wire a7_wr_req
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
reg [ 6:0] wr_bl ;
reg wr_flag ;
reg [ 6:0] bl_cnt ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
assign app_en = wr_flag && app_rdy && app_wdf_rdy;
assign app_wdf_end = app_en;
assign app_wdf_wren = app_en;
assign app_wdf_data = a7_wr_data;
assign a7_wr_req = app_en;
assign app_wdf_mask = a7_wr_mask;
assign app_cmd = 3'd0;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
wr_flag <= 1'b0;
else if(bl_cnt == wr_bl && app_en == 1'b1)
wr_flag <= 1'b0;
else if(a7_wr_start == 1'b1)
wr_flag <= 1'b1;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
wr_bl <= 7'd0;
else if(a7_wr_start == 1'b1)
wr_bl <= a7_wr_bl;
else
wr_bl <= wr_bl;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
app_addr <= 28'd0;
else if(a7_wr_start == 1'b1)
app_addr <= a7_wr_init_addr;
else if(app_en == 1'b1)
app_addr <= app_addr + 8;
else
app_addr <= app_addr;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
bl_cnt <= 7'd0;
else if(bl_cnt == wr_bl && app_en == 1'b1 && wr_flag == 1'b1)
bl_cnt <= 7'd0;
else if(wr_flag == 1'b1 && app_en == 1'b1)
bl_cnt <= bl_cnt + 1'b1;
else
bl_cnt <= bl_cnt;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
a7_wr_end <= 1'b0;
else if(bl_cnt == wr_bl && app_en == 1'b1)
a7_wr_end <= 1'b1;
else
a7_wr_end <= 1'b0;
endmodule
a7_rd_ctrl模块:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website :
// Module Name : a7_rd_ctrl.v
// Create Time : 2020-03-01 14:32:05
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module a7_rd_ctrl(
//System Interfaces
input rst_n ,
//DDR3 Interfaces
input ui_clk ,
output reg app_en ,
output wire [ 3:0] app_cmd ,
output reg [27:0] app_addr ,
input [255:0] app_rd_data ,
input app_rd_data_valid ,
input app_rdy ,
//Communication Interfaces
input a7_rd_start ,
input [ 6:0] a7_rd_bl ,
input [27:0] a7_rd_init_addr ,
output reg [255:0] a7_rd_data ,
output reg a7_rd_data_valid ,
output reg a7_rd_end
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
reg [ 6:0] rd_bl ;
reg [ 6:0] cmd_cnt ;
reg rd_flag ;
reg [ 6:0] data_cnt ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
assign app_cmd = 3'd1;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
rd_bl <= 7'd0;
else if(a7_rd_start == 1'b1)
rd_bl <= a7_rd_bl;
else
rd_bl <= a7_rd_bl;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
app_en <= 1'b0;
else if(a7_rd_start == 1'b1)
app_en <= 1'b1;
else if(cmd_cnt == rd_bl && app_rdy == 1'b1)
app_en <= 1'b0;
else
app_en <= app_en;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
cmd_cnt <= 7'd0;
else if(rd_flag == 1'b1 && cmd_cnt == rd_bl && app_rdy == 1'b1)
cmd_cnt <= 7'd0;
else if(rd_flag == 1'b1 && app_rdy == 1'b1 && app_en == 1'b1)
cmd_cnt <= cmd_cnt + 1'b1;
else
cmd_cnt <= cmd_cnt;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
rd_flag <= 1'b0;
else if(a7_rd_start == 1'b1)
rd_flag <= 1'b1;
else if(data_cnt == rd_bl && app_rd_data_valid == 1'b1)
rd_flag <= 1'b0;
else
rd_flag <= rd_flag;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
app_addr <= 28'd0;
else if(a7_rd_start == 1'b1)
app_addr <= a7_rd_init_addr;
else if(rd_flag == 1'b1 && app_rdy == 1'b1)
app_addr <= app_addr + 8;
else
app_addr <= app_addr;
always @(posedge ui_clk)
a7_rd_data <= app_rd_data;
always @(posedge ui_clk)
a7_rd_data_valid <= app_rd_data_valid;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
a7_rd_end <= 1'b0;
else if(data_cnt == rd_bl && app_rd_data_valid == 1'b1)
a7_rd_end <= 1'b1;
else
a7_rd_end <= 1'b0;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
data_cnt <= 7'd0;
else if(data_cnt == rd_bl && rd_flag == 1'b1 && app_rd_data_valid == 1'b1)
data_cnt <= 7'd0;
else if(rd_flag == 1'b1 && app_rd_data_valid == 1'b1)
data_cnt <= data_cnt + 1'b1;
else
data_cnt <= data_cnt;
endmodule
arbit模块:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2020/03/01 15:17:14
// Design Name:
// Module Name: arbit
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module arbit(
//System Interfaces
input rst_n ,
//DDR3 Interfaces
input ui_clk ,
output reg [27:0] app_addr ,
output reg [ 2:0] app_cmd ,
output reg app_en ,
output reg [255:0] app_wdf_data ,
output reg app_wdf_end ,
output reg app_wdf_wren ,
input app_rd_data_valid ,
output reg [31:0] app_wdf_mask ,
//a7_wr_ctrl_inst1
input app_en_wr1 ,
input [ 3:0] app_cmd_wr1 ,
input [27:0] app_addr_wr1 ,
input app_wdf_wren_wr1 ,
input [255:0] app_wdf_data_wr1 ,
input [31:0] app_wdf_mask_wr1 ,
input app_wdf_end_wr1 ,
output reg a7_wr_start_w1 ,
input a7_wr_end_wr1 ,
input c3_p0_cmd_empty ,
//a7_wr_ctrl_inst1
input app_en_wr2 ,
input [ 3:0] app_cmd_wr2 ,
input [27:0] app_addr_wr2 ,
input app_wdf_wren_wr2 ,
input [255:0] app_wdf_data_wr2 ,
input [31:0] app_wdf_mask_wr2 ,
input app_wdf_end_wr2 ,
output reg a7_wr_start_w2 ,
input a7_wr_end_wr2 ,
input c3_p1_cmd_empty ,
//a7_rd_ctrl_inst1
input app_en_rd1 ,
input [ 3:0] app_cmd_rd1 ,
input [27:0] app_addr_rd1 ,
output reg app_rd_data_valid_rd1 ,
output reg a7_rd_start_rd1 ,
input a7_rd_end_rd1 ,
input c3_p2_cmd_empty ,
//a7_rd_ctrl_inst2
input app_en_rd2 ,
input [ 3:0] app_cmd_rd2 ,
input [27:0] app_addr_rd2 ,
output reg app_rd_data_valid_rd2 ,
output reg a7_rd_start_rd2 ,
input a7_rd_end_rd2 ,
input c3_p3_cmd_empty
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
parameter IDLE = 6'b000001 ;
parameter ARBIT = 6'b000010 ;
parameter WR1 = 6'b000100 ;
parameter WR2 = 6'b001000 ;
parameter RD1 = 6'b010000 ;
parameter RD2 = 6'b100000 ;
reg [ 5:0] state ;
reg [ 2:0] rand_cnt ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
rand_cnt <= 3'd0;
else if(rand_cnt == 3'd3)
rand_cnt <= 3'd0;
else
rand_cnt <= rand_cnt + 1'b1;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
state <= IDLE;
else case(state)
IDLE : state <= ARBIT;
ARBIT : if(c3_p0_cmd_empty == 1'b0 && rand_cnt == 3'd0)
state <= WR1;
else if(c3_p1_cmd_empty == 1'b0 && rand_cnt == 3'd1)
state <= WR2;
else if(c3_p2_cmd_empty == 1'b0 && rand_cnt == 3'd2)
state <= RD1;
else if(c3_p3_cmd_empty == 1'b0 && rand_cnt == 3'd3)
state <= RD2;
else
state <= state;
WR1 : if(a7_wr_end_wr1 == 1'b1)
state <= ARBIT;
else
state <= state;
WR2 : if(a7_wr_end_wr2 == 1'b1)
state <= ARBIT;
else
state <= state;
RD1 : if(a7_rd_end_rd1 == 1'b1)
state <= ARBIT;
else
state <= state;
RD2 : if(a7_rd_end_rd2 == 1'b1)
state <= ARBIT;
else
state <= state;
default : state <= IDLE;
endcase
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
a7_wr_start_w1 <= 1'b0;
else if(state == ARBIT && c3_p0_cmd_empty == 1'b0 && rand_cnt == 3'd0)
a7_wr_start_w1 <= 1'b1;
else
a7_wr_start_w1 <= 1'b0;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
a7_wr_start_w2 <= 1'b0;
else if(state == ARBIT && c3_p1_cmd_empty == 1'b0 && rand_cnt == 3'd1)
a7_wr_start_w2 <= 1'b1;
else
a7_wr_start_w2 <= 1'b0;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
a7_rd_start_rd1 <= 1'b0;
else if(state == ARBIT && c3_p2_cmd_empty == 1'b0 && rand_cnt == 3'd2)
a7_rd_start_rd1 <= 1'b1;
else
a7_rd_start_rd1 <= 1'b0;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
a7_rd_start_rd2 <= 1'b0;
else if(state == ARBIT && c3_p3_cmd_empty == 1'b0 && rand_cnt == 3'd3)
a7_rd_start_rd2 <= 1'b1;
else
a7_rd_start_rd2 <= 1'b0;
always @(*)
case(state)
WR1 : begin
app_addr = app_addr_wr1;
app_cmd = app_cmd_wr1;
app_en = app_en_wr1;
app_wdf_data = app_wdf_data_wr1;
app_wdf_end = app_wdf_end_wr1;
app_wdf_wren = app_wdf_wren_wr1;
app_wdf_mask = app_wdf_mask_wr1;
end
WR2 : begin
app_addr = app_addr_wr2;
app_cmd = app_cmd_wr2;
app_en = app_en_wr2;
app_wdf_data = app_wdf_data_wr2;
app_wdf_end = app_wdf_end_wr2;
app_wdf_wren = app_wdf_wren_wr2;
app_wdf_mask = app_wdf_mask_wr2;
end
RD1 : begin
app_addr = app_addr_rd1;
app_cmd = app_cmd_rd1;
app_en = app_en_rd1;
app_rd_data_valid_rd1 = app_rd_data_valid;
end
RD2 : begin
app_addr = app_addr_rd2;
app_cmd = app_cmd_rd2;
app_en = app_en_rd2;
app_rd_data_valid_rd2 = app_rd_data_valid;
end
default : begin
app_addr = 28'd0;
app_cmd = 3'd0;
app_en = 1'b0;
app_wdf_data = 256'd0;
app_wdf_end = 1'b0;
app_wdf_wren = 1'b0;
app_rd_data_valid_rd1 = 1'b0;
app_rd_data_valid_rd2 = 1'b0;
app_wdf_mask = 32'd0;
end
endcase
endmodule
从上面得代码中,我们便把vivado得MIG封装成了双读双写得ISE中的MIG接口。
DDR3封装模块测试代码
top模块:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website :
// Module Name : top.v
// Create Time : 2020-03-01 20:33:42
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module top(
//System Interfaces
input sclk ,
input rst_n ,
//DDR3 Interfaces
output wire [13:0] ddr3_addr ,
output wire [ 2:0] ddr3_ba ,
output wire ddr3_cas_n ,
output wire ddr3_ck_n ,
output wire ddr3_ck_p ,
output wire ddr3_cke ,
output wire ddr3_ras_n ,
output wire ddr3_reset_n ,
output wire ddr3_we_n ,
inout [31:0] ddr3_dq ,
inout [ 3:0] ddr3_dqs_n ,
inout [ 3:0] ddr3_dqs_p ,
output wire [ 0:0] ddr3_cs_n ,
output wire [ 3:0] ddr3_dm ,
output wire [ 0:0] ddr3_odt ,
//Debug
input test_trig
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
//clk_wiz_0_inst
wire clk_200m ;
wire locked ;
wire clk_100m ;
//ddr3_drive_inst
wire c3_p0_cmd_clk ;
wire c3_p0_cmd_en ;
wire [ 2:0] c3_p0_cmd_instr ;
wire [27:0] c3_p0_cmd_byte_addr ;
wire [ 6:0] c3_p0_cmd_bl ;
wire c3_p0_wr_clk ;
wire c3_p0_wr_en ;
wire [31:0] c3_p0_wr_mask ;
wire [255:0] c3_p0_wr_data ;
wire [ 6:0] c3_p0_wr_count ;
wire c3_p1_cmd_clk ;
wire c3_p1_cmd_en ;
wire [ 2:0] c3_p1_cmd_instr ;
wire [27:0] c3_p1_cmd_byte_addr ;
wire [ 6:0] c3_p1_cmd_bl ;
wire c3_p1_rd_clk ;
wire c3_p1_rd_en ;
wire [255:0] c3_p1_rd_data ;
wire [ 6:0] c3_p1_rd_count ;
wire [20:0] err_cnt ;
wire err_done ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
clk_wiz_0 clk_wiz_0_inst(
// Clock out ports
.clk_out1 (clk_200m ), // output clk_out1
.clk_out2 (clk_100m ),
// Status and control signals
.reset (~rst_n ), // input reset
.locked (locked ), // output locked
// Clock in ports
.clk_in1 (sclk )
); // input clk_in1
ddr3_top ddr3_top_inst(
//System Interfaces
.rst_n (rst_n ),
.locked (locked ),
.clk_200m (clk_200m ),
//DDR3 Interfaces
.ddr3_addr (ddr3_addr ),
.ddr3_ba (ddr3_ba ),
.ddr3_cas_n (ddr3_cas_n ),
.ddr3_ck_n (ddr3_ck_n ),
.ddr3_ck_p (ddr3_ck_p ),
.ddr3_cke (ddr3_cke ),
.ddr3_ras_n (ddr3_ras_n ),
.ddr3_reset_n (ddr3_reset_n ),
.ddr3_we_n (ddr3_we_n ),
.ddr3_dq (ddr3_dq ),
.ddr3_dqs_n (ddr3_dqs_n ),
.ddr3_dqs_p (ddr3_dqs_p ),
.ddr3_cs_n (ddr3_cs_n ),
.ddr3_dm (ddr3_dm ),
.ddr3_odt (ddr3_odt ),
//User Interfaces
.c3_p0_cmd_clk (c3_p0_cmd_clk ),
.c3_p0_cmd_en (c3_p0_cmd_en ),
.c3_p0_cmd_bl (c3_p0_cmd_bl ),
.c3_p0_cmd_byte_addr (c3_p0_cmd_byte_addr ),
.c3_p0_cmd_empty ( ),
.c3_p0_cmd_full ( ),
.c3_p0_wr_clk (c3_p0_wr_clk ),
.c3_p0_wr_en (c3_p0_wr_en ),
.c3_p0_wr_mask (c3_p0_wr_mask ),
.c3_p0_wr_data (c3_p0_wr_data ),
.c3_p0_wr_full ( ),
.c3_p0_wr_empty ( ),
.c3_p0_wr_count (c3_p0_wr_count ),
.c3_p1_cmd_clk ('d0 ),
.c3_p1_cmd_en ('d0 ),
.c3_p1_cmd_bl ('d0 ),
.c3_p1_cmd_byte_addr ('d0 ),
.c3_p1_cmd_empty ( ),
.c3_p1_cmd_full ( ),
.c3_p1_wr_clk ('d0 ),
.c3_p1_wr_en ('d0 ),
.c3_p1_wr_mask ('d0 ),
.c3_p1_wr_data ('d0 ),
.c3_p1_wr_full ( ),
.c3_p1_wr_empty ( ),
.c3_p1_wr_count ( ),
.c3_p2_cmd_clk (c3_p1_cmd_clk ),
.c3_p2_cmd_en (c3_p1_cmd_en ),
.c3_p2_cmd_bl (c3_p1_cmd_bl ),
.c3_p2_cmd_byte_addr (c3_p1_cmd_byte_addr ),
.c3_p2_cmd_empty ( ),
.c3_p2_cmd_full ( ),
.c3_p2_rd_clk (c3_p1_rd_clk ),
.c3_p2_rd_en (c3_p1_rd_en ),
.c3_p2_rd_data (c3_p1_rd_data ),
.c3_p2_rd_full ( ),
.c3_p2_rd_empty ( ),
.c3_p2_rd_count (c3_p1_rd_count ),
.c3_p3_cmd_clk ('d0 ),
.c3_p3_cmd_en ('d0 ),
.c3_p3_cmd_bl ('d0 ),
.c3_p3_cmd_byte_addr ('d0 ),
.c3_p3_cmd_empty ( ),
.c3_p3_cmd_full ( ),
.c3_p3_rd_clk ('d0 ),
.c3_p3_rd_en ('d0 ),
.c3_p3_rd_data ( ),
.c3_p3_rd_full ( ),
.c3_p3_rd_empty ( ),
.c3_p3_rd_count ( )
);
ddr3_drive ddr3_drive_inst(
//System Interfaces
.sclk (clk_100m ),
.rst_n (locked ),
//DDR3 Interfaces
.c3_p0_cmd_clk (c3_p0_cmd_clk ),
.c3_p0_cmd_en (c3_p0_cmd_en ),
.c3_p0_cmd_instr (c3_p0_cmd_instr ),
.c3_p0_cmd_byte_addr (c3_p0_cmd_byte_addr ),
.c3_p0_cmd_bl (c3_p0_cmd_bl ),
.c3_p0_wr_clk (c3_p0_wr_clk ),
.c3_p0_wr_en (c3_p0_wr_en ),
.c3_p0_wr_mask (c3_p0_wr_mask ),
.c3_p0_wr_data (c3_p0_wr_data ),
.c3_p0_wr_count (c3_p0_wr_count ),
.c3_p1_cmd_clk (c3_p1_cmd_clk ),
.c3_p1_cmd_en (c3_p1_cmd_en ),
.c3_p1_cmd_instr (c3_p1_cmd_instr ),
.c3_p1_cmd_byte_addr (c3_p1_cmd_byte_addr ),
.c3_p1_cmd_bl (c3_p1_cmd_bl ),
.c3_p1_rd_clk (c3_p1_rd_clk ),
.c3_p1_rd_en (c3_p1_rd_en ),
.c3_p1_rd_data (c3_p1_rd_data ),
.c3_p1_rd_count (c3_p1_rd_count ),
//Debug
.test_trig (test_trig ),
.err_cnt (err_cnt ),
.err_done (err_done )
);
endmodule
ddr3_drive模块:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website :
// Module Name : ddr3_drive.v
// Create Time : 2020-02-22 11:41:08
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module ddr3_drive(
//System Interfaces
input sclk ,
input rst_n ,
//DDR3 Interfaces
output c3_p0_cmd_clk ,
output wire c3_p0_cmd_en ,
output wire [ 2:0] c3_p0_cmd_instr ,
output reg [27:0] c3_p0_cmd_byte_addr ,
output wire [ 6:0] c3_p0_cmd_bl ,
output c3_p0_wr_clk ,
output reg c3_p0_wr_en ,
output wire [31:0] c3_p0_wr_mask ,
output reg [255:0] c3_p0_wr_data ,
input [ 6:0] c3_p0_wr_count ,
output c3_p1_cmd_clk ,
output reg c3_p1_cmd_en ,
output wire [ 2:0] c3_p1_cmd_instr ,
output reg [27:0] c3_p1_cmd_byte_addr ,
output wire [ 6:0] c3_p1_cmd_bl ,
output c3_p1_rd_clk ,
output reg c3_p1_rd_en ,
input [255:0] c3_p1_rd_data ,
input [ 6:0] c3_p1_rd_count ,
//Debug
input test_trig ,
output reg [20:0] err_cnt ,
output reg err_done
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
//parameter BURST_NUM = 1048576 ;
parameter BURST_NUM = 100 ;
parameter BURST_LENFTH = 7'd15 ;
reg flag_done ;
reg test_trig_r ;
reg [ 3:0] wr_cnt ;
reg c3_p0_wr_en_r ;
reg c3_p1_rd_en_r ;
wire c3_p1_rd_en_nege ;
reg [20:0] burst_cnt ;
reg rd_flag ;
reg rd_cmd_flag ;
reg [ 3:0] rd_cnt ;
reg [255:0] check_data ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
assign c3_p0_cmd_instr = 3'b000;
assign c3_p0_cmd_bl = BURST_LENFTH;
assign c3_p0_cmd_en = ~c3_p0_wr_en && c3_p0_wr_en_r;
assign c3_p0_cmd_clk = sclk;
assign c3_p0_wr_clk = sclk;
assign c3_p0_wr_mask = 32'd0;
assign c3_p1_cmd_instr = 3'b001;
assign c3_p1_cmd_bl = BURST_LENFTH;
assign c3_p1_rd_en_nege = ~c3_p1_rd_en && c3_p1_rd_en_r;
assign c3_p1_cmd_clk = sclk;
assign c3_p1_rd_clk = sclk;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
flag_done <= 1'b0;
else if(burst_cnt == BURST_NUM - 1'b1 && c3_p1_rd_en_nege == 1'b1)
flag_done <= 1'b0;
else if(test_trig == 1'b1)
flag_done <= 1'b1;
else
flag_done <= flag_done;
always @(posedge sclk)
test_trig_r <= test_trig;
always @(posedge sclk)
c3_p1_rd_en_r <= c3_p1_rd_en;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
c3_p0_wr_en <= 1'b0;
else if(flag_done == 1'b1 && test_trig_r == 1'b1)
c3_p0_wr_en <= 1'b1;
else if(c3_p1_rd_en_nege == 1'b1 && burst_cnt < BURST_NUM - 1'b1)
c3_p0_wr_en <= 1'b1;
else if(wr_cnt == 4'd15)
c3_p0_wr_en <= 1'b0;
else
c3_p0_wr_en <= c3_p0_wr_en;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
wr_cnt <= 4'd0;
else if(c3_p0_wr_en == 1'b1)
wr_cnt <= wr_cnt + 1'b1;
else
wr_cnt <= 4'd0;
always @(posedge sclk)
c3_p0_wr_en_r <= c3_p0_wr_en;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
rd_cmd_flag <= 1'b0;
else if(c3_p0_cmd_en == 1'b1)
rd_cmd_flag <= 1'b1;
else if(rd_flag == 1'b1 && c3_p0_wr_count <= 7'd2)
rd_cmd_flag <= 1'b0;
else
rd_cmd_flag <= rd_cmd_flag;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
c3_p1_cmd_en <= 1'b0;
else if(rd_cmd_flag == 1'b1 && c3_p0_wr_count <= 7'd2)
c3_p1_cmd_en <= 1'b1;
else
c3_p1_cmd_en <= 1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
rd_flag <= 1'b0;
else if(c3_p0_cmd_en == 1'b1)
rd_flag <= 1'b1;
else if(rd_cnt == 4'd15)
rd_flag <= 1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
c3_p1_rd_en <= 1'b0;
else if(rd_cnt == 4'd15)
c3_p1_rd_en <= 1'b0;
else if(rd_flag == 1'b1 && c3_p1_rd_count >= BURST_LENFTH - 2)
c3_p1_rd_en <= 1'b1;
else
c3_p1_rd_en <= c3_p1_rd_en;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
rd_cnt <= 4'd0;
else if(c3_p1_rd_en == 1'b1)
rd_cnt <= rd_cnt + 1'b1;
else
rd_cnt <= 4'd0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
c3_p0_wr_data <= 256'd0;
else if(c3_p0_wr_en == 1'b1 && flag_done == 1'b1)
c3_p0_wr_data <= c3_p0_wr_data + 1'b1;
else
c3_p0_wr_data <= c3_p0_wr_data;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
check_data <= 256'd0;
else if(c3_p1_rd_en == 1'b1 && flag_done == 1'b1)
check_data <= check_data + 1'b1;
else
check_data <= check_data;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
err_cnt <= 21'd0;
else if(test_trig == 1'b1)
err_cnt <= 21'd0;
else if(c3_p1_rd_en == 1'b1 && check_data != c3_p1_rd_data)
err_cnt <= err_cnt + 1'b1;
else
err_cnt <= err_cnt;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
burst_cnt <= 21'd0;
else if(burst_cnt == BURST_NUM - 1'b1 && c3_p1_rd_en_nege == 1'b1)
burst_cnt <= 21'd0;
else if(c3_p1_rd_en_nege == 1'b1)
burst_cnt <= burst_cnt + 1'b1;
else
burst_cnt <= burst_cnt;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
err_done <= 1'b0;
else if(burst_cnt == BURST_NUM - 1'b1 && c3_p1_rd_en_nege == 1'b1)
err_done <= 1'b1;
else
err_done <= 1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
c3_p0_cmd_byte_addr <= 28'd0;
else if(burst_cnt == BURST_NUM - 1'b1 && c3_p0_cmd_en == 1'b1)
c3_p0_cmd_byte_addr <= 28'd0;
else if(c3_p0_cmd_en == 1'b1)
c3_p0_cmd_byte_addr <= c3_p0_cmd_byte_addr + 28'd128;
else
c3_p0_cmd_byte_addr <= c3_p0_cmd_byte_addr;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
c3_p1_cmd_byte_addr <= 28'd0;
else if(burst_cnt == BURST_NUM - 1'b1 && c3_p1_cmd_en == 1'b1)
c3_p1_cmd_byte_addr <= 28'd0;
else if(c3_p1_cmd_en == 1'b1)
c3_p1_cmd_byte_addr <= c3_p1_cmd_byte_addr + 28'd128;
else
c3_p1_cmd_byte_addr <= c3_p1_cmd_byte_addr;
endmodule
tb_ddr3模块:
`timescale 1ns / 1ps
`define CLOCK 20
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website :
// Module Name : tb_ddr3.v
// Create Time : 2020-02-27 23:36:46
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module tb_ddr3;
parameter DQ_WIDTH = 32;
localparam MEMORY_WIDTH = 16;
localparam NUM_COMP = DQ_WIDTH/MEMORY_WIDTH ;
reg sclk ;
reg rst_n ;
wire [13:0] ddr3_addr ;
wire [ 2:0] ddr3_ba ;
wire ddr3_cas_n ;
wire ddr3_ck_n ;
wire ddr3_ck_p ;
wire ddr3_cke ;
wire ddr3_ras_n ;
wire ddr3_reset_n ;
wire ddr3_we_n ;
wire [31:0] ddr3_dq ;
wire [ 3:0] ddr3_dqs_n ;
wire [ 3:0] ddr3_dqs_p ;
wire init_calib_complete ;
wire [ 0:0] ddr3_cs_n ;
wire [ 3:0] ddr3_dm ;
wire [ 0:0] ddr3_odt ;
reg test_start ;
initial begin
sclk = 1'b0;
rst_n <= 1'b0;
test_start <= 1'b0;
#(100*`CLOCK);
rst_n <= 1'b1;
@(posedge top_inst.ddr3_top_inst.init_calib_complete)
#(100*`CLOCK);
test_start <= 1'b1;
#(15)
test_start <= 1'b0;
#(200000)
test_start <= 1'b1;
#(15)
test_start <= 1'b0;
end
always #(`CLOCK/2) sclk = ~sclk;
top top_inst(
//System Interfaces
.sclk (sclk ),
.rst_n (rst_n ),
//DDR3 Interfaces
.ddr3_addr (ddr3_addr ),
.ddr3_ba (ddr3_ba ),
.ddr3_cas_n (ddr3_cas_n ),
.ddr3_ck_n (ddr3_ck_n ),
.ddr3_ck_p (ddr3_ck_p ),
.ddr3_cke (ddr3_cke ),
.ddr3_ras_n (ddr3_ras_n ),
.ddr3_reset_n (ddr3_reset_n ),
.ddr3_we_n (ddr3_we_n ),
.ddr3_dq (ddr3_dq ),
.ddr3_dqs_n (ddr3_dqs_n ),
.ddr3_dqs_p (ddr3_dqs_p ),
.ddr3_cs_n (ddr3_cs_n ),
.ddr3_dm (ddr3_dm ),
.ddr3_odt (ddr3_odt ),
.test_trig (test_start )
);
genvar i;
for (i = 0; i < NUM_COMP; i = i + 1) begin: gen_mem
ddr3_model u_comp_ddr3(
.rst_n (ddr3_reset_n ),
.ck (ddr3_ck_p ),
.ck_n (ddr3_ck_n ),
.cke (ddr3_cke ),
.cs_n (ddr3_cs_n ),
.ras_n (ddr3_ras_n ),
.cas_n (ddr3_cas_n ),
.we_n (ddr3_we_n ),
.dm_tdqs (ddr3_dm[(2*(i+1)-1):(2*i)] ),
.ba (ddr3_ba ),
.addr (ddr3_addr ),
.dq (ddr3_dq[16*(i+1)-1:16*(i)] ),
.dqs (ddr3_dqs_p[(2*(i+1)-1):(2*i)] ),
.dqs_n (ddr3_dqs_n[(2*(i+1)-1):(2*i)] ),
.tdqs_n ( ),
.odt (ddr3_odt )
);
end
endmodule
DDR3封装模块测试仿真
Modelsim仿真结果如下:
从仿真结果中,我们可以看出我们程序的正确性。
项目代码
上面我们将VIVODO中DDR3的IP接口重新封装成双读双写的接口,接下来我们将完成博客开始的时候提出的项目,就是将图像经过DDR3缓存,然后经过USB3发到上位机显示。这里模块的代码我们主要参考了ISE软件关于DDR3应用的第三个博客,因为那里我们没有开发板也就只给出了模块与时序图。这里我们利用那篇博客进行重新写代码。
这里为了方便同学们学习,我将所有的代码重新贴上,包括上面的DDR3封装模块的代码。这里我们用到了详细代码如下:
top模块:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website :
// Module Name : top.v
// Create Time : 2020-03-01 20:33:42
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module top(
//System Interfaces
input sclk ,
input rst_n ,
//DDR3 Interfaces
output wire [13:0] ddr3_addr ,
output wire [ 2:0] ddr3_ba ,
output wire ddr3_cas_n ,
output wire ddr3_ck_n ,
output wire ddr3_ck_p ,
output wire ddr3_cke ,
output wire ddr3_ras_n ,
output wire ddr3_reset_n ,
output wire ddr3_we_n ,
inout [31:0] ddr3_dq ,
inout [ 3:0] ddr3_dqs_n ,
inout [ 3:0] ddr3_dqs_p ,
output wire [ 0:0] ddr3_cs_n ,
output wire [ 3:0] ddr3_dm ,
output wire [ 0:0] ddr3_odt ,
//USB3 Interfaces
output wire USBSS_EN ,
input USB_clk ,
inout [15:0] data ,
inout [ 1:0] be ,
input rxf_n ,
input txf_n ,
output wire oe_n ,
output wire wr_n ,
output wire siwu_n ,
output wire rd_n ,
output wire wakeup ,
output wire [ 1:0] gpio
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
//clk_wiz_0_inst
wire clk_200m ;
wire locked ;
wire clk_100m ;
//ddr3_drive_inst
wire init_calib_complete ;
wire c3_p0_cmd_clk ;
wire c3_p0_cmd_en ;
wire [ 2:0] c3_p0_cmd_instr ;
wire [27:0] c3_p0_cmd_byte_addr ;
wire [ 6:0] c3_p0_cmd_bl ;
wire c3_p0_wr_clk ;
wire c3_p0_wr_en ;
wire [31:0] c3_p0_wr_mask ;
wire [255:0] c3_p0_wr_data ;
wire [10:0] c3_p0_wr_count ;
wire c3_p1_cmd_clk ;
wire c3_p1_cmd_en ;
wire [ 2:0] c3_p1_cmd_instr ;
wire [27:0] c3_p1_cmd_byte_addr ;
wire [ 6:0] c3_p1_cmd_bl ;
wire c3_p1_rd_clk ;
wire c3_p1_rd_en ;
wire [255:0] c3_p1_rd_data ;
wire [10:0] c3_p1_rd_count ;
//sensor_data_gen_inst
wire clk_24m ;
wire data_wr_en ;
wire [31:0] data_wr ;
//usb3_drive_inst
wire [15:0] data_in ;
wire data_req ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
clk_wiz_0 clk_wiz_0_inst(
// Clock out ports
.clk_out1 (clk_200m ), // output clk_out1
.clk_out2 (clk_100m ),
.clk_out3 (clk_24m ),
// Status and control signals
.reset (~rst_n ), // input reset
.locked (locked ), // output locked
// Clock in ports
.clk_in1 (sclk )
); // input clk_in1
ddr3_top ddr3_top_inst(
//System Interfaces
.rst_n (rst_n ),
.locked (locked ),
.clk_200m (clk_200m ),
//DDR3 Interfaces
.ddr3_addr (ddr3_addr ),
.ddr3_ba (ddr3_ba ),
.ddr3_cas_n (ddr3_cas_n ),
.ddr3_ck_n (ddr3_ck_n ),
.ddr3_ck_p (ddr3_ck_p ),
.ddr3_cke (ddr3_cke ),
.ddr3_ras_n (ddr3_ras_n ),
.ddr3_reset_n (ddr3_reset_n ),
.ddr3_we_n (ddr3_we_n ),
.ddr3_dq (ddr3_dq ),
.ddr3_dqs_n (ddr3_dqs_n ),
.ddr3_dqs_p (ddr3_dqs_p ),
.ddr3_cs_n (ddr3_cs_n ),
.ddr3_dm (ddr3_dm ),
.ddr3_odt (ddr3_odt ),
//User Interfaces
.init_calib_complete (init_calib_complete ),
.c3_p0_cmd_clk (c3_p0_cmd_clk ),
.c3_p0_cmd_en (c3_p0_cmd_en ),
.c3_p0_cmd_bl (c3_p0_cmd_bl ),
.c3_p0_cmd_byte_addr (c3_p0_cmd_byte_addr ),
.c3_p0_cmd_empty ( ),
.c3_p0_cmd_full ( ),
.c3_p0_wr_clk (c3_p0_wr_clk ),
.c3_p0_wr_en (c3_p0_wr_en ),
.c3_p0_wr_mask (c3_p0_wr_mask ),
.c3_p0_wr_data (c3_p0_wr_data ),
.c3_p0_wr_full ( ),
.c3_p0_wr_empty ( ),
.c3_p0_wr_count (c3_p0_wr_count ),
.c3_p1_cmd_clk ('d0 ),
.c3_p1_cmd_en ('d0 ),
.c3_p1_cmd_bl ('d0 ),
.c3_p1_cmd_byte_addr ('d0 ),
.c3_p1_cmd_empty ( ),
.c3_p1_cmd_full ( ),
.c3_p1_wr_clk ('d0 ),
.c3_p1_wr_en ('d0 ),
.c3_p1_wr_mask ('d0 ),
.c3_p1_wr_data ('d0 ),
.c3_p1_wr_full ( ),
.c3_p1_wr_empty ( ),
.c3_p1_wr_count ( ),
.c3_p2_cmd_clk (c3_p1_cmd_clk ),
.c3_p2_cmd_en (c3_p1_cmd_en ),
.c3_p2_cmd_bl (c3_p1_cmd_bl ),
.c3_p2_cmd_byte_addr (c3_p1_cmd_byte_addr ),
.c3_p2_cmd_empty ( ),
.c3_p2_cmd_full ( ),
.c3_p2_rd_clk (c3_p1_rd_clk ),
.c3_p2_rd_en (c3_p1_rd_en ),
.c3_p2_rd_data (c3_p1_rd_data ),
.c3_p2_rd_full ( ),
.c3_p2_rd_empty ( ),
.c3_p2_rd_count (c3_p1_rd_count ),
.c3_p3_cmd_clk ('d0 ),
.c3_p3_cmd_en ('d0 ),
.c3_p3_cmd_bl ('d0 ),
.c3_p3_cmd_byte_addr ('d0 ),
.c3_p3_cmd_empty ( ),
.c3_p3_cmd_full ( ),
.c3_p3_rd_clk ('d0 ),
.c3_p3_rd_en ('d0 ),
.c3_p3_rd_data ( ),
.c3_p3_rd_full ( ),
.c3_p3_rd_empty ( ),
.c3_p3_rd_count ( )
);
ddr3_drive ddr3_drive_inst(
//System Interfaces
.rst_n (init_calib_complete ),
//DDR3 Interfaces
.c3_p0_cmd_clk (c3_p0_cmd_clk ),
.c3_p0_cmd_en (c3_p0_cmd_en ),
.c3_p0_cmd_instr (c3_p0_cmd_instr ),
.c3_p0_cmd_byte_addr (c3_p0_cmd_byte_addr ),
.c3_p0_cmd_bl (c3_p0_cmd_bl ),
.c3_p0_wr_clk (c3_p0_wr_clk ),
.c3_p0_wr_en (c3_p0_wr_en ),
.c3_p0_wr_mask (c3_p0_wr_mask ),
.c3_p0_wr_data (c3_p0_wr_data ),
.c3_p0_wr_count (c3_p0_wr_count ),
.c3_p1_cmd_clk (c3_p1_cmd_clk ),
.c3_p1_cmd_en (c3_p1_cmd_en ),
.c3_p1_cmd_instr (c3_p1_cmd_instr ),
.c3_p1_cmd_byte_addr (c3_p1_cmd_byte_addr ),
.c3_p1_cmd_bl (c3_p1_cmd_bl ),
.c3_p1_rd_clk (c3_p1_rd_clk ),
.c3_p1_rd_en (c3_p1_rd_en ),
.c3_p1_rd_data (c3_p1_rd_data ),
.c3_p1_rd_count (c3_p1_rd_count ),
//Write DDR3
.clk_24m (clk_24m ),
.data_wr_en (data_wr_en ),
.data_wr (data_wr ),
Read DDR3
.USB_clk (USB_clk ),
.wr_n (data_req ),
.data_in (data_in )
);
sensor_data_gen sensor_data_gen_inst(
.clk (clk_24m ),
.rst_n (init_calib_complete ),
.rgb ({data_wr[15:0],data_wr[31:16]} ),
.de (data_wr_en ),
.vsync ( ),
.hsync ( )
);
//lways @(posedge clk_24m)
// if(init_calib_complete == 1'b0)
// data_wr_en <= 1'b0;
// else
// data_wr_en <= 1'b1;
//lways @(posedge clk_24m)
// if(init_calib_complete == 1'b0)
// data_wr <= 32'd0;
// else if(data_wr_en == 1'b1)
// data_wr <= data_wr + 1'b1;
usb3_drive usb3_drive_inst(
//System Interfaces
.rst_n (init_calib_complete ),
//USB3 Interfaces
.USBSS_EN (USBSS_EN ),
.sclk (USB_clk ),
.data (data ),
.be (be ),
.rxf_n (rxf_n ),
.txf_n (txf_n ),
.oe_n (oe_n ),
.wr_n (wr_n ),
.siwu_n (siwu_n ),
.rd_n (rd_n ),
.wakeup (wakeup ),
.gpio (gpio ),
//Communication Interfaces
.data_in (data_in ),
.data_req (data_req )
);
endmodule
驱动封装好的DDR3模块的代码,ddr3_drive模块:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website :
// Module Name : ddr3_drive.v
// Create Time : 2020-02-22 11:41:08
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module ddr3_drive(
//System Interfaces
input rst_n ,
//Write DDR3
input clk_24m ,
input data_wr_en ,
input [31:0] data_wr ,
//Read DDR3
input USB_clk ,
input wr_n ,
output wire [15:0] data_in ,
//DDR3 Interfaces
output c3_p0_cmd_clk ,
output reg c3_p0_cmd_en ,
output wire [ 2:0] c3_p0_cmd_instr ,
output reg [27:0] c3_p0_cmd_byte_addr ,
output wire [10:0] c3_p0_cmd_bl ,
output c3_p0_wr_clk ,
output reg c3_p0_wr_en ,
output wire [31:0] c3_p0_wr_mask ,
output reg [255:0] c3_p0_wr_data ,
input [ 6:0] c3_p0_wr_count ,
output c3_p1_cmd_clk ,
output reg c3_p1_cmd_en ,
output wire [ 2:0] c3_p1_cmd_instr ,
output reg [27:0] c3_p1_cmd_byte_addr ,
output wire [ 6:0] c3_p1_cmd_bl ,
output c3_p1_rd_clk ,
output reg c3_p1_rd_en ,
input [255:0] c3_p1_rd_data ,
input [10:0] c3_p1_rd_count
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
//parameter BURST_NUM = 1048576 ;
parameter BURST_NUM = 7200 ;
parameter BURST_LENFTH = 7'd15 ;
reg [ 3:0] data_cnt ;
reg [ 6:0] wr_data_cnt ;
reg [15:0] bl_cnt ;
reg wr_n_flag ;
reg [31:0] usb_data ;
reg [ 3:0] data_cnt_rd ;
reg [15:0] bl_cnt_r ;
reg rd_first ;
reg [255:0] c3_p1_rd_data_r ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
assign c3_p0_cmd_clk = clk_24m;
assign c3_p0_wr_clk = clk_24m;
assign c3_p0_cmd_instr = 3'd0;
assign c3_p0_cmd_bl = BURST_LENFTH;
assign c3_p0_wr_mask = 32'd0;
assign data_in = wr_n_flag == 1'b0 ? usb_data[31:16] : usb_data[15:0];
assign c3_p1_cmd_clk = USB_clk;
assign c3_p1_rd_clk = USB_clk;
assign c3_p1_cmd_instr = 3'd1;
assign c3_p1_cmd_bl = BURST_LENFTH;
always @(posedge clk_24m or negedge rst_n)
if(rst_n == 1'b0)
data_cnt <= 4'd0;
else if(data_cnt == 4'd7 && data_wr_en == 1'b1)
data_cnt <= 4'd0;
else if(data_wr_en == 1'b1)
data_cnt <= data_cnt + 1'b1;
else
data_cnt <= data_cnt;
always @(posedge clk_24m or negedge rst_n)
if(rst_n == 1'b0)
c3_p0_wr_data <= 256'd0;
else if(data_wr_en == 1'b1)
c3_p0_wr_data <= {c3_p0_wr_data[223:0],data_wr};
else
c3_p0_wr_data <= c3_p0_wr_data;
always @(posedge clk_24m or negedge rst_n)
if(rst_n == 1'b0)
c3_p0_wr_en <= 1'b0;
else if(data_cnt == 4'd7 && data_wr_en == 1'b1)
c3_p0_wr_en <= 1'b1;
else
c3_p0_wr_en <= 1'b0;
always @(posedge clk_24m or negedge rst_n)
if(rst_n == 1'b0)
wr_data_cnt <= 7'd0;
else if(wr_data_cnt == BURST_LENFTH && c3_p0_wr_en == 1'b1)
wr_data_cnt <= 7'd0;
else if(c3_p0_wr_en == 1'b1)
wr_data_cnt <= wr_data_cnt + 1'b1;
else
wr_data_cnt <= wr_data_cnt;
always @(posedge clk_24m or negedge rst_n)
if(rst_n == 1'b0)
c3_p0_cmd_en <= 1'b0;
else if(wr_data_cnt == BURST_LENFTH && c3_p0_wr_en == 1'b1)
c3_p0_cmd_en <= 1'b1;
else
c3_p0_cmd_en <= 1'b0;
always @(posedge clk_24m or negedge rst_n)
if(rst_n == 1'b0)
c3_p0_cmd_byte_addr <= 28'd0;
else if(bl_cnt == BURST_NUM - 1'b1 && c3_p0_cmd_en == 1'b1)
c3_p0_cmd_byte_addr <= 28'd0;
else if(c3_p0_cmd_en == 1'b1)
c3_p0_cmd_byte_addr <= c3_p0_cmd_byte_addr + 'd128;
always @(posedge clk_24m or negedge rst_n)
if(rst_n == 1'b0)
bl_cnt <= 16'd0;
else if(bl_cnt == BURST_NUM - 1'b1 && c3_p0_cmd_en == 1'b1)
bl_cnt <= 16'd0;
else if(c3_p0_cmd_en == 1'b1)
bl_cnt <= bl_cnt + 1'b1;
else
bl_cnt <= bl_cnt;
always @(posedge USB_clk or negedge rst_n)
if(rst_n == 1'b0)
wr_n_flag <= 1'b0;
else if(wr_n == 1'b0)
wr_n_flag <= wr_n_flag + 1'b1;
else
wr_n_flag <= wr_n_flag;
always @(posedge USB_clk or negedge rst_n)
if(rst_n == 1'b0)
data_cnt_rd <= 4'd0;
else if(data_cnt_rd == 4'd7 && wr_n_flag == 1'b1 && wr_n == 1'b0)
data_cnt_rd <= 4'd0;
else if(wr_n_flag == 1'b1 && wr_n == 1'b0)
data_cnt_rd <= data_cnt_rd + 1'b1;
else
data_cnt_rd <= data_cnt_rd;
always @(posedge USB_clk or negedge rst_n)
if(rst_n == 1'b0)
rd_first <= 1'b0;
else if(c3_p1_rd_count >= BURST_LENFTH/2 && rd_first == 1'b0)
rd_first <= 1'b1;
else
rd_first <= rd_first;
always @(posedge USB_clk or negedge rst_n)
if(rst_n == 1'b0)
c3_p1_rd_en <= 1'b0;
else if(c3_p1_rd_count >= BURST_LENFTH/2 && rd_first == 1'b0)
c3_p1_rd_en <= 1'b1;
else if(data_cnt_rd == 4'd7 && wr_n_flag == 1'b1 && wr_n == 1'b0)
c3_p1_rd_en <= 1'b1;
else
c3_p1_rd_en <= 1'b0;
always @(posedge USB_clk or negedge rst_n)
if(rst_n == 1'b0)
c3_p1_cmd_en <= 1'b0;
else if(c3_p1_rd_count <= BURST_LENFTH/2)
c3_p1_cmd_en <= 1'b1;
else
c3_p1_cmd_en <= 1'b0;
always @(posedge USB_clk or negedge rst_n)
if(rst_n == 1'b0)
c3_p1_cmd_byte_addr <= 28'd0;
else if(bl_cnt_r == BURST_NUM - 1'b1 && c3_p1_cmd_en == 1'b1)
c3_p1_cmd_byte_addr <= 28'd0;
else if(c3_p1_cmd_en == 1'b1)
c3_p1_cmd_byte_addr <= c3_p1_cmd_byte_addr + 128;
else
c3_p1_cmd_byte_addr <= c3_p1_cmd_byte_addr;
always @(posedge USB_clk or negedge rst_n)
if(rst_n == 1'b0)
bl_cnt_r <= 16'd0;
else if(bl_cnt_r == BURST_NUM - 1'b1 && c3_p1_cmd_en == 1'b1)
bl_cnt_r <= 16'd0;
else if(c3_p1_cmd_en == 1'b1)
bl_cnt_r <= bl_cnt_r + 1'b1;
else
bl_cnt_r <= bl_cnt_r;
always @(posedge USB_clk or negedge rst_n)
if(rst_n == 1'b0)
c3_p1_rd_data_r <= 256'd0;
else if(c3_p1_rd_en == 1'b1)
c3_p1_rd_data_r <= c3_p1_rd_data;
else
c3_p1_rd_data_r <= c3_p1_rd_data_r;
always @(*)
if(c3_p1_rd_en == 1'b1)
usb_data <= c3_p1_rd_data[255:224];
else case(data_cnt_rd)
0 : usb_data <= c3_p1_rd_data_r[255:224];
1 : usb_data <= c3_p1_rd_data_r[223:192];
2 : usb_data <= c3_p1_rd_data_r[191:160];
3 : usb_data <= c3_p1_rd_data_r[159:128];
4 : usb_data <= c3_p1_rd_data_r[127:96];
5 : usb_data <= c3_p1_rd_data_r[95:64];
6 : usb_data <= c3_p1_rd_data_r[63:32];
7 : usb_data <= c3_p1_rd_data_r[31:0];
default : usb_data <= 32'd0;
endcase
endmodule
数据产生模块的代码,由于在家中没有相应的摄像头,所以我们手动写出一些图像用的测试代码,这里我们并没有自己手写,因为手写的图像测试代码图像过于简单,于是我们使用了米联客给出的代码。sensor_data_gen模块:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2017/06/12 13:20:12
// Design Name:
// Module Name: sensor_data_gen
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module sensor_data_gen (
input clk,
input rst_n,
output [23:0]rgb,
output de,
output vsync,
output hsync
);
reg [23:0] colour=24'd0;
reg [11:0] hcounter=12'd0;
reg [11:0] vcounter=12'd0;
// Colours converted using The RGB -> YCbCr converter app found on Google Gadgets
// Y Cb Cr
`define C_BLACK 24'h000000; // 16 128 128
`define C_RED 24'hFF0000; // 81 90 240
`define C_GREEN 24'h00FF00; // 172 42 27
`define C_BLUE 24'h0000FF; // 32 240 118
`define C_WHITE 24'hFFFFFF; // 234 128 128
// -- Set the video mode to 1920x1080x60Hz (150MHz pixel clock needed)
/* parameter hVisible = 1920;
parameter hStartSync = 1920+88;
parameter hEndSync = 1920+88+44;
parameter hMax = 1920+88+44+148; //2200
parameter vVisible = 1080;
parameter vStartSync = 1080+4;
parameter vEndSync = 1080+4+5;
parameter vMax = 1080+4+5+36; //1125
*/
// -- Set the video mode to 1440x900x60Hz (106.47MHz pixel clock needed)
/* parameter hVisible = 1440;
parameter hStartSync = 1440+80;
parameter hEndSync = 1440+80+152;
parameter hMax = 1440+80+152+232; //1904
parameter vVisible = 900;
parameter vStartSync = 900+1;
parameter vEndSync = 900+1+3;
parameter vMax = 900+1+3+28; //932
*/
// -- Set the video mode to 1280x720x60Hz (75MHz pixel clock needed)
parameter hVisible = 1280;
parameter hStartSync = 1280+72;
parameter hEndSync = 1280+72+80;
parameter hMax = 1280+72+80+216; //1647
parameter vVisible = 720;
parameter vStartSync = 720+3;
parameter vEndSync = 720+3+5;
parameter vMax = 720+3+5+22; //749
/* */
// -- Set the video mode to 800x600x60Hz (40MHz pixel clock needed)
/* parameter hVisible = 800;
parameter hStartSync = 840; //800+40
parameter hEndSync = 968; //800+40+128
parameter hMax = 1056; //800+40+128+88
parameter vVisible = 600;
parameter vStartSync = 601; //600+1
parameter vEndSync = 605; //600+1+4
parameter vMax = 628; //600+1+4+23
// -- Set the video mode to 640x480x60Hz (25MHz pixel clock needed)
parameter hVisible = 640;
parameter hStartSync = 656; //640+16
parameter hEndSync = 752; //640+16+96
parameter hMax = 800; //640+16+96+48
parameter vVisible = 480;
parameter vStartSync = 490; //480+10
parameter vEndSync = 492; //480+10+2
parameter vMax = 525; //480+10+2+33
*/
//------------------------------------------
//v_sync counter & generator
always@(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0)
hcounter <= 12'd0;
else if(hcounter < hMax - 12'd1) //line over
hcounter <= hcounter + 12'd1;
else
hcounter <= 12'd0;
end
always@(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0)
vcounter <= 12'd0;
else if(hcounter == hMax - 12'd1) begin
if(vcounter < vMax - 12'd1) //frame over
vcounter <= vcounter + 12'd1;
else
vcounter <= 12'd0;
end
end
always@(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0)
begin colour <= `C_BLACK;end
else if (hcounter <= hVisible/5) begin colour <= `C_RED; end
else if(hcounter <= 2*hVisible/5) begin colour <= `C_GREEN; end
else if(hcounter <= 3*hVisible/5) begin colour <= `C_BLUE; end
else if(hcounter <= 4*hVisible/5) begin colour <= `C_WHITE; end
else begin colour <= `C_BLACK; end
end
/*
assign r = colour[23:16];
assign g = colour[15:8];
assign b = colour[7:0];
*/
reg [7:0]VGA_R_reg;
reg [7:0]VGA_G_reg;
reg [7:0]VGA_B_reg;
reg [10:0] dis_mode;
always @(posedge clk) begin
if((vcounter == vMax - 12'd1)&&(hcounter == hMax - 12'd1))
dis_mode <= dis_mode +1'b1;
end
reg[7:0] grid_data_1;
reg[7:0] grid_data_2;
always @(posedge clk) //格子图像
begin
if((hcounter[4]==1'b1)^(vcounter[4]==1'b1))
grid_data_1 <= 8'h00;
else
grid_data_1 <= 8'hff;
if((hcounter[6]==1'b1)^(vcounter[6]==1'b1))
grid_data_2 <= 8'h00;
else
grid_data_2 <= 8'hff;
end
reg[23:0] color_bar;
always @(posedge clk)
begin
if(hcounter==260)
color_bar <= 24'hff0000;
else if(hcounter==420)
color_bar <= 24'h00ff00;
else if(hcounter==580)
color_bar <= 24'h0000ff;
else if(hcounter==740)
color_bar <= 24'hff00ff;
else if(hcounter==900)
color_bar <= 24'hffff00;
else if(hcounter==1060)
color_bar <= 24'h00ffff;
else if(hcounter==1220)
color_bar <= 24'hffffff;
else if(hcounter==1380)
color_bar <= 24'h000000;
else
color_bar <= color_bar;
end
always @(posedge clk)
begin
if(1'b0)
begin
VGA_R_reg<=0;
VGA_G_reg<=0;
VGA_B_reg<=0;
end
else
case(dis_mode[10:7])
4'd0:begin
VGA_R_reg<=0; //LCD显示彩色条
VGA_G_reg<=0;
VGA_B_reg<=0;
end
4'd1:begin
VGA_R_reg<=8'b11111111; //LCD显示全白
VGA_G_reg<=8'b11111111;
VGA_B_reg<=8'b11111111;
end
4'd2:begin
VGA_R_reg<=8'b11111111; //LCD显示全红
VGA_G_reg<=0;
VGA_B_reg<=0;
end
4'd3:begin
VGA_R_reg<=0; //LCD显示全绿
VGA_G_reg<=8'b11111111;
VGA_B_reg<=0;
end
4'd4:begin
VGA_R_reg<=0; //LCD显示全蓝
VGA_G_reg<=0;
VGA_B_reg<=8'b11111111;
end
4'd5:begin
VGA_R_reg<=grid_data_1; // LCD显示方格1
VGA_G_reg<=grid_data_1;
VGA_B_reg<=grid_data_1;
end
4'd6:begin
VGA_R_reg<=grid_data_2; // LCD显示方格2
VGA_G_reg<=grid_data_2;
VGA_B_reg<=grid_data_2;
end
4'd7:begin
VGA_R_reg<=hcounter[7:0]; //LCD显示水平渐变色
VGA_G_reg<=hcounter[7:0];
VGA_B_reg<=hcounter[7:0];
end
4'd8:begin
VGA_R_reg<=vcounter[8:1]; //LCD显示垂直渐变色
VGA_G_reg<=hcounter[8:1];
VGA_B_reg<=hcounter[8:1];
end
4'd9:begin
VGA_R_reg<=hcounter[7:0]; //LCD显示红水平渐变色
VGA_G_reg<=0;
VGA_B_reg<=0;
end
4'd10:begin
VGA_R_reg<=0; //LCD显示绿水平渐变色
VGA_G_reg<=hcounter[7:0];
VGA_B_reg<=0;
end
4'd11:begin
VGA_R_reg<=0; //LCD显示蓝水平渐变色
VGA_G_reg<=0;
VGA_B_reg<=hcounter[7:0];
end
4'd12:begin
VGA_R_reg<=color_bar[23:16]; //LCD显示彩色条
VGA_G_reg<=color_bar[15:8];
VGA_B_reg<=color_bar[7:0];
end
default:begin
VGA_R_reg<=8'b11111111; //LCD显示全白
VGA_G_reg<=8'b11111111;
VGA_B_reg<=8'b11111111;
end
endcase
end
assign hsync = ((hcounter >= (hStartSync - 2'd2))&&(hcounter < (hEndSync - 2'd2)))? 1'b0:1'b1; //Generate the hSync Pulses
assign vsync = ((vcounter >= (vStartSync - 1'b1))&&(vcounter < (vEndSync - 1'b1)))? 1'b0:1'b1; //Generate the vSync Pulses
assign de = (vcounter >= vVisible || hcounter >= hVisible) ? 1'b0 : 1'b1;
assign rgb = {VGA_R_reg,VGA_G_reg,VGA_B_reg};
endmodule
相应的USB3发送模块的代码我们仿照了我们之前写的博客中USB循环测试的代码。usb3_drive模块的代码如下:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website :
// Module Name : usb3_drive.v
// Create Time : 2020-03-03 10:36:21
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module usb3_drive(
input rst_n ,
output wire USBSS_EN ,
input sclk ,
inout [15:0] data ,
inout [ 1:0] be ,
input rxf_n ,
input txf_n ,
output reg oe_n ,
output reg wr_n ,
output wire siwu_n ,
output reg rd_n ,
output wire wakeup ,
output wire [ 1:0] gpio ,
//Communication Interfaces
input [15:0] data_in ,
output wire data_req
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
parameter IDLE = 4'b0001 ;
parameter JUDGE = 4'b0010 ;
parameter READ = 4'b0100 ;
parameter WRITE = 4'b1000 ;
reg [ 3:0] state ;
wire fifo_wr ;
wire [15:0] data_wr ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
assign USBSS_EN = 1'b1;
assign wakeup = 1'b1;
assign siwu_n = 1'b0;
assign gpio = 2'b00;
assign fifo_wr = (rd_n == 1'b0) && (rxf_n == 1'b0);
assign data_wr = (state == READ) ? data : 16'hzzzz;
assign data_req = ~((wr_n == 1'b0) && (txf_n == 1'b0));
assign data = (data_req == 1'b0) ? data_in : 16'hzzzz;
assign be = (state == WRITE) ? 2'b11 : 2'bzz;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
state <= IDLE;
else case(state)
IDLE : state <= JUDGE;
JUDGE : if(rxf_n == 1'b0)
state <= READ;
else if(txf_n == 1'b0)
state <= WRITE;
else
state <= JUDGE;
WRITE : if(txf_n == 1'b1)
state <= JUDGE;
else
state <= WRITE;
READ : if(rxf_n == 1'b1)
state <= JUDGE;
else
state <= READ;
default : state <= IDLE;
endcase
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
oe_n <= 1'b1;
else if(state == READ && rxf_n == 1'b1)
oe_n <= 1'b1;
else if(state == READ)
oe_n <= 1'b0;
else
oe_n <= oe_n;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
rd_n <= 1'b1;
else if(state == READ && rxf_n == 1'b1)
rd_n <= 1'b1;
else if(state == READ && oe_n == 1'b0)
rd_n <= 1'b0;
else
rd_n <= rd_n;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
wr_n <= 1'b1;
else if(state == WRITE && txf_n == 1'b1)
wr_n <= 1'b1;
else if(state == WRITE)
wr_n <= 1'b0;
else
wr_n <= wr_n;
//========================================================================================\
//******************************* Debug **********************************
//========================================================================================/
ila_0 ila_0_inst (
.clk (sclk ), // input wire clk
.probe0 (USBSS_EN ), // input wire [0:0] probe0
.probe1 (data_in ), // input wire [15:0] probe1
.probe2 (2'd1 ), // input wire [1:0] probe2
.probe3 (rxf_n ), // input wire [0:0] probe3
.probe4 (txf_n ), // input wire [0:0] probe4
.probe5 (oe_n ), // input wire [0:0] probe5
.probe6 (wr_n ), // input wire [0:0] probe6
.probe7 (siwu_n ), // input wire [0:0] probe7
.probe8 (rd_n ), // input wire [0:0] probe8
.probe9 (wakeup ), // input wire [0:0] probe9
.probe10 (gpio ) // input wire [1:0] probe10
);
endmodule
接下来我们再给出相应DDR3封装模块的代码如下,ddr3_top模块的代码:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website :
// Module Name : ddr3_top.v
// Create Time : 2020-02-27 23:16:16
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module ddr3_top(
//System Interfaces
input rst_n ,
input locked ,
input clk_200m ,
//DDR3 Interfaces
output wire [13:0] ddr3_addr ,
output wire [ 2:0] ddr3_ba ,
output wire ddr3_cas_n ,
output wire ddr3_ck_n ,
output wire ddr3_ck_p ,
output wire ddr3_cke ,
output wire ddr3_ras_n ,
output wire ddr3_reset_n ,
output wire ddr3_we_n ,
inout [31:0] ddr3_dq ,
inout [ 3:0] ddr3_dqs_n ,
inout [ 3:0] ddr3_dqs_p ,
output wire [ 0:0] ddr3_cs_n ,
output wire [ 3:0] ddr3_dm ,
output wire [ 0:0] ddr3_odt ,
//User Interfaces
output wire init_calib_complete ,
input c3_p0_cmd_clk ,
input c3_p0_cmd_en ,
input [ 6:0] c3_p0_cmd_bl ,
input [27:0] c3_p0_cmd_byte_addr ,
output wire c3_p0_cmd_empty ,
output wire c3_p0_cmd_full ,
input c3_p0_wr_clk ,
input c3_p0_wr_en ,
input [31:0] c3_p0_wr_mask ,
input [255:0] c3_p0_wr_data ,
output wire c3_p0_wr_full ,
output wire c3_p0_wr_empty ,
output wire [10:0] c3_p0_wr_count ,
input c3_p1_cmd_clk ,
input c3_p1_cmd_en ,
input [ 6:0] c3_p1_cmd_bl ,
input [27:0] c3_p1_cmd_byte_addr ,
output wire c3_p1_cmd_empty ,
output wire c3_p1_cmd_full ,
input c3_p1_wr_clk ,
input c3_p1_wr_en ,
input [31:0] c3_p1_wr_mask ,
input [255:0] c3_p1_wr_data ,
output wire c3_p1_wr_full ,
output wire c3_p1_wr_empty ,
output wire [10:0] c3_p1_wr_count ,
input c3_p2_cmd_clk ,
input c3_p2_cmd_en ,
input [ 6:0] c3_p2_cmd_bl ,
input [27:0] c3_p2_cmd_byte_addr ,
output wire c3_p2_cmd_empty ,
output wire c3_p2_cmd_full ,
input c3_p2_rd_clk ,
input c3_p2_rd_en ,
output wire [255:0] c3_p2_rd_data ,
output wire c3_p2_rd_full ,
output wire c3_p2_rd_empty ,
output wire [10:0] c3_p2_rd_count ,
input c3_p3_cmd_clk ,
input c3_p3_cmd_en ,
input [ 6:0] c3_p3_cmd_bl ,
input [27:0] c3_p3_cmd_byte_addr ,
output wire c3_p3_cmd_empty ,
output wire c3_p3_cmd_full ,
input c3_p3_rd_clk ,
input c3_p3_rd_en ,
output wire [255:0] c3_p3_rd_data ,
output wire c3_p3_rd_full ,
output wire c3_p3_rd_empty ,
output wire [10:0] c3_p3_rd_count
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
//mig_7series_0_inst
wire [27:0] app_addr ;
wire [ 2:0] app_cmd ;
wire app_en ;
wire [255:0] app_wdf_data ;
wire app_wdf_end ;
wire 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 ;
wire [31:0] app_wdf_mask ;
wire ui_clk ;
wire ui_clk_sync_rst ;
//a7_wr_ctrl_inst1
wire app_en_wr1 ;
wire [ 3:0] app_cmd_wr1 ;
wire [27:0] app_addr_wr1 ;
wire app_wdf_wren_wr1 ;
wire [255:0] app_wdf_data_wr1 ;
wire [31:0] app_wdf_mask_wr1 ;
wire app_wdf_end_wr1 ;
wire a7_wr_start_wr1 ;
wire [ 6:0] a7_wr_bl_wr1 ;
wire [27:0] a7_wr_init_addr_wr1 ;
wire [255:0] a7_wr_data_wr1 ;
wire [31:0] a7_wr_mask_wr1 ;
wire a7_wr_end_wr1 ;
wire a7_wr_req_wr1 ;
//a7_wr_ctrl_inst2
wire app_en_wr2 ;
wire [ 3:0] app_cmd_wr2 ;
wire [27:0] app_addr_wr2 ;
wire app_wdf_wren_wr2 ;
wire [255:0] app_wdf_data_wr2 ;
wire [31:0] app_wdf_mask_wr2 ;
wire app_wdf_end_wr2 ;
wire a7_wr_start_wr2 ;
wire [ 6:0] a7_wr_bl_wr2 ;
wire [27:0] a7_wr_init_addr_wr2 ;
wire [255:0] a7_wr_data_wr2 ;
wire [31:0] a7_wr_mask_wr2 ;
wire a7_wr_end_wr2 ;
wire a7_wr_req_wr2 ;
//a7_rd_ctrl_inst1
wire app_en_rd1 ;
wire [ 3:0] app_cmd_rd1 ;
wire [27:0] app_addr_rd1 ;
wire app_rd_data_valid_rd1 ;
wire a7_rd_start_rd1 ;
wire [ 6:0] a7_rd_bl_rd1 ;
wire [27:0] a7_rd_init_addr_rd1 ;
wire [255:0] a7_rd_data_rd1 ;
wire a7_rd_data_valid_rd1 ;
wire a7_rd_end_rd1 ;
//a7_rd_ctrl_inst2
wire app_en_rd2 ;
wire [ 3:0] app_cmd_rd2 ;
wire [27:0] app_addr_rd2 ;
wire app_rd_data_valid_rd2 ;
wire a7_rd_start_rd2 ;
wire [ 6:0] a7_rd_bl_rd2 ;
wire [27:0] a7_rd_init_addr_rd2 ;
wire [255:0] a7_rd_data_rd2 ;
wire a7_rd_data_valid_rd2 ;
wire a7_rd_end_rd2 ;
//arbit_inst
//wire c3_p0_cmd_empty ;
//wire c3_p1_cmd_empty ;
//wire c3_p2_cmd_empty ;
//wire c3_p3_cmd_empty ;
//rst delay
reg [ 5:0] rst_cnt ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
always @(posedge clk_200m or negedge rst_n)
if(rst_n == 1'b0)
rst_cnt <= 6'b0;
else if(locked == 1'b0)
rst_cnt <= 6'b0;
else if(rst_cnt[5] == 1'b0)
rst_cnt <= rst_cnt + 1'b1;
mig_7series_0 mig_7series_0_inst (
// Memory interface ports
.ddr3_addr (ddr3_addr ), // output [13: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 [27: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
.app_wdf_rdy (app_wdf_rdy ), // output app_wdf_rdy
.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 (ui_clk ), // output ui_clk
.ui_clk_sync_rst (ui_clk_sync_rst ), // output ui_clk_sync_rst
.app_wdf_mask (app_wdf_mask ), // input [31:0] app_wdf_mask
// System Clock Ports
.sys_clk_i (clk_200m ),
.sys_rst (locked ) // input sys_rst
);
arbit arbit_inst(
//System Interfaces
.rst_n (init_calib_complete ),
//DDR3 Interfaces
.ui_clk (ui_clk ),
.app_addr (app_addr ),
.app_cmd (app_cmd ),
.app_en (app_en ),
.app_wdf_data (app_wdf_data ),
.app_wdf_end (app_wdf_end ),
.app_wdf_wren (app_wdf_wren ),
.app_rd_data_valid (app_rd_data_valid ),
.app_wdf_mask (app_wdf_mask ),
//a7_wr_ctrl_inst1
.app_en_wr1 (app_en_wr1 ),
.app_cmd_wr1 (app_cmd_wr1 ),
.app_addr_wr1 (app_addr_wr1 ),
.app_wdf_wren_wr1 (app_wdf_wren_wr1 ),
.app_wdf_data_wr1 (app_wdf_data_wr1 ),
.app_wdf_mask_wr1 (app_wdf_mask_wr1 ),
.app_wdf_end_wr1 (app_wdf_end_wr1 ),
.a7_wr_start_w1 (a7_wr_start_wr1 ),
.a7_wr_end_wr1 (a7_wr_end_wr1 ),
.c3_p0_cmd_empty (c3_p0_cmd_empty ),
//a7_wr_ctrl_inst1
.app_en_wr2 (app_en_wr2 ),
.app_cmd_wr2 (app_cmd_wr2 ),
.app_addr_wr2 (app_addr_wr2 ),
.app_wdf_wren_wr2 (app_wdf_wren_wr2 ),
.app_wdf_data_wr2 (app_wdf_data_wr2 ),
.app_wdf_mask_wr2 (app_wdf_mask_wr2 ),
.app_wdf_end_wr2 (app_wdf_end_wr2 ),
.a7_wr_start_w2 (a7_wr_start_wr2 ),
.a7_wr_end_wr2 (a7_wr_end_wr2 ),
.c3_p1_cmd_empty (c3_p1_cmd_empty ),
//a7_rd_ctrl_inst1
.app_en_rd1 (app_en_rd1 ),
.app_cmd_rd1 (app_cmd_rd1 ),
.app_addr_rd1 (app_addr_rd1 ),
.app_rd_data_valid_rd1 (app_rd_data_valid_rd1 ),
.a7_rd_start_rd1 (a7_rd_start_rd1 ),
.a7_rd_end_rd1 (a7_rd_end_rd1 ),
.c3_p2_cmd_empty (c3_p2_cmd_empty ),
//a7_rd_ctrl_inst2
.app_en_rd2 (app_en_rd2 ),
.app_cmd_rd2 (app_cmd_rd2 ),
.app_addr_rd2 (app_addr_rd2 ),
.app_rd_data_valid_rd2 (app_rd_data_valid_rd2 ),
.a7_rd_start_rd2 (a7_rd_start_rd2 ),
.a7_rd_end_rd2 (a7_rd_end_rd2 ),
.c3_p3_cmd_empty (c3_p3_cmd_empty )
);
a7_wr_ctrl a7_wr_ctrl_inst1(
//System Interfaces
.rst_n (init_calib_complete ),
//DDR3 Interfaces
.ui_clk (ui_clk ),
.app_rdy (app_rdy ),
.app_wdf_rdy (app_wdf_rdy ),
.app_en (app_en_wr1 ),
.app_cmd (app_cmd_wr1 ),
.app_addr (app_addr_wr1 ),
.app_wdf_wren (app_wdf_wren_wr1 ),
.app_wdf_data (app_wdf_data_wr1 ),
.app_wdf_mask (app_wdf_mask_wr1 ),
.app_wdf_end (app_wdf_end_wr1 ),
//Communication Interfaces
.a7_wr_start (a7_wr_start_wr1 ),
.a7_wr_bl (a7_wr_bl_wr1 ),
.a7_wr_init_addr (a7_wr_init_addr_wr1 ),
.a7_wr_data (a7_wr_data_wr1 ),
.a7_wr_mask (a7_wr_mask_wr1 ),
.a7_wr_end (a7_wr_end_wr1 ),
.a7_wr_req (a7_wr_req_wr1 )
);
fifo_generator_0 cmd_wr1_fifo (
.rst (~init_calib_complete ), // input wire rst
.wr_clk (c3_p0_cmd_clk ), // input wire wr_clk
.rd_clk (ui_clk ), // input wire rd_clk
.din ({c3_p0_cmd_bl,c3_p0_cmd_byte_addr}), // input wire [38 : 0] din
.wr_en (c3_p0_cmd_en ), // input wire wr_en
.rd_en (a7_wr_start_wr1 ), // input wire rd_en
.dout ({a7_wr_bl_wr1,a7_wr_init_addr_wr1}), // output wire [38 : 0] dout
.full (c3_p0_cmd_full ), // output wire full
.empty (c3_p0_cmd_empty )
);
fifo_generator_1 data_wr1_fifo (
.rst (~init_calib_complete ), // input wire rst
.wr_clk (c3_p0_wr_clk ), // input wire wr_clk
.rd_clk (ui_clk ), // input wire rd_clk
.din ({c3_p0_wr_mask,c3_p0_wr_data} ), // input wire [287 : 0] din
.wr_en (c3_p0_wr_en ), // input wire wr_en
.rd_en (a7_wr_req_wr1 ), // input wire rd_en
.dout ({a7_wr_mask_wr1,a7_wr_data_wr1}), // output wire [287 : 0] dout
.full (c3_p0_wr_full ), // output wire full
.empty (c3_p0_wr_empty ), // output wire empty
.wr_data_count (c3_p0_wr_count ) // output wire [10 : 0] wr_data_count
);
a7_wr_ctrl a7_wr_ctrl_inst2(
//System Interfaces
.rst_n (init_calib_complete ),
//DDR3 Interfaces
.ui_clk (ui_clk ),
.app_rdy (app_rdy ),
.app_wdf_rdy (app_wdf_rdy ),
.app_en (app_en_wr2 ),
.app_cmd (app_cmd_wr2 ),
.app_addr (app_addr_wr2 ),
.app_wdf_wren (app_wdf_wren_wr2 ),
.app_wdf_data (app_wdf_data_wr2 ),
.app_wdf_mask (app_wdf_mask_wr2 ),
.app_wdf_end (app_wdf_end_wr2 ),
//Communication Interfaces
.a7_wr_start (a7_wr_start_wr2 ),
.a7_wr_bl (a7_wr_bl_wr2 ),
.a7_wr_init_addr (a7_wr_init_addr_wr2 ),
.a7_wr_data (a7_wr_data_wr2 ),
.a7_wr_mask (a7_wr_mask_wr2 ),
.a7_wr_end (a7_wr_end_wr2 ),
.a7_wr_req (a7_wr_req_wr2 )
);
fifo_generator_0 cmd_wr2_fifo (
.rst (~init_calib_complete ), // input wire rst
.wr_clk (c3_p1_cmd_clk ), // input wire wr_clk
.rd_clk (ui_clk ), // input wire rd_clk
.din ({c3_p1_cmd_bl,c3_p1_cmd_byte_addr}), // input wire [38 : 0] din
.wr_en (c3_p1_cmd_en ), // input wire wr_en
.rd_en (a7_wr_start_wr2 ), // input wire rd_en
.dout ({a7_wr_bl_wr2,a7_wr_init_addr_wr2}), // output wire [38 : 0] dout
.full (c3_p1_cmd_full ), // output wire full
.empty (c3_p1_cmd_empty )
);
fifo_generator_1 data_wr2_fifo (
.rst (~init_calib_complete ), // input wire rst
.wr_clk (c3_p1_wr_clk ), // input wire wr_clk
.rd_clk (ui_clk ), // input wire rd_clk
.din ({c3_p1_wr_mask,c3_p1_wr_data} ), // input wire [287 : 0] din
.wr_en (c3_p1_wr_en ), // input wire wr_en
.rd_en (a7_wr_req_wr2 ), // input wire rd_en
.dout ({a7_wr_mask_wr2,a7_wr_data_wr2}), // output wire [287 : 0] dout
.full (c3_p1_wr_full ), // output wire full
.empty (c3_p1_wr_empty ), // output wire empty
.wr_data_count (c3_p1_wr_count ) // output wire [10 : 0] wr_data_count
);
a7_rd_ctrl a7_rd_ctrl_inst1(
//System Interfaces
.rst_n (init_calib_complete ),
//DDR3 Interfaces
.ui_clk (ui_clk ),
.app_en (app_en_rd1 ),
.app_cmd (app_cmd_rd1 ),
.app_addr (app_addr_rd1 ),
.app_rd_data (app_rd_data ),
.app_rd_data_valid (app_rd_data_valid_rd1 ),
.app_rdy (app_rdy ),
//Communication Interfaces
.a7_rd_start (a7_rd_start_rd1 ),
.a7_rd_bl (a7_rd_bl_rd1 ),
.a7_rd_init_addr (a7_rd_init_addr_rd1 ),
.a7_rd_data (a7_rd_data_rd1 ),
.a7_rd_data_valid (a7_rd_data_valid_rd1 ),
.a7_rd_end (a7_rd_end_rd1 )
);
fifo_generator_0 cmd_rd1_fifo (
.rst (~rst_cnt[5] ), // input wire rst
.wr_clk (c3_p2_cmd_clk ), // input wire wr_clk
.rd_clk (ui_clk ), // input wire rd_clk
.din ({c3_p2_cmd_bl,c3_p2_cmd_byte_addr}), // input wire [38 : 0] din
.wr_en (c3_p2_cmd_en ), // input wire wr_en
.rd_en (a7_rd_start_rd1 ), // input wire rd_en
.dout ({a7_rd_bl_rd1,a7_rd_init_addr_rd1}), // output wire [38 : 0] dout
.full (c3_p2_cmd_full ), // output wire full
.empty (c3_p2_cmd_empty )
);
fifo_generator_2 data_rd1_fifo (
.rst (~rst_cnt[5] ), // input wire rst
.wr_clk (ui_clk ), // input wire wr_clk
.rd_clk (c3_p2_rd_clk ), // input wire rd_clk
.din (a7_rd_data_rd1 ), // input wire [255 : 0] din
.wr_en (a7_rd_data_valid_rd1 ), // input wire wr_en
.rd_en (c3_p2_rd_en ), // input wire rd_en
.dout (c3_p2_rd_data ), // output wire [255 : 0] dout
.full (c3_p2_rd_full ), // output wire full
.empty (c3_p2_rd_empty ), // output wire empty
.rd_data_count (c3_p2_rd_count ) // output wire [10 : 0] rd_data_count
);
a7_rd_ctrl a7_rd_ctrl_inst2(
//System Interfaces
.rst_n (init_calib_complete ),
//DDR3 Interfaces
.ui_clk (ui_clk ),
.app_en (app_en_rd2 ),
.app_cmd (app_cmd_rd2 ),
.app_addr (app_addr_rd2 ),
.app_rd_data (app_rd_data ),
.app_rd_data_valid (app_rd_data_valid_rd2 ),
.app_rdy (app_rdy ),
//Communication Interfaces
.a7_rd_start (a7_rd_start_rd2 ),
.a7_rd_bl (a7_rd_bl_rd2 ),
.a7_rd_init_addr (a7_rd_init_addr_rd2 ),
.a7_rd_data (a7_rd_data_rd2 ),
.a7_rd_data_valid (a7_rd_data_valid_rd2 ),
.a7_rd_end (a7_rd_end_rd2 )
);
fifo_generator_0 cmd_rd2_fifo (
.rst (~rst_cnt[5] ), // input wire rst
.wr_clk (c3_p3_cmd_clk ), // input wire wr_clk
.rd_clk (ui_clk ), // input wire rd_clk
.din ({c3_p3_cmd_bl,c3_p3_cmd_byte_addr}), // input wire [38 : 0] din
.wr_en (c3_p3_cmd_en ), // input wire wr_en
.rd_en (a7_rd_start_rd2 ), // input wire rd_en
.dout ({a7_rd_bl_rd2,a7_rd_init_addr_rd2}), // output wire [38 : 0] dout
.full (c3_p3_cmd_full ), // output wire full
.empty (c3_p3_cmd_empty )
);
fifo_generator_2 data_rd2_fifo (
.rst (~rst_cnt[5] ), // input wire rst
.wr_clk (ui_clk ), // input wire wr_clk
.rd_clk (c3_p3_rd_clk ), // input wire rd_clk
.din (a7_rd_data_rd2 ), // input wire [255 : 0] din
.wr_en (a7_rd_data_valid_rd2 ), // input wire wr_en
.rd_en (c3_p3_rd_en ), // input wire rd_en
.dout (c3_p3_rd_data ), // output wire [255 : 0] dout
.full (c3_p3_rd_full ), // output wire full
.empty (c3_p3_rd_empty ), // output wire empty
.rd_data_count (c3_p3_rd_count ) // output wire [10 : 0] rd_data_count
);
endmodule
arbit模块的代码:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2020/03/01 15:17:14
// Design Name:
// Module Name: arbit
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module arbit(
//System Interfaces
input rst_n ,
//DDR3 Interfaces
input ui_clk ,
output reg [27:0] app_addr ,
output reg [ 2:0] app_cmd ,
output reg app_en ,
output reg [255:0] app_wdf_data ,
output reg app_wdf_end ,
output reg app_wdf_wren ,
input app_rd_data_valid ,
output reg [31:0] app_wdf_mask ,
//a7_wr_ctrl_inst1
input app_en_wr1 ,
input [ 3:0] app_cmd_wr1 ,
input [27:0] app_addr_wr1 ,
input app_wdf_wren_wr1 ,
input [255:0] app_wdf_data_wr1 ,
input [31:0] app_wdf_mask_wr1 ,
input app_wdf_end_wr1 ,
output reg a7_wr_start_w1 ,
input a7_wr_end_wr1 ,
input c3_p0_cmd_empty ,
//a7_wr_ctrl_inst1
input app_en_wr2 ,
input [ 3:0] app_cmd_wr2 ,
input [27:0] app_addr_wr2 ,
input app_wdf_wren_wr2 ,
input [255:0] app_wdf_data_wr2 ,
input [31:0] app_wdf_mask_wr2 ,
input app_wdf_end_wr2 ,
output reg a7_wr_start_w2 ,
input a7_wr_end_wr2 ,
input c3_p1_cmd_empty ,
//a7_rd_ctrl_inst1
input app_en_rd1 ,
input [ 3:0] app_cmd_rd1 ,
input [27:0] app_addr_rd1 ,
output reg app_rd_data_valid_rd1 ,
output reg a7_rd_start_rd1 ,
input a7_rd_end_rd1 ,
input c3_p2_cmd_empty ,
//a7_rd_ctrl_inst2
input app_en_rd2 ,
input [ 3:0] app_cmd_rd2 ,
input [27:0] app_addr_rd2 ,
output reg app_rd_data_valid_rd2 ,
output reg a7_rd_start_rd2 ,
input a7_rd_end_rd2 ,
input c3_p3_cmd_empty
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
parameter IDLE = 6'b000001 ;
parameter ARBIT = 6'b000010 ;
parameter WR1 = 6'b000100 ;
parameter WR2 = 6'b001000 ;
parameter RD1 = 6'b010000 ;
parameter RD2 = 6'b100000 ;
reg [ 5:0] state ;
reg [ 2:0] rand_cnt ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
rand_cnt <= 3'd0;
else if(rand_cnt == 3'd3)
rand_cnt <= 3'd0;
else
rand_cnt <= rand_cnt + 1'b1;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
state <= IDLE;
else case(state)
IDLE : state <= ARBIT;
ARBIT : if(c3_p0_cmd_empty == 1'b0 && rand_cnt == 3'd0)
state <= WR1;
else if(c3_p1_cmd_empty == 1'b0 && rand_cnt == 3'd1)
state <= WR2;
else if(c3_p2_cmd_empty == 1'b0 && rand_cnt == 3'd2)
state <= RD1;
else if(c3_p3_cmd_empty == 1'b0 && rand_cnt == 3'd3)
state <= RD2;
else
state <= state;
WR1 : if(a7_wr_end_wr1 == 1'b1)
state <= ARBIT;
else
state <= state;
WR2 : if(a7_wr_end_wr2 == 1'b1)
state <= ARBIT;
else
state <= state;
RD1 : if(a7_rd_end_rd1 == 1'b1)
state <= ARBIT;
else
state <= state;
RD2 : if(a7_rd_end_rd2 == 1'b1)
state <= ARBIT;
else
state <= state;
default : state <= IDLE;
endcase
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
a7_wr_start_w1 <= 1'b0;
else if(state == ARBIT && c3_p0_cmd_empty == 1'b0 && rand_cnt == 3'd0)
a7_wr_start_w1 <= 1'b1;
else
a7_wr_start_w1 <= 1'b0;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
a7_wr_start_w2 <= 1'b0;
else if(state == ARBIT && c3_p1_cmd_empty == 1'b0 && rand_cnt == 3'd1)
a7_wr_start_w2 <= 1'b1;
else
a7_wr_start_w2 <= 1'b0;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
a7_rd_start_rd1 <= 1'b0;
else if(state == ARBIT && c3_p2_cmd_empty == 1'b0 && rand_cnt == 3'd2)
a7_rd_start_rd1 <= 1'b1;
else
a7_rd_start_rd1 <= 1'b0;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
a7_rd_start_rd2 <= 1'b0;
else if(state == ARBIT && c3_p3_cmd_empty == 1'b0 && rand_cnt == 3'd3)
a7_rd_start_rd2 <= 1'b1;
else
a7_rd_start_rd2 <= 1'b0;
always @(*)
case(state)
WR1 : begin
app_addr = app_addr_wr1;
app_cmd = app_cmd_wr1;
app_en = app_en_wr1;
app_wdf_data = app_wdf_data_wr1;
app_wdf_end = app_wdf_end_wr1;
app_wdf_wren = app_wdf_wren_wr1;
app_wdf_mask = app_wdf_mask_wr1;
end
WR2 : begin
app_addr = app_addr_wr2;
app_cmd = app_cmd_wr2;
app_en = app_en_wr2;
app_wdf_data = app_wdf_data_wr2;
app_wdf_end = app_wdf_end_wr2;
app_wdf_wren = app_wdf_wren_wr2;
app_wdf_mask = app_wdf_mask_wr2;
end
RD1 : begin
app_addr = app_addr_rd1;
app_cmd = app_cmd_rd1;
app_en = app_en_rd1;
app_rd_data_valid_rd1 = app_rd_data_valid;
end
RD2 : begin
app_addr = app_addr_rd2;
app_cmd = app_cmd_rd2;
app_en = app_en_rd2;
app_rd_data_valid_rd2 = app_rd_data_valid;
end
default : begin
app_addr = 28'd0;
app_cmd = 3'd0;
app_en = 1'b0;
app_wdf_data = 256'd0;
app_wdf_end = 1'b0;
app_wdf_wren = 1'b0;
app_rd_data_valid_rd1 = 1'b0;
app_rd_data_valid_rd2 = 1'b0;
app_wdf_mask = 32'd0;
end
endcase
endmodule
a7_wr_ctrl模块的代码:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website :
// Module Name : a7_wr_ctrl.v
// Create Time : 2020-02-29 22:19:50
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module a7_wr_ctrl(
//System Interfaces
input rst_n ,
//DDR3 Interfaces
input ui_clk ,
input app_rdy ,
input app_wdf_rdy ,
output wire app_en ,
output wire [ 3:0] app_cmd ,
output reg [27:0] app_addr ,
output wire app_wdf_wren ,
output wire [255:0] app_wdf_data ,
output wire [31:0] app_wdf_mask ,
output wire app_wdf_end ,
//Communication Interfaces
input a7_wr_start ,
input [ 6:0] a7_wr_bl ,
input [27:0] a7_wr_init_addr ,
input [255:0] a7_wr_data ,
input [31:0] a7_wr_mask ,
output reg a7_wr_end ,
output wire a7_wr_req
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
reg [ 6:0] wr_bl ;
reg wr_flag ;
reg [ 6:0] bl_cnt ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
assign app_en = wr_flag && app_rdy && app_wdf_rdy;
assign app_wdf_end = app_en;
assign app_wdf_wren = app_en;
assign app_wdf_data = a7_wr_data;
assign a7_wr_req = app_en;
assign app_wdf_mask = a7_wr_mask;
assign app_cmd = 3'd0;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
wr_flag <= 1'b0;
else if(bl_cnt == wr_bl && app_en == 1'b1)
wr_flag <= 1'b0;
else if(a7_wr_start == 1'b1)
wr_flag <= 1'b1;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
wr_bl <= 7'd0;
else if(a7_wr_start == 1'b1)
wr_bl <= a7_wr_bl;
else
wr_bl <= wr_bl;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
app_addr <= 28'd0;
else if(a7_wr_start == 1'b1)
app_addr <= a7_wr_init_addr;
else if(app_en == 1'b1)
app_addr <= app_addr + 8;
else
app_addr <= app_addr;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
bl_cnt <= 7'd0;
else if(bl_cnt == wr_bl && app_en == 1'b1 && wr_flag == 1'b1)
bl_cnt <= 7'd0;
else if(wr_flag == 1'b1 && app_en == 1'b1)
bl_cnt <= bl_cnt + 1'b1;
else
bl_cnt <= bl_cnt;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
a7_wr_end <= 1'b0;
else if(bl_cnt == wr_bl && app_en == 1'b1)
a7_wr_end <= 1'b1;
else
a7_wr_end <= 1'b0;
endmodule
a7_rd_ctrl模块的代码:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website :
// Module Name : a7_rd_ctrl.v
// Create Time : 2020-03-01 14:32:05
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module a7_rd_ctrl(
//System Interfaces
input rst_n ,
//DDR3 Interfaces
input ui_clk ,
output reg app_en ,
output wire [ 3:0] app_cmd ,
output reg [27:0] app_addr ,
input [255:0] app_rd_data ,
input app_rd_data_valid ,
input app_rdy ,
//Communication Interfaces
input a7_rd_start ,
input [ 6:0] a7_rd_bl ,
input [27:0] a7_rd_init_addr ,
output reg [255:0] a7_rd_data ,
output reg a7_rd_data_valid ,
output reg a7_rd_end
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
reg [ 6:0] rd_bl ;
reg [ 6:0] cmd_cnt ;
reg rd_flag ;
reg [ 6:0] data_cnt ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
assign app_cmd = 3'd1;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
rd_bl <= 7'd0;
else if(a7_rd_start == 1'b1)
rd_bl <= a7_rd_bl;
else
rd_bl <= a7_rd_bl;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
app_en <= 1'b0;
else if(a7_rd_start == 1'b1)
app_en <= 1'b1;
else if(cmd_cnt == rd_bl && app_rdy == 1'b1)
app_en <= 1'b0;
else
app_en <= app_en;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
cmd_cnt <= 7'd0;
else if(rd_flag == 1'b1 && cmd_cnt == rd_bl && app_rdy == 1'b1)
cmd_cnt <= 7'd0;
else if(rd_flag == 1'b1 && app_rdy == 1'b1 && app_en == 1'b1)
cmd_cnt <= cmd_cnt + 1'b1;
else
cmd_cnt <= cmd_cnt;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
rd_flag <= 1'b0;
else if(a7_rd_start == 1'b1)
rd_flag <= 1'b1;
else if(data_cnt == rd_bl && app_rd_data_valid == 1'b1)
rd_flag <= 1'b0;
else
rd_flag <= rd_flag;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
app_addr <= 28'd0;
else if(a7_rd_start == 1'b1)
app_addr <= a7_rd_init_addr;
else if(app_en == 1'b1 && app_rdy == 1'b1)
app_addr <= app_addr + 8;
else
app_addr <= app_addr;
always @(posedge ui_clk)
a7_rd_data <= app_rd_data;
always @(posedge ui_clk)
a7_rd_data_valid <= app_rd_data_valid;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
a7_rd_end <= 1'b0;
else if(data_cnt == rd_bl && app_rd_data_valid == 1'b1)
a7_rd_end <= 1'b1;
else
a7_rd_end <= 1'b0;
always @(posedge ui_clk or negedge rst_n)
if(rst_n == 1'b0)
data_cnt <= 7'd0;
else if(data_cnt == rd_bl && rd_flag == 1'b1 && app_rd_data_valid == 1'b1)
data_cnt <= 7'd0;
else if(rd_flag == 1'b1 && app_rd_data_valid == 1'b1)
data_cnt <= data_cnt + 1'b1;
else
data_cnt <= data_cnt;
endmodule
其余程序中,我们还用到一些异步FIFO,这些异步FIFO使用的时候自己添加上即可,当然也可以进群下载代码,自我学习。
项目测试模块代码
我们这里也给出相应项目的测试代码,但是相应的测试结果不再给出,因为看不出来神秘结果,当然要想看出来结果,可以将图像数据改成递增数。
`timescale 1ns / 1ps
`define CLOCK 20
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website :
// Module Name : tb_ddr3.v
// Create Time : 2020-02-27 23:36:46
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module tb_ddr3;
parameter DQ_WIDTH = 32;
localparam MEMORY_WIDTH = 16;
localparam NUM_COMP = DQ_WIDTH/MEMORY_WIDTH ;
reg sclk ;
reg rst_n ;
wire [13:0] ddr3_addr ;
wire [ 2:0] ddr3_ba ;
wire ddr3_cas_n ;
wire ddr3_ck_n ;
wire ddr3_ck_p ;
wire ddr3_cke ;
wire ddr3_ras_n ;
wire ddr3_reset_n ;
wire ddr3_we_n ;
wire [31:0] ddr3_dq ;
wire [ 3:0] ddr3_dqs_n ;
wire [ 3:0] ddr3_dqs_p ;
wire init_calib_complete ;
wire [ 0:0] ddr3_cs_n ;
wire [ 3:0] ddr3_dm ;
wire [ 0:0] ddr3_odt ;
reg test_start ;
reg USB_clk ;
reg txf_n ;
reg [31:0] check_data ;
reg flag_req ;
reg [63:0] err_cnt ;
wire [15:0] data ;
initial begin
sclk = 1'b0;
rst_n <= 1'b0;
test_start <= 1'b0;
#(100*`CLOCK);
rst_n <= 1'b1;
// @(posedge top_inst.ddr3_top_inst.init_calib_complete)
// #(100*`CLOCK);
// test_start <= 1'b1;
// #(15)
// test_start <= 1'b0;
// #(200000)
// test_start <= 1'b1;
// #(15)
// test_start <= 1'b0;
end
always #(`CLOCK/2) sclk = ~sclk;
initial begin
USB_clk = 1'b0;
end
always #(10/2) USB_clk = ~USB_clk;
initial begin
txf_n <= 1'b1;
#(4000000);
txf_n <= 1'b0;
end
always @(posedge USB_clk)
if(top_inst.init_calib_complete == 1'b0)
check_data <= 32'd0;
else if(top_inst.data_req == 1'b0 && flag_req == 1'b1)
check_data <= check_data + 1'b1;
always @(posedge USB_clk)
if(top_inst.init_calib_complete == 1'b0)
flag_req <= 1'b0;
else if(top_inst.data_req == 1'b0)
flag_req <= ~flag_req;
always @(posedge USB_clk)
if(top_inst.init_calib_complete == 1'b0)
err_cnt <= 64'd0;
else if(check_data[31:16] != data && flag_req == 1'b0 && top_inst.data_req == 1'b0)
err_cnt <= err_cnt + 1'b1;
else if(check_data[15:0] != data && flag_req == 1'b1 && top_inst.data_req == 1'b0)
err_cnt <= err_cnt + 1'b1;
else
err_cnt <= err_cnt;
top top_inst(
//System Interfaces
.sclk (sclk ),
.rst_n (rst_n ),
//DDR3 Interfaces
.ddr3_addr (ddr3_addr ),
.ddr3_ba (ddr3_ba ),
.ddr3_cas_n (ddr3_cas_n ),
.ddr3_ck_n (ddr3_ck_n ),
.ddr3_ck_p (ddr3_ck_p ),
.ddr3_cke (ddr3_cke ),
.ddr3_ras_n (ddr3_ras_n ),
.ddr3_reset_n (ddr3_reset_n ),
.ddr3_we_n (ddr3_we_n ),
.ddr3_dq (ddr3_dq ),
.ddr3_dqs_n (ddr3_dqs_n ),
.ddr3_dqs_p (ddr3_dqs_p ),
.ddr3_cs_n (ddr3_cs_n ),
.ddr3_dm (ddr3_dm ),
.ddr3_odt (ddr3_odt ),
.USBSS_EN ( ),
.USB_clk (USB_clk ),
.data (data ),
.be ( ),
.rxf_n (1'b1 ),
.txf_n (txf_n ),
.oe_n ( ),
.wr_n ( ),
.siwu_n ( ),
.rd_n ( ),
.wakeup ( ),
.gpio ( )
);
genvar i;
for (i = 0; i < NUM_COMP; i = i + 1) begin: gen_mem
ddr3_model u_comp_ddr3(
.rst_n (ddr3_reset_n ),
.ck (ddr3_ck_p ),
.ck_n (ddr3_ck_n ),
.cke (ddr3_cke ),
.cs_n (ddr3_cs_n ),
.ras_n (ddr3_ras_n ),
.cas_n (ddr3_cas_n ),
.we_n (ddr3_we_n ),
.dm_tdqs (ddr3_dm[(2*(i+1)-1):(2*i)] ),
.ba (ddr3_ba ),
.addr (ddr3_addr ),
.dq (ddr3_dq[16*(i+1)-1:16*(i)] ),
.dqs (ddr3_dqs_p[(2*(i+1)-1):(2*i)] ),
.dqs_n (ddr3_dqs_n[(2*(i+1)-1):(2*i)] ),
.tdqs_n ( ),
.odt (ddr3_odt )
);
end
endmodule
上面还缺少相应的仿真模型、参数化文件,为了简洁性不再给出,可以自己从DDR3的示例工程中获得,当然也可以进群自取。
下板结果
这里我们用了米联客的上位机,因为自己写上位机又得重新学习。结果如下:
从上面两张图形中可以证明我们逻辑书写的正确性。
总结
创作不易,认为文章有帮助的同学们可以关注、点赞、转发支持。(工程也都在群中)对文章有什么看法或者需要更近一步交流的同学,可以加入下面的群: