434 lines
16 KiB
Systemverilog
434 lines
16 KiB
Systemverilog
// Copyright © 2019-2023
|
|
//
|
|
// 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
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// 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.
|
|
|
|
`include "VX_platform.vh"
|
|
|
|
`TRACING_OFF
|
|
module VX_dp_ram #(
|
|
parameter DATAW = 1,
|
|
parameter SIZE = 1,
|
|
parameter WRENW = 1,
|
|
parameter OUT_REG = 0,
|
|
parameter NO_RWCHECK = 0,
|
|
parameter LUTRAM = 0,
|
|
parameter INIT_ENABLE = 0,
|
|
parameter INIT_FILE = "",
|
|
parameter [DATAW-1:0] INIT_VALUE = 0,
|
|
parameter ADDRW = `LOG2UP(SIZE)
|
|
) (
|
|
input wire clk,
|
|
input wire read,
|
|
input wire write,
|
|
input wire [WRENW-1:0] wren,
|
|
input wire [ADDRW-1:0] waddr,
|
|
input wire [DATAW-1:0] wdata,
|
|
input wire [ADDRW-1:0] raddr,
|
|
output wire [DATAW-1:0] rdata
|
|
);
|
|
localparam WSELW = DATAW / WRENW;
|
|
`STATIC_ASSERT((WRENW * WSELW == DATAW), ("invalid parameter"))
|
|
|
|
`define RAM_INITIALIZATION \
|
|
if (INIT_ENABLE != 0) begin \
|
|
if (INIT_FILE != "") begin \
|
|
initial $readmemh(INIT_FILE, ram); \
|
|
end else begin \
|
|
initial \
|
|
for (integer i = 0; i < SIZE; ++i) \
|
|
ram[i] = INIT_VALUE; \
|
|
end \
|
|
end
|
|
|
|
`UNUSED_VAR (read)
|
|
|
|
`ifdef SYNTHESIS
|
|
if (WRENW > 1) begin
|
|
`ifdef QUARTUS
|
|
if (LUTRAM != 0) begin
|
|
if (OUT_REG != 0) begin
|
|
reg [DATAW-1:0] rdata_r;
|
|
`USE_FAST_BRAM reg [WRENW-1:0][WSELW-1:0] ram [SIZE-1:0];
|
|
`RAM_INITIALIZATION
|
|
always @(posedge clk) begin
|
|
if (write) begin
|
|
for (integer i = 0; i < WRENW; ++i) begin
|
|
if (wren[i])
|
|
ram[waddr][i] <= wdata[i * WSELW +: WSELW];
|
|
end
|
|
end
|
|
if (read) begin
|
|
rdata_r <= ram[raddr];
|
|
end
|
|
end
|
|
assign rdata = rdata_r;
|
|
end else begin
|
|
`USE_FAST_BRAM reg [WRENW-1:0][WSELW-1:0] ram [SIZE-1:0];
|
|
`RAM_INITIALIZATION
|
|
always @(posedge clk) begin
|
|
if (write) begin
|
|
for (integer i = 0; i < WRENW; ++i) begin
|
|
if (wren[i])
|
|
ram[waddr][i] <= wdata[i * WSELW +: WSELW];
|
|
end
|
|
end
|
|
end
|
|
assign rdata = ram[raddr];
|
|
end
|
|
end else begin
|
|
if (OUT_REG != 0) begin
|
|
reg [DATAW-1:0] rdata_r;
|
|
reg [WRENW-1:0][WSELW-1:0] ram [SIZE-1:0];
|
|
`RAM_INITIALIZATION
|
|
always @(posedge clk) begin
|
|
if (write) begin
|
|
for (integer i = 0; i < WRENW; ++i) begin
|
|
if (wren[i])
|
|
ram[waddr][i] <= wdata[i * WSELW +: WSELW];
|
|
end
|
|
end
|
|
if (read) begin
|
|
rdata_r <= ram[raddr];
|
|
end
|
|
end
|
|
assign rdata = rdata_r;
|
|
end else begin
|
|
if (NO_RWCHECK != 0) begin
|
|
`NO_RW_RAM_CHECK reg [WRENW-1:0][WSELW-1:0] ram [SIZE-1:0];
|
|
`RAM_INITIALIZATION
|
|
always @(posedge clk) begin
|
|
if (write) begin
|
|
for (integer i = 0; i < WRENW; ++i) begin
|
|
if (wren[i])
|
|
ram[waddr][i] <= wdata[i * WSELW +: WSELW];
|
|
end
|
|
end
|
|
end
|
|
assign rdata = ram[raddr];
|
|
end else begin
|
|
reg [WRENW-1:0][WSELW-1:0] ram [SIZE-1:0];
|
|
`RAM_INITIALIZATION
|
|
always @(posedge clk) begin
|
|
if (write) begin
|
|
for (integer i = 0; i < WRENW; ++i) begin
|
|
if (wren[i])
|
|
ram[waddr][i] <= wdata[i * WSELW +: WSELW];
|
|
end
|
|
end
|
|
end
|
|
assign rdata = ram[raddr];
|
|
end
|
|
end
|
|
end
|
|
`else
|
|
// default synthesis
|
|
if (LUTRAM != 0) begin
|
|
`USE_FAST_BRAM reg [DATAW-1:0] ram [SIZE-1:0];
|
|
`RAM_INITIALIZATION
|
|
if (OUT_REG != 0) begin
|
|
reg [DATAW-1:0] rdata_r;
|
|
always @(posedge clk) begin
|
|
if (write) begin
|
|
for (integer i = 0; i < WRENW; ++i) begin
|
|
if (wren[i])
|
|
ram[waddr][i * WSELW +: WSELW] <= wdata[i * WSELW +: WSELW];
|
|
end
|
|
end
|
|
if (read) begin
|
|
rdata_r <= ram[raddr];
|
|
end
|
|
end
|
|
assign rdata = rdata_r;
|
|
end else begin
|
|
always @(posedge clk) begin
|
|
if (write) begin
|
|
for (integer i = 0; i < WRENW; ++i) begin
|
|
if (wren[i])
|
|
ram[waddr][i * WSELW +: WSELW] <= wdata[i * WSELW +: WSELW];
|
|
end
|
|
end
|
|
end
|
|
assign rdata = ram[raddr];
|
|
end
|
|
end else begin
|
|
`ifndef FIRESIM
|
|
if (DATAW == 1024 && SIZE == 16) begin // dcache data
|
|
(* dont_touch = "yes" *) dcache_data ram (
|
|
.R0_addr(raddr),
|
|
.R0_clk(clk),
|
|
.R0_data(/*rdata*/),
|
|
.R0_en(read),
|
|
.W0_addr(waddr),
|
|
.W0_clk(clk),
|
|
.W0_data(wdata),
|
|
.W0_en(write),
|
|
.W0_mask(wren)
|
|
);
|
|
end else if (DATAW == 305 && SIZE == 8) begin // mshr
|
|
(* dont_touch = "yes" *) cache_mshr ram (
|
|
.R0_addr(raddr),
|
|
.R0_clk(clk),
|
|
.R0_data(/*rdata*/),
|
|
.R0_en(read),
|
|
.W0_addr(waddr),
|
|
.W0_clk(clk),
|
|
.W0_data(wdata),
|
|
.W0_en(write)
|
|
);
|
|
end else if (DATAW == 24 && SIZE == 16) begin // dcache tags
|
|
(* dont_touch = "yes" *) dcache_tags ram (
|
|
.R0_addr(raddr),
|
|
.R0_clk(clk),
|
|
.R0_data(/*rdata*/),
|
|
.R0_en(read),
|
|
.W0_addr(waddr),
|
|
.W0_clk(clk),
|
|
.W0_data(wdata),
|
|
.W0_en(write)
|
|
);
|
|
end else if (DATAW == 1024 && SIZE == 128) begin // icache data
|
|
(* dont_touch = "yes" *) icache_data ram (
|
|
.R0_addr(raddr),
|
|
.R0_clk(clk),
|
|
.R0_data(/*rdata*/),
|
|
.R0_en(read),
|
|
.W0_addr(waddr),
|
|
.W0_clk(clk),
|
|
.W0_data(wdata),
|
|
.W0_en(write),
|
|
.W0_mask(wren)
|
|
);
|
|
end else if (DATAW == 21 && SIZE == 128) begin // icache tags
|
|
(* dont_touch = "yes" *) icache_tags ram (
|
|
.R0_addr(raddr),
|
|
.R0_clk(clk),
|
|
.R0_data(/*rdata*/),
|
|
.R0_en(read),
|
|
.W0_addr(waddr),
|
|
.W0_clk(clk),
|
|
.W0_data(wdata),
|
|
.W0_en(write)
|
|
);
|
|
end else if (DATAW == 32 && SIZE == 64) begin // register file
|
|
(* dont_touch = "yes" *) rf_bank ram (
|
|
.R0_addr(raddr),
|
|
.R0_clk(clk),
|
|
.R0_data(/*rdata*/),
|
|
.R0_en(read),
|
|
.W0_addr(waddr),
|
|
.W0_clk(clk),
|
|
.W0_data(wdata),
|
|
.W0_en(write)
|
|
);
|
|
end // else begin
|
|
`endif
|
|
if (OUT_REG != 0) begin
|
|
reg [DATAW-1:0] ram [SIZE-1:0];
|
|
reg [DATAW-1:0] rdata_r;
|
|
`RAM_INITIALIZATION
|
|
always @(posedge clk) begin
|
|
if (write) begin
|
|
for (integer i = 0; i < WRENW; ++i) begin
|
|
if (wren[i])
|
|
ram[waddr][i * WSELW +: WSELW] <= wdata[i * WSELW +: WSELW];
|
|
end
|
|
end
|
|
if (read) begin
|
|
rdata_r <= ram[raddr];
|
|
end
|
|
end
|
|
assign rdata = rdata_r;
|
|
end else begin
|
|
if (NO_RWCHECK != 0) begin
|
|
`NO_RW_RAM_CHECK reg [DATAW-1:0] ram [SIZE-1:0];
|
|
`RAM_INITIALIZATION
|
|
always @(posedge clk) begin
|
|
if (write) begin
|
|
for (integer i = 0; i < WRENW; ++i) begin
|
|
if (wren[i])
|
|
ram[waddr][i * WSELW +: WSELW] <= wdata[i * WSELW +: WSELW];
|
|
end
|
|
end
|
|
end
|
|
assign rdata = ram[raddr];
|
|
end else begin
|
|
reg [DATAW-1:0] ram [SIZE-1:0];
|
|
`RAM_INITIALIZATION
|
|
always @(posedge clk) begin
|
|
if (write) begin
|
|
for (integer i = 0; i < WRENW; ++i) begin
|
|
if (wren[i])
|
|
ram[waddr][i * WSELW +: WSELW] <= wdata[i * WSELW +: WSELW];
|
|
end
|
|
end
|
|
end
|
|
assign rdata = ram[raddr];
|
|
end
|
|
end
|
|
`ifndef FIRESIM
|
|
// end
|
|
`endif
|
|
end
|
|
`endif
|
|
end else begin
|
|
// (WRENW == 1)
|
|
if (LUTRAM != 0) begin
|
|
`USE_FAST_BRAM reg [DATAW-1:0] ram [SIZE-1:0];
|
|
`RAM_INITIALIZATION
|
|
if (OUT_REG != 0) begin
|
|
reg [DATAW-1:0] rdata_r;
|
|
always @(posedge clk) begin
|
|
if (write) begin
|
|
ram[waddr] <= wdata;
|
|
end
|
|
if (read) begin
|
|
rdata_r <= ram[raddr];
|
|
end
|
|
end
|
|
assign rdata = rdata_r;
|
|
end else begin
|
|
always @(posedge clk) begin
|
|
if (write) begin
|
|
ram[waddr] <= wdata;
|
|
end
|
|
end
|
|
assign rdata = ram[raddr];
|
|
end
|
|
end else begin
|
|
if (DATAW == 305 && SIZE == 8) begin // mshr
|
|
(* dont_touch = "yes" *) cache_mshr ram (
|
|
.R0_addr(raddr),
|
|
.R0_clk(clk),
|
|
.R0_data(/*rdata*/),
|
|
.R0_en(read),
|
|
.W0_addr(waddr),
|
|
.W0_clk(clk),
|
|
.W0_data(wdata),
|
|
.W0_en(write)
|
|
);
|
|
end else if (DATAW == 24 && SIZE == 16) begin // dcache tags
|
|
(* dont_touch = "yes" *) dcache_tags ram (
|
|
.R0_addr(raddr),
|
|
.R0_clk(clk),
|
|
.R0_data(/*rdata*/),
|
|
.R0_en(read),
|
|
.W0_addr(waddr),
|
|
.W0_clk(clk),
|
|
.W0_data(wdata),
|
|
.W0_en(write)
|
|
);
|
|
end else if (DATAW == 21 && SIZE == 128) begin // icache tags
|
|
(* dont_touch = "yes" *) icache_tags ram (
|
|
.R0_addr(raddr),
|
|
.R0_clk(clk),
|
|
.R0_data(/*rdata*/),
|
|
.R0_en(read),
|
|
.W0_addr(waddr),
|
|
.W0_clk(clk),
|
|
.W0_data(wdata),
|
|
.W0_en(write)
|
|
);
|
|
end else if (DATAW == 32 && SIZE == 64) begin // register file
|
|
(* dont_touch = "yes" *) rf_bank ram (
|
|
.R0_addr(raddr),
|
|
.R0_clk(clk),
|
|
.R0_data(/*rdata*/),
|
|
.R0_en(read),
|
|
.W0_addr(waddr),
|
|
.W0_clk(clk),
|
|
.W0_data(wdata),
|
|
.W0_en(write)
|
|
);
|
|
end // else begin
|
|
if (OUT_REG != 0) begin
|
|
reg [DATAW-1:0] ram [SIZE-1:0];
|
|
reg [DATAW-1:0] rdata_r;
|
|
`RAM_INITIALIZATION
|
|
always @(posedge clk) begin
|
|
if (write) begin
|
|
ram[waddr] <= wdata;
|
|
end
|
|
if (read) begin
|
|
rdata_r <= ram[raddr];
|
|
end
|
|
end
|
|
assign rdata = rdata_r;
|
|
end else begin
|
|
if (NO_RWCHECK != 0) begin
|
|
`NO_RW_RAM_CHECK reg [DATAW-1:0] ram [SIZE-1:0];
|
|
`RAM_INITIALIZATION
|
|
always @(posedge clk) begin
|
|
if (write) begin
|
|
ram[waddr] <= wdata;
|
|
end
|
|
end
|
|
assign rdata = ram[raddr];
|
|
end else begin
|
|
reg [DATAW-1:0] ram [SIZE-1:0];
|
|
`RAM_INITIALIZATION
|
|
always @(posedge clk) begin
|
|
if (write) begin
|
|
ram[waddr] <= wdata;
|
|
end
|
|
end
|
|
assign rdata = ram[raddr];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
`else
|
|
// RAM emulation
|
|
reg [DATAW-1:0] ram [SIZE-1:0];
|
|
`RAM_INITIALIZATION
|
|
|
|
wire [DATAW-1:0] ram_n;
|
|
for (genvar i = 0; i < WRENW; ++i) begin
|
|
assign ram_n[i * WSELW +: WSELW] = ((WRENW == 1) | wren[i]) ? wdata[i * WSELW +: WSELW] : ram[waddr][i * WSELW +: WSELW];
|
|
end
|
|
|
|
if (OUT_REG != 0) begin
|
|
reg [DATAW-1:0] rdata_r;
|
|
always @(posedge clk) begin
|
|
if (write) begin
|
|
ram[waddr] <= ram_n;
|
|
end
|
|
if (read) begin
|
|
rdata_r <= ram[raddr];
|
|
end
|
|
end
|
|
assign rdata = rdata_r;
|
|
end else begin
|
|
reg [DATAW-1:0] prev_data;
|
|
reg [ADDRW-1:0] prev_waddr;
|
|
reg prev_write;
|
|
always @(posedge clk) begin
|
|
if (write) begin
|
|
ram[waddr] <= ram_n;
|
|
end
|
|
prev_write <= (| wren);
|
|
prev_data <= ram[waddr];
|
|
prev_waddr <= waddr;
|
|
end
|
|
if (LUTRAM || !NO_RWCHECK) begin
|
|
`UNUSED_VAR (prev_write)
|
|
`UNUSED_VAR (prev_data)
|
|
`UNUSED_VAR (prev_waddr)
|
|
assign rdata = ram[raddr];
|
|
end else begin
|
|
assign rdata = (prev_write && (prev_waddr === raddr)) ? prev_data : ram[raddr];
|
|
end
|
|
end
|
|
`endif
|
|
|
|
endmodule
|
|
`TRACING_ON
|