📄 ddr2_32mx32_controller_0.v
字号:
///////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2005-2007 Xilinx, Inc.
// This design is confidential and proprietary of Xilinx, All Rights Reserved.
///////////////////////////////////////////////////////////////////////////////
// ____ ____
// / /\/ /
// /___/ \ / Vendor : Xilinx
// \ \ \/ Version : $Name: i+IP+131489 $
// \ \ Application : MIG
// / / Filename : ddr2_32Mx32_controller_0.v
// /___/ /\ Date Last Modified : $Date: 2007/09/21 15:23:17 $
// \ \ / \ Date Created : Mon May 2 2005
// \___\/\___\
// Device : Spartan-3/3A/3A-DSP
// Design Name : DDR2 SDRAM
// Purpose : This is main controller block. This includes the following
// features:
// - The controller state machine that controls the
// initialization process upon power up, as well as the
// read, write, and refresh commands.
// - Accepts and decodes the user commands.
// - Generates the address and Bank address and control signals
// to the memory
// - Generates control signals for other modules.
///////////////////////////////////////////////////////////////////////////////
`timescale 1ns/100ps
`include "../rtl/ddr2_32Mx32_parameters_0.v"
module ddr2_32Mx32_controller_0
(
input clk/* synthesis syn_keep=1 */,
input rst0,
input rst180,
input [((`ROW_ADDRESS
+ `COL_AP_WIDTH)-1):0] address,
input [`BANK_ADDRESS-1:0] bank_address,
input [2:0] command_register,
input burst_done,
output ddr_rasb_cntrl,
output ddr_casb_cntrl,
output [`BANK_ADDRESS-1:0] ddr_ba_cntrl,
output [`ROW_ADDRESS-1:0] ddr_address_cntrl,
output ddr_csb_cntrl,
output dqs_enable,
output dqs_reset /* synthesis syn_keep=1 */,
output rst_dqs_div_int,
output cmd_ack,
output init,
output ddr_web_cntrl,
output ddr_cke_cntrl,
output reg write_enable,
output reg rst_calib,
output reg ddr_odt_cntrl,
output reg ar_done,
input wait_200us,
output auto_ref_req
);
localparam IDLE = 4'b0000;
localparam PRECHARGE = 4'b0001;
localparam AUTO_REFRESH = 4'b0010;
localparam ACTIVE = 4'b0011;
localparam FIRST_WRITE = 4'b0100;
localparam WRITE_WAIT = 4'b0101;
localparam BURST_WRITE = 4'b0110;
localparam PRECHARGE_AFTER_WRITE = 4'b0111;
localparam PRECHARGE_AFTER_WRITE_2 = 4'b1000;
localparam READ_WAIT = 4'b1001;
localparam BURST_READ = 4'b1010;
localparam ACTIVE_WAIT = 4'b1011;
localparam INIT_IDLE = 2'b00;
localparam INIT_PRECHARGE = 2'b01;
localparam INIT_LOAD_MODE_REG = 2'b10;
localparam INIT_AUTO_REFRESH = 2'b11;
localparam [5:0] CNTNEXT = 6'd40;
reg [3:0] current_state;
reg [3:0] next_state;
reg [1:0] init_current_state;
reg [1:0] init_next_state;
reg [((`ROW_ADDRESS
+ `COL_AP_WIDTH)-1):0] address_reg;
reg auto_ref;
reg auto_ref1;
reg autoref_value;
reg auto_ref_detect1;
reg [(`MAX_REF_WIDTH-1):0] autoref_count;
reg auto_ref_issued;
reg [`BANK_ADDRESS-1:0] ba_address_reg1;
reg [`BANK_ADDRESS-1:0] ba_address_reg2;
reg [2:0] burst_length;
reg [2:0] cas_count;
reg [`ROW_ADDRESS-1:0] column_address_reg;
reg [`ROW_ADDRESS-1:0] column_address_reg1;
reg [2:0] wr;
reg ddr_rasb2;
reg ddr_casb2;
reg ddr_web2;
reg [`BANK_ADDRESS-1:0] ddr_ba1;
reg [`ROW_ADDRESS-1:0] ddr_address1;
reg [3:0] init_count;
reg init_done;
reg init_done_r1;
reg init_memory;
reg init_mem;
reg [6:0] init_pre_count;
reg [7:0] dll_rst_count;
reg [(`MAX_REF_WIDTH-1):0] ref_freq_cnt;
reg read_cmd1;
reg read_cmd2;
reg read_cmd3;
reg [2:0] rcdr_count;
reg [2:0] rcdw_count;
reg [5:0] rfc_counter_value;
reg rfc_count_reg;
reg ar_done_reg;
reg rdburst_end_1;
reg rdburst_end_2;
reg [2:0] rp_count;
reg [5:0] rfc_count;
reg [`ROW_ADDRESS-1:0] row_address_reg;
reg rst_dqs_div_r;
reg rst_dqs_div_r1; //For Reg Dimm
reg [2:0] wrburst_end_cnt;
reg wrburst_end_1;
reg wrburst_end_2;
reg wrburst_end_3;
reg [2:0] wr_count;
reg write_cmd1;
reg write_cmd2;
reg write_cmd3;
reg [2:0] dqs_div_cascount;
reg [2:0] dqs_div_rdburstcount;
reg dqs_enable1;
reg dqs_enable2;
reg dqs_enable3;
reg dqs_reset1_clk0;
reg dqs_reset2_clk0;
reg dqs_reset3_clk0;
reg dqs_enable_int;
reg dqs_reset_int;
reg rst180_r;
reg rst0_r;
reg ddr_odt2;
reg go_to_active;
reg accept_cmd_in;
reg odt_deassert;
reg rpcnt0 ;
reg auto_ref_wait;
reg auto_ref_wait1;
reg auto_ref_wait2;
reg [5:0] count6;
wire [`ROW_ADDRESS - 1:0] lmr;
wire [`ROW_ADDRESS - 1:0] emr;
wire [`ROW_ADDRESS - 1:0] lmr_dll_rst;
wire [`ROW_ADDRESS - 1:0] lmr_dll_set;
wire [`ROW_ADDRESS-1:0] column_address;
wire write_cmd_in;
wire wrburst_end;
wire [`ROW_ADDRESS-1:0] row_address;
wire rdburst_end;
wire [2:0] rp_cnt_value;
wire init_done_value;
wire initialize_memory;
wire read_cmd;
wire ddr_rasb1;
wire ddr_casb1;
wire ddr_web1;
wire ack_reg;
wire ack_o;
wire auto_ref_issued_p;
wire ar_done_p;
wire go_to_active_value;
wire ddr_odt1;
wire rst_dqs_div_int1;
wire [2:0] burst_cnt_max;
// Input : COMMAND REGISTER FORMAT
// 000 - NOP
// 010 - Initialize memory
// 100 - Write Request
// 110 - Read request
// Input : Address format
// row address = address((`ROW_ADDRESS+ `COL_AP_WIDTH) -1 : `COL_AP_WIDTH)
// column addres = address( `COL_AP_WIDTH-1 : 0)
assign ddr_csb_cntrl = 1'b0;
assign row_address = address_reg[((`ROW_ADDRESS +
`COL_AP_WIDTH)-1):
`COL_AP_WIDTH];
assign column_address = {address_reg[`ROW_ADDRESS - 1:11],
1'b0,address_reg[9:0]};
assign init = init_done;
assign ddr_rasb_cntrl = ddr_rasb2;
assign ddr_casb_cntrl = ddr_casb2;
assign ddr_web_cntrl = ddr_web2;
assign ddr_address_cntrl = ddr_address1;
assign ddr_ba_cntrl = ddr_ba1;
assign rst_dqs_div_int = rst_dqs_div_int1;
assign emr = `EXT_LOAD_MODE_REGISTER;
assign lmr = `LOAD_MODE_REGISTER;
assign lmr_dll_rst = {lmr[`ROW_ADDRESS - 1 : 9],1'b1,lmr[7:0]};
assign lmr_dll_set = {lmr[`ROW_ADDRESS - 1 : 9],1'b0,lmr[7:0]};
assign ddr_cke_cntrl = ~wait_200us;
always @ (negedge clk)
rst180_r <= rst180;
always @ (posedge clk)
rst0_r <= rst0;
//******************************************************************************
// Register user address
//******************************************************************************
always @ (negedge clk) begin
row_address_reg <= row_address;
column_address_reg <= column_address;
ba_address_reg1 <= bank_address;
ba_address_reg2 <= ba_address_reg1;
address_reg <= address;
end
always @ (negedge clk) begin
if (rst180_r == 1'b1) begin
burst_length <= 3'b000;
wr <= 3'd0;
end
else begin
burst_length <= lmr[2:0];
wr <= `TWR_COUNT_VALUE;
end
end
always @( negedge clk ) begin
if ( rst180_r )
accept_cmd_in <= 1'b0;
else if ( current_state == IDLE && ((rpcnt0 && rfc_count_reg &&
!auto_ref_wait && !auto_ref_issued)))
accept_cmd_in <= 1'b1;
else
accept_cmd_in <= 1'b0;
end
//******************************************************************************
// Commands from user.
//******************************************************************************
assign initialize_memory = (command_register == 3'b010);
assign write_cmd_in = (command_register == 3'b100 &&
accept_cmd_in == 1'b1) ;
assign read_cmd = (command_register == 3'b110 &&
accept_cmd_in == 1'b1) ;
//******************************************************************************
// write_cmd1 is asserted when user issued write command and the controller s/m
// is in idle state and AUTO_REF is not asserted.
//******************************************************************************
always @ (negedge clk) begin
if (rst180_r == 1'b1) begin
write_cmd1 <= 1'b0;
write_cmd2 <= 1'b0;
write_cmd3 <= 1'b0;
end
else begin
if (accept_cmd_in)
write_cmd1 <= write_cmd_in;
write_cmd2 <= write_cmd1;
write_cmd3 <= write_cmd2;
end
end
//******************************************************************************
// read_cmd1 is asserted when user issued read command and the controller s/m
// is in idle state and AUTO_REF is not asserted.
//******************************************************************************
always @ (negedge clk) begin
if (rst180_r == 1'b1) begin
read_cmd1 <= 1'b0;
read_cmd2 <= 1'b0;
read_cmd3 <= 1'b0;
end
else begin
if (accept_cmd_in)
read_cmd1 <= read_cmd;
read_cmd2 <= read_cmd1;
read_cmd3 <= read_cmd2;
end
end
//******************************************************************************
// rfc_count
// An executable command can be issued only after Trfc period after a AUTOREFRESH
// command is issued. rfc_count_value is set in the parameter file depending on
// the memory device speed grade and the selected frequency.For example for 5B
// speed grade, trfc= 75 at 133Mhz, rfc_counter_value = 6'b001010.
// ( Trfc/clk_period= 75/7.5= 10)
//******************************************************************************
always @( negedge clk ) begin
if (rst180_r == 1'b1)
rfc_count <= 6'd0;
else if(current_state == AUTO_REFRESH)
rfc_count <= rfc_counter_value;
else if(rfc_count != 6'b000000)
rfc_count <= rfc_count - 1'b1;
end
//******************************************************************************
// rp_count
// An executable command can be issued only after Trp period after a PRECHARGE
// command is issued. rp_count value is fixed to support all memory speed grades.
//******************************************************************************
assign rp_cnt_value = (current_state == PRECHARGE) ? 3'b100 :
(rpcnt0 != 1'b1) ? (rp_count - 1'b1) :
3'b000;
//******************************************************************************
// ACTIVE to READ/WRITE counter
//
// rcdr_count
// ACTIVE to READ delay - Minimum interval between ACTIVE and READ command.
// rcdr_count value is fixed to support all memory speed grades.
//
// rcdw_count
// ACTIVE to WRITE delay - Minimum interval between ACTIVE and WRITE command.
// rcdw_count value is fixed to support all memory speed grades.
//
//******************************************************************************
always @( negedge clk ) begin
if ( rst180_r )
rcdr_count <= 3'b000;
else if ( current_state == ACTIVE )
rcdr_count <= 3'b001;
else if ( rcdr_count != 3'b000 )
rcdr_count <= rcdr_count - 1'b1;
end
always @( negedge clk ) begin
if ( rst180_r )
rcdw_count <= 3'b000;
else if ( current_state == ACTIVE)
rcdw_count <= 3'b001;
else if ( rcdw_count != 3'b000 )
rcdw_count <= rcdw_count - 1'b1;
end
//******************************************************************************
// WR Counter a PRECHARGE command can be applied only after 3 cycles after a
// WRITE command has finished executing
//******************************************************************************
always @(negedge clk) begin
if (rst180_r)
wr_count <= 3'b000;
else
if (dqs_enable_int)
wr_count <= wr ;
else if (wr_count != 3'b000)
wr_count <= wr_count - 3'b001;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -