OpenCores
URL https://opencores.org/ocsvn/s1_core/s1_core/trunk

Subversion Repositories s1_core

[/] [s1_core/] [trunk/] [hdl/] [rtl/] [sparc_core/] [sparc_exu_ecl_divcntl.v] - Diff between revs 105 and 113

Show entire file | Details | Blame | View Log

Rev 105 Rev 113
Line 16... Line 16...
// You should have received a copy of the GNU General Public
// You should have received a copy of the GNU General Public
// License along with this work; if not, write to the Free Software
// License along with this work; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
// 
// 
// ========== Copyright Header End ============================================
// ========== Copyright Header End ============================================
 
`ifdef SIMPLY_RISC_TWEAKS
 
`define SIMPLY_RISC_SCANIN .si(0)
 
`else
 
`define SIMPLY_RISC_SCANIN .si()
 
`endif
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/*
/*
//  Module Name: sparc_exu_divcntl
//  Module Name: sparc_exu_divcntl
//      Description: Control block for div.  Division takes 1 cycle to load
//      Description: Control block for div.  Division takes 1 cycle to load
//              the values, 65 cycles to calculate the result, and 1 cycle to
//              the values, 65 cycles to calculate the result, and 1 cycle to
//    calculate the ccs and check for overflow.
//    calculate the ccs and check for overflow.
//      Controlled by a one hot state machine and a 6 bit counter.
//      Controlled by a one hot state machine and a 6 bit counter.
*/
*/
 
 
 
`define IDLE 0
 
`define RUN 1
 
`define LAST_CALC 2
 
`define CHK_OVFL 3
 
`define FIX_OVFL 4
 
`define DONE 5
 
 
module sparc_exu_ecl_divcntl (/*AUTOARG*/
module sparc_exu_ecl_divcntl (/*AUTOARG*/
   // Outputs
   // Outputs
   ecl_div_xinmask, ecl_div_keep_d, ecl_div_ld_inputs,
   ecl_div_xinmask, ecl_div_keep_d, ecl_div_ld_inputs,
   ecl_div_sel_adder, ecl_div_last_cycle, ecl_div_almostlast_cycle,
   ecl_div_sel_adder, ecl_div_last_cycle, ecl_div_almostlast_cycle,
Line 169... Line 174...
   wire         cntris63;
   wire         cntris63;
 
 
   /////////////////////////////////
   /////////////////////////////////
   // G arbitration between MUL/DIV
   // G arbitration between MUL/DIV
   /////////////////////////////////
   /////////////////////////////////
   assign        divcntl_wb_req_g = div_state[5] |
   assign        divcntl_wb_req_g = div_state[`DONE] |
                      (~(div_state[5] | div_state[3] | div_state[4]) &mdqctl_divcntl_muldone);
                      (~(div_state[`DONE] | div_state[`CHK_OVFL] | div_state[`FIX_OVFL]) &mdqctl_divcntl_muldone);
   assign        ecl_div_sel_div = ~(~(div_state[5] | div_state[3] | div_state[4]) &
   assign        ecl_div_sel_div = ~(~(div_state[`DONE] | div_state[`CHK_OVFL] | div_state[`FIX_OVFL]) &
                                    mdqctl_divcntl_muldone);
                                    mdqctl_divcntl_muldone);
 
 
   // state flop
   // state flop
   dff #(6) divstate_dff(.din(next_state[5:0]), .clk(clk), .q(div_state[5:0]), .se(se), .si(),
   dff_s #(6) divstate_dff(.din(next_state[5:0]), .clk(clk), .q(div_state[5:0]), .se(se), `SIMPLY_RISC_SCANIN,
                    .so());
                    .so());
 
 
   // output logic and state decode
   // output logic and state decode
   assign        ecl_div_almostlast_cycle = go_last_calc & ~ecl_div_ld_inputs;
   assign        ecl_div_almostlast_cycle = go_last_calc & ~ecl_div_ld_inputs;
   assign        ecl_div_sel_adder = (div_state[1] | div_state[2]) & ~ecl_div_ld_inputs;
   assign        ecl_div_sel_adder = (div_state[`RUN] | div_state[`LAST_CALC]) & ~ecl_div_ld_inputs;
   assign        ecl_div_last_cycle = div_state[2];
   assign        ecl_div_last_cycle = div_state[`LAST_CALC];
   assign        ecl_div_ld_inputs = mdqctl_divcntl_input_vld;
   assign        ecl_div_ld_inputs = mdqctl_divcntl_input_vld;
   assign        ecl_div_keep_d = ~(ecl_div_sel_adder | ecl_div_ld_inputs);
   assign        ecl_div_keep_d = ~(ecl_div_sel_adder | ecl_div_ld_inputs);
   assign        reset_cnt = ~div_state[1];
   assign        reset_cnt = ~div_state[`RUN];
 
 
   // next state logic
   // next state logic
   assign        stay_idle = div_state[0] & ~mdqctl_divcntl_input_vld;
   assign        stay_idle = div_state[`IDLE] & ~mdqctl_divcntl_input_vld;
   assign        go_idle = div_state[5] & wb_divcntl_ack_g;
   assign        go_idle = div_state[`DONE] & wb_divcntl_ack_g;
   assign        next_state[0] = go_idle | stay_idle | mdqctl_divcntl_reset_div | reset;
   assign        next_state[`IDLE] = go_idle | stay_idle | mdqctl_divcntl_reset_div | reset;
 
 
   assign        stay_run = div_state[1] & ~cntris63 & ~ecl_div_muls;
   assign        stay_run = div_state[`RUN] & ~cntris63 & ~ecl_div_muls;
   assign        go_run = (div_state[0] & mdqctl_divcntl_input_vld);
   assign        go_run = (div_state[`IDLE] & mdqctl_divcntl_input_vld);
   assign        next_state[1] = (go_run | stay_run) &
   assign        next_state[`RUN] = (go_run | stay_run) &
                                      ~mdqctl_divcntl_reset_div & ~reset;
                                      ~mdqctl_divcntl_reset_div & ~reset;
 
 
   assign        go_last_calc = div_state[1] & (cntris63);
   assign        go_last_calc = div_state[`RUN] & (cntris63);
   assign        next_state[2] = go_last_calc & ~mdqctl_divcntl_reset_div & ~reset;
   assign        next_state[`LAST_CALC] = go_last_calc & ~mdqctl_divcntl_reset_div & ~reset;
 
 
   // chk_ovfl and fix_ovfl are place holders to guarantee that the overflow checking
   // chk_ovfl and fix_ovfl are place holders to guarantee that the overflow checking
   // takes place on the result.  No special logic occurs in them compared to the done state.
   // takes place on the result.  No special logic occurs in them compared to the done state.
   assign        go_chk_ovfl = div_state[2];
   assign        go_chk_ovfl = div_state[`LAST_CALC];
   assign        next_state[3] = go_chk_ovfl & ~mdqctl_divcntl_reset_div & ~reset;
   assign        next_state[`CHK_OVFL] = go_chk_ovfl & ~mdqctl_divcntl_reset_div & ~reset;
 
 
   assign        go_fix_ovfl = div_state[3] | (div_state[1] & ecl_div_muls);
   assign        go_fix_ovfl = div_state[`CHK_OVFL] | (div_state[`RUN] & ecl_div_muls);
   assign        next_state[4] = go_fix_ovfl & ~mdqctl_divcntl_reset_div & ~reset;
   assign        next_state[`FIX_OVFL] = go_fix_ovfl & ~mdqctl_divcntl_reset_div & ~reset;
 
 
   assign        go_done = div_state[4];
   assign        go_done = div_state[`FIX_OVFL];
   assign        stay_done = div_state[5] & ~wb_divcntl_ack_g;
   assign        stay_done = div_state[`DONE] & ~wb_divcntl_ack_g;
   assign        next_state[5] = (go_done | stay_done) & ~mdqctl_divcntl_reset_div & ~reset;
   assign        next_state[`DONE] = (go_done | stay_done) & ~mdqctl_divcntl_reset_div & ~reset;
 
 
   // counter
   // counter
   sparc_exu_ecl_cnt6 cnt6(.reset       (reset_cnt),
   sparc_exu_ecl_cnt6 cnt6(.reset       (reset_cnt),
                           /*AUTOINST*/
                           /*AUTOINST*/
                           // Outputs
                           // Outputs
Line 258... Line 263...
   dp_mux2es qnext_cout_mux(.dout(q_next),
   dp_mux2es qnext_cout_mux(.dout(q_next),
                            .in0(q_next_nocout[1]),
                            .in0(q_next_nocout[1]),
                            .in1(q_next_nocout[0]),
                            .in1(q_next_nocout[0]),
                            .sel(div_ecl_cout64));
                            .sel(div_ecl_cout64));
 
 
   dff q_dff(.din(q_next), .clk(clk), .q(ecl_div_newq), .se(se), .si(),
   dff_s q_dff(.din(q_next), .clk(clk), .q(ecl_div_newq), .se(se), `SIMPLY_RISC_SCANIN,
               .so());
               .so());
 
 
 
 
   ////////////////////////////
   ////////////////////////////
   // Subtraction logic and subtract flop
   // Subtraction logic and subtract flop
Line 285... Line 290...
   dp_mux2es subtract_cout_mux(.dout(sub_next),
   dp_mux2es subtract_cout_mux(.dout(sub_next),
                            .in0(sub_next_nocout[1]),
                            .in0(sub_next_nocout[1]),
                            .in1(sub_next_nocout[0]),
                            .in1(sub_next_nocout[0]),
                            .sel(div_ecl_cout64));
                            .sel(div_ecl_cout64));
 
 
   dff sub_dff(.din(sub_next), .clk(clk), .q(subtract), .se(se), .si(),
   dff_s sub_dff(.din(sub_next), .clk(clk), .q(subtract), .se(se), `SIMPLY_RISC_SCANIN,
               .so());
               .so());
 
 
   assign        ecl_div_subtract_l = ~subtract;
   assign        ecl_div_subtract_l = ~subtract;
 
 
 
 
Line 310... Line 315...
                                                     (~div_ecl_d_62 | ecl_div_almostlast_cycle);
                                                     (~div_ecl_d_62 | ecl_div_almostlast_cycle);
 -----/\----- EXCLUDED -----/\----- */
 -----/\----- EXCLUDED -----/\----- */
   assign new_zero_rem_with_zero = ~ecl_div_ld_inputs & (~div_ecl_d_62 | ecl_div_almostlast_cycle);
   assign new_zero_rem_with_zero = ~ecl_div_ld_inputs & (~div_ecl_d_62 | ecl_div_almostlast_cycle);
   assign new_zero_rem_no_zero = zero_rem_q & new_zero_rem_with_zero;
   assign new_zero_rem_no_zero = zero_rem_q & new_zero_rem_with_zero;
   assign zero_rem_d = (detect_zero)? new_zero_rem_with_zero: new_zero_rem_no_zero;
   assign zero_rem_d = (detect_zero)? new_zero_rem_with_zero: new_zero_rem_no_zero;
   dff zero_rem_dff(.din(zero_rem_d), .clk(clk), .q(zero_rem_q),
   dff_s zero_rem_dff(.din(zero_rem_d), .clk(clk), .q(zero_rem_q),
                    .se(se), .si(), .so());
                    .se(se), `SIMPLY_RISC_SCANIN, .so());
 
 
/* -----\/----- EXCLUDED -----\/-----
/* -----\/----- EXCLUDED -----\/-----
   // changed for timing
   // changed for timing
   assign last_cin_next = ecl_div_signed_div & (divisor_sign & ~div_ecl_d_62 |
   assign last_cin_next = ecl_div_signed_div & (divisor_sign & ~div_ecl_d_62 |
                                                ~divisor_sign &div_ecl_d_62&~zero_rem_d |
                                                ~divisor_sign &div_ecl_d_62&~zero_rem_d |
Line 326... Line 331...
                                                divisor_sign &div_ecl_d_62&new_zero_rem_with_zero);
                                                divisor_sign &div_ecl_d_62&new_zero_rem_with_zero);
   assign last_cin_no_zero = ecl_div_signed_div & (divisor_sign & ~div_ecl_d_62 |
   assign last_cin_no_zero = ecl_div_signed_div & (divisor_sign & ~div_ecl_d_62 |
                                                ~divisor_sign &div_ecl_d_62&~new_zero_rem_no_zero |
                                                ~divisor_sign &div_ecl_d_62&~new_zero_rem_no_zero |
                                                divisor_sign &div_ecl_d_62&new_zero_rem_no_zero);
                                                divisor_sign &div_ecl_d_62&new_zero_rem_no_zero);
   assign last_cin_next = (detect_zero)? last_cin_with_zero: last_cin_no_zero;
   assign last_cin_next = (detect_zero)? last_cin_with_zero: last_cin_no_zero;
   dff last_cin_dff(.din(last_cin_next), .clk(clk), .q(last_cin),
   dff_s last_cin_dff(.din(last_cin_next), .clk(clk), .q(last_cin),
                    .se(se), .si(), .so());
                    .se(se), `SIMPLY_RISC_SCANIN, .so());
 
 
   ///////////////////////////////
   ///////////////////////////////
   // Condition code generation
   // Condition code generation
   ///////////////////////////////
   ///////////////////////////////
   // There is a special case:
   // There is a special case:
Line 341... Line 346...
   wire   inputs_neg_d;
   wire   inputs_neg_d;
   wire   inputs_neg_q;
   wire   inputs_neg_q;
   wire   large_neg_ovfl;
   wire   large_neg_ovfl;
   assign inputs_neg_d = div_ecl_dividend_msb & div_ecl_divisorin_31;
   assign inputs_neg_d = div_ecl_dividend_msb & div_ecl_divisorin_31;
   assign large_neg_ovfl = inputs_neg_q & ~gencc_in_msb_l_d1;
   assign large_neg_ovfl = inputs_neg_q & ~gencc_in_msb_l_d1;
   dffe inputs_neg_dff(.din(inputs_neg_d), .clk(clk), .q(inputs_neg_q),
   dffe_s inputs_neg_dff(.din(inputs_neg_d), .clk(clk), .q(inputs_neg_q),
                       .en(ecl_div_ld_inputs), .se(se), .si(), .so());
                       .en(ecl_div_ld_inputs), .se(se), `SIMPLY_RISC_SCANIN, .so());
   dff #(5) cc_sig_dff(.din({div_ecl_upper32_equal, div_ecl_gencc_in_msb_l,
   dff_s #(5) cc_sig_dff(.din({div_ecl_upper32_equal, div_ecl_gencc_in_msb_l,
                             div_ecl_gencc_in_31, ecl_div_sel_div, div_ecl_low32_nonzero}),
                             div_ecl_gencc_in_31, ecl_div_sel_div, div_ecl_low32_nonzero}),
                         .q({upper32_equal_d1, gencc_in_msb_l_d1,
                         .q({upper32_equal_d1, gencc_in_msb_l_d1,
                             gencc_in_31_d1, sel_div_d1, low32_nonzero_d1}),
                             gencc_in_31_d1, sel_div_d1, low32_nonzero_d1}),
                         .clk(clk), .se(se), .si(), .so());
                         .clk(clk), .se(se), `SIMPLY_RISC_SCANIN, .so());
   // selects for correcting divide overflow
   // selects for correcting divide overflow
   assign        ecl_div_sel_64b = ecl_div_div64 | ecl_div_muls;
   assign        ecl_div_sel_64b = ecl_div_div64 | ecl_div_muls;
   assign        ecl_div_sel_u32 = ~ecl_div_sel_64b & ~ecl_div_signed_div;
   assign        ecl_div_sel_u32 = ~ecl_div_sel_64b & ~ecl_div_signed_div;
   assign                        ecl_div_sel_pos32 = (~ecl_div_sel_64b & ecl_div_signed_div &
   assign                        ecl_div_sel_pos32 = (~ecl_div_sel_64b & ecl_div_signed_div &
                                      (gencc_in_msb_l_d1 | large_neg_ovfl));
                                      (gencc_in_msb_l_d1 | large_neg_ovfl));
Line 371... Line 376...
   assign        pos_ovfl = ecl_div_sel_pos32 & ~ecl_div_upper33_zero & sel_div_d1;
   assign        pos_ovfl = ecl_div_sel_pos32 & ~ecl_div_upper33_zero & sel_div_d1;
   assign        neg_ovfl = ecl_div_sel_neg32 & ~ecl_div_upper33_one & sel_div_d1;
   assign        neg_ovfl = ecl_div_sel_neg32 & ~ecl_div_upper33_one & sel_div_d1;
   assign        div_v = pos_ovfl | unsign_ovfl | neg_ovfl;
   assign        div_v = pos_ovfl | unsign_ovfl | neg_ovfl;
 
 
   // muls carry and overflow
   // muls carry and overflow
   assign next_muls_c = (div_state[1]) ? div_ecl_cout32: muls_c;
   assign next_muls_c = (div_state[`RUN]) ? div_ecl_cout32: muls_c;
 
 
   assign        muls_rs1_data_31_m = ~muls_rs1_31_m_l;
   assign        muls_rs1_data_31_m = ~muls_rs1_31_m_l;
   dff #(3) muls_overlow_dff(.din({muls_rs1_data_31_m, rs2_data_31_m, div_ecl_adder_out_31}),
   dff_s #(3) muls_overlow_dff(.din({muls_rs1_data_31_m, rs2_data_31_m, div_ecl_adder_out_31}),
                             .q({muls_rs1_data_31_w, rs2_data_31_w, div_adder_out_31_w}),
                             .q({muls_rs1_data_31_w, rs2_data_31_w, div_adder_out_31_w}),
                             .clk(clk), .se(se), .si(), .so());
                             .clk(clk), .se(se), `SIMPLY_RISC_SCANIN, .so());
   assign ovfl_32 = ((muls_rs1_data_31_w & rs2_data_31_w & ~div_adder_out_31_w) |
   assign ovfl_32 = ((muls_rs1_data_31_w & rs2_data_31_w & ~div_adder_out_31_w) |
                     (~muls_rs1_data_31_w & ~rs2_data_31_w & div_adder_out_31_w));
                     (~muls_rs1_data_31_w & ~rs2_data_31_w & div_adder_out_31_w));
   assign next_muls_v = (div_state[4]) ? ovfl_32: muls_v;
   assign next_muls_v = (div_state[`FIX_OVFL]) ? ovfl_32: muls_v;
   dff muls_c_dff(.din(next_muls_c), .clk(clk), .q(muls_c),
   dff_s muls_c_dff(.din(next_muls_c), .clk(clk), .q(muls_c),
                  .se(se), .si(), .so());
                  .se(se), `SIMPLY_RISC_SCANIN, .so());
   dff muls_v_dff(.din(next_muls_v), .clk(clk), .q(muls_v),
   dff_s muls_v_dff(.din(next_muls_v), .clk(clk), .q(muls_v),
                  .se(se), .si(), .so());
                  .se(se), `SIMPLY_RISC_SCANIN, .so());
 
 
   // negative
   // negative
   assign xcc[3] = ~gencc_in_msb_l_d1 & ~unsign_ovfl & ~pos_ovfl;
   assign xcc[3] = ~gencc_in_msb_l_d1 & ~unsign_ovfl & ~pos_ovfl;
   assign icc[3] = (gencc_in_31_d1 & ~pos_ovfl) | neg_ovfl | unsign_ovfl;
   assign icc[3] = (gencc_in_31_d1 & ~pos_ovfl) | neg_ovfl | unsign_ovfl;
   // zero
   // zero

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.