blob: f7f224b9c818c6789e2ee60716397e8aaf98be05 [file] [log] [blame]
// Copyright 2020 ETH Zurich and University of Bologna.
// Copyright 2017 Embecosm Limited <www.embecosm.com>
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
module dp_ram #(
parameter int unsigned ADDR_WIDTH = 8,
parameter int unsigned INSTR_RDATA_WIDTH = 128
) (
input logic clk_i,
input logic en_a_i,
input logic [ADDR_WIDTH-1:0] addr_a_i,
input logic [31:0] wdata_a_i,
output logic [INSTR_RDATA_WIDTH-1:0] rdata_a_o,
input logic we_a_i,
input logic [3:0] be_a_i,
input logic en_b_i,
input logic [ADDR_WIDTH-1:0] addr_b_i,
input logic [31:0] wdata_b_i,
output logic [31:0] rdata_b_o,
input logic we_b_i,
input logic [3:0] be_b_i
);
localparam bytes = 2**ADDR_WIDTH;
logic [7:0] mem[bytes];
logic [ADDR_WIDTH-1:0] addr_a_int;
logic [ADDR_WIDTH-1:0] addr_b_int;
always_comb addr_a_int = {addr_a_i[ADDR_WIDTH-1:2], 2'b0};
always_comb addr_b_int = {addr_b_i[ADDR_WIDTH-1:2], 2'b0};
always @(posedge clk_i) begin
for (int i = 0; i < INSTR_RDATA_WIDTH/8; i++) begin
rdata_a_o[(i*8)+: 8] <= mem[addr_a_int + i];
end
/* addr_b_i is the actual memory address referenced */
if (en_b_i) begin
/* handle writes */
if (we_b_i) begin
if (be_b_i[0]) mem[addr_b_int ] <= wdata_b_i[ 0+:8];
if (be_b_i[1]) mem[addr_b_int + 1] <= wdata_b_i[ 8+:8];
if (be_b_i[2]) mem[addr_b_int + 2] <= wdata_b_i[16+:8];
if (be_b_i[3]) mem[addr_b_int + 3] <= wdata_b_i[24+:8];
end
/* handle reads */
else begin
if ($test$plusargs("verbose"))
$display("read addr=0x%08x: data=0x%08x", addr_b_int,
{mem[addr_b_int + 3], mem[addr_b_int + 2],
mem[addr_b_int + 1], mem[addr_b_int + 0]});
rdata_b_o[ 7: 0] <= mem[addr_b_int ];
rdata_b_o[15: 8] <= mem[addr_b_int + 1];
rdata_b_o[23:16] <= mem[addr_b_int + 2];
rdata_b_o[31:24] <= mem[addr_b_int + 3];
end
end
end
export "DPI-C" function read_byte;
export "DPI-C" task write_byte;
function int read_byte(input logic [ADDR_WIDTH-1:0] byte_addr);
read_byte = mem[byte_addr];
endfunction
task write_byte(input integer byte_addr, logic [7:0] val, output logic [7:0] other);
mem[byte_addr] = val;
other = mem[byte_addr];
endtask
endmodule // dp_ram