Line data Source code
1 : // SPDX-License-Identifier: Apache-2.0
2 : // Copyright 2020 Western Digital Corporation or its affiliates.
3 : // Copyright (c) 2023 Antmicro <www.antmicro.com>
4 : //
5 : // Licensed under the Apache License, Version 2.0 (the "License");
6 : // you may not use this file except in compliance with the License.
7 : // You may obtain a copy of the License at
8 : //
9 : // http://www.apache.org/licenses/LICENSE-2.0
10 : //
11 : // Unless required by applicable law or agreed to in writing, software
12 : // distributed under the License is distributed on an "AS IS" BASIS,
13 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : // See the License for the specific language governing permissions and
15 : // limitations under the License.
16 :
17 : //********************************************************************************
18 : // $Id$
19 : //
20 : //
21 : // Owner:
22 : // Function: DCCM for LSU pipe
23 : // Comments: Single ported memory
24 : //
25 : //
26 : // DC1 -> DC2 -> DC3 -> DC4 (Commit)
27 : //
28 : // //********************************************************************************
29 :
30 : module el2_lsu_dccm_mem
31 : import el2_pkg::*;
32 : #(
33 : `include "el2_param.vh"
34 : )(
35 61847773 : input logic clk, // Clock only while core active. Through one clock header. For flops with second clock header built in. Connected to ACTIVE_L2CLK.
36 61847773 : input logic active_clk, // Clock only while core active. Through two clock headers. For flops without second clock header built in.
37 317 : input logic rst_l, // reset, active low
38 0 : input logic clk_override, // Override non-functional clock gating
39 :
40 263892 : input logic dccm_wren, // write enable
41 562000 : input logic dccm_rden, // read enable
42 18924 : input logic [pt.DCCM_BITS-1:0] dccm_wr_addr_lo, // write address
43 18924 : input logic [pt.DCCM_BITS-1:0] dccm_wr_addr_hi, // write address
44 471893 : input logic [pt.DCCM_BITS-1:0] dccm_rd_addr_lo, // read address
45 678300 : input logic [pt.DCCM_BITS-1:0] dccm_rd_addr_hi, // read address for the upper bank in case of a misaligned access
46 5613 : input logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_wr_data_lo, // write data
47 5613 : input logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_wr_data_hi, // write data
48 : el2_mem_if.veer_dccm dccm_mem_export, // RAM repositioned in testbench and connected by this interface
49 :
50 47429 : output logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_rd_data_lo, // read data from the lo bank
51 47429 : output logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_rd_data_hi, // read data from the hi bank
52 :
53 0 : input logic scan_mode
54 : );
55 :
56 :
57 : localparam logic [5:0] DCCM_WIDTH_BITS = $clog2(pt.DCCM_BYTE_WIDTH);
58 : localparam logic [7:0] DCCM_INDEX_BITS = 8'(pt.DCCM_BITS - pt.DCCM_BANK_BITS - pt.DCCM_WIDTH_BITS);
59 : localparam logic [31:0] DCCM_INDEX_DEPTH = ((pt.DCCM_SIZE)*1024)/((pt.DCCM_BYTE_WIDTH)*(pt.DCCM_NUM_BANKS)); // Depth of memory bank
60 :
61 59820 : logic [pt.DCCM_NUM_BANKS-1:0] wren_bank;
62 143252 : logic [pt.DCCM_NUM_BANKS-1:0] rden_bank;
63 689342 : logic [pt.DCCM_NUM_BANKS-1:0] [pt.DCCM_BITS-1:(pt.DCCM_BANK_BITS+2)] addr_bank;
64 0 : logic [pt.DCCM_BITS-1:(pt.DCCM_BANK_BITS+DCCM_WIDTH_BITS)] rd_addr_even, rd_addr_odd;
65 0 : logic rd_unaligned, wr_unaligned;
66 1846 : logic [pt.DCCM_NUM_BANKS-1:0] [pt.DCCM_FDATA_WIDTH-1:0] dccm_bank_dout;
67 0 : logic [pt.DCCM_FDATA_WIDTH-1:0] wrdata;
68 :
69 5613 : logic [pt.DCCM_NUM_BANKS-1:0][pt.DCCM_FDATA_WIDTH-1:0] wr_data_bank;
70 :
71 1201391 : logic [(DCCM_WIDTH_BITS+pt.DCCM_BANK_BITS-1):DCCM_WIDTH_BITS] dccm_rd_addr_lo_q;
72 1201485 : logic [(DCCM_WIDTH_BITS+pt.DCCM_BANK_BITS-1):DCCM_WIDTH_BITS] dccm_rd_addr_hi_q;
73 :
74 190014 : logic [pt.DCCM_NUM_BANKS-1:0] dccm_clken;
75 :
76 : assign rd_unaligned = (dccm_rd_addr_lo[DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS] != dccm_rd_addr_hi[DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS]);
77 : assign wr_unaligned = (dccm_wr_addr_lo[DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS] != dccm_wr_addr_hi[DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS]);
78 :
79 : // Align the read data
80 : assign dccm_rd_data_lo[pt.DCCM_FDATA_WIDTH-1:0] = dccm_bank_dout[dccm_rd_addr_lo_q[pt.DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS]][pt.DCCM_FDATA_WIDTH-1:0];
81 : assign dccm_rd_data_hi[pt.DCCM_FDATA_WIDTH-1:0] = dccm_bank_dout[dccm_rd_addr_hi_q[DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS]][pt.DCCM_FDATA_WIDTH-1:0];
82 :
83 :
84 : // 8 Banks, 16KB each (2048 x 72)
85 1272 : for (genvar i=0; i<pt.DCCM_NUM_BANKS; i++) begin: mem_bank
86 : assign wren_bank[i] = dccm_wren & ((dccm_wr_addr_hi[2+:pt.DCCM_BANK_BITS] == i) | (dccm_wr_addr_lo[2+:pt.DCCM_BANK_BITS] == i));
87 : assign rden_bank[i] = dccm_rden & ((dccm_rd_addr_hi[2+:pt.DCCM_BANK_BITS] == i) | (dccm_rd_addr_lo[2+:pt.DCCM_BANK_BITS] == i));
88 : assign addr_bank[i][(pt.DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] = wren_bank[i] ? (((dccm_wr_addr_hi[2+:pt.DCCM_BANK_BITS] == i) & wr_unaligned) ?
89 : dccm_wr_addr_hi[(pt.DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] :
90 : dccm_wr_addr_lo[(pt.DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS]) :
91 : (((dccm_rd_addr_hi[2+:pt.DCCM_BANK_BITS] == i) & rd_unaligned) ?
92 : dccm_rd_addr_hi[(pt.DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] :
93 : dccm_rd_addr_lo[(pt.DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS]);
94 :
95 : assign wr_data_bank[i] = ((dccm_wr_addr_hi[2+:pt.DCCM_BANK_BITS] == i) & wr_unaligned) ? dccm_wr_data_hi[pt.DCCM_FDATA_WIDTH-1:0] : dccm_wr_data_lo[pt.DCCM_FDATA_WIDTH-1:0];
96 :
97 : // clock gating section
98 : assign dccm_clken[i] = (wren_bank[i] | rden_bank[i] | clk_override) ;
99 : // end clock gating section
100 :
101 : // Connect to exported RAM Banks
102 1272 : always_comb begin
103 1272 : dccm_mem_export.dccm_clken[i] = dccm_clken[i];
104 1272 : dccm_mem_export.dccm_wren_bank[i] = wren_bank[i];
105 1272 : dccm_mem_export.dccm_addr_bank[i] = addr_bank[i];
106 1272 : dccm_mem_export.dccm_wr_data_bank[i] = wr_data_bank[i][pt.DCCM_DATA_WIDTH-1:0];
107 1272 : dccm_mem_export.dccm_wr_ecc_bank[i] = wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:pt.DCCM_DATA_WIDTH];
108 1272 : dccm_bank_dout[i][pt.DCCM_DATA_WIDTH-1:0] = dccm_mem_export.dccm_bank_dout[i];
109 1272 : dccm_bank_dout[i][pt.DCCM_FDATA_WIDTH-1:pt.DCCM_DATA_WIDTH] = dccm_mem_export.dccm_bank_ecc[i];
110 : end
111 :
112 : end : mem_bank
113 :
114 : // Flops
115 : rvdff #(pt.DCCM_BANK_BITS) rd_addr_lo_ff (.*, .din(dccm_rd_addr_lo[DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS]), .dout(dccm_rd_addr_lo_q[DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS]), .clk(active_clk));
116 : rvdff #(pt.DCCM_BANK_BITS) rd_addr_hi_ff (.*, .din(dccm_rd_addr_hi[DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS]), .dout(dccm_rd_addr_hi_q[DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS]), .clk(active_clk));
117 :
118 : endmodule // el2_lsu_dccm_mem
119 :
120 :
|