当前位置: 首页 > news >正文

UDP--DDR--SFP,FPGA实现之模块梳理及AXI读写DDR读写上板测试

模块梳理介绍

在之前的几篇文章中,笔者详细介绍了整个项目的框架结构以及部分关键模块的实现细节。这些模块包括UDP协议栈、UDP指令监测、数据跨时钟域处理、DDR读写控制、内存读取控制以及DDR AXI控制器等。这些模块共同构成了项目的基础架构,每个模块都经过精心设计和实现,以确保系统的稳定性和高效性。

鉴于后续的GT收发器功能模块配置相对简单,而之前的模块已经形成了一定的体系规模,笔者现在将对这些模块进行功能联调,以实现全面的仿真测试。功能联调是确保各个模块能够协同工作的重要步骤,通过仿真测试可以验证模块之间的接口是否匹配,数据传输是否准确,以及整体系统是否能够按照预期运行。

而对于UDP协议栈的仿真,由于在之前的专栏已经较为详尽,在本章节中,便不再进行仿真,而是直接模拟UDP数据的发送,对于MIG核笔者同样不进行仿真,考虑到移植仿真文件比较麻烦,不如在验证AXI的正确性后,直接进行上板验证。

模块整体结构代码

module k7325t_top(input               i_sysclk        ,/*sfp*/input               i_gtrefclk_p    ,input               i_gtrefclk_n    ,output              o_gt_tx_p       ,output              o_gt_tx_n       ,input               i_gt_rx_p       ,input               i_gt_rx_n       ,output  [1 :0]      o_sfp_disable   ,input               i_rxc           ,input   [3 :0]      i_rxd           ,input               i_rx_ctl        ,output              o_txc           ,output  [3 :0]      o_txd           ,output              o_tx_ctl        ,output              phy_rst         ,/*ddr*/output  [14:0]      ddr3_addr       ,output  [2 :0]      ddr3_ba         ,output		        ddr3_cas_n      ,output  [0 :0]      ddr3_ck_n       ,output  [0 :0]      ddr3_ck_p       ,output  [0 :0]      ddr3_cke        ,output		        ddr3_ras_n      ,output			    ddr3_reset_n    ,output			    ddr3_we_n       ,inout   [31:0]		ddr3_dq         ,inout   [3 :0]		ddr3_dqs_n      ,inout   [3 :0]		ddr3_dqs_p      ,output  [0 :0]		ddr3_cs_n       ,output  [3 :0]		ddr3_dm         ,output  [0 :0]		ddr3_odt        );
wire                    w_udp_clk       ;
wire                    w_udp_rst       ;
wire                    w_sfp_clk       ;
wire                    w_sfp_rst       ;
wire [15:0]             w_udp_len       ;
wire [7 :0]             w_udp_data      ;
wire                    w_udp_last      ;
wire                    w_udp_valid     ;
wire    [31:0]          w_send_data     ;
wire                    w_send_valid    ;
assign  phy_rst = 1'b1;
wire                    w_sys_clk       ;
wire                    w_ddr_clk       ;
wire                    w_locked        ;
wire                    w_ui_clk        ;
wire                    w_ui_rst        ;
wire    [1 :0]          w_op_cmd        ;
wire    [29:0]          w_op_waddr      ;
wire    [29:0]          w_op_raddr      ;
wire                    w_op_valid      ;
wire                    w_op_ready      ;
wire    [31:0]          w_write_data    ;
wire                    w_write_valid   ;
wire    [31:0]          w_read_data     ;
wire                    w_read_valid    ;wire                    w_read_cmd       ;
wire    [7 :0]          w_store_udp_data ;
wire                    w_store_udp_valid;
wire                    w_store_done     ;
wire                    w_raddr_clear    ;
wire                    w_sync_clear     ;
wire    [15:0]          w_store_size     ;
wire                    w_read_back      ;
wire    [31:0]          w_sfp_data       ;
wire                    w_sfp_valid      ;/*生成全局时钟*/
clk_gen clk_gen_u0(.clk_out2           (w_ddr_clk          ),.clk_out1           (w_sys_clk          ),.locked             (w_locked           ),.clk_in1            (i_sysclk           ));/*UDP协议栈*/
udp_module udp_module_u0(.i_rxc              (i_rxc              ),.i_rxd              (i_rxd              ),.i_rx_ctl           (i_rx_ctl           ),.o_txc              (o_txc              ),.o_txd              (o_txd              ),.o_tx_ctl           (o_tx_ctl           ),.o_udp_clk          (w_udp_clk          ),.o_udp_rst          (w_udp_rst          ),.o_rec_len          (w_udp_len          ),.o_rec_data         (w_udp_data         ),.o_rec_last         (w_udp_last         ),.o_rec_valid        (w_udp_valid        )
);/*指令监测,输出监测后数据*/
udp_cmd_check udp_cmd_check_u0(.i_clk              (w_udp_clk          ),.i_rst              (w_udp_rst          ),.i_udp_data         (w_udp_data         ),.i_udp_valid        (w_udp_valid        ),.o_udp_data         (w_store_udp_data   ),.o_udp_valid        (w_store_udp_valid  ),.o_store_done       (w_store_done       ),.o_raddr_clear      (w_raddr_clear      ));/*跨时钟域处理,1Byte-->4Bytes,udp-->ddr*/
ASYNC_BUF_DDR ASYNC_BUF_DDR_U0(.i_udp_clk          (w_udp_clk          ),.i_udp_rst          (w_udp_rst          ),.i_ui_clk           (w_ui_clk           ),.i_ui_rst           (w_ui_rst           ),.i_udp_data         (w_store_udp_data   ),.i_udp_valid        (w_store_udp_valid  ),.o_send_data        (w_send_data        ),.o_send_valid       (w_send_valid       ));/*读取地址清除信号跨时钟*/
sync_s2f sync_s2f_u0(.i_clk_slow	        (w_udp_clk          ),.i_signal	        (w_raddr_clear      ),.i_clk_fast 	    (w_ui_clk           ),.o_sync		        (w_sync_clear       )
);/*内存读取控制器*/
read_memory_ctrl read_memory_ctrl_u0(.i_ui_clk           (w_ui_clk           ),.i_ui_rst           (w_ui_rst           ),.i_sfp_clk          (w_sfp_clk          ),.i_sfp_rst          (w_sfp_rst          ),.i_store_done       (w_store_done       ),.i_store_size       (w_store_size       ),.i_raddr_clear      (w_sync_clear       ),.o_read_back        (w_read_back        ),.o_read_cmd         (w_read_cmd         ),.i_read_data        (w_read_data        ),.i_read_valid       (w_read_valid       ),.o_sfp_data         (w_sfp_data         ),.o_sfp_valid        (w_sfp_valid        ));/*ddr读写控制器*/
ddr_rw_control ddr_rw_control_u0(.i_ui_clk           (w_ui_clk           ),.i_ui_rst           (w_ui_rst           ),.i_send_data        (w_send_data        ),.i_send_valid       (w_send_valid       ),.i_read_cmd         (w_read_cmd         ),.i_raddr_clear      (w_sync_clear       ),.i_read_back        (w_read_back        ),.o_store_size       (w_store_size       ),.o_op_cmd           (w_op_cmd           ),.o_op_waddr         (w_op_waddr         ),.o_op_raddr         (w_op_raddr         ),.o_op_valid         (w_op_valid         ),.i_op_ready         (w_op_ready         ),.o_write_data       (w_write_data       ),.o_write_valid      (w_write_valid      ),.i_read_data        (w_read_data        ),.i_read_valid       (w_read_valid       ));/*ddr axi读写驱动*/
ddr_top ddr_top_u0(.i_ddr_clk          (w_ddr_clk          ),.i_ddr_rstn         (w_locked           ),.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           ),.ui_clk             (w_ui_clk           ),.ui_clk_sync_rst    (w_ui_rst           ),.i_op_cmd           (w_op_cmd           ),.i_op_waddr         (w_op_waddr         ),.i_op_raddr         (w_op_raddr         ),.i_op_valid         (w_op_valid         ),.o_op_ready         (w_op_ready         ),.i_write_data       (w_write_data       ),.i_write_valid      (w_write_valid      ),.o_read_data        (w_read_data        ),.o_read_valid       (w_read_valid       ));/*光纤传输器*/
gt_one_top gt_one_top_u0(.i_sysclk            (w_sys_clk         ),.i_gtrefclk_p        (i_gtrefclk_p      ),.i_gtrefclk_n        (i_gtrefclk_n      ),.o_gt_tx_p           (o_gt_tx_p         ),.o_gt_tx_n           (o_gt_tx_n         ),.i_gt_rx_p           (i_gt_rx_p         ),.i_gt_rx_n           (i_gt_rx_n         ),.o_sfp_disable       (o_sfp_disable     ),.o_sfp_txclk         (w_sfp_clk         ),.o_sfp_txrst         (w_sfp_rst         ),.i_send_data         (w_sfp_data        ),.i_send_valid        (w_sfp_valid       ));

整体模块仿真(不包含GT收发器部分)

那么接下来便进行仿真流程的梳理

  • 模拟UDP接收到500K数据,在数据文件下发前,发送擦除指令,在数据文件下发后,发送传输完成指令
  • UDP指令监测模块对输入的UDP模拟数据做解析,解析出指令或是数据
  • 数据跨时钟模块接收指令监测模块输出的数据,进行位宽转换和跨时钟处理
  • 单次输出1K数据到DDR读写控制模块,DDR读写控制模块传输数据至DDR_AXI控制器
  • DDR_AXI控制器转译OP总线指令,转换为AXI总线,进行文件数据写入
  • 内存读取控制模块监测文件传输完成指令,控制DDR读写控制模块,进行文件循环读取
  • 仿真激励代码如下
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/05/09 09:32:42
// Design Name: 
// Module Name: tb_module
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//module tb_module();reg                 i_udp_clk       = 1'b0;
reg                 i_udp_rst       = 1'b0;
reg                 i_ui_clk        = 1'b0;
reg                 i_ui_rst        = 1'b0;
reg                 i_sfp_clk       = 1'b0;
reg                 i_sfp_rst       = 1'b0;
reg     [7 :0]      i_udp_data      = 8'd0;
reg                 i_udp_valid     = 1'd0;
reg                 i_rcmd          = 1'b0;
wire    [7 :0]      w_store_udp_data    ;
wire                w_store_udp_valid   ;
wire                w_store_done        ;
wire                w_raddr_clear       ;
wire                w_sync_clear        ;
wire                w_read_cmd          ;
reg     [31:0]      r_read_data     = 32'd0;
reg                 r_read_valid    = 1'd0 ;
wire    [31:0]      w_sfp_data          ; 
wire                w_sfp_valid         ;
wire    [31:0]      w_send_data         ;
wire                w_send_valid        ;
wire    [1 :0]      w_op_cmd            ;
wire    [29:0]      w_op_waddr          ;
wire    [29:0]      w_op_raddr          ;
wire                w_op_valid          ;
wire    [31:0]      w_write_data        ;
wire                w_write_valid       ;
wire    [15:0]      w_store_size        ;integer i = 0;
integer j = 0;
always #4   i_udp_clk = ~i_udp_clk;
always #2.5 i_ui_clk  = ~i_ui_clk ;
always #2   i_sfp_clk = ~i_sfp_clk;
initial begini_udp_rst = 1;i_sfp_rst = 1;i_ui_rst  = 1;#100@(i_sfp_clk) begini_udp_rst <= 1'b0;i_sfp_rst <= 1'b0;i_ui_rst  <= 1'b0;end#100/*传输擦除指令*/@(posedge i_udp_clk)udp_cmd(64'HD5D5D5D5_FCFCFCFC);/*传输200KB*/@(posedge i_udp_clk)for(i = 0;i < 300; i = i + 1) begin@(posedge i_udp_clk)udp_send(1024);#500@(posedge i_udp_clk);end/*传输完成指令*/@(posedge i_udp_clk)udp_cmd(64'HA5A5A5A5_BCBCBCBC);
end/*指令监测,输出监测后数据*/
udp_cmd_check udp_cmd_check_u0(.i_clk              (i_udp_clk          ),.i_rst              (i_udp_rst          ),.i_udp_data         (i_udp_data         ),.i_udp_valid        (i_udp_valid        ),.o_udp_data         (w_store_udp_data   ),.o_udp_valid        (w_store_udp_valid  ),.o_store_done       (w_store_done       ),.o_raddr_clear      (w_raddr_clear      ));/*跨时钟域处理,1Byte-->4Bytes,udp-->ddr*/
ASYNC_BUF_DDR ASYNC_BUF_DDR_U0(.i_udp_clk          (i_udp_clk          ),.i_udp_rst          (i_udp_rst          ),.i_ui_clk           (i_ui_clk           ),.i_ui_rst           (i_ui_rst           ),.i_udp_data         (w_store_udp_data   ),.i_udp_valid        (w_store_udp_valid  ),.o_send_data        (w_send_data        ),.o_send_valid       (w_send_valid       ));/*读取地址清除信号跨时钟*/
sync_s2f sync_s2f_u0(.i_clk_slow	        (i_udp_clk          ),.i_signal	        (w_raddr_clear      ),.i_clk_fast 	    (i_ui_clk           ),.o_sync		        (w_sync_clear       )
);ddr_rw_control ddr_rw_control_u0(.i_ui_clk           (i_ui_clk           ),.i_ui_rst           (i_ui_rst           ),.i_send_data        (w_send_data        ),.i_send_valid       (w_send_valid       ),.i_read_cmd         (i_rcmd             ),.i_raddr_clear      (w_sync_clear       ),.i_read_back        (1'b0               ),.o_store_size       (w_store_size       ),.o_op_cmd           (w_op_cmd           ),.o_op_waddr         (w_op_waddr         ),.o_op_raddr         (w_op_raddr         ),.o_op_valid         (w_op_valid         ),.i_op_ready         (1'b1               ),.o_write_data       (w_write_data       ),.o_write_valid      (w_write_valid      ),.i_read_data        (32'd0              ),.i_read_valid       (1'b0               ));always @(posedge i_ui_clk) beginif (w_read_cmd) beginddr_data(256);end
end/*内存读取控制器*/
read_memory_ctrl read_memory_ctrl_u0(.i_ui_clk           (i_ui_clk           ),.i_ui_rst           (i_ui_rst           ),.i_sfp_clk          (i_sfp_clk          ),.i_sfp_rst          (i_sfp_rst          ),.i_store_done       (w_store_done       ),.i_store_size       (w_store_size       ),.i_raddr_clear      (w_sync_clear       ),.o_read_cmd         (w_read_cmd         ),.i_read_data        (r_read_data        ),.i_read_valid       (r_read_valid       ),.o_sfp_data         (w_sfp_data         ),.o_sfp_valid        (w_sfp_valid        ));task udp_send(input    [15:0]  byte_len);begin : datainteger i;i_udp_data   = 8'd0;i_udp_valid  = 1'd0;@(posedge i_udp_clk);for(i = 0;i < byte_len ;i = i + 1)begini_udp_data  <= i_udp_data + 1'b1;i_udp_valid <= 1'b1;@(posedge i_udp_clk);endi_udp_data   <= 8'd0;i_udp_valid  <= 1'd0;
end
endtasktask udp_cmd(input    [63:0]  i_cmd);begin : cmdinteger i;i_udp_data   = 8'd0;i_udp_valid  = 1'd0;@(posedge i_udp_clk);for(i = 0;i < 8 ;i = i + 1)begini_udp_data  <= i_cmd[63:56];i_cmd <= {i_cmd[55:0],8'h0};i_udp_valid <= 1'b1;@(posedge i_udp_clk);endi_udp_data   <= 8'd0;i_udp_valid  <= 1'd0;
end
endtasktask ddr_data(input    [15:0]  byte_len);begin : ddrinteger i;r_read_data   = 32'd0;r_read_valid  = 1 'd0;@(posedge i_ui_clk);for(i = 0;i < 256 ;i = i + 1)beginr_read_data  <= r_read_data + 1'b1;r_read_valid <= 1'b1;@(posedge i_ui_clk);endr_read_data   = 32'd0;r_read_valid  = 1 'd0;
end
endtaskendmodule

上述测试流程实际是对之前文章的测试进行了总结,所以在此,便不进行贴图展示结果了。
接下来,将进行AXI读写DDR的上板测试,如下所示,是笔者写的一个DDR模块顶层代码,实际是,将AXI读写DDR的控制器的op总线部分交互变为一与个可控模块进行交互,通过vio控制可控模块进行数据总线输出,读写DDR。

AXI接口的MIG核读写DDR上板测试

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/04/25 15:17:48
// Design Name: 
// Module Name: ddr_top
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//module ddr_top(// input               i_ddr_clk       ,// input               i_ddr_rstn      ,input               i_sysclk        ,output  [14:0]      ddr3_addr       ,output  [2 :0]      ddr3_ba         ,output		        ddr3_cas_n      ,output  [0 :0]      ddr3_ck_n       ,output  [0 :0]      ddr3_ck_p       ,output  [0 :0]      ddr3_cke        ,output		        ddr3_ras_n      ,output			    ddr3_reset_n    ,output			    ddr3_we_n       ,inout   [31:0]		ddr3_dq         ,inout   [3 :0]		ddr3_dqs_n      ,inout   [3 :0]		ddr3_dqs_p      ,output  [0 :0]		ddr3_cs_n       ,output  [3 :0]		ddr3_dm         ,output  [0 :0]		ddr3_odt        // output              ui_clk          ,// output              ui_clk_sync_rst ,// input   [1 :0]      i_op_cmd        ,// input   [29:0]      i_op_waddr      ,// input   [29:0]      i_op_raddr      ,// input               i_op_valid      ,// output              o_op_ready      ,// input   [31:0]      i_write_data    ,// input               i_write_valid   ,// output  [31:0]      o_read_data     ,// output              o_read_valid    );(*mark_debug = "true"*)wire                    init_calib_complete ;
wire                    w_ui_clk_sync_rst   ;
wire    [3 :0]          M_AXI_AWID          ;
(*mark_debug = "true"*)wire    [29:0]          M_AXI_AWADDR        ;
(*mark_debug = "true"*)wire    [7 :0]          M_AXI_AWLEN         ;
wire    [2 :0]          M_AXI_AWSIZE        ;
wire    [1 :0]          M_AXI_AWBURST       ;
wire    [0 :0]          M_AXI_AWLOCK        ;
wire    [3 :0]          M_AXI_AWCACHE       ;
wire    [2 :0]          M_AXI_AWPROT        ;
wire    [3 :0]          M_AXI_AWQOS         ;
(*mark_debug = "true"*)wire                    M_AXI_AWVALID       ;
(*mark_debug = "true"*)wire                    M_AXI_AWREADY       ;
(*mark_debug = "true"*)wire    [31:0]          M_AXI_WDATA         ;
(*mark_debug = "true"*)wire    [3 :0]          M_AXI_WSTRB         ;
(*mark_debug = "true"*)wire                    M_AXI_WLAST         ;
(*mark_debug = "true"*)wire                    M_AXI_WVALID        ;
wire                    M_AXI_WREADY        ;
wire    [3 :0]          M_AXI_BID           ;
wire    [1 :0]          M_AXI_BRESP         ;
wire                    M_AXI_BVALID        ;
wire                    M_AXI_BREADY        ;
wire    [3 :0]          M_AXI_ARID          ;
(*mark_debug = "true"*)wire    [29:0]          M_AXI_ARADDR        ;
(*mark_debug = "true"*)wire    [7 :0]          M_AXI_ARLEN         ;
wire    [2 :0]          M_AXI_ARSIZE        ;
wire    [1 :0]          M_AXI_ARBURST       ;
wire    [0 :0]          M_AXI_ARLOCK        ;
wire    [3 :0]          M_AXI_ARCACHE       ;
wire    [2 :0]          M_AXI_ARPROT        ;
wire    [3 :0]          M_AXI_ARQOS         ;
(*mark_debug = "true"*)wire                    M_AXI_ARVALID       ;
(*mark_debug = "true"*)wire                    M_AXI_ARREADY       ;
wire    [3 :0]          M_AXI_RID           ;
(*mark_debug = "true"*)wire    [31:0]          M_AXI_RDATA         ;
(*mark_debug = "true"*)wire    [1 :0]          M_AXI_RRESP         ;
(*mark_debug = "true"*)wire                    M_AXI_RLAST         ;
(*mark_debug = "true"*)wire                    M_AXI_RVALID        ;
wire                    M_AXI_RREADY        ;wire    [0 :0]          M_AXI_AWUSER        ;
wire    [0 :0]          M_AXI_WUSER         ;
wire    [0 :0]          M_AXI_BUSER         ;
wire    [0 :0]          M_AXI_ARUSER        ;
wire    [0 :0]          M_AXI_RUSER         ;
wire                    w_ddr_clk           ;
wire                    w_locked            ;
wire    [1 :0]          w_op_cmd            ;
wire    [29:0]          w_op_waddr          ;
wire    [29:0]          w_op_raddr          ;
wire                    w_op_valid          ;
wire                    w_op_ready          ;
wire    [31:0]          w_write_data        ;
wire                    w_write_valid       ;
wire    [31:0]          w_read_data         ;
wire                    w_read_valid        ;
/*生成全局时钟*/
clk_gen clk_gen_u0(.clk_out2           (w_ddr_clk          ),.clk_out1           (                   ),.locked             (w_locked           ),.clk_in1            (i_sysclk           ));
wire    ui_clk  ;
// assign  ui_clk_sync_rst = w_ui_clk_sync_rst;wire    i_wcmd  ;
wire    i_rcmd  ;
vio_0 vio_0_u0 (.clk          (ui_clk),.probe_out0   (i_wcmd),.probe_out1   (i_rcmd) 
);rw_fsm_gen rw_fsm_gen_u0(.i_clk                          (ui_clk             ),.i_rst                          (w_ui_clk_sync_rst  ),.i_wcmd                         (i_wcmd             ),.i_rcmd                         (i_rcmd             ),.o_can_cmd                      (),.o_op_cmd                       (w_op_cmd           ),.o_op_waddr                     (w_op_waddr         ),.o_op_raddr                     (w_op_raddr         ),.o_op_valid                     (w_op_valid         ),.i_op_ready                     (w_op_ready         ),.o_write_data                   (w_write_data       ),.o_write_valid                  (w_write_valid      ),.i_read_data                    (w_read_data        ),.i_read_valid                   (w_read_valid       ));ddr_axi_rw#(.C_M_TARGET_SLAVE_BASE_ADDR     (32'h00000000       ),.C_M_AXI_BURST_LEN	            (256                ),.C_M_AXI_ID_WIDTH	            (3                  ),.C_M_AXI_ADDR_WIDTH	            (30                 ),.C_M_AXI_DATA_WIDTH	            (32                 ),.C_M_AXI_AWUSER_WIDTH           (1                  ),.C_M_AXI_ARUSER_WIDTH           (1                  ),.C_M_AXI_WUSER_WIDTH	        (1                  ),.C_M_AXI_RUSER_WIDTH	        (1                  ),.C_M_AXI_BUSER_WIDTH	        (1                  )
)ddr_axi_rw_u0(.init_calib_complete            (init_calib_complete),.i_op_cmd                       (w_op_cmd           ),.i_op_waddr                     (w_op_waddr         ),.i_op_raddr                     (w_op_raddr         ),.i_op_valid                     (w_op_valid         ),.o_op_ready                     (w_op_ready         ),.i_write_data                   (w_write_data       ),.i_write_valid                  (w_write_valid      ),.o_read_data                    (w_read_data        ),.o_read_valid                   (w_read_valid       ),.M_AXI_ACLK                     (ui_clk             ),.M_AXI_ARESETN                  (~w_ui_clk_sync_rst ),.M_AXI_AWID                     (M_AXI_AWID         ),.M_AXI_AWADDR                   (M_AXI_AWADDR       ),.M_AXI_AWLEN                    (M_AXI_AWLEN        ),.M_AXI_AWSIZE                   (M_AXI_AWSIZE       ),.M_AXI_AWBURST                  (M_AXI_AWBURST      ),.M_AXI_AWLOCK                   (M_AXI_AWLOCK       ),.M_AXI_AWCACHE                  (M_AXI_AWCACHE      ),.M_AXI_AWPROT                   (M_AXI_AWPROT       ),.M_AXI_AWQOS                    (M_AXI_AWQOS        ),.M_AXI_AWUSER                   (M_AXI_AWUSER       ),.M_AXI_AWVALID                  (M_AXI_AWVALID      ),.M_AXI_AWREADY                  (M_AXI_AWREADY      ),.M_AXI_WDATA                    (M_AXI_WDATA        ),.M_AXI_WSTRB                    (M_AXI_WSTRB        ),.M_AXI_WLAST                    (M_AXI_WLAST        ),.M_AXI_WUSER                    (M_AXI_WUSER        ),.M_AXI_WVALID                   (M_AXI_WVALID       ),.M_AXI_WREADY                   (M_AXI_WREADY       ),.M_AXI_BID                      (M_AXI_BID          ),.M_AXI_BRESP                    (M_AXI_BRESP        ),.M_AXI_BUSER                    (M_AXI_BUSER        ),.M_AXI_BVALID                   (M_AXI_BVALID       ),.M_AXI_BREADY                   (M_AXI_BREADY       ), .M_AXI_ARID                     (M_AXI_ARID         ),.M_AXI_ARADDR                   (M_AXI_ARADDR       ),.M_AXI_ARLEN                    (M_AXI_ARLEN        ),.M_AXI_ARSIZE                   (M_AXI_ARSIZE       ),.M_AXI_ARBURST                  (M_AXI_ARBURST      ),.M_AXI_ARLOCK                   (M_AXI_ARLOCK       ),.M_AXI_ARCACHE                  (M_AXI_ARCACHE      ),.M_AXI_ARPROT                   (M_AXI_ARPROT       ),.M_AXI_ARQOS                    (M_AXI_ARQOS        ),.M_AXI_ARUSER                   (M_AXI_ARUSER       ),.M_AXI_ARVALID                  (M_AXI_ARVALID      ),.M_AXI_ARREADY                  (M_AXI_ARREADY      ),.M_AXI_RID                      (M_AXI_RID          ),.M_AXI_RDATA                    (M_AXI_RDATA        ),.M_AXI_RRESP                    (M_AXI_RRESP        ),.M_AXI_RLAST                    (M_AXI_RLAST        ),.M_AXI_RUSER                    (M_AXI_RUSER        ),.M_AXI_RVALID                   (M_AXI_RVALID       ),.M_AXI_RREADY                   (M_AXI_RREADY       ) );mig_7series_0 u_mig_axi (.ddr3_addr                      (ddr3_addr                  ),  // output [14: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.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  .ui_clk                         (ui_clk                     ),  // output			ui_clk.ui_clk_sync_rst                (w_ui_clk_sync_rst          ),  // output			ui_clk_sync_rst.init_calib_complete            (init_calib_complete        ),  // output			init_calib_complete.mmcm_locked                    (                           ),  // output			mmcm_locked.app_sr_req                     (0                          ),  // input			app_sr_req.app_ref_req                    (0                          ),  // input			app_ref_req.app_zq_req                     (0                          ),  // 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.aresetn                        (~ui_clk_sync_rst           ),  // input			aresetn.s_axi_awid                     (M_AXI_AWID                 ),  // input [3:0]			s_axi_awid.s_axi_awaddr                   (M_AXI_AWADDR               ),  // input [29:0]			s_axi_awaddr.s_axi_awlen                    (M_AXI_AWLEN                ),  // input [7:0]			s_axi_awlen.s_axi_awsize                   (M_AXI_AWSIZE               ),  // input [2:0]			s_axi_awsize.s_axi_awburst                  (M_AXI_AWBURST              ),  // input [1:0]			s_axi_awburst.s_axi_awlock                   (M_AXI_AWLOCK               ),  // input [0:0]			s_axi_awlock.s_axi_awcache                  (M_AXI_AWCACHE              ),  // input [3:0]			s_axi_awcache.s_axi_awprot                   (M_AXI_AWPROT               ),  // input [2:0]			s_axi_awprot.s_axi_awqos                    (M_AXI_AWQOS                ),  // input [3:0]			s_axi_awqos.s_axi_awvalid                  (M_AXI_AWVALID              ),  // input			s_axi_awvalid.s_axi_awready                  (M_AXI_AWREADY              ),  // output			s_axi_awready.s_axi_wdata                    (M_AXI_WDATA                ),  // input [255:0]			s_axi_wdata.s_axi_wstrb                    (M_AXI_WSTRB                ),  // input [31:0]			s_axi_wstrb.s_axi_wlast                    (M_AXI_WLAST                ),  // input			s_axi_wlast.s_axi_wvalid                   (M_AXI_WVALID               ),  // input			s_axi_wvalid.s_axi_wready                   (M_AXI_WREADY               ),  // output			s_axi_wready.s_axi_bid                      (M_AXI_BID                  ),  // output [3:0]			s_axi_bid.s_axi_bresp                    (M_AXI_BRESP                ),  // output [1:0]			s_axi_bresp.s_axi_bvalid                   (M_AXI_BVALID               ),  // output			s_axi_bvalid.s_axi_bready                   (M_AXI_BREADY               ),  // input			s_axi_bready.s_axi_arid                     (M_AXI_ARID                 ),  // input [3:0]			s_axi_arid.s_axi_araddr                   (M_AXI_ARADDR               ),  // input [29:0]			s_axi_araddr.s_axi_arlen                    (M_AXI_ARLEN                ),  // input [7:0]			s_axi_arlen.s_axi_arsize                   (M_AXI_ARSIZE               ),  // input [2:0]			s_axi_arsize.s_axi_arburst                  (M_AXI_ARBURST              ),  // input [1:0]			s_axi_arburst.s_axi_arlock                   (M_AXI_ARLOCK               ),  // input [0:0]			s_axi_arlock.s_axi_arcache                  (M_AXI_ARCACHE              ),  // input [3:0]			s_axi_arcache.s_axi_arprot                   (M_AXI_ARPROT               ),  // input [2:0]			s_axi_arprot.s_axi_arqos                    (M_AXI_ARQOS                ),  // input [3:0]			s_axi_arqos.s_axi_arvalid                  (M_AXI_ARVALID              ),  // input			s_axi_arvalid.s_axi_arready                  (M_AXI_ARREADY              ),  // output			s_axi_arready.s_axi_rid                      (M_AXI_RID                  ),  // output [3:0]			s_axi_rid.s_axi_rdata                    (M_AXI_RDATA                ),  // output [255:0]			s_axi_rdata.s_axi_rresp                    (M_AXI_RRESP                ),  // output [1:0]			s_axi_rresp.s_axi_rlast                    (M_AXI_RLAST                ),  // output			s_axi_rlast.s_axi_rvalid                   (M_AXI_RVALID               ),  // output			s_axi_rvalid.s_axi_rready                   (M_AXI_RREADY               ),  // input			s_axi_rready.sys_clk_i                      (w_ddr_clk                  ),.clk_ref_i                      (w_ddr_clk                  ),.sys_rst                        (w_locked                   )   // input sys_rst 低有效
);
endmodule
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/04/25 15:57:46
// Design Name: 
// Module Name: rw_fsm_gen
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//module rw_fsm_gen(input               i_clk           ,input               i_rst           ,input               i_wcmd          ,input               i_rcmd          ,output              o_can_cmd       ,output  [1 :0]      o_op_cmd        ,output  [29:0]      o_op_waddr      ,output  [29:0]      o_op_raddr      ,output              o_op_valid      ,input               i_op_ready      ,output  [31:0]      o_write_data    ,output              o_write_valid   ,input   [31:0]      i_read_data     ,input               i_read_valid);reg                     ri_wcmd         ;
reg                     ri_rcmd         ;
reg     [1 :0]          ro_op_cmd       ;
reg     [29:0]          ro_op_waddr     ;
reg     [29:0]          ro_op_raddr     ;
reg                     ro_op_valid     ;
reg                     ri_op_ready     ;
reg     [31:0]          ro_write_data   ;
reg                     ro_write_valid  ;
reg     [15:0]          r_write_cnt     ;
wire                    wcmd_pos        ;
wire                    rcmd_pos        ;localparam      P_WADDR = 4*256         ;
localparam      P_RADDR = 4*256         ;assign  wcmd_pos = ~ri_wcmd & i_wcmd    ;
assign  rcmd_pos = ~ri_rcmd & i_rcmd    ;
assign  o_op_cmd       = ro_op_cmd      ;
assign  o_op_waddr     = ro_op_waddr    ;
assign  o_op_raddr     = ro_op_raddr    ;
assign  o_op_valid     = ro_op_valid    ;   
assign  o_write_data   = ro_write_data  ;
assign  o_write_valid  = ro_write_valid ;
assign  o_can_cmd      = ~ro_write_valid & ~ i_read_valid;always @(posedge i_clk,posedge i_rst) beginif(i_rst) beginri_wcmd <= 1'b0;ri_rcmd <= 1'b0;ri_op_ready <= 1'b0;endelse beginri_wcmd <= i_wcmd;ri_rcmd <= i_rcmd;ri_op_ready <= i_op_ready;end
endalways @(posedge i_clk,posedge i_rst) beginif(i_rst)ro_op_cmd <= 2'b00;else if(wcmd_pos)ro_op_cmd <= 2'b01;else if(rcmd_pos)ro_op_cmd <= 2'b10;else if(ro_op_valid && ri_op_ready)ro_op_cmd <= 2'b00;
endalways @(posedge i_clk,posedge i_rst) beginif(i_rst)ro_op_valid <= 1'b0;else if(ro_op_valid && ri_op_ready)ro_op_valid <= 1'b0;else if(~ro_op_valid && wcmd_pos)ro_op_valid <= 1'b1;else if(~ro_op_valid && rcmd_pos)ro_op_valid <= 1'b1;
endalways @(posedge i_clk,posedge i_rst) beginif(i_rst)ro_op_waddr <= 'd0;else if(ro_op_valid && ri_op_ready && ro_op_cmd == 2'b01)ro_op_waddr <= ro_op_waddr + P_WADDR;
endalways @(posedge i_clk,posedge i_rst) beginif(i_rst)ro_op_raddr <= 'd0;else if(ro_op_valid && ri_op_ready && ro_op_cmd == 2'b10)ro_op_raddr <= ro_op_raddr + P_RADDR;
endalways @(posedge i_clk,posedge i_rst) beginif(i_rst) beginro_write_data  <= 32'd0;ro_write_valid <= 1'b0 ;endelse if(r_write_cnt == 'd4095) beginro_write_data  <= 32'd0;ro_write_valid <= 1'b0 ;endelse if((~ro_op_valid && wcmd_pos) || ro_write_valid) beginro_write_data  <= ro_write_data + 1'b1;ro_write_valid <= 1'b1;end
endalways @(posedge i_clk,posedge i_rst) beginif(i_rst) r_write_cnt <= 16'd0;else if(r_write_cnt == 'd4095)r_write_cnt <= 16'd0;else if(ro_write_valid)r_write_cnt <= r_write_cnt + 1'b1;
endendmodule

接下来,笔者便进行上板测试

由下图可知,MIG核成功实现对DDR的初始化,init信号为高在这里插入图片描述

首先通过vio进行两次写数据测试,vio控制输出逻辑为0~1的电平跳变,而代码中通过捕获上升沿,实现读或写指令的输出,写测试如下图所示:
在这里插入图片描述
图中展示的是第二次突发长度为256的写测试,注意写地址
AXI总线的地址最小操控单元为Byte,而笔者读写数据的位宽为4Byte,4*256 = 1Kbyte;对应地址即为0x0400,那么第二次写的地址即为0x0400,地址正确。
接下来进行读测试 ,以0地址为起始地址,突发长度256,读到的数据为1~256,与写入数据对应。
在这里插入图片描述
进行第二次读,读到的数据为257~512,与写入数据对应
在这里插入图片描述
经过上述仿真与上板测试,可以看出从UDP到DDR这条线路已经是ok的,接下来将进行GT收发器的使用讲解,关于本节代码的问题,以及优化意见,欢迎大家在评论区指出,如果想要对应工程进行学习,欢迎大家私信。

相关文章:

  • 【自然语言处理与大模型】大模型(LLM)基础知识④
  • 六、磁盘划分与磁盘配额
  • 鸿蒙ArkUI体验:Hexo博客客户端开发心得
  • day016-系统负载压力测试-磁盘管理
  • linux标准库头文件解析
  • C++ -命名空间-详解
  • chmod 777含义:
  • 全端同步!ZKmall开源商城如何用B2B2C模板让消费者跨设备购物体验无缝衔接?
  • QT之LayOut布局
  • MCP LLM Bridge:连接Model Context Protocol与OpenAI兼容LLM的桥梁
  • (4)python爬虫--JsonPath
  • 学习笔记:黑马程序员JavaWeb开发教程(2025.4.7)
  • 如何在前端页面上展示解析后的 JSON 数据?
  • DeepSeek 赋能量子计算:突破与未来图景
  • CoverM:contig/bin的相对丰度计算
  • 思路收集文档
  • 高频面试题(含笔试高频算法整理)基本总结回顾61
  • 2.单链表两数相加(java)
  • SpringBoot--自动配置原理详解
  • 从专家编码到神经网络学习:DTM 的符号操作新范式
  • 纽约市长称墨海军帆船撞桥已致2人死亡,撞桥前船只疑似失去动力
  • 陶石不语,玉见文明:临平玉架山考古博物馆明日开馆
  • 坚决打好产业生态培育攻坚战!陈吉宁调研奉贤区
  • 中国情怀:时代记录与家国镜相|澎湃·镜相第三届非虚构写作大赛暨七猫第六届百万奖金现实题材征文大赛征稿启事
  • “朱雀玄武敕令”改名“周乔治华盛顿”?警方称未通过审核
  • 一周文化讲座|“我的生命不过是温柔的疯狂”