📄 phy_init.v
字号:
// RZQ/6 assign load_mode_reg1[5] = 1'b0; assign load_mode_reg1[6] = ((ODT_TYPE == 2) || (ODT_TYPE == 3)) ? 1'b1 : 1'b0; // Make zero WRITE_LEVEL assign load_mode_reg1[7] = 0; assign load_mode_reg1[8] = 1'b0; assign load_mode_reg1[9] = 1'b0; assign load_mode_reg1[10] = 1'b0; assign load_mode_reg1[15:11] = 5'b00000; end endgenerate //***************************************************************** // DDR3 Load mode reg2 // Mode Register (MR2): // [15:11] - unused - 00 // [10:9] - RTT_WR - 00 (Dynamic ODT off) // [8] - reserved - 0 (must be '0') // [7] - self-refresh temperature range - // 0 (normal), 1 (extended) // [6] - Auto Self-Refresh - 0 (manual), 1(auto) // [5:3] - CAS Write Latency (CWL) - // 000 (5 for 400 MHz device), // 001 (6 for 400 MHz to 533 MHz devices), // 010 (7 for 533 MHz to 667 MHz devices), // 011 (8 for 667 MHz to 800 MHz) // [2:0] - Partial Array Self-Refresh (Optional) - // 000 (full array) //***************************************************************** generate if (DDR_TYPE == DDR3) begin: gen_ext_mode_reg2_ddr3 assign load_mode_reg2[2:0] = 3'b000; assign load_mode_reg2[5:3] = (CAS_LAT == 5) ? 3'b000 : (CAS_LAT == 6) ? 3'b001 : 3'b111; assign load_mode_reg2[6] = 1'b0; // Manual Self-Refresh assign load_mode_reg2[7] = 1'b0; assign load_mode_reg2[8] = 1'b0; assign load_mode_reg2[10:9] = 2'b00; assign load_mode_reg2[15:11] = 5'b00000; end endgenerate //***************************************************************** // DDR3 Load mode reg3 // Mode Register (MR3): // [15:3] - unused - All zeros // [2] - MPR Operation - 0(normal operation), 1(data flow from MPR) // [1:0] - MPR location - 00 (Predefined pattern) //***************************************************************** generate if (DDR_TYPE == DDR3)begin: gen_ext_mode_reg3_ddr3 assign load_mode_reg3[1:0] = 2'b00; assign load_mode_reg3[2] = 1'b0; assign load_mode_reg3[15:3] = 13'b0000000000000; end endgenerate //*************************************************************************** // Logic for calibration start, and for auto-refresh during cal request // CALIB_REF_REQ is used by calibration logic to request auto-refresh // durign calibration (used to avoid tRAS violation is certain calibration // stages take a long time). Once the auto-refresh is complete and cal can // be resumed, CALIB_REF_DONE is asserted by PHY_INIT. //*************************************************************************** // 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_DUMMY_ACTIVE_WAIT)); // Generate positive-edge triggered, latched signal to force initialization // to pause calibration, and to issue auto-refresh. Clear flag as soon as // refresh initiated always @(posedge clkdiv0) if (rstdiv0) begin calib_ref_req_r <= 1'b0; calib_ref_req_posedge <= 1'b0; refresh_req <= 1'b0; end else begin calib_ref_req_r <= calib_ref_req; calib_ref_req_posedge <= calib_ref_req & ~calib_ref_req_r; if (init_state_r1 == INIT_AUTO_REFRESH) refresh_req <= 1'b0; else if (calib_ref_req_posedge) refresh_req <= 1'b1; end // flag to tell cal1 calibration was started. // This flag is used for cal1 auto refreshes // some of these bits may not be needed - only needed for those stages that // need refreshes within the stage (i.e. very long stages) always @(posedge clkdiv0) if (rstdiv0) begin cal1_started_r <= 1'b0; cal2_started_r <= 1'b0; cal4_started_r <= 1'b0; end else begin if (calib_start[0]) cal1_started_r <= 1'b1; if (calib_start[1]) cal2_started_r <= 1'b1; if (calib_start[3]) cal4_started_r <= 1'b1; end // 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. // In first stage of calibration periodic auto refreshes // will be issued to meet memory timing. calib_start_shift0_r[15] will be // asserted more than once.calib_start[0] is anded with cal1_started_r so // that it is asserted only once. cal1_refresh_done is anded with // cal1_started_r so that it is asserted after the auto refreshes. always @(posedge clkdiv0) 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] & ~cal1_started_r; calib_start[1] <= calib_start_shift1_r[15] & ~cal2_started_r; calib_start[2] <= calib_start_shift2_r[15]; calib_start[3] <= calib_start_shift3_r[15] & ~cal4_started_r; calib_ref_done <= calib_start_shift0_r[15] | calib_start_shift1_r[15] | 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 clkdiv0) 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: cnt_cmd_r <= cnt_cmd_r + 1; default: cnt_cmd_r <= 7'b0000000; endcase end // assert when count reaches the value always @(posedge clkdiv0) begin if(cnt_cmd_r == CNTNEXT_CMD) cnt_cmd_ok_r <= 1'b1; else cnt_cmd_ok_r <= 1'b0; end always @(posedge clkdiv0) begin case (init_state_r) INIT_CAL3_READ_WAIT, INIT_CAL4_READ_WAIT: cnt_rd_r <= cnt_rd_r + 1; default: cnt_rd_r <= 4'b0000; endcase end always @(posedge clkdiv0) begin if(cnt_rd_r == CNTNEXT_RD) cnt_rd_ok_r <= 1'b1; else cnt_rd_ok_r <= 1'b0; end //*************************************************************************** // Initial delay after power-on //*************************************************************************** // register the refresh flag from the controller. // The refresh flag is in full frequency domain - so a pulsed version must // be generated for half freq domain using 2 consecutive full clk cycles // The registered version is used for the 200us counter always @(posedge clk0) ctrl_ref_flag_r <= ctrl_ref_flag; always @(posedge clkdiv0) cke_200us_cnt_en_r <= ctrl_ref_flag || ctrl_ref_flag_r; // 200us counter for cke always @(posedge clkdiv0) if (rstdiv0) begin // skip power-up count if only simulating if (SIM_ONLY) cke_200us_cnt_r <= 5'b00001; else cke_200us_cnt_r <= 5'd27; end else if (cke_200us_cnt_en_r) cke_200us_cnt_r <= cke_200us_cnt_r - 1; always @(posedge clkdiv0) if (rstdiv0) done_200us_r <= 1'b0; else if (!done_200us_r) done_200us_r <= (cke_200us_cnt_r == 5'b00000); // 200 clocks counter - count value : h'64 required for initialization // Counts 100 divided by two clocks always @(posedge clkdiv0) if (rstdiv0 || (init_state_r == INIT_CNT_200)) cnt_200_cycle_r <= 8'h64; else if (init_state_r == INIT_ZQCL) // ddr3 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 clkdiv0) if (rstdiv0 || (init_state_r == INIT_CNT_200) || (init_state_r == INIT_ZQCL)) 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 clkdiv0) if (rstdiv0) 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 clkdiv0) if (rstdiv0) begin ddr_cs_n_r <= {CS_NUM{1'b1}}; end else begin ddr_cs_n_r <= {CS_NUM{1'b1}}; if ((init_state_r == INIT_DUMMY_ACTIVE) || (init_state_r == INIT_PRECHARGE) || (init_state_r == INIT_LOAD_MODE) || (init_state_r == INIT_AUTO_REFRESH) || (init_state_r == INIT_ZQCL ) || (((init_state_r == INIT_CAL1_READ) || (init_state_r == INIT_CAL2_READ) || (init_state_r == INIT_CAL3_READ) || (init_state_r == INIT_CAL4_READ) || (init_state_r == INIT_CAL1_WRITE) || (init_state_r == INIT_CAL2_WRITE) || (init_state_r == INIT_CAL3_WRITE)) && (burst_cnt_r == 2'b00))) ddr_cs_n_r[chip_cnt_r] <= 1'b0; else ddr_cs_n_r[chip_cnt_r] <= 1'b1; 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 = ((init_state_r == INIT_CAL1_READ) || (init_state_r == INIT_CAL2_READ) || (init_state_r == INIT_CAL3_READ) || (init_state_r == INIT_CAL4_READ) || (init_state_r == INIT_CAL1_WRITE) || (init_state_r == INIT_CAL2_WRITE) || (init_state_r == INIT_CAL3_WRITE)); assign burst_val = (BURST_LEN == 4) ? 2'b00 : (BURST_LEN == 8) ? 2'b01 : 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 clkdiv0) if (cal_write_read) burst_addr_r <= burst_addr_r + 2; else burst_addr_r <= 2'b00; // write/read burst count always @(posedge clkdiv0) if (cal_write_read) if (burst_cnt_r == 2'b00) burst_cnt_r <= burst_val; else // SHOULD THIS BE -2 CHECK THIS LOGIC burst_cnt_r <= burst_cnt_r - 1; else burst_cnt_r <= 2'b00; // indicate when a write is occurring always @(posedge clkdiv0) // MIG 2.1: Remove (burst_addr_r<4) term - not used // phy_init_wren <= cal_write && (burst_addr_r < 3'd4); phy_init_wren <= cal_write; // used for read enable calibration, pulse to indicate when read issued always @(posedge clkdiv0) // MIG 2.1: Remove (burst_addr_r<4) term - not used // phy_init_rden <= cal_read && (burst_addr_r < 3'd4); phy_init_rden <= cal_read; //*************************************************************************** // Initialization state machine //*************************************************************************** always @(posedge clkdiv0) // every time we need to initialize another rank of memory, need to // reset init count, and repeat the entire initialization (but not // calibration) sequence if (rstdiv0 || (init_state_r == INIT_DEEP_MEMORY_ST)) init_cnt_r <= INIT_CNTR_INIT; else if ((DDR_TYPE == DDR1) && (init_state_r == INIT_PRECHARGE) && (init_cnt_r == INIT_CNTR_PRECH_1)) // skip EMR(2) and EMR(3) register loads init_cnt_r <= INIT_CNTR_EMR_EN_DLL; else if ((DDR_TYPE == DDR1) && (init_state_r == INIT_LOAD_MODE) && (init_cnt_r == INIT_CNTR_MR_ACT_DLL)) // skip OCD calibration for DDR1 init_cnt_r <= INIT_CNTR_DEEP_MEM; else if ((DDR_TYPE == DDR3) && (init_state_r == INIT_ZQCL)) // skip states for DDR3 init_cnt_r <= INIT_CNTR_DEEP_MEM; else if ((init_state_r == INIT_LOAD_MODE) || ((init_state_r == INIT_PRECHARGE) && (init_state_r1 != INIT_CALIB_REF))|| ((init_state_r == INIT_AUTO_REFRESH) && (~init_done_r))|| (init_state_r == INIT_CNT_200)) init_cnt_r <= init_cnt_r + 1; always @(posedge clkdiv0) begin if ((init_state_r == INIT_IDLE) && (init_cnt_r == INIT_CNTR_DONE)) begin phy_init_done_r <= 1'b1; end else phy_init_done_r <= 1'b0; end // phy_init_done to the controller and the user interface. // It is delayed by four clocks to account for the // multi cycle path constraint to the (phy_init_data_sel) // to the phy layer. always @(posedge clkdiv0)begin phy_init_done_r1 <= phy_init_done_r; phy_init_done_r2 <= phy_init_done_r1; phy_init_done_r3 <= phy_init_done_r2; phy_init_done <= phy_init_done_r3; end // Instantiate primitive to allow this flop to be attached to multicycle // path constraint in UCF. This signal goes to PHY_WRITE and PHY_CTL_IO // datapath logic only. Because it is a multi-cycle path, it can be // clocked by either CLKDIV0 or CLK0. FD u_ff_phy_init_data_sel ( .Q (phy_init_data_sel), .C (clkdiv0), .D (phy_init_done_r1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -