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 69844592 : 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 69844592 : input logic active_clk, // Clock only while core active. Through two clock headers. For flops without second clock header built in.
37 339 : input logic rst_l, // reset, active low
38 2 : input logic clk_override, // Override non-functional clock gating
39 :
40 263894 : 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 471069 : input logic [pt.DCCM_BITS-1:0] dccm_rd_addr_lo, // read address
45 677464 : input logic [pt.DCCM_BITS-1:0] dccm_rd_addr_hi, // read address for the upper bank in case of a misaligned access
46 5615 : input logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_wr_data_lo, // write data
47 5615 : 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 47433 : output logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_rd_data_lo, // read data from the lo bank
51 47433 : output logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_rd_data_hi, // read data from the hi bank
52 :
53 : // Excluding scan_mode from coverage as its usage is determined by the integrator of the VeeR core.
54 : /*verilator coverage_off*/
55 : input logic scan_mode
56 : /*verilator coverage_on*/
57 : );
58 :
59 :
60 : localparam logic [5:0] DCCM_WIDTH_BITS = $clog2(pt.DCCM_BYTE_WIDTH);
61 : localparam logic [7:0] DCCM_INDEX_BITS = 8'(pt.DCCM_BITS - pt.DCCM_BANK_BITS - pt.DCCM_WIDTH_BITS);
62 : localparam logic [31:0] DCCM_INDEX_DEPTH = ((pt.DCCM_SIZE)*1024)/((pt.DCCM_BYTE_WIDTH)*(pt.DCCM_NUM_BANKS)); // Depth of memory bank
63 :
64 59820 : logic [pt.DCCM_NUM_BANKS-1:0] wren_bank;
65 143252 : logic [pt.DCCM_NUM_BANKS-1:0] rden_bank;
66 688518 : logic [pt.DCCM_NUM_BANKS-1:0] [pt.DCCM_BITS-1:(pt.DCCM_BANK_BITS+2)] addr_bank;
67 0 : logic [pt.DCCM_BITS-1:(pt.DCCM_BANK_BITS+DCCM_WIDTH_BITS)] rd_addr_even, rd_addr_odd;
68 0 : logic rd_unaligned, wr_unaligned;
69 1846 : logic [pt.DCCM_NUM_BANKS-1:0] [pt.DCCM_FDATA_WIDTH-1:0] dccm_bank_dout;
70 0 : logic [pt.DCCM_FDATA_WIDTH-1:0] wrdata;
71 :
72 5615 : logic [pt.DCCM_NUM_BANKS-1:0][pt.DCCM_FDATA_WIDTH-1:0] wr_data_bank;
73 :
74 1200531 : logic [(DCCM_WIDTH_BITS+pt.DCCM_BANK_BITS-1):DCCM_WIDTH_BITS] dccm_rd_addr_lo_q;
75 1200611 : logic [(DCCM_WIDTH_BITS+pt.DCCM_BANK_BITS-1):DCCM_WIDTH_BITS] dccm_rd_addr_hi_q;
76 :
77 190016 : logic [pt.DCCM_NUM_BANKS-1:0] dccm_clken;
78 :
79 : 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]);
80 : 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]);
81 :
82 : // Align the read data
83 : 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];
84 : 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];
85 :
86 :
87 : // 8 Banks, 16KB each (2048 x 72)
88 1360 : for (genvar i=0; i<pt.DCCM_NUM_BANKS; i++) begin: mem_bank
89 : 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));
90 : 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));
91 : 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) ?
92 : dccm_wr_addr_hi[(pt.DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] :
93 : dccm_wr_addr_lo[(pt.DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS]) :
94 : (((dccm_rd_addr_hi[2+:pt.DCCM_BANK_BITS] == i) & rd_unaligned) ?
95 : dccm_rd_addr_hi[(pt.DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] :
96 : dccm_rd_addr_lo[(pt.DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS]);
97 :
98 : 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];
99 :
100 : // clock gating section
101 : assign dccm_clken[i] = (wren_bank[i] | rden_bank[i] | clk_override) ;
102 : // end clock gating section
103 :
104 : // Connect to exported RAM Banks
105 1360 : always_comb begin
106 1360 : dccm_mem_export.dccm_clken[i] = dccm_clken[i];
107 1360 : dccm_mem_export.dccm_wren_bank[i] = wren_bank[i];
108 1360 : dccm_mem_export.dccm_addr_bank[i] = addr_bank[i];
109 1360 : dccm_mem_export.dccm_wr_data_bank[i] = wr_data_bank[i][pt.DCCM_DATA_WIDTH-1:0];
110 1360 : dccm_mem_export.dccm_wr_ecc_bank[i] = wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:pt.DCCM_DATA_WIDTH];
111 1360 : dccm_bank_dout[i][pt.DCCM_DATA_WIDTH-1:0] = dccm_mem_export.dccm_bank_dout[i];
112 1360 : dccm_bank_dout[i][pt.DCCM_FDATA_WIDTH-1:pt.DCCM_DATA_WIDTH] = dccm_mem_export.dccm_bank_ecc[i];
113 : end
114 :
115 : end : mem_bank
116 :
117 : // Flops
118 : 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));
119 : 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));
120 :
121 : endmodule // el2_lsu_dccm_mem
122 :
123 :
|