DDR-MIG 学习记录

news2024/12/27 10:55:42

MIG调试总结:

       对vivado软件中用于控制DDR2 / DDR3 的 控制器MIG(Memory Interface Generator)IP核进行了仿真测试,以学习如何用IP核来控制FPGA板载SDRAM的读写。我们只需要学会MIG的接口控制就可以。

       ①配置IP核

Xilinx 的 DDR 控制器的名称简写为 MIG(Memory Interface Generator),在 Vivado 左侧窗口点击 IP Catalog,然后在 IP Catalog 窗口直接搜索关键字“mig”,就可以很容易的找到

MIG IP核有user interface 和 AXI4 interface两种接口以供选择,我们可以选择熟悉的接口来控制MIG。这里我选择用user interface。

创建完IP核后,可以通过观察它的仿真模型的波形来学习控制信号的设计,vivado提供的仿真例子从下图中打开:

       打开后会创建一个新的工程文件,找到该工程便可直接进行simulation,进行波形的观察。

为了进行逻辑设计,先打开ip的例化模板(instance module),查看它的IO口,以确定需要设计哪些信号(不要关注太多信号,容易懵,看与所需功能相关的就好);或者直接打开此IP核的user guide,查看它的接口和对应注释,如下:

根据仿真波形的观察和user guide的注释,确定input的作用和output的时序,进行总结:

①根据mig IP的user interface 的output 反馈:

ui_clk : 此UI时钟必须是DRAM时钟的一半或四分之一。(用来设计读写逻辑

ui_clk_sync_rst : This is the active-High UI reset.(有用,1-指示用户逻辑复位

       init_calib_complete : PHY在校准完成(初始化ddr3完成,(要用,指示可以开始读写了))

       app_rdy : 1 - UI可以接收命令 (要用)

       app_rd_data : 读取的数据 (要用)

       app_rd_data_valid : 高电平时表示读出的数据有效 (要用)

       app_wdf_rdy : 该输出表示写入数据FIFO已准备好接收数据。当app_wdf_rdy=1'b1和app_wdf_wren=1'b1时,接受写入数据 (要用)

       app_sr_active : 此输出是保留的。(暂时不用

app_rd_data_end : 暂时不知道是否要用到,看波形一直为1,注释也不太清楚(暂时不用

       app_ref_ack : 1-表示内存控制器已将请求的刷新命令发送到PHY接口(暂时不用

       app_zq_ack : 1-指示存储器控制器已将所请求的ZQ校准命令发送到PHY接口。(暂时不用

app_ecc_multiple_err[7:0] : This signal should only be used when ECC is enabled 当ECC被启用并且与app_rd_data_valid一起有效时,该信号适用。如果来自外部存储器的读取数据在读取突发的每个节拍具有两个比特错误,则app_ecc_multiple_err[3:0]信号为非零。SECDED算法不校正相应的读取数据,并在此信号上设置一个非零值,以通知UI上损坏的读取数据。(暂时不用

app_ecc_single_err[7:0] : 该信号在启用ECC时适用,并且与app_rd_data_vali一起有效。如果来自外部存储器的读取数据在读取突发的每个节拍具有单个比特错误,则app_ecc_single_err信号为非零(暂时不用

②设计mig输入信号:

       app_addr : 当前请求的地址

       app_cmd : 当前请求的命令 :001-读 ; 000 – 写

       app_en : 这是app_addr、app_cmd、app_sz、app_hi_pri信号的选通信;

app_wdf_data : 要写的数据

app_wdf_wren : 选通app_wdf_data ;

app_wdf_end : 该活动的高输入表示当前时钟周期是app_wdf_data[]上输入数据的最后一个周期。从仿真波形上看,与app_adf_wren保持一致即可。

app_hi_pri : 高输入提高当前请求的优先级。简单操作的话应该用不上?(不管,置0)

app_sz : 此输入是保留的,应绑定到0(置0)

app_sr_req : 此输入是保留的,应绑定到0(置0)

app_wdf_mask : 这为app_wdf_data[]提供了掩码(先不管,置0)

app_ref_req :高输入请求向DRAM发出刷新命令。(刷新用的,暂时不用,置0

app_zq_req : 高输入请求向DRAM发出ZQ校准命令 (校准用的,先不用,置0)

app_correct_en_i : 当断言时,该有效的高信号校正单比特数据错误。只有在GUI中启用ECC时,此输入才有效。在示例设计中,该信号总是与1绑定。(校正单比特数据,只有启动ECC时有效,置1即可)

根据以上总结设计控制信号如下:

       memc_en即app_en,其他同理。wr_sig和rd_sig为自己设计的由外部输入的读信号和写信号,根据这两个信号来启动读和写操作。

       app_cmd :000 为写 , 001 为读。

       app_wr_en : 写信号产生且写准备高电平时置高,否则为低。

       app_wr_end : 与app_wr_en一致。

       app_addr : 读信号高时为读地址,否则为写地址。

       app_en : 写状态时:写准备高电平、命令准备高电平时置高;

读状态:命令准备信号高电平时置高。

       设计完控制信号后,完成模块间的连线,然后设计测试模块。

       从vivado提供的测试工程中复制出ddr3仿真模型和wire_delay模块,在test_bench中完成连线,并从例子中复制出对应的逻辑。(testbench最好直接copy测试工程的,然后替换我们设计的控制模块,否则跟我一样仅仅例化了ddr3模块并连线,得到的结果是init_calib_done信号一直没有拉高)。

设计时注意位宽参数的参数传递,确保对应位宽正确;根据资料,DDR3的burst length(突发长度)固定为8,所以我们可能不需要进行模式寄存器的加载?目前还不知怎么用user interface加载模式寄存器。

       输入激励信号进行测试:值得注意的是,每次ddr3读写8个数据,对于mig端来说,意味着读写一个数据,地址位需要改变8(因为mig端数据位宽是ddr3读写位宽的8倍)。

读写时地址位改变小于8会造成重复读写,导致出错(没错就是我)。

仿真结果如下:

可以看到,72没有在wren高电平时写入,所以读出来不是72(而是ddr3原本存的数据)。

结尾:本次测试mig的user interface接口,引入读写信号wr_sig和rd_sig,设计的app逻辑如下:

       结果符合要求。后续根据设计要求,增删wr_sig和rd_sig信号,对上述信号进行逻辑设计即可。

PS:

如果需要查看IP核的user guide,点击下图:

如果跳出网页:

则直接通过前面的网址进入官网,然后搜索最后圈出来的文件即可找到。

//
// Create Date: 2023/11/25 17:44:55
//
`timescale 1ps/1ps
module mig_ctrl #(
    parameter DATA_WIDTH = 64,
    parameter ADDR_WIDTH = 32 
    )
(   //system
    input clk ,
    input rst_n ,    
    input memc_init_done ,
    
    //user
    input wr_sig ,
    input rd_sig ,    
    input [ADDR_WIDTH - 1:0]wr_addr ,
    input [ DATA_WIDTH - 1 : 0]wr_data, 
    input [ADDR_WIDTH - 1:0]rd_addr ,
    
    //cmd
    input memc_cmd_rdy ,
    output wire memc_en ,
    output wire[2:0]app_cmd ,
    output wire[ADDR_WIDTH - 1:0]memc_addr ,
    
    //write
    input memc_wr_rdy ,
    output wire memc_wr_en ,
    output wire memc_wr_end ,
    output wire [ DATA_WIDTH - 1 : 0]memc_wr_data ,
    output wire [ DATA_WIDTH/8 - 1 : 0]memc_wr_mask ,
    
    //read
    input memc_rd_data,
    input memc_rd_valid
    );
 
localparam wr_cmd = 3'b000;
localparam rd_cmd = 3'b001;    

assign memc_en = (app_cmd == wr_cmd)?(memc_init_done && memc_wr_rdy && memc_cmd_rdy ):(memc_cmd_rdy);
assign app_cmd = ((memc_init_done && rd_sig))?rd_cmd:wr_cmd;
assign memc_addr = (memc_init_done && rd_sig)?rd_addr:(wr_sig?wr_addr:0);
assign memc_wr_en = (memc_init_done && memc_wr_rdy && memc_cmd_rdy && wr_sig )?1:0;
assign memc_wr_end = memc_wr_en;
assign memc_wr_mask = 0 ;
assign memc_wr_data = (memc_init_done && memc_wr_rdy && wr_sig)?wr_data:0;
    
endmodule

//
// Create Date: 2023/11/25 20:18:42
//
`timescale 1ps/1ps
module mig_test #(
   //***************************************************************************
   parameter PORT_MODE             = "BI_MODE",
   parameter DATA_MODE             = 4'b0010,
   parameter TST_MEM_INSTR_MODE    = "R_W_INSTR_MODE",
   parameter EYE_TEST              = "FALSE",
   parameter DATA_PATTERN          = "DGEN_ALL",
   parameter CMD_PATTERN           = "CGEN_ALL",
   parameter CMD_WDT               = 'h3FF,
   parameter WR_WDT                = 'h1FFF,
   parameter RD_WDT                = 'h3FF,
   parameter SEL_VICTIM_LINE       = 0,
   parameter BEGIN_ADDRESS         = 32'h00000000,
   parameter END_ADDRESS           = 32'h00ffffff,
   parameter PRBS_EADDR_MASK_POS   = 32'hff000000,
   parameter CK_WIDTH              = 1,
   parameter nCS_PER_RANK          = 1,
   parameter CKE_WIDTH             = 1,
   parameter DM_WIDTH              = 2,
   parameter ODT_WIDTH             = 1,
   parameter BANK_WIDTH            = 3,
   parameter COL_WIDTH             = 10,
   parameter CS_WIDTH              = 1,
   parameter DQ_WIDTH              = 16,
   parameter DQS_WIDTH             = 2,
   parameter DQS_CNT_WIDTH         = 1,
   parameter DRAM_WIDTH            = 8,
   parameter ECC                   = "OFF",
   parameter ECC_TEST              = "OFF",
   //parameter nBANK_MACHS           = 4,
   parameter nBANK_MACHS           = 4,
   parameter RANKS                 = 1,
   parameter ROW_WIDTH             = 14,
   parameter ADDR_WIDTH            = 28,
   parameter BURST_MODE            = "8",
   parameter CLKIN_PERIOD          = 5000,
   parameter CLKFBOUT_MULT         = 4,
   parameter DIVCLK_DIVIDE         = 1,
   parameter CLKOUT0_PHASE         = 0.0,
   parameter CLKOUT0_DIVIDE        = 1,
   parameter CLKOUT1_DIVIDE        = 2,
   parameter CLKOUT2_DIVIDE        = 32,
   parameter CLKOUT3_DIVIDE        = 8,
   parameter MMCM_VCO              = 800,
   parameter MMCM_MULT_F           = 8,
   parameter MMCM_DIVCLK_DIVIDE    = 1,
   parameter SIMULATION            = "FALSE",
   parameter TCQ                   = 100,
   parameter DRAM_TYPE             = "DDR3",
   parameter nCK_PER_CLK           = 4,
   parameter DEBUG_PORT            = "OFF",
   parameter RST_ACT_LOW           = 1
)
(
     // Inouts
   inout [15:0]                         ddr3_dq,
   inout [1:0]                        ddr3_dqs_n,
   inout [1:0]                        ddr3_dqs_p,

   // Outputs
   output [13:0]                       ddr3_addr,
   output [2:0]                      ddr3_ba,
   output                                       ddr3_ras_n,
   output                                       ddr3_cas_n,
   output                                       ddr3_we_n,
   output                                       ddr3_reset_n,
   output [0:0]                        ddr3_ck_p,
   output [0:0]                        ddr3_ck_n,
   output [0:0]                       ddr3_cke,
   output [0:0]                       ddr3_cs_n,
   output [1:0]                        ddr3_dm,
   output [0:0]                       ddr3_odt,

   // Inputs
   // Single-ended system clock
   input wr_sig ,
   input rd_sig ,    
   input [ADDR_WIDTH-1:0] wr_addr ,
   input [APP_DATA_WIDTH-1:0] wr_data , 
   input [ADDR_WIDTH-1:0] rd_addr ,
     
   input                                        sys_clk_i,
   output                                       init_calib_complete,
   output app_en ,
   // System reset - Default polarity of sys_rst pin is Active Low.
   // System reset polarity will change based on the option 
   // selected in GUI.
   input                                        sys_rst
    );
 localparam DATA_WIDTH            = 16;
  localparam PAYLOAD_WIDTH         = (ECC_TEST == "OFF") ? DATA_WIDTH : DQ_WIDTH;
  localparam APP_DATA_WIDTH        = 2 * nCK_PER_CLK * PAYLOAD_WIDTH;
  localparam APP_MASK_WIDTH        = APP_DATA_WIDTH / 8;
  localparam MASK_SIZE             = DATA_WIDTH/8;

  wire [ADDR_WIDTH-1:0]                 app_addr;
  wire [2:0]                            app_cmd;
  //wire                                  app_en;
  wire                                  app_rdy;
  wire [APP_DATA_WIDTH-1:0]             app_rd_data;
  wire                                  app_rd_data_end;
  wire                                  app_rd_data_valid;
  wire [APP_DATA_WIDTH-1:0]             app_wdf_data;
  wire                                  app_wdf_end;
  wire [APP_MASK_WIDTH-1:0]             app_wdf_mask;
  wire                                  app_wdf_rdy;
  wire                                  app_sr_active;
  wire                                  app_ref_ack;
  wire                                  app_zq_ack;
  wire                                  app_wdf_wren;
wire ui_clk ;
wire ui_clk_sync_rst;
    
 mig_16b u_mig_16b (
    // 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 [15:0]		ddr3_dq
    .ddr3_dqs_n                     (ddr3_dqs_n),  // inout [1:0]		ddr3_dqs_n
    .ddr3_dqs_p                     (ddr3_dqs_p),  // inout [1: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 [1: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 [127: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 [127: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                     ('b0),  // input			app_sr_req
    .app_ref_req                    ('b0),  // input			app_ref_req
    .app_zq_req                     ('b0),  // input			app_zq_req
    .app_sr_active                  (app_sr_active),  // output			app_sr_active
    .app_ref_ack                    (app_ref_ack),  // output			app_ref_ack
    .app_zq_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 [15:0]		app_wdf_mask

    // System Clock Ports
    .sys_clk_i                       (sys_clk_i),
    .sys_rst                        (sys_rst) // input sys_rst
    );


mig_ctrl #(
    .DATA_WIDTH(APP_DATA_WIDTH),
    .ADDR_WIDTH(ADDR_WIDTH)
    )
mig_ctrl_inst(   //system
    .clk(ui_clk) ,
    .rst_n(~ui_clk_sync_rst) ,    
    .memc_init_done(init_calib_complete) ,

    .wr_sig(wr_sig) ,
    .rd_sig(rd_sig) ,    
    .wr_addr(wr_addr) ,
    .wr_data(wr_data), 
    .rd_addr(rd_addr) ,


    .memc_cmd_rdy(app_rdy) ,
    .memc_en(app_en) ,
    .app_cmd(app_cmd) ,
    .memc_addr(app_addr) ,


    .memc_wr_rdy(app_wdf_rdy) ,
    .memc_wr_en(app_wdf_wren) ,
    .memc_wr_end(app_wdf_end) ,
    .memc_wr_data(app_wdf_data) ,
    .memc_wr_mask(app_wdf_mask) ,

    .memc_rd_data(app_rd_data),
    .memc_rd_valid(app_rd_data_valid)
    );
    
    
endmodule

`timescale 1ps/100fs
//
// Create Date: 2023/11/26 13:20:38
//


module mig_test_tb(    );

  parameter COL_WIDTH             = 10;
                                     // # of memory Column Address bits.
   parameter CS_WIDTH              = 1;
                                     // # of unique CS outputs to memory.
   parameter DM_WIDTH              = 2;
                                     // # of DM (data mask)
   parameter DQ_WIDTH              = 16;
                                     // # of DQ (data)
   parameter DQS_WIDTH             = 2;
   parameter DQS_CNT_WIDTH         = 1;
                                     // = ceil(log2(DQS_WIDTH))
   parameter DRAM_WIDTH            = 8;
                                     // # of DQ per DQS
   parameter ECC                   = "OFF";
   parameter RANKS                 = 1;
                                     // # of Ranks.
   parameter ODT_WIDTH             = 1;
                                     // # of ODT outputs to memory.
   parameter ROW_WIDTH             = 14;
                                     // # of memory Row Address bits.
   parameter ADDR_WIDTH            = 28;
   parameter CLKIN_PERIOD          = 5000;
  parameter REFCLK_FREQ           = 200.0;
  parameter tCK                   = 2500;
  parameter CA_MIRROR             = "OFF";
  wire                               ddr3_reset_n;
  wire [DQ_WIDTH-1:0]                ddr3_dq_fpga;
  wire [DQS_WIDTH-1:0]               ddr3_dqs_p_fpga;
  wire [DQS_WIDTH-1:0]               ddr3_dqs_n_fpga;
  wire [ROW_WIDTH-1:0]               ddr3_addr_fpga;
  wire [3-1:0]                       ddr3_ba_fpga;
  wire                               ddr3_ras_n_fpga;
  wire                               ddr3_cas_n_fpga;
  wire                               ddr3_we_n_fpga;
  wire [1-1:0]                       ddr3_cke_fpga;
  wire [1-1:0]                       ddr3_ck_p_fpga;
  wire [1-1:0]                       ddr3_ck_n_fpga;
  wire [DQ_WIDTH-1:0]                ddr3_dq_sdram;
  reg [ROW_WIDTH-1:0]                ddr3_addr_sdram [0:1];
  reg [3-1:0]               ddr3_ba_sdram [0:1];
  reg                                ddr3_ras_n_sdram;
  reg                                ddr3_cas_n_sdram;
  reg                                ddr3_we_n_sdram;
  wire [(CS_WIDTH*1)-1:0] ddr3_cs_n_sdram;
  wire [ODT_WIDTH-1:0]               ddr3_odt_sdram;
  reg [1-1:0]                ddr3_cke_sdram;
  wire [DM_WIDTH-1:0]                ddr3_dm_sdram;
  wire [DQS_WIDTH-1:0]               ddr3_dqs_p_sdram;
  wire [DQS_WIDTH-1:0]               ddr3_dqs_n_sdram;
  reg [1-1:0]                 ddr3_ck_p_sdram;
  reg [1-1:0]                 ddr3_ck_n_sdram;  
  reg [ODT_WIDTH-1:0]                ddr3_odt_sdram_tmp;
  wire                               init_calib_complete;
  wire [(CS_WIDTH*1)-1:0] ddr3_cs_n_fpga; 
  wire [DM_WIDTH-1:0]                ddr3_dm_fpga;
  wire [ODT_WIDTH-1:0]               ddr3_odt_fpga;
  
   reg                     sys_clk_i;
   reg sys_rst;
   reg [DM_WIDTH-1:0]                 ddr3_dm_sdram_tmp;
   reg wr_sig ;
   reg rd_sig ;
   reg [ADDR_WIDTH-1:0]wr_addr ;
   reg [127:0]wr_data ;
   reg [ADDR_WIDTH-1:0]rd_addr ;
   reg [(CS_WIDTH*1)-1:0] ddr3_cs_n_sdram_tmp;
     // Local parameters Declarations
  //**************************************************************************//

  localparam real TPROP_DQS          = 0.00;
                                       // Delay for DQS signal during Write Operation
  localparam real TPROP_DQS_RD       = 0.00;
                       // Delay for DQS signal during Read Operation
  localparam real TPROP_PCB_CTRL     = 0.00;
                       // Delay for Address and Ctrl signals
  localparam real TPROP_PCB_DATA     = 0.00;
                       // Delay for data signal during Write operation
  localparam real TPROP_PCB_DATA_RD  = 0.00;
                       // Delay for data signal during Read operation

  localparam MEMORY_WIDTH            = 16;
  localparam NUM_COMP                = DQ_WIDTH/MEMORY_WIDTH;
  localparam ECC_TEST 		   	= "OFF" ;
  localparam ERR_INSERT = (ECC_TEST == "ON") ? "OFF" : ECC ;
  

  localparam real REFCLK_PERIOD = (1000000.0/(2*REFCLK_FREQ));
  localparam RESET_PERIOD = 200000; //in pSec  
  localparam real SYSCLK_PERIOD = tCK;
   
   wire app_en ;
   
mig_test mig_test_inst
(
     // Inouts
   .ddr3_dq(ddr3_dq_fpga),
   .ddr3_dqs_n(ddr3_dqs_n_fpga),
   .ddr3_dqs_p(ddr3_dqs_p_fpga),

   // Outputs
   .ddr3_addr(ddr3_addr_fpga),
   .ddr3_ba(ddr3_ba_fpga),
   .ddr3_ras_n(ddr3_ras_n_fpga),
   .ddr3_cas_n(ddr3_cas_n_fpga),
   .ddr3_we_n(ddr3_we_n_fpga),
   .ddr3_reset_n(ddr3_reset_n),
   .ddr3_ck_p(ddr3_ck_p_fpga),
   .ddr3_ck_n(ddr3_ck_n_fpga),
   .ddr3_cke(ddr3_cke_fpga),
   .ddr3_cs_n(ddr3_cs_n_fpga),
   .ddr3_dm(ddr3_dm_fpga),
   .ddr3_odt(ddr3_odt_fpga),

   // Inputs
   // Single-ended system clock
   .wr_sig(wr_sig) ,
   .rd_sig(rd_sig) ,    
   .wr_addr(wr_addr) ,
   .wr_data(wr_data) , 
   .rd_addr(rd_addr) ,
   
   .sys_clk_i(sys_clk_i),
   .init_calib_complete(init_calib_complete),
   .app_en(app_en),
   // System reset - Default polarity of sys_rst pin is Active Low.
   // System reset polarity will change based on the option 
   // selected in GUI.
   .sys_rst(sys_rst)
    );
  genvar r,i;
  generate
    for (r = 0; r < CS_WIDTH; r = r + 1) begin: mem_rnk
      if(DQ_WIDTH/16) begin: mem
        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_sdram),
             .ck_n    (ddr3_ck_n_sdram),
             .cke     (ddr3_cke_sdram[r]),
             .cs_n    (ddr3_cs_n_sdram[r]),
             .ras_n   (ddr3_ras_n_sdram),
             .cas_n   (ddr3_cas_n_sdram),
             .we_n    (ddr3_we_n_sdram),
             .dm_tdqs (ddr3_dm_sdram[(2*(i+1)-1):(2*i)]),
             .ba      (ddr3_ba_sdram[r]),
             .addr    (ddr3_addr_sdram[r]),
             .dq      (ddr3_dq_sdram[16*(i+1)-1:16*(i)]),
             .dqs     (ddr3_dqs_p_sdram[(2*(i+1)-1):(2*i)]),
             .dqs_n   (ddr3_dqs_n_sdram[(2*(i+1)-1):(2*i)]),
             .tdqs_n  (),
             .odt     (ddr3_odt_sdram[r])
             );
        end
      end
      if (DQ_WIDTH%16) begin: gen_mem_extrabits
        ddr3_model u_comp_ddr3
          (
           .rst_n   (ddr3_reset_n),
           .ck      (ddr3_ck_p_sdram),
           .ck_n    (ddr3_ck_n_sdram),
           .cke     (ddr3_cke_sdram[r]),
           .cs_n    (ddr3_cs_n_sdram[r]),
           .ras_n   (ddr3_ras_n_sdram),
           .cas_n   (ddr3_cas_n_sdram),
           .we_n    (ddr3_we_n_sdram),
           .dm_tdqs ({ddr3_dm_sdram[DM_WIDTH-1],ddr3_dm_sdram[DM_WIDTH-1]}),
           .ba      (ddr3_ba_sdram[r]),
           .addr    (ddr3_addr_sdram[r]),
           .dq      ({ddr3_dq_sdram[DQ_WIDTH-1:(DQ_WIDTH-8)],
                      ddr3_dq_sdram[DQ_WIDTH-1:(DQ_WIDTH-8)]}),
           .dqs     ({ddr3_dqs_p_sdram[DQS_WIDTH-1],
                      ddr3_dqs_p_sdram[DQS_WIDTH-1]}),
           .dqs_n   ({ddr3_dqs_n_sdram[DQS_WIDTH-1],
                      ddr3_dqs_n_sdram[DQS_WIDTH-1]}),
           .tdqs_n  (),
           .odt     (ddr3_odt_sdram[r])
           );
      end
    end
  endgenerate

  initial
    sys_clk_i = 1'b0;
  always
    sys_clk_i = #(CLKIN_PERIOD/2.0) ~sys_clk_i;

  initial begin
    wr_sig = 0 ;
    rd_sig = 0 ;
    wr_addr = 0 ;
    rd_addr = 0 ;
    wr_data = 0 ;
    sys_rst = 0 ;
    #1000;
    sys_rst = 1;
    wait(init_calib_complete);
    wr_sig = 1 ;
    repeat(32)begin
    wait(app_en);
    wr_sig = 1 ;
    wr_addr = wr_addr + 8 ;
    wr_data = wr_data + 8 ;
    #10000;
    wr_sig = 0 ;
    end 
    #80000;
    wr_addr = 0;
    wr_sig = 0 ; 
    #200000 ;
    rd_sig = 1 ;
    repeat(32)begin
     wait(app_en);
     rd_sig = 1 ;
     rd_addr = rd_addr + 8   ;
    #10000;
    rd_sig = 0 ;
    end
    #5000000;
    $finish;
    
  end
    
    


  always @( * ) begin
    ddr3_ck_p_sdram      <=  #(TPROP_PCB_CTRL) ddr3_ck_p_fpga;
    ddr3_ck_n_sdram      <=  #(TPROP_PCB_CTRL) ddr3_ck_n_fpga;
    ddr3_addr_sdram[0]   <=  #(TPROP_PCB_CTRL) ddr3_addr_fpga;
    ddr3_addr_sdram[1]   <=  #(TPROP_PCB_CTRL) (CA_MIRROR == "ON") ?
                                                 {ddr3_addr_fpga[ROW_WIDTH-1:9],
                                                  ddr3_addr_fpga[7], ddr3_addr_fpga[8],
                                                  ddr3_addr_fpga[5], ddr3_addr_fpga[6],
                                                  ddr3_addr_fpga[3], ddr3_addr_fpga[4],
                                                  ddr3_addr_fpga[2:0]} :
                                                 ddr3_addr_fpga;
    ddr3_ba_sdram[0]     <=  #(TPROP_PCB_CTRL) ddr3_ba_fpga;
    ddr3_ba_sdram[1]     <=  #(TPROP_PCB_CTRL) (CA_MIRROR == "ON") ?
                                                 {ddr3_ba_fpga[3-1:2],
                                                  ddr3_ba_fpga[0],
                                                  ddr3_ba_fpga[1]} :
                                                 ddr3_ba_fpga;
    ddr3_ras_n_sdram     <=  #(TPROP_PCB_CTRL) ddr3_ras_n_fpga;
    ddr3_cas_n_sdram     <=  #(TPROP_PCB_CTRL) ddr3_cas_n_fpga;
    ddr3_we_n_sdram      <=  #(TPROP_PCB_CTRL) ddr3_we_n_fpga;
    ddr3_cke_sdram       <=  #(TPROP_PCB_CTRL) ddr3_cke_fpga;
  end
    

  always @( * )
    ddr3_cs_n_sdram_tmp   <=  #(TPROP_PCB_CTRL) ddr3_cs_n_fpga;
  assign ddr3_cs_n_sdram =  ddr3_cs_n_sdram_tmp;
    

  always @( * )
    ddr3_dm_sdram_tmp <=  #(TPROP_PCB_DATA) ddr3_dm_fpga;//DM signal generation
  assign ddr3_dm_sdram = ddr3_dm_sdram_tmp;
    

  always @( * )
    ddr3_odt_sdram_tmp  <=  #(TPROP_PCB_CTRL) ddr3_odt_fpga;
  assign ddr3_odt_sdram =  ddr3_odt_sdram_tmp;
    

// Controlling the bi-directional BUS

  genvar dqwd;
  generate
    for (dqwd = 1;dqwd < DQ_WIDTH;dqwd = dqwd+1) begin : dq_delay
      WireDelay #
       (
        .Delay_g    (TPROP_PCB_DATA),
        .Delay_rd   (TPROP_PCB_DATA_RD),
        .ERR_INSERT ("OFF")
       )
      u_delay_dq
       (
        .A             (ddr3_dq_fpga[dqwd]),
        .B             (ddr3_dq_sdram[dqwd]),
        .reset         (sys_rst_n),
        .phy_init_done (init_calib_complete)
       );
    end
          WireDelay #
       (
        .Delay_g    (TPROP_PCB_DATA),
        .Delay_rd   (TPROP_PCB_DATA_RD),
        .ERR_INSERT ("OFF")
       )
      u_delay_dq_0
       (
        .A             (ddr3_dq_fpga[0]),
        .B             (ddr3_dq_sdram[0]),
        .reset         (sys_rst_n),
        .phy_init_done (init_calib_complete)
       );
  endgenerate

  genvar dqswd;
  generate
    for (dqswd = 0;dqswd < DQS_WIDTH;dqswd = dqswd+1) begin : dqs_delay
      WireDelay #
       (
        .Delay_g    (TPROP_DQS),
        .Delay_rd   (TPROP_DQS_RD),
        .ERR_INSERT ("OFF")
       )
      u_delay_dqs_p
       (
        .A             (ddr3_dqs_p_fpga[dqswd]),
        .B             (ddr3_dqs_p_sdram[dqswd]),
        .reset         (sys_rst_n),
        .phy_init_done (init_calib_complete)
       );

      WireDelay #
       (
        .Delay_g    (TPROP_DQS),
        .Delay_rd   (TPROP_DQS_RD),
        .ERR_INSERT ("OFF")
       )
      u_delay_dqs_n
       (
        .A             (ddr3_dqs_n_fpga[dqswd]),
        .B             (ddr3_dqs_n_sdram[dqswd]),
        .reset         (sys_rst_n),
        .phy_init_done (init_calib_complete)
       );
    end    
endgenerate
endmodule

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1265674.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解密Long型数据传递:Spring Boot后台如何避免精度丢失问题

前端和后端之间的数据传递至关重要。然而&#xff0c;当涉及到Long类型数据时&#xff0c;可能会出现精度丢失问题&#xff0c;这会影响数据的准确性。本文将为你介绍两种解决方案&#xff0c;帮助你确保Long类型数据在前端和后端之间的精确传递。 精度丢失测试 访问:http://l…

深度学习可解释性Python库

本文整理了10个常用于可解释AI的Python库&#xff0c;方便我们更好的理解AI模型的决策。 原文阅读 什么是XAI&#xff1f; XAI&#xff08;Explainable AI&#xff09;的目标是为模型的行为和决策提供合理的解释&#xff0c;这有助于增加信任、提供问责制和模型决策的透明度…

SAP FB01 更新采购凭证历史EKBE

参考链接BAPI_ACC_DOCUMENT_POST – Vendor Down payment: Update Purchase order info and PO history 不需要链接里的替代过程&#xff0c;可以直接写在函数BAPI_ACC_DOCUMENT_POST的增强结构EXTENSION2里 需要复制BTE增强1050 在其中调用函数ME_CREATE_HISTORY_FINANCE 即…

工具 | docker删除不使用的容器

工具 | docker删除不使用的容器 Docker 清理命令

ESP32-Web-Server 实战编程-通过网页控制设备的 GPIO

ESP32-Web-Server 实战编程-通过网页控制设备的 GPIO 概述 前述博客讲解了 Web 编程的基本知识&#xff0c;包括 HTML、CSS、JavaScript 三个部分&#xff0c;从这节开始&#xff0c;我们进入实战部分&#xff0c;在实际项目中进一步学习 ESP32-Web 编程。 GPIO &#xff08…

产品解读:GreatADM如何快速改造单实例为双主、MGR、读写分离架构?

前言 单机GreatDB/GreatSQL/MySQL将架构调整为多副本复制的好处有哪些&#xff1f;为什么要调整&#xff1f; 性能优化&#xff1a;如果单个GreatDB服务器的处理能力达到瓶颈&#xff0c;可能需要通过主从复制、双主复制或MGR及其他高可用方案来提高整体性能。通过将读请求分发…

免交互语法expect

目录 前瞻 相关命令 范例一&#xff1a;免密登录另外一台主机并创建用户 范例二&#xff1a;免密登录另外三台主机并创建用户 前瞻 expect是建立在tcl&#xff08;tool command language&#xff09;语言基础上的一个工具&#xff0c;常被用于进行自动化控制和测试&#xf…

前后端分离开发出现的跨域问题

先说说什么是跨域。 请求的URL地址中的协议、域名、端口号中的任意一个与当前URL不同就是跨域。 比如&#xff1a; 当前页面的URL请求的URL是否跨域原因htttp://localhost:8080htttps://localhost:8080是协议不同htttp://localhostll:8080htttp://localhost:8080是域名不同htt…

校园跑腿的核心功能

校园跑腿是指在校园内提供各种代办和服务的便利服务。 1. 快速送货&#xff1a;校园跑腿可以提供快速的送货服务&#xff0c;包括食品、快递、文件等物品的送达。 2. 打印复印&#xff1a;校园跑腿可以提供打印、复印等文档处理服务&#xff0c;方便学生和教职工处理各种文档…

Glide结合OkHttp保证短信验证接口携带图形验证码接口返回Cookie值去做网络请求

一、实现效果 二、步骤 注意&#xff1a;仅展示核心部分代码 1、导入依赖 api com.github.bumptech.glide:glide:4.10.0 kapt com.github.bumptech.glide:compiler:4.10.0 api com.squareup.okhttp3:okhttp:3.11.0 api com.squareup.okhttp3:logging-interceptor:3.11.02、自…

【Web】BJDCTF 2020 个人复现

目录 ①easy_md5 ②ZJCTF&#xff0c;不过如此 ③Cookie is so subtle! ④Ezphp ⑤The Mystery of IP ①easy_md5 ffifdyop绕过SQL注入 sql注入&#xff1a;md5($password,true) 右键查看源码 数组绕过 ?a[]1&b[]2 跳转到levell14.php 同样是数组绕过 param1[…

C语言第三十六弹--实现转移表的多种方法

使用C语言通过多种方法实现转移表 方法一、普通法 思路&#xff1a;如图实现多种操作&#xff0c;首先创建菜单&#xff0c;需要运行一次再判断条件&#xff0c;所以通过do{}while(); 循环来实现多次。有多种选择&#xff0c;使用switch case选择语句&#xff0c;再在对应case…

蓝桥杯第229题 迷宫与陷阱 BFS C++ 模拟 带你理解迷宫的深奥

题目 迷宫与陷阱 - 蓝桥云课 (lanqiao.cn)https://www.lanqiao.cn/problems/229/learning/?page1&first_category_id1&name%E8%BF%B7%E5%AE%AB%E4%B8%8E%E9%99%B7%E9%98%B1 思路和解题方法 首先&#xff0c;定义了一个结构体node来表示迷宫中的每个节点&#xff0c;包…

计算机丢失vcomp140.dll是什么意思,如何解决与修复(附教程)

vcomp140.dll缺失的5种解决方法以及vcomp140.dll缺失原因 引言&#xff1a; 在日常使用电脑的过程中&#xff0c;我们可能会遇到一些错误提示&#xff0c;其中之一就是“vcomp140.dll缺失”。这个错误提示通常出现在运行某些程序或游戏时&#xff0c;给使用者带来了困扰。本文…

Java数据结构之优先级队列(PriorityQueue)

1、概念 队列&#xff1a;是一种FIFO&#xff08;First-In-First-Out&#xff09;先进先出的数据结构&#xff0c;对应于生活中的排队的场景&#xff0c; 排在前面的人总是先通过&#xff0c;依次进行。 优先队列&#xff1a;是特殊的队列&#xff0c;从“优先”一词&#xff…

免调试计量表,4G无线电表,可以远程抄表,安科瑞ADW300一款全能实现?

1.概述 ADW300 无线计量仪表主要用于计量低压网络的三相有功电能&#xff0c;具有体积小、精度高、功能丰富等优点&#xff0c;并 且可选通讯方式多&#xff0c;可支持 RS485 通讯和 Lora、NB、4G、wifi 等无线通讯方式&#xff0c;增加了外置互感器的电流采样 模式&#xff0…

计算机毕业设计 基于PHP的考研互助交流系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

设备管理的方法与思路

阅读本文你将了解设备管理的思路与方法&#xff1a;一、制定全面的管理计划&#xff1b;二、标准化管理流程&#xff1b;三、设备维护与保养&#xff1b;四、风险管理与预防&#xff1b;五、引入数字化工具。 设备管理在生产制造领域是保障生产安全和效率的核心环节。通过引入…

【c++|SDL】开始使用之---demo

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 SDL 记录 1. hello word #include<SDL2/SDL.h>SDL_Window* g_pWindow 0; SDL_Renderer* g_pRenderer 0;int main(int argc, char* args[]) {//…

DS八大排序之直接插入排序和希尔排序

前言 我们前面几期介绍了线性和非线性的基本数据结构。例如顺序表、链表、栈和队列、二叉树等~&#xff01;本期和接下来的几期我们来详解介绍各个排序的概念、实现以及性能分析&#xff01; 本期内容 排序的概念以及其运用 常见的排序算法 直接插入排序 希尔排序 一、排序的…