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.

260 lines
11 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 - Rotate Component
//
//*****************************************************************************
module tri_st_rot_rol64(
word,
right,
amt,
data_i,
res_rot
);
input [0:1] word; // PPC word mode rotate <2 copies>
input [0:2] right; // emulate a shift right with a rotate left <2 copies>
input [0:5] amt; // shift amout [0:63]
input [0:63] data_i; // data to be shifted
output [0:63] res_rot; // mask shows which rotator bits to keep in the result.
wire [0:2] right_b;
wire [0:5] amt_b;
wire [0:1] word_b;
wire [0:31] word_bus;
wire [0:31] word_bus_b;
wire [0:31] data_i0_adj_b;
wire [0:63] data_i_adj;
wire [0:63] data_i1_adj_b;
wire [0:63] rolx16_0;
wire [0:63] rolx16_1;
wire [0:63] rolx16_2;
wire [0:63] rolx16_3;
wire [0:63] rolx04_0;
wire [0:63] rolx04_1;
wire [0:63] rolx04_2;
wire [0:63] rolx04_3;
wire [0:63] rolx01_0;
wire [0:63] rolx01_1;
wire [0:63] rolx01_2;
wire [0:63] rolx01_3;
wire [0:63] rolx01_4;
wire [0:63] shd16;
wire [0:63] shd16_0_b;
wire [0:63] shd16_1_b;
wire [0:63] shd04;
wire [0:63] shd04_0_b;
wire [0:63] shd04_1_b;
wire [0:63] shd01_0_b;
wire [0:63] shd01_1_b;
wire [0:63] shd01_2_b;
wire [0:3] x16_lft_b;
wire [0:3] x16_rgt_b;
wire [0:3] lftx16;
wire [0:3] x04_lft_b;
wire [0:3] x04_rgt_b;
wire [0:3] lftx04;
wire [0:3] x01_lft_b;
wire [0:3] x01_rgt_b;
wire [0:4] lftx01;
wire [0:4] lftx01_inv;
wire [0:4] lftx01_buf0;
wire [0:4] lftx01_buf1;
wire [0:3] lftx04_inv;
wire [0:3] lftx04_buf0;
wire [0:3] lftx04_buf1;
wire [0:3] lftx16_inv;
wire [0:3] lftx16_buf0;
wire [0:3] lftx16_buf1;
wire [0:63] lftx16_0_bus;
wire [0:63] lftx16_1_bus;
wire [0:63] lftx16_2_bus;
wire [0:63] lftx16_3_bus;
wire [0:63] lftx04_0_bus;
wire [0:63] lftx04_1_bus;
wire [0:63] lftx04_2_bus;
wire [0:63] lftx04_3_bus;
wire [0:63] lftx01_0_bus;
wire [0:63] lftx01_1_bus;
wire [0:63] lftx01_2_bus;
wire [0:63] lftx01_3_bus;
wire [0:63] lftx01_4_bus;
// -------------------------------------------------------------
// how the ppc emulates a rot32 using rot64 hardware.
// this makes the wrapping corect for the low order 32 bits.
// upper 32 result bits a garbage
//--------------------------------------------------------------
assign word_b[0:1] = (~word[0:1]);
assign word_bus_b[0:15] = {16{word_b[0]}};
assign word_bus_b[16:31] = {16{word_b[1]}};
assign word_bus[0:15] = {16{word[0]}};
assign word_bus[16:31] = {16{word[1]}};
assign data_i0_adj_b[0:31] = (~(data_i[0:31] & word_bus_b[0:31]));
assign data_i1_adj_b[0:31] = (~(data_i[32:63] & word_bus[0:31]));
assign data_i_adj[0:31] = (~(data_i0_adj_b[0:31] & data_i1_adj_b[0:31]));
assign data_i1_adj_b[32:63] = (~(data_i[32:63]));
assign data_i_adj[32:63] = (~(data_i1_adj_b[32:63]));
//---------------------------------------------------------------
// decoder without the adder
//---------------------------------------------------------------
//rotate right by [n] == rotate_left by width -[n] == !n + 1
assign right_b[0:2] = (~right[0:2]);
assign amt_b[0:5] = (~amt[0:5]);
assign x16_lft_b[0] = (~(right_b[0] & amt_b[0] & amt_b[1]));
assign x16_lft_b[1] = (~(right_b[0] & amt_b[0] & amt[1]));
assign x16_lft_b[2] = (~(right_b[0] & amt[0] & amt_b[1]));
assign x16_lft_b[3] = (~(right_b[0] & amt[0] & amt[1]));
assign x16_rgt_b[0] = (~(right[0] & amt_b[0] & amt_b[1]));
assign x16_rgt_b[1] = (~(right[0] & amt_b[0] & amt[1]));
assign x16_rgt_b[2] = (~(right[0] & amt[0] & amt_b[1]));
assign x16_rgt_b[3] = (~(right[0] & amt[0] & amt[1]));
assign lftx16[0] = (~(x16_lft_b[0] & x16_rgt_b[3]));
assign lftx16[1] = (~(x16_lft_b[1] & x16_rgt_b[2]));
assign lftx16[2] = (~(x16_lft_b[2] & x16_rgt_b[1]));
assign lftx16[3] = (~(x16_lft_b[3] & x16_rgt_b[0]));
assign x04_lft_b[0] = (~(right_b[1] & amt_b[2] & amt_b[3]));
assign x04_lft_b[1] = (~(right_b[1] & amt_b[2] & amt[3]));
assign x04_lft_b[2] = (~(right_b[1] & amt[2] & amt_b[3]));
assign x04_lft_b[3] = (~(right_b[1] & amt[2] & amt[3]));
assign x04_rgt_b[0] = (~(right[1] & amt_b[2] & amt_b[3]));
assign x04_rgt_b[1] = (~(right[1] & amt_b[2] & amt[3]));
assign x04_rgt_b[2] = (~(right[1] & amt[2] & amt_b[3]));
assign x04_rgt_b[3] = (~(right[1] & amt[2] & amt[3]));
assign lftx04[0] = (~(x04_lft_b[0] & x04_rgt_b[3]));
assign lftx04[1] = (~(x04_lft_b[1] & x04_rgt_b[2]));
assign lftx04[2] = (~(x04_lft_b[2] & x04_rgt_b[1]));
assign lftx04[3] = (~(x04_lft_b[3] & x04_rgt_b[0]));
assign x01_lft_b[0] = (~(right_b[2] & amt_b[4] & amt_b[5]));
assign x01_lft_b[1] = (~(right_b[2] & amt_b[4] & amt[5]));
assign x01_lft_b[2] = (~(right_b[2] & amt[4] & amt_b[5]));
assign x01_lft_b[3] = (~(right_b[2] & amt[4] & amt[5]));
assign x01_rgt_b[0] = (~(right[2] & amt_b[4] & amt_b[5]));
assign x01_rgt_b[1] = (~(right[2] & amt_b[4] & amt[5]));
assign x01_rgt_b[2] = (~(right[2] & amt[4] & amt_b[5]));
assign x01_rgt_b[3] = (~(right[2] & amt[4] & amt[5]));
assign lftx01[0] = (~(x01_lft_b[0])); // the shift is like the +1
assign lftx01[1] = (~(x01_lft_b[1] & x01_rgt_b[3]));
assign lftx01[2] = (~(x01_lft_b[2] & x01_rgt_b[2]));
assign lftx01[3] = (~(x01_lft_b[3] & x01_rgt_b[1]));
assign lftx01[4] = (~(x01_rgt_b[0]));
assign lftx16_inv[0:3] = (~(lftx16[0:3]));
assign lftx16_buf0[0:3] = (~(lftx16_inv[0:3]));
assign lftx16_buf1[0:3] = (~(lftx16_inv[0:3]));
assign lftx04_inv[0:3] = (~(lftx04[0:3]));
assign lftx04_buf0[0:3] = (~(lftx04_inv[0:3]));
assign lftx04_buf1[0:3] = (~(lftx04_inv[0:3]));
assign lftx01_inv[0:4] = (~(lftx01[0:4]));
assign lftx01_buf0[0:4] = (~(lftx01_inv[0:4]));
assign lftx01_buf1[0:4] = (~(lftx01_inv[0:4]));
assign lftx16_0_bus[0:31] = {32{lftx16_buf0[0]}};
assign lftx16_0_bus[32:63] = {32{lftx16_buf1[0]}};
assign lftx16_1_bus[0:31] = {32{lftx16_buf0[1]}};
assign lftx16_1_bus[32:63] = {32{lftx16_buf1[1]}};
assign lftx16_2_bus[0:31] = {32{lftx16_buf0[2]}};
assign lftx16_2_bus[32:63] = {32{lftx16_buf1[2]}};
assign lftx16_3_bus[0:31] = {32{lftx16_buf0[3]}};
assign lftx16_3_bus[32:63] = {32{lftx16_buf1[3]}};
assign lftx04_0_bus[0:31] = {32{lftx04_buf0[0]}};
assign lftx04_0_bus[32:63] = {32{lftx04_buf1[0]}};
assign lftx04_1_bus[0:31] = {32{lftx04_buf0[1]}};
assign lftx04_1_bus[32:63] = {32{lftx04_buf1[1]}};
assign lftx04_2_bus[0:31] = {32{lftx04_buf0[2]}};
assign lftx04_2_bus[32:63] = {32{lftx04_buf1[2]}};
assign lftx04_3_bus[0:31] = {32{lftx04_buf0[3]}};
assign lftx04_3_bus[32:63] = {32{lftx04_buf1[3]}};
assign lftx01_0_bus[0:31] = {32{lftx01_buf0[0]}};
assign lftx01_0_bus[32:63] = {32{lftx01_buf1[0]}};
assign lftx01_1_bus[0:31] = {32{lftx01_buf0[1]}};
assign lftx01_1_bus[32:63] = {32{lftx01_buf1[1]}};
assign lftx01_2_bus[0:31] = {32{lftx01_buf0[2]}};
assign lftx01_2_bus[32:63] = {32{lftx01_buf1[2]}};
assign lftx01_3_bus[0:31] = {32{lftx01_buf0[3]}};
assign lftx01_3_bus[32:63] = {32{lftx01_buf1[3]}};
assign lftx01_4_bus[0:31] = {32{lftx01_buf0[4]}};
assign lftx01_4_bus[32:63] = {32{lftx01_buf1[4]}};
//---------------------------------------------------------------
// the shifter
//---------------------------------------------------------------
assign rolx16_0[0:63] = data_i_adj[0:63];
assign rolx16_1[0:63] = {data_i_adj[16:63], data_i_adj[0:15]};
assign rolx16_2[0:63] = {data_i_adj[32:63], data_i_adj[0:31]};
assign rolx16_3[0:63] = {data_i_adj[48:63], data_i_adj[0:47]};
assign shd16_0_b[0:63] = (~((lftx16_0_bus[0:63] & rolx16_0[0:63]) | (lftx16_1_bus[0:63] & rolx16_1[0:63])));
assign shd16_1_b[0:63] = (~((lftx16_2_bus[0:63] & rolx16_2[0:63]) | (lftx16_3_bus[0:63] & rolx16_3[0:63])));
assign shd16[0:63] = (~(shd16_0_b[0:63] & shd16_1_b[0:63]));
assign rolx04_0[0:63] = shd16[0:63];
assign rolx04_1[0:63] = {shd16[4:63], shd16[0:3]};
assign rolx04_2[0:63] = {shd16[8:63], shd16[0:7]};
assign rolx04_3[0:63] = {shd16[12:63], shd16[0:11]};
assign shd04_0_b[0:63] = (~((lftx04_0_bus[0:63] & rolx04_0[0:63]) | (lftx04_1_bus[0:63] & rolx04_1[0:63])));
assign shd04_1_b[0:63] = (~((lftx04_2_bus[0:63] & rolx04_2[0:63]) | (lftx04_3_bus[0:63] & rolx04_3[0:63])));
assign shd04[0:63] = (~(shd04_0_b[0:63] & shd04_1_b[0:63]));
assign rolx01_0[0:63] = shd04[0:63];
assign rolx01_1[0:63] = {shd04[1:63], shd04[0]};
assign rolx01_2[0:63] = {shd04[2:63], shd04[0:1]};
assign rolx01_3[0:63] = {shd04[3:63], shd04[0:2]};
assign rolx01_4[0:63] = {shd04[4:63], shd04[0:3]};
assign shd01_0_b[0:63] = (~((lftx01_0_bus[0:63] & rolx01_0[0:63]) | (lftx01_1_bus[0:63] & rolx01_1[0:63])));
assign shd01_1_b[0:63] = (~((lftx01_2_bus[0:63] & rolx01_2[0:63]) | (lftx01_3_bus[0:63] & rolx01_3[0:63])));
assign shd01_2_b[0:63] = (~(lftx01_4_bus[0:63] & rolx01_4[0:63]));
assign res_rot[0:63] = (~(shd01_0_b[0:63] & shd01_1_b[0:63] & shd01_2_b[0:63]));
endmodule