📄 mem_interface_top_phy_init_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_phy_init_0.v
// /___/ /\ Date Last Modified: $Date: 2007/04/18 13:49:32 $
// \ \ / \ Date Created: Thu Aug 24 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
//Reference:
// This module is the intialization control logic of the memory interface.
// All commands are issued from here acoording to the burst, CAS Latency and
// the user commands.
//Revision History:
//*****************************************************************************
`timescale 1ns/1ps
module mem_interface_top_phy_init_0 #
(
parameter BANK_WIDTH = 3,
parameter CKE_WIDTH = 1,
parameter COL_WIDTH = 10,
parameter CS_NUM = 1,
parameter DQ_WIDTH = 72,
parameter ODT_WIDTH = 1,
parameter ROW_WIDTH = 14,
parameter ADDITIVE_LAT = 0,
parameter BURST_LEN = 4,
parameter BURST_TYPE = 0,
parameter CAS_LAT = 3,
parameter ODT_TYPE = 0,
parameter REDUCE_DRV = 0,
parameter REG_ENABLE = 1,
parameter DDR2_ENABLE = 1,
parameter DQS_GATE_EN = 0,
parameter SIM_ONLY = 0
)
(
input clk0,
input rst0,
input [3:0] calib_done,
input ctrl_ref_flag,
output reg [3:0] calib_start,
output reg phy_init_wren,
output reg phy_init_rden,
output phy_init_wdf_wren,
output [63:0] phy_init_wdf_data,
output [ROW_WIDTH-1:0] phy_init_addr,
output [BANK_WIDTH-1:0] phy_init_ba,
output phy_init_ras_n,
output phy_init_cas_n,
output phy_init_we_n,
output [CS_NUM-1:0] phy_init_cs_n,
output [CKE_WIDTH-1:0] phy_init_cke,
output reg phy_init_done /* synthesis syn_maxfan = 1 */
);
// time to wait after initialization-related writes and reads (used as a
// generic delay - exact number doesn't matter as long as it's large enough)
localparam CNTNEXT = 6'b101011;
localparam INIT_IDLE = 5'h00;
localparam INIT_CNT_200 = 5'h01;
localparam INIT_CNT_200_WAIT = 5'h02;
localparam INIT_PRECHARGE = 5'h03;
localparam INIT_PRECHARGE_WAIT = 5'h04;
localparam INIT_LOAD_MODE = 5'h05;
localparam INIT_MODE_REGISTER_WAIT = 5'h06;
localparam INIT_AUTO_REFRESH = 5'h07;
localparam INIT_AUTO_REFRESH_WAIT = 5'h08;
localparam INIT_DEEP_MEMORY_ST = 5'h09;
localparam INIT_DUMMY_ACTIVE = 5'h0A;
localparam INIT_DUMMY_ACTIVE_WAIT = 5'h0B;
localparam INIT_CAL1_WRITE = 5'h0C;
localparam INIT_CAL1_WRITE_READ = 5'h0D;
localparam INIT_CAL1_READ = 5'h0E;
localparam INIT_CAL1_READ_WAIT = 5'h0F;
localparam INIT_CAL2_WRITE = 5'h10;
localparam INIT_CAL2_WRITE_READ = 5'h11;
localparam INIT_CAL2_READ = 5'h12;
localparam INIT_CAL2_READ_WAIT = 5'h13;
localparam INIT_CAL3_WRITE = 5'h14;
localparam INIT_CAL3_WRITE_READ = 5'h15;
localparam INIT_CAL3_READ = 5'h16;
localparam INIT_CAL3_READ_WAIT = 5'h17;
localparam INIT_CAL4_READ = 5'h18;
localparam INIT_CAL4_READ_WAIT = 5'h19;
reg [1:0] burst_addr_r;
reg [1:0] burst_cnt_r;
wire [1:0] burst_val;
wire cal_read;
wire cal_write;
wire cal_write_read;
reg [15:0] calib_start_shift0_r;
reg [15:0] calib_start_shift1_r;
reg [15:0] calib_start_shift2_r;
reg [15:0] calib_start_shift3_r;
reg [1:0] chip_cnt_r;
reg [4:0] cke_200us_cnt_r;
reg [7:0] cnt_200_cycle_r;
reg cnt_200_cycle_done_r;
reg [5:0] cnt6_r;
reg done_200us_r;
reg [ROW_WIDTH-1:0] ddr_addr_r;
reg [ROW_WIDTH-1:0] ddr_addr_r1;
reg [BANK_WIDTH-1:0] ddr_ba_r;
reg [BANK_WIDTH-1:0] ddr_ba_r1;
reg ddr_cas_n_r;
reg ddr_cas_n_r1;
reg [CKE_WIDTH-1:0] ddr_cke_r;
reg [CS_NUM-1:0] ddr_cs_n_r;
reg ddr_ras_n_r;
reg ddr_ras_n_r1;
reg ddr_we_n_r;
reg ddr_we_n_r1;
wire [15:0] ext_mode_reg;
reg [3:0] init_cnt_r /* synthesis syn_maxfan = 1 */;
reg [4:0] init_next_state;
reg [4:0] init_state_r /* synthesis syn_maxfan = 3 */;
reg [4:0] init_state_r1 /* synthesis syn_maxfan = 3 */;
reg [4:0] init_state_r2 /* synthesis syn_maxfan = 3 */;
wire [15:0] load_mode_reg;
wire [3:0] start_cal;
reg [3:0] init_wdf_cnt_r;
reg [63:0] init_data_r;
reg init_done_r;
reg init_wren_r;
reg [3:0] calib_done_r;
reg phy_init_done_r;
//***************************************************************************
//*****************************************************************
// Mode Register (MR):
// [15:14] - unused - 00
// [13] - reserved - 0
// [12] - Power-down mode - 0 (normal)
// [11:9] - write recovery - same value as written to CAS LAT
// [8] - DLL reset - 0 or 1
// [7] - Test Mode - 0 (normal)
// [6:4] - CAS latency - CAS_LAT
// [3] - Burst Type - BURST_TYPE
// [2:0] - Burst Length - BURST_LEN
//*****************************************************************
generate
if (DDR2_ENABLE) begin: gen_load_mode_reg_ddr2
assign load_mode_reg[2:0] = (BURST_LEN == 8) ? 3'b011 :
((BURST_LEN == 4) ? 3'b010 : 3'b111);
assign load_mode_reg[3] = BURST_TYPE;
assign load_mode_reg[6:4] = (CAS_LAT == 3) ? 3'b011 :
((CAS_LAT == 4) ? 3'b100 :
((CAS_LAT == 5) ? 3'b101 : 3'b111));
assign load_mode_reg[7] = 1'b0;
assign load_mode_reg[8] = 1'b0; // init value only (DLL not reset)
assign load_mode_reg[11:9] = load_mode_reg[6:4];
assign load_mode_reg[15:12] = 4'b000;
end else begin: gen_load_mode_reg_ddr1
assign load_mode_reg[2:0] = (BURST_LEN == 8) ? 3'b011 :
((BURST_LEN == 4) ? 3'b010 :
((BURST_LEN == 2) ? 3'b001 : 3'b111));
assign load_mode_reg[3] = BURST_TYPE;
assign load_mode_reg[6:4] = (CAS_LAT == 2) ? 3'b010 :
((CAS_LAT == 3) ? 3'b011 :
((CAS_LAT == 25) ? 3'b110 : 3'b111));
assign load_mode_reg[12:7] = 6'b000000; // init value only
assign load_mode_reg[15:13] = 3'b000;
end
endgenerate
//*****************************************************************
// Extended Mode Register (MR):
// [15:14] - unused - 00
// [13] - reserved - 0
// [12] - output enable - 0 (enabled)
// [11] - RDQS enable - 0 (disabled)
// [10] - DQS# enable - 0 (enabled)
// [9:7] - OCD Program - 111 or 000 (first 111, then 000 during init)
// [6] - RTT[1] - RTT[1:0] = 0(no ODT), 1(75), 2(150), 3(50)
// [5:3] - Additive CAS - ADDITIVE_CAS
// [2] - RTT[0]
// [1] - Output drive - REDUCE_DRV (= 0(full), = 1 (reduced)
// [0] - DLL enable - 0 (normal)
//*****************************************************************
generate
if (DDR2_ENABLE) begin: gen_ext_mode_reg_ddr2
assign ext_mode_reg[0] = 1'b0;
assign ext_mode_reg[1] = REDUCE_DRV;
assign ext_mode_reg[2] = ((ODT_TYPE == 1) || (ODT_TYPE == 3)) ?
1'b1 : 1'b0;
assign ext_mode_reg[5:3] = (ADDITIVE_LAT == 0) ? 3'b000 :
((ADDITIVE_LAT == 1) ? 3'b001 :
((ADDITIVE_LAT == 2) ? 3'b010 :
((ADDITIVE_LAT == 3) ? 3'b011 :
((ADDITIVE_LAT == 4) ? 3'b100 :
3'b111))));
assign ext_mode_reg[6] = ((ODT_TYPE == 2) || (ODT_TYPE == 3)) ?
1'b1 : 1'b0;
assign ext_mode_reg[9:7] = 3'b000;
assign ext_mode_reg[10] = 1'b0;
assign ext_mode_reg[15:10] = 6'b000000;
end else begin: gen_ext_mode_reg_ddr1
assign ext_mode_reg[0] = 1'b0;
assign ext_mode_reg[1] = REDUCE_DRV;
assign ext_mode_reg[12:2] = 11'b00000000000;
assign ext_mode_reg[15:13] = 3'b000;
end
endgenerate
//***************************************************************************
// generate pulse for each of calibration start controls
assign start_cal[0] = ((init_state_r1 == INIT_CAL1_READ) &&
(init_state_r2 != INIT_CAL1_READ));
assign start_cal[1] = ((init_state_r1 == INIT_CAL2_READ) &&
(init_state_r2 != INIT_CAL2_READ));
assign start_cal[2] = ((init_state_r1 == INIT_CAL3_READ) &&
(init_state_r2 == INIT_CAL3_WRITE_READ));
assign start_cal[3] = ((init_state_r1 == INIT_CAL4_READ) &&
(init_state_r2 == INIT_CAL3_READ_WAIT));
// Delay start of each calibration by 16 clock cycles to
// ensure that when calibration logic begins, that read data is already
// appearing on the bus. Don't really need it, it's more for simulation
// purposes. Each circuit should synthesize using an SRL16.
always @(posedge clk0) begin
calib_start_shift0_r <= {calib_start_shift0_r[14:0], start_cal[0]};
calib_start_shift1_r <= {calib_start_shift1_r[14:0], start_cal[1]};
calib_start_shift2_r <= {calib_start_shift2_r[14:0], start_cal[2]};
calib_start_shift3_r <= {calib_start_shift3_r[14:0], start_cal[3]};
calib_start[0] <= calib_start_shift0_r[15];
calib_start[1] <= calib_start_shift1_r[15];
calib_start[2] <= calib_start_shift2_r[15];
calib_start[3] <= calib_start_shift3_r[15];
end
// generate delay for various states that require it (no maximum delay
// requirement, make sure that terminal count is large enough to cover
// all cases)
always @(posedge clk0) begin
case (init_state_r)
INIT_PRECHARGE_WAIT,
INIT_MODE_REGISTER_WAIT,
INIT_AUTO_REFRESH_WAIT,
INIT_DUMMY_ACTIVE_WAIT,
INIT_CAL1_WRITE_READ,
INIT_CAL1_READ_WAIT,
INIT_CAL2_WRITE_READ,
INIT_CAL2_READ_WAIT,
INIT_CAL3_WRITE_READ,
INIT_CAL3_READ_WAIT,
INIT_CAL4_READ_WAIT:
cnt6_r <= cnt6_r + 1;
default:
cnt6_r <= 6'b000000;
endcase
end
//***************************************************************************
// Initial delay after power-on
//***************************************************************************
// 200us counter for cke
always @(posedge clk0)
if (rst0) begin
// skip power-up count if only simulating
if (SIM_ONLY)
cke_200us_cnt_r <= 5'b00001;
else
cke_200us_cnt_r <= 5'b11011;
end else if (ctrl_ref_flag)
cke_200us_cnt_r <= cke_200us_cnt_r - 1;
// refresh detect in 266 MHz clock
always @(posedge clk0)
if (rst0)
done_200us_r <= 1'b0;
else if (!done_200us_r)
done_200us_r <= (cke_200us_cnt_r == 5'b00000);
// 200 clocks counter - count value : C8 required for initialization
always @(posedge clk0)
if (rst0 || (init_state_r == INIT_CNT_200))
cnt_200_cycle_r <= 8'hC8;
else if (cnt_200_cycle_r != 8'h00)
cnt_200_cycle_r <= cnt_200_cycle_r - 1;
always @(posedge clk0)
if (rst0 || (init_state_r == INIT_CNT_200))
cnt_200_cycle_done_r <= 1'b0;
else if (cnt_200_cycle_r == 8'h00)
cnt_200_cycle_done_r <= 1'b1;
//*****************************************************************
// handle deep memory configuration:
// During initialization: Repeat initialization sequence once for each
// chip select. Note that we could perform initalization for all chip
// selects simulataneously. Probably fine - any potential SI issues with
// auto refreshing all chip selects at once?
// Once initialization complete, assert only CS[0] for calibration.
//*****************************************************************
always @(posedge clk0)
if (rst0) begin
chip_cnt_r <= 2'b00;
end else if (init_state_r == INIT_DEEP_MEMORY_ST) begin
if (chip_cnt_r != CS_NUM)
chip_cnt_r <= chip_cnt_r + 1;
else
chip_cnt_r <= 2'b00;
end
always @(posedge clk0)
if (rst0)
ddr_cs_n_r <= {CS_NUM{1'b1}};
else begin
ddr_cs_n_r <= {CS_NUM{1'b1}};
ddr_cs_n_r[chip_cnt_r] <= 1'b0;
end
//***************************************************************************
// Write/read burst logic
//***************************************************************************
assign cal_write = ((init_state_r == INIT_CAL1_WRITE) ||
(init_state_r == INIT_CAL2_WRITE) ||
(init_state_r == INIT_CAL3_WRITE));
assign cal_read = ((init_state_r == INIT_CAL1_READ) ||
(init_state_r == INIT_CAL2_READ) ||
(init_state_r == INIT_CAL3_READ) ||
(init_state_r == INIT_CAL4_READ));
assign cal_write_read = cal_write | cal_read;
assign burst_val = (BURST_LEN == 4) ? 2'b01 :
(BURST_LEN == 8) ? 2'b11 : 2'b00;
// keep track of current address - need this if burst length < 8 for
// stage 2-4 calibration writes and reads. Make sure value always gets
// initialized to 0 before we enter write/read state. This is used to
// keep track of when another burst must be issued
always @(posedge clk0)
if (cal_write_read)
burst_addr_r <= burst_addr_r + 1;
else
burst_addr_r <= 3'b000;
// write/read burst count
always @(posedge clk0)
if (cal_write_read)
if (burst_cnt_r == 2'b00)
burst_cnt_r <= burst_val;
else
burst_cnt_r <= burst_cnt_r - 1;
else
burst_cnt_r <= 2'b00;
// indicate when a write is occurring
always @(posedge clk0)
phy_init_wren <= cal_write;
// used for read enable calibration, pulse to indicate when read issued
always @(posedge clk0)
phy_init_rden <= cal_read;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -