// ========== 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