⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 monitor.v

📁 DDR2 的控制器
💻 V
📖 第 1 页 / 共 5 页
字号:
// ===========================================================================
// Verilog module generated by IPexpress
// Filename: monitor.v  
// Copyright 2006 (c) Lattice Semiconductor Corporation. All rights reserved.
// ===========================================================================

`timescale 1 ps / 1 ps

module	monitor(
    clk,
    user_clk,
    rst_n,

    //------- Signals from the test bench
    endoftest,                  // when high, signals the end of the test

    //------- Signals from User Interface
    cmd,			// Command 
    cmd_valid,			// Command valid
    dmsel,			// Data mask inputs 
    addr,			// Address bus 
    datain,			// Data input bus 
    burst_cnt,			// Burst access count
    init_start,                 // request initialization
    init_done,                  // init complete
    ar_burst_en,                // Auto refresh burst
    ext_reg_en,                 // Write to EMR during init
    db_size,                    // data bus size
    burst_term,                 // burst termination

    //------- Signals from SDRAM side
    ddr_cke,                    // DDR SDRAM Clock enable
    ddr_cs_n,                   // DDR SDRAM Chip select
    ddr_we_n,                   // DDR SDRAM Write enable
    ddr_cas_n,                  // DDR SDRAM Column address strobe
    ddr_ras_n,                  // DDR SDRAM Row address strobe
    ddr_ad,                     // DDR SDRAM Address bus
    ddr_ba,                     // DDR SDRAM Bank bus
    ddr_dqm,			// DDR SDRAM Data Mask signal
    ddr_dq,			// DDR SDRAM Data Bus 
    ddr_dqs,		        // DDR SDRAM Data Strobe

    //------- Signals to the user interface
    dataout,			// Data output bus
    cmd_rdy,			// Ready to accept a command
    dataout_valid,		// Valid signal for read data 
    datain_valid 		// data ack.(write data)

);

input                 clk;
input                 user_clk;
input                 rst_n;

input                 endoftest;

input  [3:0]           cmd;
input  [`DSIZE/8-1:0]  dmsel;
input  [`ADDR_WIDTH-1:0]    addr;
input  [`DSIZE-1:0]    datain;
input  [4:0]           burst_cnt;
input                  init_start;
input                  init_done;
input  [2:0]           ar_burst_en;
input                  ext_reg_en;
input  [2:0]           db_size;
input                  burst_term;

input                  ddr_cke;
input  [`CS_WIDTH-1:0] ddr_cs_n;
input                  ddr_we_n;
input                  ddr_cas_n;
input                  ddr_ras_n;
input  [`ROW_WIDTH-1:0]    ddr_ad;
input  [`BNK_WDTH-1:0] ddr_ba;
input  [`DSIZE/2-1:0]  ddr_dq;
input  [`DSIZE/16-1:0] ddr_dqm;
input  [`DSIZE/16-1:0] ddr_dqs;

input  [`DSIZE-1:0]    dataout;
input                  cmd_rdy;
input                  cmd_valid;
input                  dataout_valid;
input                  datain_valid;
reg                    init_start_d0;
reg                    init_start_d1;
reg                    init_start_d2;
reg                    init_start_d3;

///////////////////////////////////////////////////////////////////////
// delay the DQS signal so that the edge is sepearted from the clock.
wire   [`DSIZE/16-1:0] ddr_dqs_dly;
assign #1 ddr_dqs_dly = ddr_dqs;

wire   ddr_dqs_modified;
assign ddr_dqs_modified = (ddr_dqs_dly[0] === 1'bz) ? 1'b0 : ddr_dqs_dly[0];

// Since a lot of signals will be in a state of flux initially, disable checks on them.

integer disable_check;
integer i;

initial begin
    disable_check = 0;
    init_start_d0 = 0; 
    init_start_d1 = 0;
    init_start_d2 = 0;
    init_start_d3 = 0;
end

always @ (posedge clk) begin
    disable_check <= disable_check +1 ;
    init_start_d0    <= init_start;
    init_start_d1    <= init_start_d0;
    init_start_d2    <= init_start_d1;
    init_start_d3    <= init_start_d2;
end

always @ (ddr_dqs) begin
    for (i=0;i<(`DSIZE/16);i=i+1) begin
        if ((ddr_dqs[i] === 1'bx) && (disable_check > 10)) begin
	    $display ("MON ERROR: Unknown values found on dqs[%0d] at time %0t\n",i,$time);
	end
    end
end
///////////////////////////////////////////////////////////////////////
// Delay the cmd_rdy and cmd_valid in RTL simulations

wire               cmd_valid_dly;
wire               cmd_rdy_dly;

    
`ifdef GATE_SIM
    assign #2600 cmd_valid_dly = cmd_valid;
    assign #2600 cmd_rdy_dly = cmd_rdy;
`else
    assign #100 cmd_valid_dly = cmd_valid;
    assign #100 cmd_rdy_dly = cmd_rdy;
`endif
///////////////////////////////////////////////////////////////////////
// Shadow registers in the test bench
reg   [2:0]            burst_len;
reg   [2:0]            cas_lat;
reg   [2:0]            add_lat;

// Static programmable registers

reg   [15:0]           trefi;

initial begin
    //trefi            = 16'h0b35;
    trefi            = 16'h0b37;   //need to calculate the correct count.
end
///////////////////////////////////////////////////////////////////////
// logic that compares the address of every read/write command presented on the 
// user interface with the corresponding read/write command at the memory 
// interface.

// For every command received at the user interface, prepare a table listing:
// Expected command at the memory interface: 
//     read, write, self ref, powerdown, load_mr
// Expected address:
//     row address, column address, bank address

// These values will be compared against the controller output whenever 
// a command is presented on the interface.  They will be stored in a 
// FIFO that is 64 locations deep.

// negative edge is used to prevent any clocking issues 

wire  [12:0]           usr_col_addr;
wire  [4:0]            usr_bnk_addr;
wire  [13:0]           usr_row_addr;

// Addr, Command compare FIFO signals
reg   [5:0]            wr_addr;
reg   [5:0]            rd_addr;
reg   [40:0]           mem_bnk[0:63];
reg   [40:0]           fifo_out;
wire                   fifo_rd;
wire  [3:0]            fifo_out_cmd;
wire  [`ROW_WIDTH-1:0]     fifo_out_row;
wire  [`COL_WIDTH-1:0] fifo_out_col;
wire  [4:0]            fifo_out_bank;
reg   [`ROW_WIDTH-1:0]     mem_row_addr [0:31];
reg   [`ROW_WIDTH-1:0]     mem_row_addr_out;
reg   [4:0]            orig_mem_burst_cnt;
reg   [4:0]            mem_burst_cnt;
reg   [`COL_WIDTH-1:0] burst_cycle;

// flopped signals
reg            	       mem_pd_cmd_d;
reg 	               mem_sref_cmd_d;
reg	               fifo_rd_d;
reg	               mem_rd_cmd_d;
reg	               mem_rd_cmd_2d;
reg	               mem_rd_cmd_3d;
reg	               mem_rd_cmd_4d;
reg	               mem_wr_cmd_d;
reg	               mem_wr_cmd_2d;
reg	               mem_wr_cmd_3d;
reg	               mem_wr_cmd_4d;
reg	               mem_wr_cmd_5d;
reg                    mem_lmr_cmd_d;
wire   [7:0]           ddr_cs_n_d;
wire   [`BNK_WDTH-1:0] ddr_ba_d;
wire   [`ROW_WIDTH-1:0]    ddr_ad_d;


// signals that indicate the type of command at the memory interface
wire                   mem_sref_cmd;
wire                   mem_pd_cmd;
wire                   mem_lmr_cmd;
wire                   mem_aref_cmd;
wire                   mem_act_cmd;
wire                   mem_pre_cmd;
wire                   mem_rd_cmd;
wire                   mem_wr_cmd;
wire                   mem_nop_cmd;
wire                   mem_bt_cmd;

///////////////////////////////////////////////////////////////////////
// The EC device require an additional read between two non-consecutive 
// read operations.  Since the data from this additional read does not 
// reach the user, the command FIFO should not be read from when the 
// additional read happens.  The following registers are used to solve 
// this problem in EC_ONLY case.

reg                    mem_rd_cmd_3d_new;

reg   [7:0]            flop_ddr_cs_n;
reg   [7:0]            flop2_ddr_cs_n;
reg   [7:0]            flop3_ddr_cs_n;
reg   [`BNK_WDTH-1:0]  flop_ddr_ba;
reg   [`BNK_WDTH-1:0]  flop2_ddr_ba;
reg   [`BNK_WDTH-1:0]  flop3_ddr_ba;
reg   [`ROW_WIDTH-1:0]     flop_ddr_ad;
reg   [`ROW_WIDTH-1:0]     flop2_ddr_ad;
reg   [`ROW_WIDTH-1:0]     flop3_ddr_ad;

`ifdef ECP_20_ONLY
    assign ddr_ad_d = flop3_ddr_ad;
    assign ddr_ba_d = flop3_ddr_ba;
    assign ddr_cs_n_d = flop3_ddr_cs_n;
`else
    assign ddr_ad_d = flop_ddr_ad;
    assign ddr_ba_d = flop_ddr_ba;
    assign ddr_cs_n_d = flop_ddr_cs_n;
`endif
///////////////////////////////////////////////////////////////////////
// This part of the logic tracks the LMR command on the memory 
// interface and updates the shadow mode registers.

reg   [3:0]            int_burst_len;
reg                    dataout_valid_d;

always @ (posedge clk or negedge rst_n) begin
    if (!rst_n) begin
	burst_len             <= 3'b010;
	cas_lat               <= 3'b011;
	add_lat               <= 3'b011;
    end
    else if (mem_lmr_cmd && (ddr_ba[1:0] == 2'b00)) begin
	burst_len             <= ddr_ad[2:0];
	cas_lat               <= ddr_ad[6:4];
    end
    else if (mem_lmr_cmd && (ddr_ba[1:0] == 2'b01)) begin
        add_lat               <= ddr_ad[5:3];
    end

end

always @ (burst_len) begin
    case (burst_len)
	3'b001 : int_burst_len = 4'b0010;
	3'b010 : int_burst_len = 4'b0100;
	3'b011 : int_burst_len = 4'b1000;
	default : int_burst_len = 4'b0100;
    endcase
end

reg [2:0] rd_clk_cnt;
wire non_cs_rd;
reg  mem_rd_cmd_new;
reg  mem_bt_cmd_new;

// Sync the mem_rd_cmd signal
always @ (posedge clk or negedge rst_n) begin
    if (!rst_n) begin
	mem_rd_cmd_new             <= 1'b0;
	mem_bt_cmd_new             <= 1'b0;
    end
    else begin
	mem_rd_cmd_new             <= mem_rd_cmd;
	mem_bt_cmd_new             <= mem_bt_cmd;
    end
end


always @ (posedge clk or negedge rst_n) begin
    if (!rst_n) begin
	rd_clk_cnt             <= 3'b000;
    end
    else if  (mem_rd_cmd_new) begin
	rd_clk_cnt             <= int_burst_len/2;
    end
    else  if (rd_clk_cnt == 0) begin
	rd_clk_cnt             <= 3'b000;
    end
    else  begin
	rd_clk_cnt             <= rd_clk_cnt - 1;
    end
end


// The RD cmd is non consecutive when cmd doesn't come at int_burst_len/2 spaced 
assign non_cs_rd = (int_burst_len !== 2) ? mem_bt_cmd_new : !mem_rd_cmd_new && (rd_clk_cnt == 1) ; 


///////////////////////////////////////////////////////////////////////
// store the command received at the user interface in the command fifo.
always @ (negedge clk or negedge rst_n) begin
    if (!rst_n) begin
	wr_addr                      <= 0;
    end
    else begin
        if (cmd_rdy_dly && cmd_valid_dly) begin // user presents a valid command

	    case (wr_addr)
		6'd0  : mem_bnk[0]   <= {burst_cnt,cmd, addr};
		6'd1  : mem_bnk[1]   <= {burst_cnt,cmd, addr};
		6'd2  : mem_bnk[2]   <= {burst_cnt,cmd, addr};
		6'd3  : mem_bnk[3]   <= {burst_cnt,cmd, addr};
		6'd4  : mem_bnk[4]   <= {burst_cnt,cmd, addr};
		6'd5  : mem_bnk[5]   <= {burst_cnt,cmd, addr};
		6'd6  : mem_bnk[6]   <= {burst_cnt,cmd, addr};
		6'd7  : mem_bnk[7]   <= {burst_cnt,cmd, addr};
		6'd8  : mem_bnk[8]   <= {burst_cnt,cmd, addr};
		6'd9  : mem_bnk[9]   <= {burst_cnt,cmd, addr};
		6'd10 : mem_bnk[10]  <= {burst_cnt,cmd, addr};
		6'd11 : mem_bnk[11]  <= {burst_cnt,cmd, addr};
		6'd12 : mem_bnk[12]  <= {burst_cnt,cmd, addr};
		6'd13 : mem_bnk[13]  <= {burst_cnt,cmd, addr};
		6'd14 : mem_bnk[14]  <= {burst_cnt,cmd, addr};
		6'd15 : mem_bnk[15]  <= {burst_cnt,cmd, addr};
		6'd16 : mem_bnk[16]  <= {burst_cnt,cmd, addr};
		6'd17 : mem_bnk[17]  <= {burst_cnt,cmd, addr};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -