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.
345 lines
12 KiB
Verilog
345 lines
12 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 ALU Compare
|
|
//
|
|
//*****************************************************************************
|
|
`include "tri_a2o.vh"
|
|
module xu_alu_cmp(
|
|
// Clocks
|
|
input clk,
|
|
input rst,
|
|
|
|
// Power
|
|
inout vdd,
|
|
inout gnd,
|
|
|
|
// Pervasive
|
|
input d_mode_dc,
|
|
input delay_lclkr_dc,
|
|
input mpw1_dc_b,
|
|
input mpw2_dc_b,
|
|
input func_sl_force,
|
|
input func_sl_thold_0_b,
|
|
input sg_0,
|
|
input scan_in,
|
|
output scan_out,
|
|
|
|
input ex2_act,
|
|
|
|
input ex1_msb_64b_sel,
|
|
|
|
input [6:10] ex2_instr,
|
|
input ex2_sel_trap,
|
|
input ex2_sel_cmpl,
|
|
input ex2_sel_cmp,
|
|
|
|
input ex2_rs1_00,
|
|
input ex2_rs1_32,
|
|
|
|
input ex2_rs2_00,
|
|
input ex2_rs2_32,
|
|
|
|
input [64-`GPR_WIDTH:63] ex3_alu_rt,
|
|
input ex3_add_ca,
|
|
|
|
output [0:2] ex3_alu_cr,
|
|
|
|
output ex3_trap_val
|
|
);
|
|
localparam msb = 64 - `GPR_WIDTH;
|
|
// Latches
|
|
wire ex2_msb_64b_sel_q; // input=>ex1_msb_64b_sel ,act=>1'b1
|
|
wire ex3_msb_64b_sel_q; // input=>ex2_msb_64b_sel_q ,act=>ex2_act
|
|
wire ex3_diff_sign_q; // input=>ex2_diff_sign ,act=>ex2_act
|
|
wire ex2_diff_sign;
|
|
wire ex3_rs1_trm1_q; // input=>ex2_rs1_trm1 ,act=>ex2_act
|
|
wire ex2_rs1_trm1;
|
|
wire ex3_rs2_trm1_q; // input=>ex2_rs2_trm1 ,act=>ex2_act
|
|
wire ex2_rs2_trm1;
|
|
wire [6:10] ex3_instr_q; // input=>ex2_instr ,act=>ex2_act
|
|
wire ex3_sel_trap_q; // input=>ex2_sel_trap ,act=>ex2_act
|
|
wire ex3_sel_cmpl_q; // input=>ex2_sel_cmpl ,act=>ex2_act
|
|
wire ex3_sel_cmp_q; // input=>ex2_sel_cmp ,act=>ex2_act
|
|
// Scanchains
|
|
localparam ex2_msb_64b_sel_offset = 0;
|
|
localparam ex3_msb_64b_sel_offset = ex2_msb_64b_sel_offset + 1;
|
|
localparam ex3_diff_sign_offset = ex3_msb_64b_sel_offset + 1;
|
|
localparam ex3_rs1_trm1_offset = ex3_diff_sign_offset + 1;
|
|
localparam ex3_rs2_trm1_offset = ex3_rs1_trm1_offset + 1;
|
|
localparam ex3_instr_offset = ex3_rs2_trm1_offset + 1;
|
|
localparam ex3_sel_trap_offset = ex3_instr_offset + 5;
|
|
localparam ex3_sel_cmpl_offset = ex3_sel_trap_offset + 1;
|
|
localparam ex3_sel_cmp_offset = ex3_sel_cmpl_offset + 1;
|
|
localparam scan_right = ex3_sel_cmp_offset + 1;
|
|
wire [0:scan_right-1] siv;
|
|
wire [0:scan_right-1] sov;
|
|
// Signals
|
|
wire ex3_cmp0_hi;
|
|
wire ex3_cmp0_lo;
|
|
wire ex3_cmp0_eq;
|
|
wire ex2_rs1_msb;
|
|
wire ex2_rs2_msb;
|
|
wire ex3_rt_msb;
|
|
wire ex3_rslt_gt_s;
|
|
wire ex3_rslt_lt_s;
|
|
wire ex3_rslt_gt_u;
|
|
wire ex3_rslt_lt_u;
|
|
wire ex3_cmp_eq;
|
|
wire ex3_cmp_gt;
|
|
wire ex3_cmp_lt;
|
|
wire ex3_sign_cmp;
|
|
|
|
|
|
tri_st_or3232 or3232(
|
|
.d(ex3_alu_rt),
|
|
.or_hi_b(ex3_cmp0_hi),
|
|
.or_lo_b(ex3_cmp0_lo)
|
|
);
|
|
|
|
assign ex2_rs1_msb = (ex2_msb_64b_sel_q == 1'b1) ? ex2_rs1_00 : ex2_rs1_32;
|
|
|
|
assign ex2_rs2_msb = (ex2_msb_64b_sel_q == 1'b1) ? ex2_rs2_00 : ex2_rs2_32;
|
|
|
|
assign ex3_rt_msb = (ex3_msb_64b_sel_q == 1'b1) ? ex3_alu_rt[msb] : ex3_alu_rt[32];
|
|
|
|
// If the signs are different, then we immediately know if one is bigger than the other.
|
|
// but only look at this in case of compare instructions
|
|
assign ex3_cmp0_eq = (ex3_msb_64b_sel_q == 1'b1) ? (ex3_cmp0_lo & ex3_cmp0_hi) : ex3_cmp0_lo;
|
|
|
|
assign ex2_diff_sign = (ex2_rs1_msb ^ ex2_rs2_msb) & (ex2_sel_cmpl | ex2_sel_cmp | ex2_sel_trap);
|
|
|
|
// In case the sigs are not different, we need some more logic
|
|
// Look at adder carry out for compares (need to be able to check over flow case)
|
|
// Look at sign bit for record forms (overflow is ignored, ie two positives equal a negative.)
|
|
|
|
assign ex3_sign_cmp = ((ex3_sel_cmpl_q | ex3_sel_cmp_q | ex3_sel_trap_q) == 1'b1) ? ex3_add_ca : ex3_rt_msb;
|
|
assign ex2_rs1_trm1 = ex2_rs1_msb & ex2_diff_sign;
|
|
assign ex2_rs2_trm1 = ex2_rs2_msb & ex2_diff_sign;
|
|
|
|
// Signed compare
|
|
assign ex3_rslt_gt_s = (ex3_rs2_trm1_q | (~ex3_sign_cmp & ~ex3_diff_sign_q)); // RS2 < RS1
|
|
assign ex3_rslt_lt_s = (ex3_rs1_trm1_q | ( ex3_sign_cmp & ~ex3_diff_sign_q)); // RS2 > RS1
|
|
// Unsigned compare
|
|
assign ex3_rslt_gt_u = (ex3_rs1_trm1_q | (~ex3_sign_cmp & ~ex3_diff_sign_q)); // RS2 < RS1
|
|
assign ex3_rslt_lt_u = (ex3_rs2_trm1_q | ( ex3_sign_cmp & ~ex3_diff_sign_q)); // RS2 > RS1
|
|
|
|
assign ex3_cmp_eq = ex3_cmp0_eq;
|
|
assign ex3_cmp_gt = ((~ex3_sel_cmpl_q & ex3_rslt_gt_s) | (ex3_sel_cmpl_q & ex3_rslt_gt_u)) & (~ex3_cmp0_eq);
|
|
assign ex3_cmp_lt = ((~ex3_sel_cmpl_q & ex3_rslt_lt_s) | (ex3_sel_cmpl_q & ex3_rslt_lt_u)) & (~ex3_cmp0_eq);
|
|
|
|
// CR Field for Add, Logical, Rotate
|
|
assign ex3_alu_cr = {ex3_cmp_lt, ex3_cmp_gt, ex3_cmp_eq};
|
|
|
|
// Trap logic
|
|
assign ex3_trap_val = ex3_sel_trap_q &
|
|
((ex3_instr_q[6] & (~ex3_cmp_eq) & ex3_rslt_lt_s) |
|
|
(ex3_instr_q[7] & (~ex3_cmp_eq) & ex3_rslt_gt_s) |
|
|
(ex3_instr_q[8] & ex3_cmp_eq) |
|
|
(ex3_instr_q[9] & (~ex3_cmp_eq) & ex3_rslt_lt_u) |
|
|
(ex3_instr_q[10] & (~ex3_cmp_eq) & ex3_rslt_gt_u));
|
|
|
|
// Latch Instances
|
|
tri_rlmlatch_p #(.INIT(0), .NEEDS_SRESET(1)) ex2_msb_64b_sel_latch(
|
|
.clk(clk),
|
|
.rst(rst),
|
|
.vd(vdd),
|
|
.gd(gnd),
|
|
.act(1'b1),
|
|
.force_t(func_sl_force),
|
|
.d_mode(d_mode_dc),
|
|
.delay_lclkr(delay_lclkr_dc),
|
|
.mpw1_b(mpw1_dc_b),
|
|
.mpw2_b(mpw2_dc_b),
|
|
.thold_b(func_sl_thold_0_b),
|
|
.sg(sg_0),
|
|
.scin(siv[ex2_msb_64b_sel_offset]),
|
|
.scout(sov[ex2_msb_64b_sel_offset]),
|
|
.din(ex1_msb_64b_sel),
|
|
.dout(ex2_msb_64b_sel_q)
|
|
);
|
|
|
|
tri_rlmlatch_p #(.INIT(0), .NEEDS_SRESET(1)) ex3_msb_64b_sel_latch(
|
|
.clk(clk),
|
|
.rst(rst),
|
|
.vd(vdd),
|
|
.gd(gnd),
|
|
.act(ex2_act),
|
|
.force_t(func_sl_force),
|
|
.d_mode(d_mode_dc),
|
|
.delay_lclkr(delay_lclkr_dc),
|
|
.mpw1_b(mpw1_dc_b),
|
|
.mpw2_b(mpw2_dc_b),
|
|
.thold_b(func_sl_thold_0_b),
|
|
.sg(sg_0),
|
|
.scin(siv[ex3_msb_64b_sel_offset]),
|
|
.scout(sov[ex3_msb_64b_sel_offset]),
|
|
.din(ex2_msb_64b_sel_q),
|
|
.dout(ex3_msb_64b_sel_q)
|
|
);
|
|
|
|
tri_rlmlatch_p #(.INIT(0), .NEEDS_SRESET(1)) ex3_diff_sign_latch(
|
|
.clk(clk),
|
|
.rst(rst),
|
|
.vd(vdd),
|
|
.gd(gnd),
|
|
.act(ex2_act),
|
|
.force_t(func_sl_force),
|
|
.d_mode(d_mode_dc),
|
|
.delay_lclkr(delay_lclkr_dc),
|
|
.mpw1_b(mpw1_dc_b),
|
|
.mpw2_b(mpw2_dc_b),
|
|
.thold_b(func_sl_thold_0_b),
|
|
.sg(sg_0),
|
|
.scin(siv[ex3_diff_sign_offset]),
|
|
.scout(sov[ex3_diff_sign_offset]),
|
|
.din(ex2_diff_sign),
|
|
.dout(ex3_diff_sign_q)
|
|
);
|
|
|
|
tri_rlmlatch_p #(.INIT(0), .NEEDS_SRESET(1)) ex3_rs1_trm1_latch(
|
|
.clk(clk),
|
|
.rst(rst),
|
|
.vd(vdd),
|
|
.gd(gnd),
|
|
.act(ex2_act),
|
|
.force_t(func_sl_force),
|
|
.d_mode(d_mode_dc),
|
|
.delay_lclkr(delay_lclkr_dc),
|
|
.mpw1_b(mpw1_dc_b),
|
|
.mpw2_b(mpw2_dc_b),
|
|
.thold_b(func_sl_thold_0_b),
|
|
.sg(sg_0),
|
|
.scin(siv[ex3_rs1_trm1_offset]),
|
|
.scout(sov[ex3_rs1_trm1_offset]),
|
|
.din(ex2_rs1_trm1),
|
|
.dout(ex3_rs1_trm1_q)
|
|
);
|
|
|
|
tri_rlmlatch_p #(.INIT(0), .NEEDS_SRESET(1)) ex3_rs2_trm1_latch(
|
|
.clk(clk),
|
|
.rst(rst),
|
|
.vd(vdd),
|
|
.gd(gnd),
|
|
.act(ex2_act),
|
|
.force_t(func_sl_force),
|
|
.d_mode(d_mode_dc),
|
|
.delay_lclkr(delay_lclkr_dc),
|
|
.mpw1_b(mpw1_dc_b),
|
|
.mpw2_b(mpw2_dc_b),
|
|
.thold_b(func_sl_thold_0_b),
|
|
.sg(sg_0),
|
|
.scin(siv[ex3_rs2_trm1_offset]),
|
|
.scout(sov[ex3_rs2_trm1_offset]),
|
|
.din(ex2_rs2_trm1),
|
|
.dout(ex3_rs2_trm1_q)
|
|
);
|
|
|
|
tri_rlmreg_p #(.WIDTH(5), .INIT(0), .NEEDS_SRESET(1)) ex3_instr_latch(
|
|
.clk(clk),
|
|
.rst(rst),
|
|
.vd(vdd),
|
|
.gd(gnd),
|
|
.act(ex2_act),
|
|
.force_t(func_sl_force),
|
|
.d_mode(d_mode_dc),
|
|
.delay_lclkr(delay_lclkr_dc),
|
|
.mpw1_b(mpw1_dc_b),
|
|
.mpw2_b(mpw2_dc_b),
|
|
.thold_b(func_sl_thold_0_b),
|
|
.sg(sg_0),
|
|
.scin(siv[ex3_instr_offset:ex3_instr_offset + 5 - 1]),
|
|
.scout(sov[ex3_instr_offset:ex3_instr_offset + 5 - 1]),
|
|
.din(ex2_instr),
|
|
.dout(ex3_instr_q)
|
|
);
|
|
|
|
tri_rlmlatch_p #(.INIT(0), .NEEDS_SRESET(1)) ex3_sel_trap_latch(
|
|
.clk(clk),
|
|
.rst(rst),
|
|
.vd(vdd),
|
|
.gd(gnd),
|
|
.act(ex2_act),
|
|
.force_t(func_sl_force),
|
|
.d_mode(d_mode_dc),
|
|
.delay_lclkr(delay_lclkr_dc),
|
|
.mpw1_b(mpw1_dc_b),
|
|
.mpw2_b(mpw2_dc_b),
|
|
.thold_b(func_sl_thold_0_b),
|
|
.sg(sg_0),
|
|
.scin(siv[ex3_sel_trap_offset]),
|
|
.scout(sov[ex3_sel_trap_offset]),
|
|
.din(ex2_sel_trap),
|
|
.dout(ex3_sel_trap_q)
|
|
);
|
|
|
|
tri_rlmlatch_p #(.INIT(0), .NEEDS_SRESET(1)) ex3_sel_cmpl_latch(
|
|
.clk(clk),
|
|
.rst(rst),
|
|
.vd(vdd),
|
|
.gd(gnd),
|
|
.act(ex2_act),
|
|
.force_t(func_sl_force),
|
|
.d_mode(d_mode_dc),
|
|
.delay_lclkr(delay_lclkr_dc),
|
|
.mpw1_b(mpw1_dc_b),
|
|
.mpw2_b(mpw2_dc_b),
|
|
.thold_b(func_sl_thold_0_b),
|
|
.sg(sg_0),
|
|
.scin(siv[ex3_sel_cmpl_offset]),
|
|
.scout(sov[ex3_sel_cmpl_offset]),
|
|
.din(ex2_sel_cmpl),
|
|
.dout(ex3_sel_cmpl_q)
|
|
);
|
|
|
|
tri_rlmlatch_p #(.INIT(0), .NEEDS_SRESET(1)) ex3_sel_cmp_latch(
|
|
.clk(clk),
|
|
.rst(rst),
|
|
.vd(vdd),
|
|
.gd(gnd),
|
|
.act(ex2_act),
|
|
.force_t(func_sl_force),
|
|
.d_mode(d_mode_dc),
|
|
.delay_lclkr(delay_lclkr_dc),
|
|
.mpw1_b(mpw1_dc_b),
|
|
.mpw2_b(mpw2_dc_b),
|
|
.thold_b(func_sl_thold_0_b),
|
|
.sg(sg_0),
|
|
.scin(siv[ex3_sel_cmp_offset]),
|
|
.scout(sov[ex3_sel_cmp_offset]),
|
|
.din(ex2_sel_cmp),
|
|
.dout(ex3_sel_cmp_q)
|
|
);
|
|
|
|
assign siv[0:scan_right-1] = {sov[1:scan_right-1], scan_in};
|
|
assign scan_out = sov[0];
|
|
|
|
endmodule
|