📄 monitor.v
字号:
// ===========================================================================
// 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 + -