📄 mem_interface_top_ctrl_0.v
字号:
//*****************************************************************************
// Copyright (c) 2006 Xilinx, Inc.
// This design is confidential and proprietary of Xilinx, Inc.
// All Rights Reserved
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: $Name: i+IP+125372 $
// \ \ Application: MIG
// / / Filename: mem_interface_top_ctrl_0.v
// /___/ /\ Date Last Modified: $Date: 2007/04/18 13:49:32 $
// \ \ / \ Date Created: Wed Aug 30 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: 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:
//*****************************************************************************
`timescale 1ns/1ps
module mem_interface_top_ctrl_0 #
(
parameter BANK_WIDTH = 3,
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 = 3,
parameter ECC_ENABLE = 0,
parameter REG_ENABLE = 1,
parameter TREFI_NS = 7800,
parameter TRAS = 40000,
parameter TRCD = 15000,
parameter TRFC = 127500,
parameter TRP = 15000,
parameter TRTP = 7500,
parameter TWR = 15000,
parameter TWTR = 10000,
parameter CLK_PERIOD = 5000,
parameter MULTI_BANK_EN = 1,
parameter DDR2_ENABLE = 1
)
(
input clk,
input rst,
input [1:0] af_conflict,
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_BITS + 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_BITS + 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 - 1;
localparam BURST_LEN_DIV2 = BURST_LEN / 2;
localparam OPEN_BANK_NUM = 4;
// calculation counters based on clock cycle and memory parameters
// TRAS: ACTIVE->PRECHARGE interval - 2
localparam integer TRAS_CYC = (TRAS/CLK_PERIOD)+1;
// TRCD: ACTIVE->READ/WRITE interval - 3 (for DDR2 factor in ADD_LAT)
localparam integer TRCD_CYC = ((TRCD/CLK_PERIOD) + 1)-
ADDITIVE_LAT ;
// TRFC: REFRESH->REFRESH, REFRESH->ACTIVE interval - 2
localparam integer TRFC_CYC = TRFC/CLK_PERIOD +1;
// TRP: PRECHARGE->COMMAND interval - 2
localparam integer TRP_CYC = TRP/CLK_PERIOD + 1;
// TRTP: READ->PRECHARGE interval - 2 (for DDR2, TRTP = 2 clks)
localparam integer TRTP_TMP_MIN = ((TRTP/CLK_PERIOD) + 1 );
localparam integer TRTP_CYC = TRTP_TMP_MIN + ADDITIVE_LAT +
BURST_LEN_DIV2 - 2;
// TWR: WRITE->PRECHARGE interval - 2
localparam integer WR_LAT = (DDR2_ENABLE) ? CAS_LAT + ADDITIVE_LAT - 1 : 1;
localparam integer TWR_CYC = (TWR/CLK_PERIOD) + WR_LAT + BURST_LEN_DIV2 ;
// TWTR: WRITE->READ interval - 3 (for DDR1, TWTR = 2 clks)
localparam integer TWTR_TMP_MIN = ((TWTR/CLK_PERIOD)+1);
localparam integer TWTR_CYC = (DDR2_ENABLE) ? TWTR_TMP_MIN : 2;
// TRTW: READ->WRITE interval - 3
// DDR1: CL + (BL/2) + ECC/REG delays
// DDR2: (BL/2) + 2 + ECC/REG delays
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 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;
// 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_COMMAND_WAIT = 5'h0B;
localparam CTRL_WRITE_BANK_CONF = 5'h0C;
localparam CTRL_READ_BANK_CONF = 5'h0D;
localparam CTRL_COMMAND_WAIT_CONF = 5'h0E;
localparam CTRL_PRECHARGE_WAIT1 = 5'h0F;
wire [(CS_BITS+BANK_WIDTH)-1:0] af_addr_bank_cmp;
reg [30:0] af_addr_r
/* synthesis syn_maxfan = 1 */;
reg [30:0] af_addr_r1;
wire [ROW_WIDTH-1:0] af_addr_row_cmp;
reg [2:0] auto_cnt_r;
reg auto_ref_r;
reg bank_conf;
reg bank_conf_r
/* synthesis syn_maxfan = 5 */;
reg [(OPEN_BANK_NUM*CMP_WIDTH)-1:0] bank_cmp_addr_r
/* synthesis syn_maxfan = 1 */;
reg bank_hit_any_r;
reg [OPEN_BANK_NUM-1:0] bank_hit_r
/* synthesis syn_maxfan = 5 */;
reg [OPEN_BANK_NUM-1:0] bank_valid_r;
reg [CMP_WIDTH-1:0] open_bank_r;
wire conflict_detect;
reg conflict_detect_r
/* synthesis syn_maxfan = 2 */;
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_r;
reg no_precharge_wait_r;
reg phy_init_done_r
/* synthesis syn_preserve=1 */;
reg [3:0] ras_cnt_r;
reg [2:0] rcd_cnt_r;
reg [2:0] rdburst_cnt_r;
wire rd_flag;
reg rd_flag_r
/* synthesis syn_maxfan = 1 */;
reg [3:0] rd_to_wr_cnt_r;
reg ref_flag_r;
reg [11:0] refi_cnt_r;
reg [5:0] rfc_cnt_r;
reg [OPEN_BANK_NUM-1:0] row_miss_r
/* synthesis syn_maxfan = 5 */;
reg [2:0] rp_cnt_r;
reg [4:0] rtp_cnt_r;
reg [4:0] state_r
/* synthesis syn_maxfan = 5 */;
reg [4:0] state_r1;
reg [2:0] wrburst_cnt_r;
wire wr_flag;
reg wr_flag_r
/* synthesis syn_maxfan = 1 */;
reg [4:0] wr_to_rd_cnt_r;
reg [4:0] wtp_cnt_r;
//***************************************************************************
assign ctrl_af_rden = ((state_r == CTRL_BURST_WRITE) ||
(state_r == CTRL_BURST_READ));
// indicate potential address miss if there is a bank or row change from the
// previous command
assign conflict_detect = (| af_conflict);
//*****************************************************************
// interpret commands from Command/Address FIFO
//*****************************************************************
assign wr_flag = (af_empty) ? 1'b0 : ((af_cmd == 3'b000) ? 1'b1 : 1'b0);
assign rd_flag = (af_empty) ? 1'b0 : ((af_cmd == 3'b001) ? 1'b1 : 1'b0);
// synthesis attribute max_fanout of rd_flag_r is 1
// synthesis attribute max_fanout of wr_flag_r is 1
always @(posedge clk) begin
rd_flag_r <= rd_flag;
wr_flag_r <= wr_flag;
end
// register address inputs
// synthesis attribute max_fanout of af_addr_r is 1
always @(posedge clk) begin
af_addr_r <= af_addr;
af_addr_r1 <= af_addr_r;
end
//***************************************************************************
// Bank management logic
// Semi-hardcoded for now for 4 banks
// will keep multiple banks open if MULTI_BANK_EN is true.
//***************************************************************************
// synthesis attribute max_fanout of bank_hit_r is 5
// synthesis attribute max_fanout of row_miss_r is 5
// synthesis attribute max_fanout of bank_conf_r is 5
// synthesis attribute max_fanout of conflict_detect_r is 2
genvar bank_i;
generate // if multiple bank option chosen
if(MULTI_BANK_EN) begin: gen_multi_bank_open
assign af_addr_bank_cmp = af_addr[CS_RANGE_END:BANK_RANGE_START];
assign af_addr_row_cmp = af_addr[ROW_RANGE_END:ROW_RANGE_START];
for (bank_i = 0; bank_i < OPEN_BANK_NUM;
bank_i = bank_i + 1) begin: gen_bank_hit
// asserted if bank address match + open bank entry is valid
always @(posedge clk) begin
bank_hit_r[bank_i]
= ((bank_cmp_addr_r[(CMP_WIDTH*(bank_i+1))-1:
(CMP_WIDTH*bank_i)+ROW_WIDTH] ==
af_addr_bank_cmp) && bank_valid_r[bank_i]);
// asserted if row address match (no check for bank entry valid, rely
// on this term to be used in conjunction with BANK_HIT[])
row_miss_r[bank_i]
= (bank_cmp_addr_r[(CMP_WIDTH*bank_i)+ROW_WIDTH-1:
(CMP_WIDTH*bank_i)] != af_addr_row_cmp);
end
end
always @(posedge clk) begin
bank_hit_any_r <= | bank_hit_r;
no_precharge_wait_r <= bank_valid_r[3] & ~(|bank_hit_r);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -