// © 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 fs / 1 fs // *!**************************************************************** // *! FILENAME : tri_iuq_cpl_arr.v // *! DESCRIPTION : iuq completion array (fpga model) // *!**************************************************************** `include "tri_a2o.vh" module tri_iuq_cpl_arr(gnd, vdd, nclk, delay_lclkr_dc, mpw1_dc_b, mpw2_dc_b, force_t, thold_0_b, sg_0, scan_in, scan_out, re0, ra0, do0, re1, ra1, do1, we0, wa0, di0, we1, wa1, di1, perr); parameter ADDRESSABLE_PORTS = 64; // number of addressable register in this array parameter ADDRESSBUS_WIDTH = 6; // width of the bus to address all ports (2^ADDRESSBUS_WIDTH >= addressable_ports) parameter PORT_BITWIDTH = 64; // bitwidth of ports parameter LATCHED_READ = 1'b1; parameter LATCHED_READ_DATA = 1'b1; parameter LATCHED_WRITE = 1'b1; // POWER PINS (* ground_pin=1 *) inout gnd; (* power_pin=1 *) inout vdd; input [0:`NCLK_WIDTH-1] nclk; //------------------------------------------------------------------- // Pervasive //------------------------------------------------------------------- input delay_lclkr_dc; input mpw1_dc_b; input mpw2_dc_b; input force_t; input thold_0_b; input sg_0; input scan_in; output scan_out; //------------------------------------------------------------------- // Functional //------------------------------------------------------------------- input re0; input [0:ADDRESSBUS_WIDTH-1] ra0; output [0:PORT_BITWIDTH-1] do0; input re1; input [0:ADDRESSBUS_WIDTH-1] ra1; output [0:PORT_BITWIDTH-1] do1; input we0; input [0:ADDRESSBUS_WIDTH-1] wa0; input [0:PORT_BITWIDTH-1] di0; input we1; input [0:ADDRESSBUS_WIDTH-1] wa1; input [0:PORT_BITWIDTH-1] di1; output perr; reg re0_q; reg we0_q; reg [0:ADDRESSBUS_WIDTH-1] ra0_q; reg [0:ADDRESSBUS_WIDTH-1] wa0_q; reg [0:PORT_BITWIDTH-1] do0_q; wire [0:PORT_BITWIDTH-1] do0_d; reg [0:PORT_BITWIDTH-1] di0_q; reg re1_q; reg we1_q; reg [0:ADDRESSBUS_WIDTH-1] ra1_q; reg [0:ADDRESSBUS_WIDTH-1] wa1_q; reg [0:PORT_BITWIDTH-1] do1_q; wire [0:PORT_BITWIDTH-1] do1_d; reg [0:PORT_BITWIDTH-1] di1_q; wire correct_clk; wire reset; wire reset_hi; reg reset_q; wire [0:PORT_BITWIDTH-1] dout0; //std wire wen0; //std wire [0:ADDRESSBUS_WIDTH-1] addr_w0; //std wire [0:ADDRESSBUS_WIDTH-1] addr_r0; //std wire [0:PORT_BITWIDTH-1] din0; //std wire [0:PORT_BITWIDTH-1] dout1; //std wire wen1; //std wire [0:ADDRESSBUS_WIDTH-1] addr_w1; //std wire [0:ADDRESSBUS_WIDTH-1] addr_r1; //std wire [0:PORT_BITWIDTH-1] din1; //std reg we1_latch_q; reg [0:ADDRESSBUS_WIDTH-1] wa1_latch_q; reg [0:PORT_BITWIDTH-1] di1_latch_q; (* analysis_not_referenced="true" *) wire unused_SPO_0; (* analysis_not_referenced="true" *) wire unused_SPO_1; generate assign reset = nclk[1]; assign correct_clk = nclk[0]; assign reset_hi = reset; // Slow Latches (nclk) always @(posedge correct_clk or posedge reset) begin: slatch begin if (reset == 1'b1) we1_latch_q <= 1'b0; else begin we1_latch_q <= we1_q; wa1_latch_q <= wa1_q; di1_latch_q <= di1_q; end end end // repower latches for resets always @(posedge correct_clk) begin: rlatch reset_q <= reset_hi; end // need to select which array to write based on the lowest order bit of the address which will indicate odd or even itag // when both we0 and we1 are both asserted it is assumed that the low order bit of wa0 will not be equal to the low order // bit of wa1 assign addr_w0 = (wa0_q[ADDRESSBUS_WIDTH-1]) ? {wa1_q[0:ADDRESSBUS_WIDTH-2], 1'b0 } : {wa0_q[0:ADDRESSBUS_WIDTH-2], 1'b0 }; assign wen0 = (wa0_q[ADDRESSBUS_WIDTH-1]) ? we1_q : we0_q; assign din0 = (wa0_q[ADDRESSBUS_WIDTH-1]) ? di1_q : di0_q; assign addr_r0 = (ra0_q[ADDRESSBUS_WIDTH-1]) ? {ra1_q[0:ADDRESSBUS_WIDTH-2], 1'b0 } : {ra0_q[0:ADDRESSBUS_WIDTH-2], 1'b0 }; assign addr_w1 = (wa1_q[ADDRESSBUS_WIDTH-1]) ? {wa1_q[0:ADDRESSBUS_WIDTH-2], 1'b0 } : {wa0_q[0:ADDRESSBUS_WIDTH-2], 1'b0 }; assign wen1 = (wa1_q[ADDRESSBUS_WIDTH-1]) ? we1_q : we0_q; assign din1 = (wa1_q[ADDRESSBUS_WIDTH-1]) ? di1_q : di0_q; assign addr_r1 = (ra1_q[ADDRESSBUS_WIDTH-1]) ? {ra1_q[0:ADDRESSBUS_WIDTH-2], 1'b0 } : {ra0_q[0:ADDRESSBUS_WIDTH-2], 1'b0 }; assign perr = 1'b0; begin : xhdl0 genvar i; for (i = 0; i <= PORT_BITWIDTH - 1; i = i + 1) begin : array_gen0 RAM64X1D #(.INIT(64'h0000000000000000)) RAM64X1D0( .DPO(dout0[i]), .SPO(unused_SPO_0), .A0(addr_w0[0]), .A1(addr_w0[1]), .A2(addr_w0[2]), .A3(addr_w0[3]), .A4(addr_w0[4]), .A5(addr_w0[5]), //.A(addr_w0), .D(din0[i]), .DPRA0(addr_r0[0]), .DPRA1(addr_r0[1]), .DPRA2(addr_r0[2]), .DPRA3(addr_r0[3]), .DPRA4(addr_r0[4]), .DPRA5(addr_r0[5]), //.DPRA(addr_r0), .WCLK(correct_clk), .WE(wen0) ); RAM64X1D #(.INIT(64'h0000000000000000)) RAM64X1D1( .DPO(dout1[i]), .SPO(unused_SPO_1), .A0(addr_w1[0]), .A1(addr_w1[1]), .A2(addr_w1[2]), .A3(addr_w1[3]), .A4(addr_w1[4]), .A5(addr_w1[5]), //.A(addr_w1), .D(din1[i]), .DPRA0(addr_r1[0]), .DPRA1(addr_r1[1]), .DPRA2(addr_r1[2]), .DPRA3(addr_r1[3]), .DPRA4(addr_r1[4]), .DPRA5(addr_r1[5]), //.DPRA(addr_r1), .WCLK(correct_clk), .WE(wen1) ); end end assign do0_d = (ra0_q[ADDRESSBUS_WIDTH-1]) ? dout1 : dout0; assign do1_d = (ra1_q[ADDRESSBUS_WIDTH-1]) ? dout1 : dout0; assign do0 = do0_q; assign do1 = do1_q; if (LATCHED_READ == 1'b0) begin : read_latched_false always @(*) begin re0_q <= re0; ra0_q <= ra0; re1_q <= re1; ra1_q <= ra1; end end if (LATCHED_READ == 1'b1) begin : read_latched_true always @(posedge correct_clk) begin: read_latches if (correct_clk == 1'b1) begin if (reset_q == 1'b1) begin re0_q <= 1'b0; ra0_q <= {ADDRESSBUS_WIDTH{1'b0}}; re1_q <= 1'b0; ra1_q <= {ADDRESSBUS_WIDTH{1'b0}}; end else begin re0_q <= re0; ra0_q <= ra0; re1_q <= re1; ra1_q <= ra1; end end end end if (LATCHED_WRITE == 1'b0) begin : write_latched_false always @(*) begin we0_q <= we0; wa0_q <= wa0; di0_q <= di0; we1_q <= we1; wa1_q <= wa1; di1_q <= di1; end end if (LATCHED_WRITE == 1'b1) begin : write_latched_true always @(posedge correct_clk) begin: write_latches if (correct_clk == 1'b1) begin if (reset_q == 1'b1) begin we0_q <= 1'b0; wa0_q <= {ADDRESSBUS_WIDTH{1'b0}}; di0_q <= {PORT_BITWIDTH{1'b0}}; we1_q <= 1'b0; wa1_q <= {ADDRESSBUS_WIDTH{1'b0}}; di1_q <= {PORT_BITWIDTH{1'b0}}; end else begin we0_q <= we0; wa0_q <= wa0; di0_q <= di0; we1_q <= we1; wa1_q <= wa1; di1_q <= di1; end end end end if (LATCHED_READ_DATA == 1'b0) begin : read_data_latched_false always @(*) begin do0_q <= do0_d; do1_q <= do1_d; end end if (LATCHED_READ_DATA == 1'b1) begin : read_data_latched_true always @(posedge correct_clk) begin: read_data_latches if (correct_clk == 1'b1) begin if (reset_q == 1'b1) begin do0_q <= {PORT_BITWIDTH{1'b0}}; do1_q <= {PORT_BITWIDTH{1'b0}}; end else begin do0_q <= do0_d; do1_q <= do1_d; end end end end endgenerate endmodule