You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

468 lines
15 KiB
Verilog

// © IBM Corp. 2020
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by
// the terms below; you may not use the files in this repository except in
// compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the
// License, the "Work" hereby includes implementations of the work of authorship
// in physical form.
//
// 2) Notwithstanding any terms to the contrary in the License, any licenses
// necessary for implementation of the Work that are available from OpenPOWER
// via the Power ISA End User License Agreement (EULA) are explicitly excluded
// hereunder, and may be obtained from OpenPOWER under the terms and conditions
// of the EULA.
//
// Unless required by applicable law or agreed to in writing, the reference design
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
// for the specific language governing permissions and limitations under the License.
//
// Additional rights, including the ability to physically implement a softcore that
// is compliant with the required sections of the Power ISA Specification, are
// available at no cost under the terms of the OpenPOWER Power ISA EULA, which can be
// obtained (along with the Power ISA) here: https://openpowerfoundation.org.
`timescale 1 ns / 1 ns
// Description: XU Rotate/Logical Unit
//
//*****************************************************************************
module tri_st_rot_dec(
i,
ex1_zm_ins,
ex1_mb_ins,
ex1_me_ins_b,
ex1_sh_amt,
ex1_sh_right,
ex1_sh_word,
ex1_use_rb_amt_hi,
ex1_use_rb_amt_lo,
ex1_use_me_rb_hi,
ex1_use_me_rb_lo,
ex1_use_mb_rb_hi,
ex1_use_mb_rb_lo,
ex1_use_me_ins_hi,
ex1_use_me_ins_lo,
ex1_use_mb_ins_hi,
ex1_use_mb_ins_lo,
ex1_ins_prtyw,
ex1_ins_prtyd,
ex1_chk_shov_wd,
ex1_chk_shov_dw,
ex1_mb_gt_me,
ex1_cmp_byt,
ex1_sgnxtd_byte,
ex1_sgnxtd_half,
ex1_sgnxtd_wd,
ex1_sra_dw,
ex1_sra_wd,
ex1_log_fcn,
ex1_sel_rot_log
);
input [0:31] i;
output ex1_zm_ins;
output [0:5] ex1_mb_ins;
output [0:5] ex1_me_ins_b;
output [0:5] ex1_sh_amt;
output ex1_sh_right;
output ex1_sh_word;
output ex1_use_rb_amt_hi;
output ex1_use_rb_amt_lo;
output ex1_use_me_rb_hi;
output ex1_use_me_rb_lo;
output ex1_use_mb_rb_hi;
output ex1_use_mb_rb_lo;
output ex1_use_me_ins_hi;
output ex1_use_me_ins_lo;
output ex1_use_mb_ins_hi;
output ex1_use_mb_ins_lo;
output ex1_ins_prtyw;
output ex1_ins_prtyd;
output ex1_chk_shov_wd;
output ex1_chk_shov_dw;
output ex1_mb_gt_me;
output ex1_cmp_byt;
output ex1_sgnxtd_byte;
output ex1_sgnxtd_half;
output ex1_sgnxtd_wd;
output ex1_sra_dw;
output ex1_sra_wd;
output [0:3] ex1_log_fcn;
output ex1_sel_rot_log;
wire cmp_byt;
wire rotlw;
wire imm_log;
wire rotld;
wire x31;
wire f0_xxxx00;
wire f0_xxx0xx;
wire f0_xxxx0x;
wire f1_1xxxx;
wire f1_111xx;
wire f1_110xx;
wire f1_x1x1x;
wire f1_x1xx0;
wire f1_x1xx1;
wire f1_xxx00;
wire f1_xxx11;
wire f1_xx10x;
wire f2_11xxx;
wire f2_xx0xx;
wire f2_xxx00;
wire f2_xxx0x;
wire f2_111xx;
wire f1_xxx01;
wire f1_xxx10;
wire f2_xx01x;
wire f2_xx00x;
wire rotlw_nm;
wire rotlw_pass;
wire rotld_pass;
wire sh_lft_rb;
wire sh_lft_rb_dw;
wire sh_rgt;
wire sh_rgt_rb;
wire sh_rgt_rb_dw;
wire shift_imm;
wire sh_rb;
wire sh_rb_dw;
wire sh_rb_wd;
wire x31_sh_log_sgn;
wire op_sgn_xtd;
wire op_sra;
wire wd_if_sh;
wire xtd_log;
wire sh_word_int;
wire imm_xor_or;
wire imm_and_or;
wire xtd_nor;
wire xtd_eqv_orc_nand;
wire xtd_nand;
wire xtd_andc_xor_or;
wire xtd_and_eqv_orc;
wire xtd_or_orc;
wire xtd_xor_or;
wire sel_ins_amt_hi;
wire sel_ins_me_lo_wd;
wire sel_ins_me_lo_dw;
wire sel_ins_amt_lo;
wire sel_ins_me_hi;
wire rot_imm_mb;
wire gt5_g_45;
wire gt5_g_23;
wire gt5_g_1;
wire gt5_t_23;
wire gt5_t_1;
wire mb_gt_me_cmp_wd0_b;
wire mb_gt_me_cmp_wd1_b;
wire mb_gt_me_cmp_wd2_b;
wire mb_gt_me_cmp_wd;
wire gt6_g_45;
wire gt6_g_23;
wire gt6_g_01;
wire gt6_t_23;
wire gt6_t_01;
wire mb_gt_me_cmp_dw0_b;
wire mb_gt_me_cmp_dw1_b;
wire mb_gt_me_cmp_dw2_b;
wire mb_gt_me_cmp_dw;
wire [0:5] me_ins;
wire [1:5] gt5_in0;
wire [1:5] gt5_in1;
wire [0:5] gt6_in0;
wire [0:5] gt6_in1;
wire [1:5] gt5_g_b;
wire [1:4] gt5_t_b;
wire [0:5] gt6_g_b;
wire [0:4] gt6_t_b;
wire f0_xxxx11;
wire f1_0xxxx;
wire f1_1xxx0;
wire f1_xxxx0;
wire f1_xxxx1;
wire f2_xxx1x;
wire f1_xx1xx;
wire xtd_nand_or_orc;
wire rld_cr;
wire rld_cl;
wire rld_icr;
wire rld_icl;
wire rld_ic;
wire rld_imi;
wire sh_lft_imm_dw;
wire sh_lft_imm;
wire sh_rgt_imm_dw;
wire sh_rgt_imm;
wire rotld_en_mbgtme;
wire [0:3] rf1_log_fcn;
wire isel;
wire prtyw;
wire prtyd;
//--------------------------------------------------
// decode primary field opcode bits [0:5] ---
//--------------------------------------------------
assign ex1_ins_prtyw = prtyw;
assign ex1_ins_prtyd = prtyd;
assign isel = (x31 == 1'b1 & i[26:30] == 5'b01111) ? 1'b1 :
1'b0;
assign cmp_byt = (x31 == 1'b1 & i[21:30] == 10'b0111111100) ? 1'b1 : // 31/508
1'b0;
assign prtyw = (x31 == 1'b1 & i[21:30] == 10'b0010011010) ? 1'b1 : // 31/154
1'b0;
assign prtyd = (x31 == 1'b1 & i[21:30] == 10'b0010111010) ? 1'b1 : // 31/186
1'b0;
assign rotlw = (~i[0]) & i[1] & (~i[2]) & i[3]; //0101xx (20:23)
assign imm_log = (~i[0]) & i[1] & i[2] & ((~i[3]) | (~i[4])); //0110xx (24:27)
//01110x (28,29)
assign rotld = (~i[0]) & i[1] & i[2] & i[3] & i[4] & (~i[5]); //011110 (30)
assign x31 = (~i[0]) & i[1] & i[2] & i[3] & i[4] & i[5]; //011111 (31)
assign f0_xxxx00 = (~i[4]) & (~i[5]);
assign f0_xxx0xx = (~i[3]);
assign f0_xxxx0x = (~i[4]);
assign f0_xxxx11 = i[4] & i[5];
//---------------------------------------------------
// decode i(21:25)
//---------------------------------------------------
assign f1_0xxxx = (~i[21]);
assign f1_110xx = i[21] & i[22] & (~i[23]);
assign f1_111xx = i[21] & i[22] & i[23];
assign f1_1xxx0 = i[21] & (~i[25]);
assign f1_1xxxx = i[21];
assign f1_x1x1x = i[22] & i[24];
assign f1_xx1xx = i[23];
assign f1_x1xx0 = i[22] & (~i[25]);
assign f1_x1xx1 = i[22] & i[25];
assign f1_xx10x = i[23] & (~i[24]);
assign f1_xxx01 = (~i[24]) & i[25];
assign f1_xxx11 = i[24] & i[25];
assign f1_xxxx0 = (~i[25]);
assign f1_xxxx1 = i[25];
assign f1_xxx00 = (~i[24]) & (~i[25]);
assign f1_xxx10 = i[24] & (~i[25]);
//---------------------------------------------------
// decode i(26:30)
//---------------------------------------------------
assign f2_11xxx = i[26] & i[27]; // shifts / logicals / sign_xtd
assign f2_xxx0x = (~i[29]); // word / double
assign f2_111xx = i[26] & i[27] & i[28];
assign f2_xx01x = (~i[28]) & i[29];
assign f2_xx00x = (~i[28]) & (~i[29]);
assign f2_xxx1x = i[29];
assign f2_xx0xx = (~i[28]);
assign f2_xxx00 = (~i[29]) & (~i[30]);
assign rotlw_nm = rotlw & f0_xxxx11;
assign rotlw_pass = rotlw & f0_xxxx00;
assign rotld_pass = rld_imi;
assign sh_lft_rb = x31 & f1_0xxxx;
assign sh_lft_rb_dw = x31 & f1_0xxxx & f2_xxx1x;
assign sh_rgt = x31 & f1_1xxxx;
assign sh_rgt_rb = x31 & f1_1xxx0;
assign sh_rgt_rb_dw = x31 & f1_1xxx0 & f2_xxx1x;
assign shift_imm = x31 & f1_xxxx1;
assign sh_rb = x31 & f1_xxxx0;
assign sh_rb_dw = x31 & f1_xxxx0 & f2_xxx1x;
assign sh_rb_wd = x31 & f1_xxxx0 & f2_xxx0x;
assign x31_sh_log_sgn = x31 & f2_11xxx & (f2_xx0xx | f2_xxx00); // Exclude loads/stores
assign op_sgn_xtd = x31 & f1_111xx;
assign op_sra = x31 & f1_110xx;
assign wd_if_sh = x31 & f2_xxx0x;
assign xtd_log = x31 & f2_111xx;
assign sh_lft_imm_dw = 0;
assign sh_lft_imm = 0;
assign sh_rgt_imm_dw = x31 & i[21] & i[25] & i[29];
assign sh_rgt_imm = x31 & i[21] & i[25];
//---------------------------------------------------
// output signal
//---------------------------------------------------
assign ex1_cmp_byt = cmp_byt;
// (select to rot/log result instead of the adder result)
assign ex1_sel_rot_log = (cmp_byt) | (rotlw) | (imm_log) | (rotld) | (isel) | (x31_sh_log_sgn);
// prtyw, prtyd already included here....
// (zero out the mask to pass "insert_data" as the result)
// This latched, full decode ok.
assign ex1_zm_ins = (isel) | (cmp_byt) | (xtd_log) | (imm_log) | (op_sgn_xtd) | (prtyw) | (prtyd); // sgn extends
// (only needs to be correct when shifting)
assign ex1_sh_right = sh_rgt;
assign sh_word_int = (rotlw) | (wd_if_sh);
// (only needs to be correct when shifting)
assign ex1_sh_word = sh_word_int;
assign ex1_sgnxtd_byte = op_sgn_xtd & f1_xxx01 & (~isel);
assign ex1_sgnxtd_half = op_sgn_xtd & f1_xxx00 & (~isel);
assign ex1_sgnxtd_wd = op_sgn_xtd & f1_xxx10 & (~isel);
assign ex1_sra_dw = op_sra & f2_xx01x & (~isel);
assign ex1_sra_wd = op_sra & f2_xx00x & (~isel);
assign imm_xor_or = f0_xxx0xx;
assign imm_and_or = f0_xxxx0x;
assign xtd_nor = f1_xxx11;
assign xtd_eqv_orc_nand = f1_x1xx0;
assign xtd_nand = f1_x1x1x;
assign xtd_nand_or_orc = f1_xx1xx;
assign xtd_andc_xor_or = f1_xxx01;
assign xtd_and_eqv_orc = f1_xxx00;
assign xtd_or_orc = f1_xx10x;
assign xtd_xor_or = f1_x1xx1;
assign ex1_log_fcn = (cmp_byt == 1'b1) ? 4'b1001 : // xtd_log nor
rf1_log_fcn;
assign rf1_log_fcn[0] = (xtd_log & xtd_nor) | (xtd_log & xtd_eqv_orc_nand) | (cmp_byt); // xtd_log eqv,orc,nand
// xnor
// xtd_log xor,or
// xor,or
// pass rlwimi
assign rf1_log_fcn[1] = (xtd_log & xtd_xor_or) | (xtd_log & xtd_nand) | (imm_log & imm_xor_or) | (rotlw_pass) | (rotld_pass); // xtd_log nand
// pass rldimi
// xtd_log andc,xor,or
assign rf1_log_fcn[2] = (xtd_log & xtd_andc_xor_or) | (xtd_log & xtd_nand_or_orc) | (imm_log & imm_xor_or); // xtd_log nand_or_orc
// xor,or
// xnor
// xtd_log or,orc
// and,or
// pass rlwimi
assign rf1_log_fcn[3] = (cmp_byt) | (xtd_log & xtd_and_eqv_orc) | (xtd_log & xtd_or_orc) | (imm_log & imm_and_or) | (rotlw_pass) | (rotld_pass); // xtd_log and,eqv_orc
// pass rldimi
assign ex1_chk_shov_dw = (sh_rb_dw);
assign ex1_chk_shov_wd = (sh_rb_wd);
//---------------------------------------------
assign ex1_me_ins_b[0:5] = (~me_ins[0:5]);
assign me_ins[0] = (rotlw) | (i[26] & sel_ins_me_hi) | ((~i[30]) & sel_ins_amt_hi); // force_msb
assign me_ins[1:5] = (i[26:30] & {5{sel_ins_me_lo_wd}}) | (i[21:25] & {5{sel_ins_me_lo_dw}}) | ((~i[16:20]) & {5{sel_ins_amt_lo}});
assign sel_ins_me_lo_wd = rotlw;
assign sel_ins_me_lo_dw = rld_cr | rld_icr;
assign sel_ins_amt_lo = rld_ic | rld_imi | sh_lft_rb;
assign sel_ins_amt_hi = rld_ic | rld_imi | sh_lft_rb_dw;
assign sel_ins_me_hi = rld_cr | rld_icr;
assign ex1_use_me_rb_hi = (sh_lft_rb_dw);
assign ex1_use_me_rb_lo = (sh_lft_rb);
assign ex1_use_me_ins_hi = rld_cr | rld_icr | rld_imi | rld_ic | rotlw | sh_lft_imm_dw;
assign ex1_use_me_ins_lo = rld_cr | rld_icr | rld_imi | rld_ic | rotlw | sh_lft_imm;
assign rld_icl = rotld & (~i[27]) & (~i[28]) & (~i[29]);
assign rld_icr = rotld & (~i[27]) & (~i[28]) & i[29];
assign rld_ic = rotld & (~i[27]) & i[28] & (~i[29]);
assign rld_imi = rotld & (~i[27]) & i[28] & i[29];
assign rld_cl = rotld & i[27] & (~i[30]);
assign rld_cr = rotld & i[27] & i[30];
//---------------------------------------------
assign ex1_mb_ins[0] = (i[26] & rot_imm_mb) | (i[30] & shift_imm) | (rotlw) | (wd_if_sh); // force_msb
// force_msb
assign ex1_mb_ins[1:5] = (i[21:25] & {5{rot_imm_mb}}) | (i[16:20] & {5{shift_imm}});
assign rot_imm_mb = (rotlw) | (rld_cl | rld_icl | rld_ic | rld_imi);
assign ex1_use_mb_rb_lo = sh_rgt_rb;
assign ex1_use_mb_rb_hi = sh_rgt_rb_dw;
assign ex1_use_mb_ins_hi = rld_cl | rld_icl | rld_imi | rld_ic | rotlw | sh_rgt_imm_dw | wd_if_sh;
assign ex1_use_mb_ins_lo = rld_cl | rld_icl | rld_imi | rld_ic | rotlw | sh_rgt_imm;
//---------------------------------------------
assign ex1_use_rb_amt_hi = (rld_cr) | (rld_cl) | (sh_rb_dw);
assign ex1_use_rb_amt_lo = (rld_cr) | (rld_cl) | (rotlw_nm) | (sh_rb); // rlwnm
assign ex1_sh_amt[0] = i[30] & (~sh_word_int);
assign ex1_sh_amt[1:5] = i[16:20];
//---------------------------------------------
assign rotld_en_mbgtme = rld_imi | rld_ic;
assign ex1_mb_gt_me = (mb_gt_me_cmp_wd & rotlw) | (mb_gt_me_cmp_dw & rotld_en_mbgtme); // rldic,rldimi
//-------------------------------------------
assign gt5_in1[1:5] = i[21:25]; // mb
assign gt5_in0[1:5] = (~i[26:30]); // me
assign gt6_in1[0:5] = {i[26], i[21:25]}; // mb
assign gt6_in0[0:5] = {i[30], i[16:20]}; // me not( not amt )
//------------------------------------------
assign gt5_g_b[1:5] = (~(gt5_in0[1:5] & gt5_in1[1:5]));
assign gt5_t_b[1:4] = (~(gt5_in0[1:4] | gt5_in1[1:4]));
assign gt5_g_45 = (~(gt5_g_b[4] & (gt5_t_b[4] | gt5_g_b[5])));
assign gt5_g_23 = (~(gt5_g_b[2] & (gt5_t_b[2] | gt5_g_b[3])));
assign gt5_g_1 = (~(gt5_g_b[1]));
assign gt5_t_23 = (~(gt5_t_b[2] | gt5_t_b[3]));
assign gt5_t_1 = (~(gt5_t_b[1]));
assign mb_gt_me_cmp_wd0_b = (~(gt5_g_1));
assign mb_gt_me_cmp_wd1_b = (~(gt5_g_23 & gt5_t_1));
assign mb_gt_me_cmp_wd2_b = (~(gt5_g_45 & gt5_t_1 & gt5_t_23));
assign mb_gt_me_cmp_wd = (~(mb_gt_me_cmp_wd0_b & mb_gt_me_cmp_wd1_b & mb_gt_me_cmp_wd2_b));
//--------------------------------------------
assign gt6_g_b[0:5] = (~(gt6_in0[0:5] & gt6_in1[0:5]));
assign gt6_t_b[0:4] = (~(gt6_in0[0:4] | gt6_in1[0:4]));
assign gt6_g_45 = (~(gt6_g_b[4] & (gt6_t_b[4] | gt6_g_b[5])));
assign gt6_g_23 = (~(gt6_g_b[2] & (gt6_t_b[2] | gt6_g_b[3])));
assign gt6_g_01 = (~(gt6_g_b[0] & (gt6_t_b[0] | gt6_g_b[1])));
assign gt6_t_23 = (~(gt6_t_b[2] | gt6_t_b[3]));
assign gt6_t_01 = (~(gt6_t_b[0] | gt6_t_b[1]));
assign mb_gt_me_cmp_dw0_b = (~(gt6_g_01));
assign mb_gt_me_cmp_dw1_b = (~(gt6_g_23 & gt6_t_01));
assign mb_gt_me_cmp_dw2_b = (~(gt6_g_45 & gt6_t_01 & gt6_t_23));
assign mb_gt_me_cmp_dw = (~(mb_gt_me_cmp_dw0_b & mb_gt_me_cmp_dw1_b & mb_gt_me_cmp_dw2_b));
endmodule