abstractaccelerator/design/lsu/lsu_dccm_mem.sv

128 lines
7.0 KiB
Systemverilog
Raw Normal View History

2019-06-04 22:57:48 +08:00
// SPDX-License-Identifier: Apache-2.0
// Copyright 2019 Western Digital Corporation or its affiliates.
2020-02-20 10:25:04 +08:00
//
2019-06-04 22:57:48 +08:00
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
2020-02-20 10:25:04 +08:00
//
2019-06-04 22:57:48 +08:00
// http://www.apache.org/licenses/LICENSE-2.0
2020-02-20 10:25:04 +08:00
//
2019-06-04 22:57:48 +08:00
// Unless required by applicable law or agreed to in writing, software
// 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.
//********************************************************************************
// $Id$
//
2020-02-20 10:25:04 +08:00
//
// Owner:
2019-06-04 22:57:48 +08:00
// Function: DCCM for LSU pipe
// Comments: Single ported memory
//
2020-02-20 10:25:04 +08:00
//
2019-06-04 22:57:48 +08:00
// DC1 -> DC2 -> DC3 -> DC4 (Commit)
2020-02-20 10:25:04 +08:00
//
2019-06-04 22:57:48 +08:00
// //********************************************************************************
2020-02-20 10:25:04 +08:00
module lsu_dccm_mem
2019-06-04 22:57:48 +08:00
import swerv_types::*;
(
2020-02-20 10:25:04 +08:00
input logic clk, // clock
input logic rst_l,
2019-06-04 22:57:48 +08:00
input logic lsu_freeze_dc3, // freeze
input logic clk_override, // clock override
2020-02-20 10:25:04 +08:00
2019-06-04 22:57:48 +08:00
input logic dccm_wren, // write enable
input logic dccm_rden, // read enable
input logic [`RV_DCCM_BITS-1:0] dccm_wr_addr, // write address
input logic [`RV_DCCM_BITS-1:0] dccm_rd_addr_lo, // read address
input logic [`RV_DCCM_BITS-1:0] dccm_rd_addr_hi, // read address for the upper bank in case of a misaligned access
input logic [`RV_DCCM_FDATA_WIDTH-1:0] dccm_wr_data, // write data
2020-02-20 10:25:04 +08:00
2019-06-04 22:57:48 +08:00
output logic [`RV_DCCM_FDATA_WIDTH-1:0] dccm_rd_data_lo, // read data from the lo bank
output logic [`RV_DCCM_FDATA_WIDTH-1:0] dccm_rd_data_hi, // read data from the hi bank
input logic scan_mode
);
`include "global.h"
2020-02-20 10:25:04 +08:00
2019-06-04 22:57:48 +08:00
localparam DCCM_WIDTH_BITS = $clog2(DCCM_BYTE_WIDTH);
localparam DCCM_INDEX_BITS = (DCCM_BITS - DCCM_BANK_BITS - DCCM_WIDTH_BITS);
2020-02-20 10:25:04 +08:00
2019-08-14 03:48:48 +08:00
logic [DCCM_NUM_BANKS-1:0] wren_bank;
logic [DCCM_NUM_BANKS-1:0] rden_bank;
2019-06-04 22:57:48 +08:00
logic [DCCM_NUM_BANKS-1:0] [DCCM_BITS-1:(DCCM_BANK_BITS+2)] addr_bank;
logic [DCCM_BITS-1:(DCCM_BANK_BITS+DCCM_WIDTH_BITS)] rd_addr_even, rd_addr_odd;
logic rd_unaligned;
logic [DCCM_NUM_BANKS-1:0] [DCCM_FDATA_WIDTH-1:0] dccm_bank_dout;
logic [DCCM_FDATA_WIDTH-1:0] wrdata;
2019-08-14 03:48:48 +08:00
logic [DCCM_NUM_BANKS-1:0] wren_bank_q;
logic [DCCM_NUM_BANKS-1:0] rden_bank_q;
2019-06-04 22:57:48 +08:00
logic [DCCM_NUM_BANKS-1:0][DCCM_BITS-1:(DCCM_BANK_BITS+2)] addr_bank_q;
logic [DCCM_FDATA_WIDTH-1:0] dccm_wr_data_q;
logic [(DCCM_WIDTH_BITS+DCCM_BANK_BITS-1):DCCM_WIDTH_BITS] dccm_rd_addr_lo_q;
logic [(DCCM_WIDTH_BITS+DCCM_BANK_BITS-1):DCCM_WIDTH_BITS] dccm_rd_addr_hi_q;
2020-02-20 10:25:04 +08:00
2019-06-04 22:57:48 +08:00
logic [DCCM_NUM_BANKS-1:0] dccm_clk;
logic [DCCM_NUM_BANKS-1:0] dccm_clken;
2020-02-20 10:25:04 +08:00
2019-06-04 22:57:48 +08:00
assign rd_unaligned = (dccm_rd_addr_lo[DCCM_WIDTH_BITS+:DCCM_BANK_BITS] != dccm_rd_addr_hi[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]);
2020-02-20 10:25:04 +08:00
2019-06-04 22:57:48 +08:00
// Align the read data
assign dccm_rd_data_lo[DCCM_FDATA_WIDTH-1:0] = dccm_bank_dout[dccm_rd_addr_lo_q[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]][DCCM_FDATA_WIDTH-1:0];
assign dccm_rd_data_hi[DCCM_FDATA_WIDTH-1:0] = dccm_bank_dout[dccm_rd_addr_hi_q[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]][DCCM_FDATA_WIDTH-1:0];
// Generate even/odd address
2020-02-20 10:25:04 +08:00
// assign rd_addr_even[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] = dccm_rd_addr_lo[2] ? dccm_rd_addr_hi[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] :
2019-06-04 22:57:48 +08:00
// dccm_rd_addr_lo[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS];
2020-02-20 10:25:04 +08:00
// assign rd_addr_odd[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] = dccm_rd_addr_lo[2] ? dccm_rd_addr_lo[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] :
// dccm_rd_addr_hi[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS];
2019-06-04 22:57:48 +08:00
// 8 Banks, 16KB each (2048 x 72)
for (genvar i=0; i<DCCM_NUM_BANKS; i++) begin: mem_bank
assign wren_bank[i] = dccm_wren & (dccm_wr_addr[2+:DCCM_BANK_BITS] == i);
2020-02-20 10:25:04 +08:00
assign rden_bank[i] = dccm_rden & ((dccm_rd_addr_hi[2+:DCCM_BANK_BITS] == i) | (dccm_rd_addr_lo[2+:DCCM_BANK_BITS] == i));
2019-06-04 22:57:48 +08:00
assign addr_bank[i][(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] = wren_bank[i] ? dccm_wr_addr[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] :
2020-02-20 10:25:04 +08:00
(((dccm_rd_addr_hi[2+:DCCM_BANK_BITS] == i) & rd_unaligned) ?
dccm_rd_addr_hi[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] :
2019-06-04 22:57:48 +08:00
dccm_rd_addr_lo[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS]);
// if (i%2 == 0) begin
// assign addr_bank[i][(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] = wren_bank[i] ? dccm_wr_addr[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] :
// rd_addr_even[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS];
// end else begin
// assign addr_bank[i][(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] = wren_bank[i] ? dccm_wr_addr[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] :
// rd_addr_odd[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS];
// end
2020-02-20 10:25:04 +08:00
2019-06-04 22:57:48 +08:00
// clock gating section
assign dccm_clken[i] = (wren_bank[i] | rden_bank[i] | clk_override) & ~lsu_freeze_dc3;
rvclkhdr lsu_dccm_cgc (.en(dccm_clken[i]), .l1clk(dccm_clk[i]), .*);
2020-02-20 10:25:04 +08:00
// end clock gating section
2019-06-04 22:57:48 +08:00
`RV_DCCM_DATA_CELL dccm_bank (
// Primary ports
.CLK(dccm_clk[i]),
.WE(wren_bank[i]),
.ADR(addr_bank[i]),
.D(dccm_wr_data[DCCM_FDATA_WIDTH-1:0]),
.Q(dccm_bank_dout[i][DCCM_FDATA_WIDTH-1:0])
);
2020-02-20 10:25:04 +08:00
2019-06-04 22:57:48 +08:00
end : mem_bank
2020-02-20 10:25:04 +08:00
2019-06-04 22:57:48 +08:00
// Flops
rvdffs #(DCCM_BANK_BITS) rd_addr_lo_ff (.*, .din(dccm_rd_addr_lo[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]), .dout(dccm_rd_addr_lo_q[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]), .en(~lsu_freeze_dc3));
rvdffs #(DCCM_BANK_BITS) rd_addr_hi_ff (.*, .din(dccm_rd_addr_hi[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]), .dout(dccm_rd_addr_hi_q[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]), .en(~lsu_freeze_dc3));
endmodule // lsu_dccm_mem