?? ctrl.v
字號:
//*****************************************************************************// DISCLAIMER OF LIABILITY// // This text/file contains proprietary, confidential// information of Xilinx, Inc., is distributed under license// from Xilinx, Inc., and may be used, copied and/or// disclosed only pursuant to the terms of a valid license// agreement with Xilinx, Inc. Xilinx hereby grants you a // license to use this text/file solely for design, simulation, // implementation and creation of design files limited // to Xilinx devices or technologies. Use with non-Xilinx // devices or technologies is expressly prohibited and // immediately terminates your license unless covered by// a separate agreement.//// Xilinx is providing this design, code, or information // "as-is" solely for use in developing programs and // solutions for Xilinx devices, with no obligation on the // part of Xilinx to provide support. By providing this design, // code, or information as one possible implementation of // this feature, application or standard, Xilinx is making no // representation that this implementation is free from any // claims of infringement. You are responsible for // obtaining any rights you may require for your implementation. // Xilinx expressly disclaims any warranty whatsoever with // respect to the adequacy of the implementation, including // but not limited to any warranties or representations that this// implementation is free from claims of infringement, implied // warranties of merchantability or fitness for a particular // purpose.//// Xilinx products are not intended for use in life support// appliances, devices, or systems. Use in such applications is// expressly prohibited.//// Any modifications that are made to the Source Code are // done at the user抯 sole risk and will be unsupported.//// Copyright (c) 2006-2007 Xilinx, Inc. All rights reserved.//// This copyright and support notice must be retained as part // of this text at all times. //*****************************************************************************// ____ ____// / /\/ /// /___/ \ / Vendor: Xilinx// \ \ \/ Version: 2.1// \ \ Application: MIG// / / Filename: ctrl.v// /___/ /\ Date Last Modified: $Date: 2008/01/09 15:43:36 $// \ \ / \ Date Created: Wed Aug 30 2006// \___\/\___\//////Device: Virtex-5//Design Name: DDR/DDR2//Purpose:// This module is the main control logic of the memory interface. All// commands are issued from here according to the burst, CAS Latency and the// user commands.//Reference://Revision History:// Rev1.2 - Fixed auto refresh to activate bug. KP 11-19-2007//*****************************************************************************`timescale 1ns/1psmodule ctrl # ( // Following parameters are for 72-bit RDIMM design (for ML561 Reference // board design). Actual values may be different. Actual parameters values // are passed from design top module ddr2_sdram module. Please refer to // the ddr2_sdram module for actual values. parameter BANK_WIDTH = 2, parameter COL_WIDTH = 10, parameter CS_BITS = 0, parameter CS_NUM = 1, parameter ROW_WIDTH = 14, parameter ADDITIVE_LAT = 0, parameter BURST_LEN = 4, parameter CAS_LAT = 5, parameter ECC_ENABLE = 0, parameter REG_ENABLE = 1, parameter TREFI_NS = 7800, parameter TRAS = 40000, parameter TRCD = 15000, parameter TRRD = 10000, parameter TRFC = 105000, parameter TRP = 15000, parameter TRTP = 7500, parameter TWR = 15000, parameter TWTR = 10000, parameter CLK_PERIOD = 3000, parameter MULTI_BANK_EN = 1, parameter TWO_T_TIME_EN = 0, parameter DDR_TYPE = 1 ) ( input clk, input rst, input [2:0] af_cmd, input [30:0] af_addr, input af_empty, input phy_init_done, output ctrl_ref_flag, output ctrl_af_rden, output reg ctrl_wren, output reg ctrl_rden, output [ROW_WIDTH-1:0] ctrl_addr, output [BANK_WIDTH-1:0] ctrl_ba, output ctrl_ras_n, output ctrl_cas_n, output ctrl_we_n, output [CS_NUM-1:0] ctrl_cs_n ); // input address split into various ranges localparam ROW_RANGE_START = COL_WIDTH; localparam ROW_RANGE_END = ROW_WIDTH + ROW_RANGE_START - 1; localparam BANK_RANGE_START = ROW_RANGE_END + 1; localparam BANK_RANGE_END = BANK_WIDTH + BANK_RANGE_START - 1; localparam CS_RANGE_START = BANK_RANGE_START + BANK_WIDTH; localparam CS_RANGE_END = CS_NUM + CS_RANGE_START - 1; // compare address (for determining bank/row hits) split into various ranges // (compare address doesn't include column bits) localparam CMP_WIDTH = CS_NUM + BANK_WIDTH + ROW_WIDTH; localparam CMP_ROW_RANGE_START = 0; localparam CMP_ROW_RANGE_END = ROW_WIDTH + CMP_ROW_RANGE_START - 1; localparam CMP_BANK_RANGE_START = CMP_ROW_RANGE_END + 1; localparam CMP_BANK_RANGE_END = BANK_WIDTH + CMP_BANK_RANGE_START - 1; localparam CMP_CS_RANGE_START = CMP_BANK_RANGE_END + 1; localparam CMP_CS_RANGE_END = CS_BITS + CMP_CS_RANGE_START; localparam BURST_LEN_DIV2 = BURST_LEN / 2; localparam OPEN_BANK_NUM = 4; localparam CS_BITS_FIX = (CS_BITS == 0) ? 1 : CS_BITS; // calculation counters based on clock cycle and memory parameters // TRAS: ACTIVE->PRECHARGE interval - 2 localparam integer TRAS_CYC = (TRAS + CLK_PERIOD)/CLK_PERIOD; // TRCD: ACTIVE->READ/WRITE interval - 3 (for DDR2 factor in ADD_LAT) localparam integer TRRD_CYC = (TRRD + CLK_PERIOD)/CLK_PERIOD; localparam integer TRCD_CYC = (((TRCD + CLK_PERIOD)/CLK_PERIOD) > ADDITIVE_LAT )? ((TRCD+CLK_PERIOD)/ CLK_PERIOD) - ADDITIVE_LAT : 0; // TRFC: REFRESH->REFRESH, REFRESH->ACTIVE interval - 2 localparam integer TRFC_CYC = (TRFC + CLK_PERIOD)/CLK_PERIOD; // TRP: PRECHARGE->COMMAND interval - 2 // for precharge all add 1 extra clock cycle localparam integer TRP_CYC = ((TRP + CLK_PERIOD)/CLK_PERIOD) +1; // TRTP: READ->PRECHARGE interval - 2 (Al + BL/2 + (max (TRTP, 2tck))-2 localparam integer TRTP_TMP_MIN = (((TRTP + CLK_PERIOD)/CLK_PERIOD) >= 2)? ((TRTP + CLK_PERIOD)/CLK_PERIOD) : 2; localparam integer TRTP_CYC = TRTP_TMP_MIN + ADDITIVE_LAT + BURST_LEN_DIV2 - 2; // TWR: WRITE->PRECHARGE interval - 2 localparam integer WR_LAT = (DDR_TYPE > 0) ? CAS_LAT + ADDITIVE_LAT - 1 : 1; localparam integer TWR_CYC = ((TWR + CLK_PERIOD)/CLK_PERIOD) + WR_LAT + BURST_LEN_DIV2 ; // TWTR: WRITE->READ interval - 3 (for DDR1, TWTR = 2 clks) // DDR2 = CL-1 + BL/2 +TWTR localparam integer TWTR_TMP_MIN = (TWTR + CLK_PERIOD)/CLK_PERIOD; localparam integer TWTR_CYC = (DDR_TYPE > 0) ? (TWTR_TMP_MIN + (CAS_LAT -1) + BURST_LEN_DIV2 ): 2; // TRTW: READ->WRITE interval - 3 // DDR1: CL + (BL/2) // DDR2: (BL/2) + 2. Two more clocks are added to // the DDR2 counter to account for the delay in // arrival of the DQS during reads (pcb trace + buffer // delays + memory parameters). localparam TRTW_CYC = (DDR_TYPE > 0) ? BURST_LEN_DIV2 + 4 : (CAS_LAT == 25) ? 2 + BURST_LEN_DIV2 : CAS_LAT + BURST_LEN_DIV2; localparam integer CAS_LAT_RD = (CAS_LAT == 25) ? 2 : CAS_LAT; // Make sure all values >= 0 (some may be = 0) localparam TRAS_COUNT = (TRAS_CYC > 0) ? TRAS_CYC : 0; localparam TRCD_COUNT = (TRCD_CYC > 0) ? TRCD_CYC : 0; localparam TRRD_COUNT = (TRRD_CYC > 0) ? TRRD_CYC : 0; localparam TRFC_COUNT = (TRFC_CYC > 0) ? TRFC_CYC : 0; localparam TRP_COUNT = (TRP_CYC > 0) ? TRP_CYC : 0; localparam TRTP_COUNT = (TRTP_CYC > 0) ? TRTP_CYC : 0; localparam TWR_COUNT = (TWR_CYC > 0) ? TWR_CYC : 0; localparam TWTR_COUNT = (TWTR_CYC > 0) ? TWTR_CYC : 0; localparam TRTW_COUNT = (TRTW_CYC > 0) ? TRTW_CYC : 0; // Auto refresh interval localparam TREFI_COUNT = ((TREFI_NS * 1000)/CLK_PERIOD) - 1; // memory controller states localparam CTRL_IDLE = 5'h00; localparam CTRL_PRECHARGE = 5'h01; localparam CTRL_PRECHARGE_WAIT = 5'h02; localparam CTRL_AUTO_REFRESH = 5'h03; localparam CTRL_AUTO_REFRESH_WAIT = 5'h04; localparam CTRL_ACTIVE = 5'h05; localparam CTRL_ACTIVE_WAIT = 5'h06; localparam CTRL_BURST_READ = 5'h07; localparam CTRL_READ_WAIT = 5'h08; localparam CTRL_BURST_WRITE = 5'h09; localparam CTRL_WRITE_WAIT = 5'h0A; localparam CTRL_PRECHARGE_WAIT1 = 5'h0B; reg [CMP_WIDTH-1:0] act_addr_r; wire [30:0] af_addr_r; reg [30:0] af_addr_r1; reg [30:0] af_addr_r2; reg [30:0] af_addr_r3; wire [2:0] af_cmd_r; reg [2:0] af_cmd_r1; reg [2:0] af_cmd_r2; reg af_valid_r; reg af_valid_r1; reg af_valid_r2; reg [CS_BITS_FIX :0] auto_cnt_r; reg auto_ref_r; reg [(OPEN_BANK_NUM*CMP_WIDTH)-1:0] bank_cmp_addr_r; reg [OPEN_BANK_NUM-1:0] bank_hit; reg [OPEN_BANK_NUM-1:0] bank_hit_r; reg [OPEN_BANK_NUM-1:0] bank_hit_r1; reg [OPEN_BANK_NUM-1:0] bank_valid_r; reg bank_conflict_r; reg conflict_resolved_r; reg ctrl_af_rden_r; reg conflict_detect_r; wire conflict_detect; reg [ROW_WIDTH-1:0] ddr_addr_r; wire [ROW_WIDTH-1:0] ddr_addr_col; wire [ROW_WIDTH-1:0] ddr_addr_row; reg [BANK_WIDTH-1:0] ddr_ba_r; reg ddr_cas_n_r; reg [CS_NUM-1:0] ddr_cs_n_r; reg ddr_ras_n_r; reg ddr_we_n_r; reg [4:0] next_state; reg no_precharge_wait_r; reg no_precharge_r; reg no_precharge_r1; reg phy_init_done_r; reg [4:0] precharge_ok_cnt_r; reg precharge_ok_r; reg [4:0] ras_cnt_r; reg [3:0] rcd_cnt_r; reg rcd_cnt_ok_r; reg [2:0] rdburst_cnt_r; reg rdburst_ok_r; reg rdburst_rden_ok_r; reg rd_af_flag_r; wire rd_flag; reg rd_flag_r; reg [4:0] rd_to_wr_cnt_r; reg rd_to_wr_ok_r; reg ref_flag_r; reg [11:0] refi_cnt_r; reg refi_cnt_ok_r; reg rst_r /* synthesis syn_preserve = 1 */; reg rst_r1 /* synthesis syn_maxfan = 10 */; reg [7:0] rfc_cnt_r; reg rfc_ok_r; reg [3:0] row_miss; reg [3:0] row_conflict_r; reg [3:0] rp_cnt_r; reg rp_cnt_ok_r; reg [CMP_WIDTH-1:0] sb_open_add_r; reg [4:0] state_r; reg [4:0] state_r1; wire sm_rden; reg sm_rden_r; reg [2:0] trrd_cnt_r; reg trrd_cnt_ok_r; reg [2:0] two_t_enable_r; reg [CS_NUM-1:0] two_t_enable_r1; reg [2:0] wrburst_cnt_r; reg wrburst_ok_r; reg wrburst_wren_ok_r; wire wr_flag; reg wr_flag_r; reg [4:0] wr_to_rd_cnt_r; reg wr_to_rd_ok_r; // XST attributes for local reset "tree" // synthesis attribute shreg_extract of rst_r is "no"; // synthesis attribute shreg_extract of rst_r1 is "no"; // synthesis attribute equivalent_register_removal of rst_r is "no" //*************************************************************************** // sm_rden is used to assert read enable to the address FIFO assign sm_rden = ((state_r == CTRL_BURST_WRITE) || (state_r == CTRL_BURST_READ)) ; // assert read flag to the adress FIFO assign ctrl_af_rden = sm_rden || rd_af_flag_r; // local reset "tree" for controller logic only. Create this to ease timing // on reset path. Prohibit equivalent register removal on RST_R to prevent // "sharing" with other local reset trees (caution: make sure global fanout // limit is set to large enough value, otherwise SLICES may be used for // fanout control on RST_R. always @(posedge clk) begin rst_r <= rst; rst_r1 <= rst_r; end //***************************************************************** // interpret commands from Command/Address FIFO //***************************************************************** assign wr_flag = (af_valid_r2) ? ((af_cmd_r2 == 3'b000) ? 1'b1 : 1'b0): 1'b0; assign rd_flag = (af_valid_r2) ? ((af_cmd_r2 == 3'b001) ? 1'b1 : 1'b0): 1'b0; always @(posedge clk) begin rd_flag_r <= rd_flag; wr_flag_r <= wr_flag; end ////////////////////////////////////////////////// // The data from the address FIFO is fetched and // stored in two register stages. The data will be // pulled out of the second register stage whenever // the state machine can handle new data from the // address FIFO. // This flag is asserted when there is no // cmd & address in the pipe. When there is // valid cmd & addr from the address FIFO the // af_valid signals will be asserted. This flag will // be set the cycle af_valid_r is de-asserted. always @(posedge clk) begin // for simulation purposes - to force CTRL_AF_RDEN low during reset if (rst_r1) rd_af_flag_r <= 1'd0; else if((ctrl_af_rden_r) || (rd_af_flag_r && (af_valid_r || af_valid_r1))) rd_af_flag_r <= 1'd0; else if (~af_valid_r1 || ~af_valid_r) rd_af_flag_r <= 1'd1; end // First register stage for the cmd & add from the FIFO. // The af_valid_r signal gives the status of the data // in this stage. The af_valid_r will be asserted when there // is valid data. This register stage will be updated // 1. read to the FIFO and the FIFO not empty // 2. After write and read states // 3. The valid signal is not asserted in the last stage. always @(posedge clk) begin if (rst_r1)begin af_valid_r <= 1'd0; end else begin if (ctrl_af_rden_r || sm_rden_r || ~af_valid_r1 || ~af_valid_r2)begin af_valid_r <= ctrl_af_rden_r; end end end // The output register in the FIFO is used. The addr // and command are already registered in the FIFO. assign af_addr_r = af_addr; assign af_cmd_r = af_cmd; // Second register stage for the cmd & add from the FIFO. // The af_valid_r1 signal gives the status of the data // in this stage. The af_valid_r will be asserted when there // is valid data. This register stage will be updated // 1. read to the FIFO and the FIFO not empty and there // is no valid data on this stage // 2. After write and read states // 3. The valid signal is not asserted in the last stage. always@(posedge clk) begin if (rst_r1)begin af_valid_r1 <= 1'd0; af_addr_r1 <= {31{1'bx}}; af_cmd_r1 <= {3{1'bx}}; end else if (~af_valid_r1 || sm_rden_r || ~af_valid_r2) begin af_valid_r1 <= af_valid_r; af_addr_r1 <= af_addr_r; af_cmd_r1 <= af_cmd_r; end end // The state machine uses the address and command in this
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -