From 05589c3f83bab46a52a450e76af5826c35c748b3 Mon Sep 17 00:00:00 2001 From: AngeloJacobo Date: Sun, 24 Nov 2024 17:40:21 +0800 Subject: [PATCH] added self-refresh to vivado IP GUI, tested self-refresh on hardware with microblaze --- rtl/axi/ddr3_top_axi.v | 13 ++- rtl/ddr3_controller.v | 3 +- rtl/ddr3_top.v | 26 ++++- vivado_custom_ip/component.xml | 115 ++++++++++++++------ vivado_custom_ip/xgui/ddr3_top_axi_v1_0.tcl | 15 +++ vivado_custom_ip/xgui/uberddr3_axi_v1_0.tcl | 20 +++- 6 files changed, 151 insertions(+), 41 deletions(-) diff --git a/rtl/axi/ddr3_top_axi.v b/rtl/axi/ddr3_top_axi.v index e5ab389..cc37bc5 100644 --- a/rtl/axi/ddr3_top_axi.v +++ b/rtl/axi/ddr3_top_axi.v @@ -49,6 +49,7 @@ module ddr3_top_axi #( parameter[1:0] ECC_ENABLE = 0, // set to 1 or 2 to add ECC (1 = Side-band ECC per burst, 2 = Side-band ECC per 8 bursts , 3 = Inline ECC ) parameter[1:0] DIC = 2'b00, //Output Driver Impedance Control (2'b00 = RZQ/6, 2'b01 = RZQ/7, RZQ = 240ohms) (only change when you know what you are doing) parameter[2:0] RTT_NOM = 3'b011, //RTT Nominal (3'b000 = disabled, 3'b001 = RZQ/4, 3'b010 = RZQ/2 , 3'b011 = RZQ/6, RZQ = 240ohms) (only change when you know what you are doing) + parameter[1:0] SELF_REFRESH = 2'b00, // 0 = use i_user_self_refresh input, 1 = Self-refresh mode is enabled after 64 controller clock cycles of no requests, 2 = 128 cycles, 3 = 256 cycles parameter // The next parameters act more like a localparam (since user does not have to set this manually) but was added here to simplify port declaration DQ_BITS = 8, //device width (fixed to 8, if DDR3 is x16 then BYTE_LANES will be 2 while ) serdes_ratio = 4, // this controller is fixed as a 4:1 memory controller (CONTROLLER_CLK_PERIOD/DDR3_CLK_PERIOD = 4) @@ -130,11 +131,14 @@ module ddr3_top_axi #( output wire o_calib_complete, // // Debug outputs - output wire[31:0] o_debug1 + output wire[31:0] o_debug1, // output wire[31:0] o_debug2, // output wire[31:0] o_debug3, // output wire[(DQ_BITS*BYTE_LANES)/8-1:0] o_ddr3_debug_read_dqs_p, // output wire[(DQ_BITS*BYTE_LANES)/8-1:0] o_ddr3_debug_read_dqs_n + // + // User enabled self-refresh + input wire i_user_self_refresh ); wire wb_cyc; @@ -165,7 +169,8 @@ ddr3_top #( .SKIP_INTERNAL_TEST(SKIP_INTERNAL_TEST), // skip built-in self test (would require >2 seconds of internal test right after calibration) .ECC_ENABLE(ECC_ENABLE), // set to 1 or 2 to add ECC (1 = Side-band ECC per burst, 2 = Side-band ECC per 8 bursts , 3 = Inline ECC ) .DIC(DIC), // Output Driver Impedance Control (2'b00 = RZQ/6, 2'b01 = RZQ/7, RZQ = 240ohms) (only change when you know what you are doing) - .RTT_NOM(RTT_NOM) //RTT Nominal (3'b000 = disabled, 3'b001 = RZQ/4, 3'b010 = RZQ/2 , 3'b011 = RZQ/6, RZQ = 240ohms) (only change when you know what you are doing) + .RTT_NOM(RTT_NOM), //RTT Nominal (3'b000 = disabled, 3'b001 = RZQ/4, 3'b010 = RZQ/2 , 3'b011 = RZQ/6, RZQ = 240ohms) (only change when you know what you are doing) + .SELF_REFRESH(SELF_REFRESH) // Self-refresh options (0 = use i_user_self_refresh input, 1 = Self-refresh mode is enabled after 64 controller clock cycles of no requests, 2 = 128 cycles, 3 = 256 cycles) ) ddr3_top_inst ( //clock and reset @@ -222,11 +227,13 @@ ddr3_top #( .o_calib_complete(o_calib_complete), // // Debug outputs - .o_debug1(o_debug1) + .o_debug1(o_debug1), // .o_debug2(o_debug2), // .o_debug3(o_debug3), // .o_ddr3_debug_read_dqs_p(o_ddr3_debug_read_dqs_p), // .o_ddr3_debug_read_dqs_n(o_ddr3_debug_read_dqs_n) + // + .i_user_self_refresh(i_user_self_refresh) //////////////////////////////////// ); diff --git a/rtl/ddr3_controller.v b/rtl/ddr3_controller.v index 3bdb9d9..fdb7db1 100644 --- a/rtl/ddr3_controller.v +++ b/rtl/ddr3_controller.v @@ -489,7 +489,8 @@ module ddr3_controller #( initial begin o_phy_bitslip = 0; end - reg cmd_odt_q = 0, cmd_odt, cmd_ck_en, cmd_reset_n; + reg cmd_odt_q = 0, cmd_odt, cmd_reset_n; + (* mark_debug = "true" *) reg cmd_ck_en; reg o_wb_stall_q = 1, o_wb_stall_d, o_wb_stall_calib = 1; reg precharge_slot_busy; reg activate_slot_busy; diff --git a/rtl/ddr3_top.v b/rtl/ddr3_top.v index 350778d..1a36040 100644 --- a/rtl/ddr3_top.v +++ b/rtl/ddr3_top.v @@ -371,5 +371,29 @@ ddr3_top #( .o_ddr3_debug_read_dqs_p(/*o_ddr3_debug_read_dqs_p*/), .o_ddr3_debug_read_dqs_n(/*o_ddr3_debug_read_dqs_n*/) ); - + + // display value of parameters for easy debugging + initial begin + $display("\nDDR3 TOP PARAMETERS:\n-----------------------------"); + $display("CONTROLLER_CLK_PERIOD = %0d", CONTROLLER_CLK_PERIOD); + $display("DDR3_CLK_PERIOD = %0d", DDR3_CLK_PERIOD); + $display("ROW_BITS = %0d", ROW_BITS); + $display("COL_BITS = %0d", COL_BITS); + $display("BA_BITS = %0d", BA_BITS); + $display("BYTE_LANES = %0d", BYTE_LANES); + $display("AUX_WIDTH = %0d", AUX_WIDTH); + $display("WB2_ADDR_BITS = %0d", WB2_ADDR_BITS); + $display("WB2_DATA_BITS = %0d", WB2_DATA_BITS); + $display("MICRON_SIM = %0d", MICRON_SIM); + $display("ODELAY_SUPPORTED = %0d", ODELAY_SUPPORTED); + $display("SECOND_WISHBONE = %0d", SECOND_WISHBONE); + $display("WB_ERROR = %0d", WB_ERROR); + $display("SKIP_INTERNAL_TEST = %0d", SKIP_INTERNAL_TEST); + $display("ECC_ENABLE = %0d", ECC_ENABLE); + $display("DIC = %0d", DIC); + $display("RTT_NOM = %0d", RTT_NOM); + $display("SELF_REFRESH = %0d", SELF_REFRESH); + $display("End of DDR3 TOP PARAMETERS\n-----------------------------"); + end + endmodule diff --git a/vivado_custom_ip/component.xml b/vivado_custom_ip/component.xml index adfc16f..77614c3 100644 --- a/vivado_custom_ip/component.xml +++ b/vivado_custom_ip/component.xml @@ -311,28 +311,6 @@ - - i_rst_n - - - - - - - RST - - - i_rst_n - - - - - - POLARITY - ACTIVE_LOW - - - i_controller_clk @@ -387,6 +365,28 @@ + + i_rst_n + + + + + + + RST + + + i_rst_n + + + + + + POLARITY + ACTIVE_LOW + + + ddr3 ddr3 @@ -561,7 +561,7 @@ viewChecksum - e9f63973 + 1dea7b87 @@ -577,7 +577,7 @@ viewChecksum - e9f63973 + 1dea7b87 @@ -591,7 +591,7 @@ viewChecksum - 30e22270 + ce7b9cf6 @@ -1578,6 +1578,29 @@ + + i_user_self_refresh + + in + + + wire + xilinx_anylanguagesynthesis + xilinx_anylanguagebehavioralsimulation + + + + 0 + + + + + + true + + + + @@ -1655,6 +1678,11 @@ Ecc Enable 0 + + SELF_REFRESH + Self-Refresh + 0 + DIC Dic @@ -1723,6 +1751,20 @@ ACTIVE_HIGH ACTIVE_LOW + + choice_pairs_933dc0fc + 0 + 1 + 2 + 3 + + + choice_pairs_96a879b9 + 0 + 1 + 2 + 3 + @@ -1778,7 +1820,7 @@ ../rtl/axi/ddr3_top_axi.v verilogSource - CHECKSUM_4123fcc3 + CHECKSUM_f4e2d855 @@ -1841,7 +1883,7 @@ xgui/uberddr3_axi_v1_0.tcl tclSource - CHECKSUM_30e22270 + CHECKSUM_ce7b9cf6 XGUI_VERSION_2 @@ -1935,7 +1977,7 @@ ECC_ENABLE ECC Enable - 0 + 0 DIC @@ -2057,6 +2099,11 @@ Component_Name uberddr3_axi_v1_0 + + SELF_REFRESH + Self-Refresh + 0 + @@ -2090,20 +2137,20 @@ uberddr3_axi_v1_0 package_project https://github.com/AngeloJacobo/UberDDR3 - 9 - 2024-10-19T05:33:11Z + 11 + 2024-11-24T08:00:34Z 2022.1 - + - - + + - + diff --git a/vivado_custom_ip/xgui/ddr3_top_axi_v1_0.tcl b/vivado_custom_ip/xgui/ddr3_top_axi_v1_0.tcl index a462c49..f5b2bf9 100644 --- a/vivado_custom_ip/xgui/ddr3_top_axi_v1_0.tcl +++ b/vivado_custom_ip/xgui/ddr3_top_axi_v1_0.tcl @@ -15,6 +15,7 @@ proc init_gui { IPINST } { ipgui::add_param $IPINST -name "DIC" -parent ${Page_0} ipgui::add_param $IPINST -name "DQ_BITS" -parent ${Page_0} ipgui::add_param $IPINST -name "ECC_ENABLE" -parent ${Page_0} + ipgui::add_param $IPINST -name "SELF_REFRESH" -parent ${Page_0} ipgui::add_param $IPINST -name "MICRON_SIM" -parent ${Page_0} ipgui::add_param $IPINST -name "ODELAY_SUPPORTED" -parent ${Page_0} ipgui::add_param $IPINST -name "ROW_BITS" -parent ${Page_0} @@ -142,6 +143,15 @@ proc validate_PARAM_VALUE.ECC_ENABLE { PARAM_VALUE.ECC_ENABLE } { return true } +proc update_PARAM_VALUE.SELF_REFRESH { PARAM_VALUE.SELF_REFRESH } { + # Procedure called to update SELF_REFRESH when any of the dependent parameters in the arguments change +} + +proc validate_PARAM_VALUE.SELF_REFRESH { PARAM_VALUE.SELF_REFRESH } { + # Procedure called to validate SELF_REFRESH + return true +} + proc update_PARAM_VALUE.MICRON_SIM { PARAM_VALUE.MICRON_SIM } { # Procedure called to update MICRON_SIM when any of the dependent parameters in the arguments change } @@ -353,6 +363,11 @@ proc update_MODELPARAM_VALUE.ECC_ENABLE { MODELPARAM_VALUE.ECC_ENABLE PARAM_VALU set_property value [get_property value ${PARAM_VALUE.ECC_ENABLE}] ${MODELPARAM_VALUE.ECC_ENABLE} } +proc update_MODELPARAM_VALUE.SELF_REFRESH { MODELPARAM_VALUE.SELF_REFRESH PARAM_VALUE.SELF_REFRESH } { + # Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value + set_property value [get_property value ${PARAM_VALUE.SELF_REFRESH}] ${MODELPARAM_VALUE.SELF_REFRESH} +} + proc update_MODELPARAM_VALUE.DIC { MODELPARAM_VALUE.DIC PARAM_VALUE.DIC } { # Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value set_property value [get_property value ${PARAM_VALUE.DIC}] ${MODELPARAM_VALUE.DIC} diff --git a/vivado_custom_ip/xgui/uberddr3_axi_v1_0.tcl b/vivado_custom_ip/xgui/uberddr3_axi_v1_0.tcl index e20ff24..4ec1d2e 100644 --- a/vivado_custom_ip/xgui/uberddr3_axi_v1_0.tcl +++ b/vivado_custom_ip/xgui/uberddr3_axi_v1_0.tcl @@ -19,8 +19,10 @@ proc init_gui { IPINST } { set_property tooltip {Width of bank address} ${BA_BITS} set BYTE_LANES [ipgui::add_param $IPINST -name "BYTE_LANES" -parent ${Page_0}] set_property tooltip {Number of byte lanes of DDR3 RAM in the FPGA board (e.g. x16 DDR3 will have 2 byte lanes)} ${BYTE_LANES} - set ECC_ENABLE [ipgui::add_param $IPINST -name "ECC_ENABLE" -parent ${Page_0}] - set_property tooltip {0 = DIsabled, 1 = Side-band ECC per burst, 2 = Side-band ECC per 8 bursts , 3 = Inline ECC} ${ECC_ENABLE} + set ECC_ENABLE [ipgui::add_param $IPINST -name "ECC_ENABLE" -parent ${Page_0} -widget comboBox] + set_property tooltip {Type of ECC (0,1,2,3)} ${ECC_ENABLE} + set SELF_REFRESH [ipgui::add_param $IPINST -name "SELF_REFRESH" -parent ${Page_0} -widget comboBox] + set_property tooltip {Enable option for self-refresh} ${SELF_REFRESH} set SKIP_INTERNAL_TEST [ipgui::add_param $IPINST -name "SKIP_INTERNAL_TEST" -parent ${Page_0}] set_property tooltip {Check to skip built-in self-test (check this if UberDDR3 will be connected to Microblaze)} ${SKIP_INTERNAL_TEST} set ODELAY_SUPPORTED [ipgui::add_param $IPINST -name "ODELAY_SUPPORTED" -parent ${Page_0}] @@ -284,6 +286,15 @@ proc validate_PARAM_VALUE.SECOND_WISHBONE { PARAM_VALUE.SECOND_WISHBONE } { return true } +proc update_PARAM_VALUE.SELF_REFRESH { PARAM_VALUE.SELF_REFRESH } { + # Procedure called to update SELF_REFRESH when any of the dependent parameters in the arguments change +} + +proc validate_PARAM_VALUE.SELF_REFRESH { PARAM_VALUE.SELF_REFRESH } { + # Procedure called to validate SELF_REFRESH + return true +} + proc update_PARAM_VALUE.SKIP_INTERNAL_TEST { PARAM_VALUE.SKIP_INTERNAL_TEST } { # Procedure called to update SKIP_INTERNAL_TEST when any of the dependent parameters in the arguments change } @@ -405,6 +416,11 @@ proc update_MODELPARAM_VALUE.ECC_ENABLE { MODELPARAM_VALUE.ECC_ENABLE PARAM_VALU set_property value [get_property value ${PARAM_VALUE.ECC_ENABLE}] ${MODELPARAM_VALUE.ECC_ENABLE} } +proc update_MODELPARAM_VALUE.SELF_REFRESH { MODELPARAM_VALUE.SELF_REFRESH PARAM_VALUE.SELF_REFRESH } { + # Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value + set_property value [get_property value ${PARAM_VALUE.SELF_REFRESH}] ${MODELPARAM_VALUE.SELF_REFRESH} +} + proc update_MODELPARAM_VALUE.DIC { MODELPARAM_VALUE.DIC PARAM_VALUE.DIC } { # Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value set_property value [get_property value ${PARAM_VALUE.DIC}] ${MODELPARAM_VALUE.DIC}