Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / design / sys / iop / ccu / rtl / ccu_divider.v
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: ccu_divider.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 ccu_divider (
rst_n,
div,
clkin,
clkout,
phase_180
);
input rst_n;
input [4:0] div;
input clkin;
output clkout;
output phase_180;
wire rst_n;
wire [4:0] div;
wire clkin;
wire clkout; // ECO
wire pre_phase_180;
wire phase_180;
// wire clkout_tmp; // ECO
wire odd;
wire [4:0] cnt;
wire [3:0] div_by2;
wire flip;
wire reset;
reg clkout_d_; // ECO
wire clkout_q_; // ECO
assign div_by2 = div[4:1];
assign odd = div[0];
reg [4:0] cnt_in;
reg flip_in,pre_phase_180_in;
always @ (cnt or div_by2 or div ) begin
if (cnt == div_by2) begin
cnt_in = cnt + 5'b1;
flip_in = 1'b1;
pre_phase_180_in = 1'b1;
end else if (cnt == div) begin
cnt_in = 5'h00;
flip_in = 1'b1;
pre_phase_180_in = 1'b0;
end else begin
cnt_in = cnt + 5'b1;
flip_in = 1'b0;
pre_phase_180_in = 1'b0;
end
end
assign reset = ~rst_n;
ccu_msff_arst_4x_5 cnt_bank5 (
.q(cnt),
.so(),
.d(cnt_in),
.l1clk(clkin),
.si(1'b0),
.siclk(1'b0),
.soclk(1'b0),
.reset_n(rst_n)
);
my_msff_arst_4x flip_0 ( .q(flip), .so(), .d(flip_in), .l1clk(clkin),
.si(1'b0), .siclk(1'b0), .soclk(1'b0), .reset(reset) );
my_msff_arst_4x pre_phase_180_0 ( .q(pre_phase_180), .so(), .d(pre_phase_180_in), .l1clk(clkin),
.si(1'b0), .siclk(1'b0), .soclk(1'b0), .reset(reset) );
// flip => output is inverted else maintain state
wire clkout_tmp_in;
wire clkout_tmp_;
// assign clkout_tmp_in = flip ? clkout_tmp : ~clkout_tmp;
assign clkout_tmp_in = flip ^ clkout_tmp_; // ECO
my_msff_arst_4x clkout_tmp_0 (
// .q(clkout_tmp_), .so(), .d(clkout_tmp_in), .l1clk(clkin),
.q(clkout_q_), .so(), .d(clkout_d_), .l1clk(clkin), // ECO
.si(1'b0), .siclk(1'b0), .soclk(1'b0), .reset(reset) );
// assign clkout_tmp = ~clkout_tmp_; // ECO
// just pipe one stage
wire phase_180_in;
wire phase_180_;
assign phase_180_in = ~pre_phase_180;
my_msff_arst_4x phase_180_0 (
.q(phase_180_), .so(), .d(phase_180_in), .l1clk(clkin),
.si(1'b0), .siclk(1'b0), .soclk(1'b0), .reset(reset) );
assign phase_180 = ~phase_180_;
// ------------------------------------------------------------
// Quick & dirty fix to shift clocks generated by N-8 cycles
// when N is (effective) 11 or 15 for DTM
// ------------------------------------------------------------
wire [6:0] clk_shift_;
wire [6:0] clk_shift;
assign clk_shift = ~clk_shift_ ;
ccu_msff_arst_4x_7 shift_bank_7 (
.q(clk_shift_[6:0]),
.so (),
.d({clk_shift_[5:0], clkout_tmp_in}) , // ECO .d({clk_shift_[5:0], clkout_tmp_}) ,
.l1clk (clkin),
.si (1'b0),
.siclk (1'b0),
.soclk (1'b0),
.reset_n (rst_n)
);
// dtm shift not needed for div eff == 8; only for 11 & 15
wire dtm_mode = ((div == 5'h0A) || (div == 5'h0E));
assign clkout = ~clkout_q_; // ECO
assign clkout_tmp_ = dtm_mode ? clk_shift_[0] : clkout_q_ ; // ECO
always @(div or clkout_tmp_in or clk_shift_) begin // ECO @(div or clkout_tmp or clk_shift)
case (div)
5'h0A: clkout_d_ = clk_shift_[2]; // 11 => shift 3 cycles // ECO
5'h0E: clkout_d_ = clk_shift_[6]; // 15 => shift 7 cycles // ECO
default: clkout_d_ = clkout_tmp_in; // else no shift // ECO
endcase
end
// end of quick fix
// ------------------------------------------------------------
endmodule