Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / model / verilog / mem / fbdimm / design / dtm_training.v
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: dtm_training.v
// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
//
// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// For the avoidance of doubt, and except that if any non-GPL license
// choice is available it will apply instead, Sun elects to use only
// the General Public License version 2 (GPLv2) at this time for any
// software where a choice of GPL license versions is made
// available with the language indicating that GPLv2 or any later version
// may be used, or where a choice of which version of the GPL is applied is
// otherwise unspecified.
//
// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
// CA 95054 USA or visit www.sun.com if you need additional information or
// have any questions.
//
// ========== Copyright Header End ============================================
module dtm_training(link_clk,dtm_ps,dtm_ps_bar,ps,ps_bar,rst,dtm_enabled,tr_complete,dtm_sb_dummy);
input link_clk;
input [9:0] ps;
input [9:0] ps_bar;
input dtm_enabled;
output [9:0] dtm_ps;
output [9:0] dtm_ps_bar;
output tr_complete;
output [9:0] dtm_sb_dummy;
output rst;
reg [9:0] dtm_ps_reg;
reg [9:0] dtm_ps_bar_reg;
reg [11:0] ts0_header;
reg [11:0] ts0_grp1,dtm_ts0_pattern_num;
reg [11:0] ts0_grp2_11;
reg [7:0] pattern_counter;
reg [143:0] dtm_ts0_pattern;
reg [9:0] required_delay;
reg [11:0] num_ts0;
reg init_reg;
reg dtm_en;
wire init;
reg [3:0] num_nop;
reg dummy;
reg [3:0] reinit_count;
reg tr_complete_reg;
wire tr_complete_reg_d1,tr_complete_reg_d2;
reg rst_reg;
reg rst_reg_cnt;
reg dtm_tr_complete_reg;
reg [9:0] dtm_sb_dummy_reg; // Prepare headers according to the MCU SB data
wire link_clk_en = (ps === ps_bar)? 1'b1 : ~(init_reg)? 1'b0 : 1'b1;
wire link_clk_int = link_clk & link_clk_en;
assign dtm_ps = dtm_ps_reg;
assign dtm_ps_bar = dtm_ps_bar_reg;
assign tr_complete = tr_complete_reg_d1;
assign dtm_sb_dummy = dtm_sb_dummy_reg;
assign init = (link_clk_en)? 1'b1 : init_reg;
assign rst = rst_reg;
initial begin
ts0_header = 12'hbfe;
ts0_grp1 = 12'h00a;
ts0_grp2_11 = 12'haaa;
dtm_ts0_pattern = {{10{ts0_grp2_11}},ts0_grp1,ts0_header};
pattern_counter = 8'h00;
rst_reg_cnt = 1;
rst_reg = 0;
reinit_count = 0;
required_delay = 0;
dtm_ps_reg = 10'hxxx;
dtm_ps_bar_reg = 10'hxxx;
`ifdef PALLADIUM
dtm_en = dtm_enabled;
`else
#10 dtm_en = dtm_enabled;
`endif
num_nop = 10;
num_ts0 = 0;
dtm_ts0_pattern_num=25;
dummy=$value$plusargs("dtm_ts0_pattern=%h",dtm_ts0_pattern_num);
init_reg = 1;
tr_complete_reg = 0;
end
`ifdef FBDIMM_BUG_107438
always@(dtm_enabled)
dtm_en <= dtm_enabled;
`endif
always @(negedge link_clk_int)
begin
required_delay = required_delay + 1;
if(reinit_count > 0) reinit_count = reinit_count - 1;
if(dtm_en == 1'b1 && required_delay == 10'd840 && reinit_count == 0)
begin
if(rst_reg_cnt > 0)
begin
rst_reg_cnt = rst_reg_cnt - 1;
rst_reg = 1;
end
else rst_reg = 0;
dtm_ps_reg = {10{dtm_ts0_pattern[pattern_counter]}};
dtm_ps_bar_reg = ~dtm_ps_reg;
dtm_sb_dummy_reg = ps;
if(pattern_counter == 0)
num_ts0 = num_ts0+1;
pattern_counter = (pattern_counter + 1)%144;
if(num_ts0 == dtm_ts0_pattern_num)
begin
required_delay = 10'd500;
end
else
required_delay = 10'd839;
end
else if(dtm_en == 1'b1 && required_delay !== 10'd840 && reinit_count == 0)
begin
dtm_ps_reg = 10'h0;
dtm_ps_bar_reg = 10'h3ff;
dtm_sb_dummy_reg = ps;
if(required_delay == 10'd572 && (num_ts0 == dtm_ts0_pattern_num))
begin
dtm_en = 1'b0;
tr_complete_reg = 1;
num_ts0 = 0;
init_reg = 0;
end
else tr_complete_reg = 0;
end
else if(dtm_en == 1'b0 || reinit_count > 0)
begin
if(init)
begin
//dtm_en = 1;
init_reg = 1;
required_delay = 10'd813;
tr_complete_reg = 0;
num_ts0 = 0;
pattern_counter = 8'h00;
if(reinit_count == 0) reinit_count = 4'd12;
end
dtm_ps_reg = ps;
dtm_ps_bar_reg = ps_bar;
dtm_sb_dummy_reg = ps;
if(dtm_ps_reg === dtm_ps_bar_reg) //Even X's will be considered equal
begin
rst_reg = 1;
rst_reg_cnt = 1;
end
if(reinit_count > 0) reinit_count = reinit_count - 1;
end
end
shifter_p #(1) delay_tr_complete1 (.signal_in ( tr_complete_reg ),
.signal_out ( tr_complete_reg_d1 ),
.delay_cycles ( 10'd48),
.clk ( link_clk ));
shifter_p #(1) delay_tr_complete2 (.signal_in ( tr_complete_reg_d1 ),
.signal_out ( tr_complete_reg_d2 ),
.delay_cycles ( 10'd108),
.clk ( link_clk ));
endmodule