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.

344 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 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