// (C) 2001-2019 Intel Corporation. All rights reserved. // Your use of Intel Corporation's design tools, logic functions and other // software and tools, and its AMPP partner logic functions, and any output // files from any of the foregoing (including device programming or simulation // files), and any associated documentation or information are expressly subject // to the terms and conditions of the Intel Program License Subscription // Agreement, Intel FPGA IP License Agreement, or other applicable // license agreement, including, without limitation, that your use is for the // sole purpose of programming logic devices manufactured by Intel and sold by // Intel or its authorized distributors. Please refer to the applicable // agreement for further details. `timescale 1 ps / 1 ps module rw_manager_generic ( avl_clk, avl_reset_n, avl_address, avl_write, avl_writedata, avl_read, avl_readdata, avl_waitrequest, afi_clk, afi_reset_n, afi_wdata, afi_dm, afi_odt, afi_rdata, afi_rdata_valid, afi_wrank, afi_rrank, ac_masked_bus, ac_bus, csr_clk, csr_ena, csr_dout_phy, csr_dout ); parameter AVL_DATA_WIDTH = ""; parameter AVL_ADDRESS_WIDTH = ""; parameter MEM_DQ_WIDTH = ""; parameter MEM_DM_WIDTH = ""; parameter MEM_ODT_WIDTH = ""; parameter MEM_NUMBER_OF_RANKS = ""; parameter MASK_WIDTH = ""; parameter AC_ODT_BIT = ""; parameter AC_BUS_WIDTH = ""; parameter AC_MASKED_BUS_WIDTH = ""; parameter AFI_RATIO = ""; parameter MEM_READ_DQS_WIDTH = ""; parameter MEM_WRITE_DQS_WIDTH = ""; parameter DEBUG_READ_DI_WIDTH = ""; parameter DEBUG_WRITE_TO_READ_RATIO_2_EXPONENT = ""; parameter DEBUG_WRITE_TO_READ_RATIO = ""; parameter MAX_DI_BUFFER_WORDS_LOG_2 = ""; parameter RATE = ""; parameter HCX_COMPAT_MODE = 0; parameter DEVICE_FAMILY = ""; parameter AC_ROM_INIT_FILE_NAME = ""; parameter INST_ROM_INIT_FILE_NAME = ""; parameter USE_ALL_AFI_PHASES_FOR_COMMAND_ISSUE = 0; parameter AP_MODE_EN = 2'b00; parameter AVL_CLK_PS = 1000; parameter AFI_CLK_PS = 1000; parameter ENABLE_NON_DES_CAL = 0; parameter TREFI = 36000; parameter REFRESH_INTERVAL = 30000; parameter TRFC = 370; parameter REFRESH_RANKS_SIMUL = 1; input avl_clk; input avl_reset_n; input [AVL_ADDRESS_WIDTH-1:0] avl_address; input avl_write; input [AVL_DATA_WIDTH-1:0] avl_writedata; input avl_read; output [AVL_DATA_WIDTH-1:0] avl_readdata; output avl_waitrequest; input afi_clk; input afi_reset_n; output [AC_MASKED_BUS_WIDTH - 1:0] ac_masked_bus; output [AC_BUS_WIDTH - 1:0] ac_bus; output [MEM_DQ_WIDTH * 2 * AFI_RATIO - 1:0] afi_wdata; output [MEM_DM_WIDTH * 2 * AFI_RATIO - 1:0] afi_dm; output [MEM_ODT_WIDTH * AFI_RATIO - 1:0] afi_odt; output [MEM_WRITE_DQS_WIDTH * MEM_NUMBER_OF_RANKS * AFI_RATIO - 1:0] afi_wrank; output [MEM_READ_DQS_WIDTH * MEM_NUMBER_OF_RANKS * AFI_RATIO - 1:0] afi_rrank; input [MEM_DQ_WIDTH * 2 * AFI_RATIO - 1:0] afi_rdata; input afi_rdata_valid; input csr_clk; input csr_ena; input csr_dout_phy; output csr_dout; reg [AVL_DATA_WIDTH-1:0] avl_readdata; reg avl_waitrequest; wire avl_wr; reg cmd_done_avl; wire [AC_BUS_WIDTH - 1:0] ac_bus; wire [AC_MASKED_BUS_WIDTH - 1:0] ac_masked_bus; reg [AVL_DATA_WIDTH-1:0] avl_readdata_raw; wire avl_rd; wire cmd_read; wire cmd_write; reg avl_rd_r; reg avl_wr_r; typedef enum int unsigned { STATE_RW_IDLE, STATE_RW_EXEC, STATE_RW_DONE, STATE_RW_REFRESH, STATE_RW_RESTORE } STATE_RW_T; STATE_RW_T state; assign avl_rd = avl_read; wire [7:0] jump_ptr_0_export; wire [7:0] jump_ptr_1_export; wire [7:0] jump_cntr_0_export; wire [7:0] jump_cntr_1_export; wire [7:0] cs_mask_export; reg [7:0] jump_ptr_0_reg; reg [7:0] jump_ptr_1_reg; reg [7:0] jump_cntr_0_reg; reg [7:0] jump_cntr_1_reg; reg [7:0] cs_mask_reg; reg req_avl_bus; reg have_avl_bus; wire all_refresh_done; wire restore_done; reg refresh_enabled; reg refresh_took_too_long; generate if (ENABLE_NON_DES_CAL==1) begin wire decode_enable_refresh; assign decode_enable_refresh = (avl_address [11:8] == 4'b1100); always @(posedge avl_clk or negedge avl_reset_n) begin if (~avl_reset_n) refresh_enabled <= 1'b0; else if (avl_write & decode_enable_refresh) begin if (avl_writedata == {AVL_DATA_WIDTH{1'b0}}) refresh_enabled <= 1'b0; else refresh_enabled <= 1'b1; end end assign avl_wr = avl_write & ~decode_enable_refresh; assign avl_readdata = (decode_enable_refresh)? {'0, refresh_took_too_long}: avl_readdata_raw; end else begin assign req_avl_bus = 1'b0; assign avl_wr = avl_write; assign avl_readdata = avl_readdata_raw; end endgenerate always_ff @(posedge avl_clk) begin if (~avl_reset_n) begin state <= STATE_RW_IDLE; cs_mask_reg <= '0; jump_ptr_0_reg <= '0; jump_ptr_1_reg <= '0; jump_cntr_0_reg <= '0; jump_cntr_1_reg <= '0; end else begin case (state) STATE_RW_IDLE: begin if (req_avl_bus) begin state <= STATE_RW_REFRESH; cs_mask_reg <= cs_mask_export; jump_ptr_0_reg <= jump_ptr_0_export; jump_ptr_1_reg <= jump_ptr_1_export; jump_cntr_0_reg <= jump_cntr_0_export; jump_cntr_1_reg <= jump_cntr_1_export; end else begin if (avl_rd) begin state <= STATE_RW_EXEC; end if (avl_wr) begin state <= STATE_RW_EXEC; end end end STATE_RW_EXEC: if (cmd_done_avl) begin state <= STATE_RW_DONE; end STATE_RW_DONE: begin state <= STATE_RW_IDLE; end STATE_RW_REFRESH: begin if (all_refresh_done) begin state <= STATE_RW_RESTORE; end end STATE_RW_RESTORE: begin if (restore_done) begin state <= STATE_RW_DONE; end end endcase end end reg [AVL_DATA_WIDTH - 1:0] avl_writedata_avl; reg [AVL_ADDRESS_WIDTH - 1:0] avl_address_avl; wire [AVL_DATA_WIDTH - 1:0] avl_readdata_afi; wire cmd_done_afi; reg [AVL_DATA_WIDTH - 1:0] avl_writedata_avl_refresh; reg [AVL_ADDRESS_WIDTH - 1:0] avl_address_avl_refresh; wire [AVL_DATA_WIDTH - 1:0] avl_writedata_avl_muxed; wire [AVL_ADDRESS_WIDTH - 1:0] avl_address_avl_muxed; wire cmd_read_muxed; wire cmd_write_muxed; generate if (ENABLE_NON_DES_CAL==0) begin assign avl_writedata_avl_muxed = avl_writedata_avl; assign avl_address_avl_muxed = avl_address_avl; assign cmd_read_muxed = cmd_read; assign cmd_write_muxed = cmd_write; end endgenerate reg [AVL_DATA_WIDTH - 1:0] avl_readdata_g_avl; always @(posedge avl_clk or negedge avl_reset_n) begin if (~avl_reset_n) begin avl_writedata_avl <= {AVL_DATA_WIDTH{1'b0}}; avl_address_avl <= {AVL_ADDRESS_WIDTH{1'b0}}; avl_readdata_g_avl <= {AVL_DATA_WIDTH{1'b0}}; cmd_done_avl <= 1'b0; avl_rd_r <= 1'b0; avl_wr_r <= 1'b0; end else begin avl_writedata_avl <= avl_writedata; avl_address_avl <= avl_address; avl_readdata_g_avl <= avl_readdata_afi; cmd_done_avl <= cmd_done_afi; avl_rd_r <= avl_rd; avl_wr_r <= avl_wr; end end rw_manager_core rw_mgr_core_inst ( .avl_reset_n(avl_reset_n), .avl_clk(avl_clk), .afi_clk(afi_clk), .avl_address(avl_address_avl_muxed), .avl_readdata(avl_readdata_afi), .avl_writedata(avl_writedata_avl_muxed), .afi_reset_n(afi_reset_n), .afi_wdata(afi_wdata), .afi_dm(afi_dm), .afi_odt(afi_odt), .afi_rdata(afi_rdata), .afi_rdata_valid(afi_rdata_valid), .afi_wrank(afi_wrank), .afi_rrank(afi_rrank), .ac_bus(ac_bus), .ac_masked_bus(ac_masked_bus), .cmd_read(cmd_read_muxed), .cmd_write(cmd_write_muxed), .cmd_done(cmd_done_afi), .csr_clk(csr_clk), .csr_ena(csr_ena), .csr_dout_phy(csr_dout_phy), .csr_dout(csr_dout), .cs_mask_export(cs_mask_export), .jump_ptr_0_export(jump_ptr_0_export), .jump_ptr_1_export(jump_ptr_1_export), .jump_cntr_0_export(jump_cntr_0_export), .jump_cntr_1_export(jump_cntr_1_export) ); defparam rw_mgr_core_inst.AVL_DATA_WIDTH = AVL_DATA_WIDTH; defparam rw_mgr_core_inst.AVL_ADDRESS_WIDTH = AVL_ADDRESS_WIDTH; defparam rw_mgr_core_inst.MEM_DQ_WIDTH = MEM_DQ_WIDTH; defparam rw_mgr_core_inst.MEM_DM_WIDTH = MEM_DM_WIDTH; defparam rw_mgr_core_inst.MEM_ODT_WIDTH = MEM_ODT_WIDTH; defparam rw_mgr_core_inst.MEM_NUMBER_OF_RANKS = MEM_NUMBER_OF_RANKS; defparam rw_mgr_core_inst.MASK_WIDTH = MASK_WIDTH; defparam rw_mgr_core_inst.AC_ODT_BIT = AC_ODT_BIT; defparam rw_mgr_core_inst.AC_BUS_WIDTH = AC_BUS_WIDTH; defparam rw_mgr_core_inst.AC_MASKED_BUS_WIDTH = AC_MASKED_BUS_WIDTH; defparam rw_mgr_core_inst.AFI_RATIO = AFI_RATIO; defparam rw_mgr_core_inst.MEM_READ_DQS_WIDTH = MEM_READ_DQS_WIDTH; defparam rw_mgr_core_inst.MEM_WRITE_DQS_WIDTH = MEM_WRITE_DQS_WIDTH; defparam rw_mgr_core_inst.DEBUG_READ_DI_WIDTH = DEBUG_READ_DI_WIDTH; defparam rw_mgr_core_inst.DEBUG_WRITE_TO_READ_RATIO_2_EXPONENT = DEBUG_WRITE_TO_READ_RATIO_2_EXPONENT; defparam rw_mgr_core_inst.DEBUG_WRITE_TO_READ_RATIO = DEBUG_WRITE_TO_READ_RATIO; defparam rw_mgr_core_inst.RATE = RATE; defparam rw_mgr_core_inst.HCX_COMPAT_MODE = HCX_COMPAT_MODE; defparam rw_mgr_core_inst.DEVICE_FAMILY = DEVICE_FAMILY; defparam rw_mgr_core_inst.AC_ROM_INIT_FILE_NAME = AC_ROM_INIT_FILE_NAME; defparam rw_mgr_core_inst.INST_ROM_INIT_FILE_NAME = INST_ROM_INIT_FILE_NAME; defparam rw_mgr_core_inst.MAX_DI_BUFFER_WORDS_LOG_2 = MAX_DI_BUFFER_WORDS_LOG_2; defparam rw_mgr_core_inst.USE_ALL_AFI_PHASES_FOR_COMMAND_ISSUE = USE_ALL_AFI_PHASES_FOR_COMMAND_ISSUE; defparam rw_mgr_core_inst.AP_MODE_EN = AP_MODE_EN; assign cmd_read = avl_rd_r & ~cmd_done_avl & (state == STATE_RW_EXEC); assign cmd_write = avl_wr_r & ~cmd_done_avl & (state == STATE_RW_EXEC); always_comb begin if (((avl_wr || avl_rd) && (~cmd_done_avl || state != STATE_RW_EXEC)) || ~avl_reset_n || state == STATE_RW_REFRESH) avl_waitrequest = 1; else avl_waitrequest = 0; if (avl_rd) avl_readdata_raw = avl_readdata_g_avl; else avl_readdata_raw = '0; end assert property (@(posedge avl_reset_n) AC_MASKED_BUS_WIDTH == MASK_WIDTH*AFI_RATIO) $display("%t, [GENERIC ASSERT] AC_MASKED_BUS_WIDTH PARAMETER is correct", $time); else $error("%t, [GENERIC ASSERT] AC_MASKED_BUS_WIDTH PARAMETER is incorrect, AC_MASKED_BUS_WIDTH = %d, MASK_WIDTH*AFI_RATIO = %d", $time, AC_MASKED_BUS_WIDTH, MASK_WIDTH*AFI_RATIO); assert property (@(posedge avl_clk) !avl_reset_n |-> !cmd_read); assert property (@(posedge avl_clk) !avl_reset_n |-> avl_waitrequest); generate if (ENABLE_NON_DES_CAL==1) begin localparam MAX_REFI_COUNT= (REFRESH_INTERVAL*1000)/AVL_CLK_PS; localparam REALLY_MAX_REFI_COUNT = (TREFI*1000)/AVL_CLK_PS; localparam MAX_TRFC = (TRFC*1000)/AFI_CLK_PS; localparam WAIT_TIME = 400000/AVL_CLK_PS; reg [16:0] refi_counter; reg [2:0] rank_counter; wire refresh_done; wire time_for_refresh; assign time_for_refresh = (ENABLE_NON_DES_CAL==1) & (refi_counter == MAX_REFI_COUNT[16:0]); typedef enum int unsigned { STATE_RF_IDLE, STATE_RF_SET_MASK, STATE_RF_PRECHARGE, STATE_RF_REFRESH_0, STATE_RF_REFRESH_1, STATE_RF_REFRESH_2, STATE_RF_REFRESH_3, STATE_RF_REFRESH_4, STATE_RF_WAIT, STATE_RF_ACTIVATE_0, STATE_RF_ACTIVATE_1, STATE_RF_ACTIVATE_2, STATE_RF_ACTIVATE_3, STATE_RF_ACTIVATE_4, STATE_RF_RESTORE_0, STATE_RF_RESTORE_1, STATE_RF_RESTORE_2, STATE_RF_RESTORE_3, STATE_RF_RESTORE_4 } STATE_RF_T; STATE_RF_T rf_state; STATE_RF_T next_rf_state; wire start_refresh; wire issue_refresh_cmd; wire go_next_refresh; wire wait_done; reg refresh_cmd; reg refresh_wait; assign issue_refresh_cmd = refresh_cmd; assign go_next_refresh = (cmd_done_avl == 1'b0) && (refresh_wait == 1'b1); always @(posedge avl_clk or negedge avl_reset_n) begin if (~avl_reset_n) begin rf_state <= STATE_RF_IDLE; refi_counter <= '0; refresh_cmd <= 1'b0; refresh_wait <= 1'b0; refresh_took_too_long <= 1'b0; end else begin if (refresh_enabled) refi_counter <= (rf_state == STATE_RF_REFRESH_0 || rf_state == STATE_RF_REFRESH_4)? '0 : refi_counter + 1; if (refi_counter > REALLY_MAX_REFI_COUNT [16:0]) refresh_took_too_long <= 1'b1; if ( ((rf_state == STATE_RF_WAIT) & wait_done) | ((rf_state == STATE_RF_IDLE) & (start_refresh | state == STATE_RW_RESTORE)) | (~refresh_wait & cmd_done_avl & (rf_state != STATE_RF_WAIT && rf_state != STATE_RF_IDLE )) ) begin rf_state <= next_rf_state; refresh_cmd <= 1'b0; refresh_wait <= 1'b1; end else if (rf_state != STATE_RF_WAIT & rf_state != STATE_RF_IDLE) begin if (~cmd_done_avl) refresh_wait <= 1'b0; if (~refresh_wait) refresh_cmd <= 1'b1; end end end reg [16:0] wait_cntr; always @(posedge avl_clk or negedge avl_reset_n) begin if (~avl_reset_n) wait_cntr <= '0; else begin if (rf_state == STATE_RF_WAIT) wait_cntr <= wait_cntr + 1; else wait_cntr <= 0; end end assign wait_done = (wait_cntr == WAIT_TIME); wire [AVL_DATA_WIDTH-1:0] rank_mask; assign rank_mask = (REFRESH_RANKS_SIMUL == 1)? '0 : {'0, ~(7'h01 << rank_counter)}; always_comb begin case (rf_state) STATE_RF_IDLE: begin avl_address_avl_refresh = '0; avl_writedata_avl_refresh = '0; next_rf_state = (state == STATE_RW_REFRESH & start_refresh)? STATE_RF_SET_MASK : (state == STATE_RW_RESTORE)? STATE_RF_RESTORE_0 : STATE_RF_IDLE; end STATE_RF_SET_MASK: begin avl_address_avl_refresh = {20'h00000 ,4'b0101, 8'h00}; avl_writedata_avl_refresh = rank_mask; next_rf_state = STATE_RF_PRECHARGE; end STATE_RF_PRECHARGE: begin avl_address_avl_refresh = 32'h0000; avl_writedata_avl_refresh = 32'h12; next_rf_state = STATE_RF_REFRESH_0; end STATE_RF_REFRESH_0: begin avl_address_avl_refresh = 32'h0300; avl_writedata_avl_refresh = 32'h14; next_rf_state = STATE_RF_REFRESH_1; end STATE_RF_REFRESH_1: begin avl_address_avl_refresh = 32'h0301; avl_writedata_avl_refresh = 32'h0015; next_rf_state = STATE_RF_REFRESH_2; end STATE_RF_REFRESH_2: begin avl_address_avl_refresh = 32'h0200; avl_writedata_avl_refresh = 32'h0007; next_rf_state = STATE_RF_REFRESH_3; end STATE_RF_REFRESH_3: begin avl_address_avl_refresh = 32'h0201; avl_writedata_avl_refresh = MAX_TRFC; next_rf_state = STATE_RF_REFRESH_4; end STATE_RF_REFRESH_4: begin avl_address_avl_refresh = 32'h0000; avl_writedata_avl_refresh = 32'h14; next_rf_state = STATE_RF_WAIT; end STATE_RF_WAIT: begin avl_address_avl_refresh = 32'h0000; avl_writedata_avl_refresh = 32'd0; next_rf_state = STATE_RF_ACTIVATE_0; end STATE_RF_ACTIVATE_0: begin avl_address_avl_refresh = 32'h0200; avl_writedata_avl_refresh = 32'h00; next_rf_state = STATE_RF_ACTIVATE_1; end STATE_RF_ACTIVATE_1: begin avl_address_avl_refresh = 32'h0201; avl_writedata_avl_refresh = 32'h0F; next_rf_state = STATE_RF_ACTIVATE_2; end STATE_RF_ACTIVATE_2: begin avl_address_avl_refresh = 32'h0300; avl_writedata_avl_refresh = 32'h0E; next_rf_state = STATE_RF_ACTIVATE_3; end STATE_RF_ACTIVATE_3: begin avl_address_avl_refresh = 32'h0301; avl_writedata_avl_refresh = 32'h10; next_rf_state = STATE_RF_ACTIVATE_4; end STATE_RF_ACTIVATE_4: begin avl_address_avl_refresh = 32'h0000; avl_writedata_avl_refresh = 32'h0D; next_rf_state = STATE_RF_IDLE; end STATE_RF_RESTORE_0: begin avl_address_avl_refresh = {20'h00000 ,4'b0101, 8'h00}; avl_writedata_avl_refresh = cs_mask_reg; next_rf_state = STATE_RF_RESTORE_1; end STATE_RF_RESTORE_1: begin avl_address_avl_refresh = 32'h0200; avl_writedata_avl_refresh = jump_cntr_0_reg; next_rf_state = STATE_RF_RESTORE_2; end STATE_RF_RESTORE_2: begin avl_address_avl_refresh = 32'h0201; avl_writedata_avl_refresh = jump_cntr_1_reg; next_rf_state = STATE_RF_RESTORE_3; end STATE_RF_RESTORE_3: begin avl_address_avl_refresh = 32'h0300; avl_writedata_avl_refresh = jump_ptr_0_reg; next_rf_state = STATE_RF_RESTORE_4; end STATE_RF_RESTORE_4: begin avl_address_avl_refresh = 32'h0301; avl_writedata_avl_refresh = jump_ptr_1_reg; next_rf_state = STATE_RF_IDLE; end default: begin avl_address_avl_refresh = 32'h0000; avl_writedata_avl_refresh = 32'd0; next_rf_state = STATE_RF_IDLE; end endcase end assign refresh_done = (rf_state == STATE_RF_ACTIVATE_3); assign restore_done = (rf_state == STATE_RF_RESTORE_4) & cmd_done_avl & ~refresh_wait; always @(posedge avl_clk or negedge avl_reset_n) begin if (~avl_reset_n) rank_counter <= '0; else begin if (all_refresh_done | (REFRESH_RANKS_SIMUL == 1)) rank_counter <= '0; else if (refresh_done & go_next_refresh) rank_counter <= rank_counter + 1; end end assign all_refresh_done = ((rank_counter == MEM_NUMBER_OF_RANKS[2:0]) | (REFRESH_RANKS_SIMUL == 1)) & refresh_done; reg [7:0] idle_wait; localparam IDLE_WAIT_CNT= 32; assign start_refresh = (idle_wait == IDLE_WAIT_CNT[7:0]) & have_avl_bus; assign avl_writedata_avl_muxed = (have_avl_bus)? avl_writedata_avl_refresh : avl_writedata_avl; assign avl_address_avl_muxed = (have_avl_bus)? avl_address_avl_refresh : avl_address_avl; assign cmd_read_muxed = (have_avl_bus)? 1'b0 : cmd_read; assign cmd_write_muxed = (have_avl_bus)? issue_refresh_cmd : cmd_write; always @(posedge avl_clk or negedge avl_reset_n) begin if (~avl_reset_n) begin idle_wait <= '0; req_avl_bus <= 1'b0; have_avl_bus <= 1'b0; end else begin if (time_for_refresh) req_avl_bus <= 1'b1; else if (have_avl_bus) req_avl_bus <= 1'b0; if (req_avl_bus & state == STATE_RW_REFRESH) have_avl_bus <= 1'b1; else if (restore_done ) have_avl_bus <= 1'b0; if (have_avl_bus & rf_state == STATE_RF_IDLE) idle_wait <= idle_wait +1; else idle_wait <= '0; end end end endgenerate endmodule