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

📄 odt_watchdog.v

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

`timescale 1 ps / 1 ps

module	odt_watchdog(
    mem_clk,
    rst_n,

    //------- 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
    ddr_odt                     // DDR SDRAM ODT signal

);

input                  mem_clk;
input                  rst_n;

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  [`CS_WIDTH-1:0] ddr_odt;

///////////////////////////////////////////////////////////////////////
// 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;
///////////////////////////////////////////////////////////////////////
// Shadow registers in the test bench
reg   [2:0]            burst_len;
reg   [2:0]            cas_lat;
reg   [2:0]            add_lat;

///////////////////////////////////////////////////////////////////////
// flopped signals
reg            	       mem_pd_cmd_d;
reg 	               mem_sref_cmd_d;
reg	               mem_rd_cmd_d;
reg	               mem_wr_cmd_d;
reg                    mem_lmr_cmd_d;
reg   [1:0]            ddr_cs_n_d[0:7];
reg   [1:0]            wr_ddr_cs_n_d[0:7];
reg   [1:0]            ddr_ba_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  [2:0]            read_lat;
wire  [2:0]            write_lat;

wire  [1:0]            chipsel;    // chip select signals to the memory
reg   [2:0]            cmd_cnt_ptr; // cmd_fifo write pointer
reg   [3:0]            cmd_counter[0:7]; 
reg   [7:0]            cmd_count_en;

reg   [2:0]            wr_cmd_cnt_ptr; // cmd_fifo write pointer
reg   [3:0]            wr_cmd_counter[0:7]; 
reg   [7:0]            wr_cmd_count_en;
///////////////////////////////////////////////////////////////////////
// Debug logic

wire  [3:0]            debug_cmd_counter_0;
wire  [3:0]            debug_cmd_counter_1;
wire  [3:0]            debug_cmd_counter_2;
wire  [3:0]            debug_cmd_counter_3;
wire  [3:0]            debug_cmd_counter_4;
wire  [3:0]            debug_cmd_counter_5;
wire  [3:0]            debug_cmd_counter_6;
wire  [3:0]            debug_cmd_counter_7;

assign debug_cmd_counter_0 = cmd_counter[0];
assign debug_cmd_counter_1 = cmd_counter[1];
assign debug_cmd_counter_2 = cmd_counter[2];
assign debug_cmd_counter_3 = cmd_counter[3];
assign debug_cmd_counter_4 = cmd_counter[4];
assign debug_cmd_counter_5 = cmd_counter[5];
assign debug_cmd_counter_6 = cmd_counter[6];
assign debug_cmd_counter_7 = cmd_counter[7];
///////////////////////////////////////////////////////////////////////
// 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;

initial begin
    cmd_count_en = 8'b0;
    wr_cmd_count_en = 8'b0;
end

always @ (posedge mem_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

assign read_lat = cas_lat + add_lat;
assign write_lat = read_lat - 1;

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

///////////////////////////////////////////////////////////////////////
// This logic detects the command presented at the memory interface.

// self refresh: cke=0, cs=0, ras=0, cas=0, we=1
// powerdown: cke=0
// lmr: cs=0, ras=0, cas=0, we=0
// act: cs=0, ras=0, cas=1, we=1
// pre: cs=0, ras=0, cas=1, we=0
// nop: cs=0, ras=1, cas=1, we=1
// Read: cs=0, ras=1, cas=0, we=1
// Write: cs=0, ras=1, cas=0, we=0

assign mem_rd_cmd = ~(&ddr_cs_n) & ddr_ras_n & ~ddr_cas_n & ddr_we_n;
assign mem_wr_cmd = ~(&ddr_cs_n) & ddr_ras_n & ~ddr_cas_n & ~ddr_we_n;
assign mem_sref_cmd = ~(&ddr_cs_n) & ~ddr_cke &
                      ~ddr_ras_n & ~ddr_cas_n & ddr_we_n;

assign mem_pd_cmd = ~(&ddr_cs_n) & ddr_ras_n & ddr_cas_n & ddr_we_n & ~ddr_cke;

assign mem_lmr_cmd = ~(&ddr_cs_n) & ~ddr_ras_n & ~ddr_cas_n & ~ddr_we_n;
assign mem_act_cmd = ~(&ddr_cs_n) & ~ddr_ras_n & ddr_cas_n & ddr_we_n;
assign mem_pre_cmd = ~(&ddr_cs_n) & ~ddr_ras_n & ddr_cas_n & ~ddr_we_n;
assign mem_nop_cmd = (~(&ddr_cs_n) & ddr_ras_n & ddr_cas_n & ddr_we_n) |
                     &ddr_cs_n;

///////////////////////////////////////////////////////////////////////
// This logic stores the read, write commands seen at the 
// memory interface in cmd_fifo.

`ifdef CS_WIDTH_1
    assign chipsel = 2'b00;   // both are set to 0 for just one chip sel
`else
    assign chipsel = ddr_cs_n;
`endif

always @ (posedge mem_clk or negedge rst_n) begin
    if (!rst_n) begin
	cmd_cnt_ptr    <= 8'b0;
	wr_cmd_cnt_ptr <= 3'b0;
    end
    else begin
	if (mem_rd_cmd) begin
	    cmd_cnt_ptr <= cmd_cnt_ptr + 1;
        end
	if (mem_wr_cmd) begin
	    wr_cmd_cnt_ptr <= wr_cmd_cnt_ptr + 1;
        end
    end
end

///////////////////////////////////////////////////////////////////////
// Edge that samples command is edge 0.  All clock edges are then 
// counted in the increasing order.

// Check if the ODT signal for both chip selects are asserted

`ifdef CS_WIDTH_1
`else
always @ (posedge mem_clk) begin
    if (^ddr_odt == 1'b0 && |ddr_odt == 1'b1) begin
	$display ("ODT ERROR: two ODT signals asserted at time %0t\n",$time);
    end
end
`endif

///////////////////////////////////////////////////////////////////////
// The monitor accepts upto eight commands in a queue.  The commands
// are numbered based on the cmd_cnt_ptr value.  Each command has it's
// own edge counter to determine the edges where the ODT signal should be
// sampled asserted.  These counters kick in from the moment a command is
// presented to the queue.  Since the read command with CL=4, AL=4 and
// BL=8 requires a count of upto 9, the counters are 4 bit long and will
// be reset when they reach the max count possible for the configuration.

integer i;

always @ (posedge mem_clk) begin
    if (mem_rd_cmd) begin

	case (cmd_cnt_ptr)
	    3'd0: begin
		cmd_count_en[0] <= 1;
		cmd_counter[0]  <= 1;
		ddr_cs_n_d[0]   <= ddr_cs_n;
	    end

	    3'd1: begin
		cmd_count_en[1] <= 1;
		cmd_counter[1]  <= 1;
		ddr_cs_n_d[1]   <= ddr_cs_n;
	    end

	    3'd2: begin
		cmd_count_en[2] <= 1;
		cmd_counter[2]  <= 1;
		ddr_cs_n_d[2]   <= ddr_cs_n;
	    end

	    3'd3: begin
		cmd_count_en[3] <= 1;
		cmd_counter[3]  <= 1;
		ddr_cs_n_d[3]   <= ddr_cs_n;
	    end

	    3'd4: begin
		cmd_count_en[4] <= 1;
		cmd_counter[4]  <= 1;
		ddr_cs_n_d[4]   <= ddr_cs_n;
	    end

	    3'd5: begin
		cmd_count_en[5] <= 1;
		cmd_counter[5]  <= 1;
		ddr_cs_n_d[5]   <= ddr_cs_n;
	    end

	    3'd6: begin
		cmd_count_en[6] <= 1;
		cmd_counter[6]  <= 1;
		ddr_cs_n_d[6]   <= ddr_cs_n;
	    end

	    3'd7: begin
		cmd_count_en[7] <= 1;
		cmd_counter[7]  <= 1;
		ddr_cs_n_d[7]   <= ddr_cs_n;
	    end
	endcase
    end

    ///////////////////////////////////////////////////////////////////////
    if (mem_wr_cmd) begin

	case (wr_cmd_cnt_ptr)
	    3'd0: begin
		wr_cmd_count_en[0] <= 1;
		wr_cmd_counter[0]  <= 1;
		wr_ddr_cs_n_d[0]   <= ddr_cs_n;

⌨️ 快捷键说明

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