block ram redesign to support synthesizable write-first mode
Some checks are pending
CI / setup (push) Waiting to run
CI / build (32) (push) Blocked by required conditions
CI / build (64) (push) Blocked by required conditions
CI / tests (cache, 32) (push) Blocked by required conditions
CI / tests (cache, 64) (push) Blocked by required conditions
CI / tests (config1, 32) (push) Blocked by required conditions
CI / tests (config1, 64) (push) Blocked by required conditions
CI / tests (config2, 32) (push) Blocked by required conditions
CI / tests (config2, 64) (push) Blocked by required conditions
CI / tests (debug, 32) (push) Blocked by required conditions
CI / tests (debug, 64) (push) Blocked by required conditions
CI / tests (opencl, 32) (push) Blocked by required conditions
CI / tests (opencl, 64) (push) Blocked by required conditions
CI / tests (regression, 32) (push) Blocked by required conditions
CI / tests (regression, 64) (push) Blocked by required conditions
CI / tests (scope, 32) (push) Blocked by required conditions
CI / tests (scope, 64) (push) Blocked by required conditions
CI / tests (stress, 32) (push) Blocked by required conditions
CI / tests (stress, 64) (push) Blocked by required conditions
CI / tests (synthesis, 32) (push) Blocked by required conditions
CI / tests (synthesis, 64) (push) Blocked by required conditions
CI / complete (push) Blocked by required conditions

This commit is contained in:
Blaise Tine 2024-10-18 23:54:20 -07:00
parent 6b1091e08f
commit 8f29ad58ae
15 changed files with 273 additions and 320 deletions

View file

@ -173,6 +173,7 @@ endgenerate
`ifdef QUARTUS
`define MAX_FANOUT 8
`define MAX_LUTRAM 1024
`define IF_DATA_SIZE(x) $bits(x.data)
`define USE_BLOCK_BRAM (* ramstyle = "block" *)
`define USE_FAST_BRAM (* ramstyle = "MLAB, no_rw_check" *)
@ -182,6 +183,7 @@ endgenerate
`define STRING string
`elsif VIVADO
`define MAX_FANOUT 8
`define MAX_LUTRAM 1024
`define IF_DATA_SIZE(x) $bits(x.data)
`define USE_BLOCK_BRAM (* ram_style = "block" *)
`define USE_FAST_BRAM (* ram_style = "distributed" *)
@ -191,6 +193,7 @@ endgenerate
`define STRING
`else
`define MAX_FANOUT 8
`define MAX_LUTRAM 1024
`define IF_DATA_SIZE(x) x.DATA_WIDTH
`define USE_BLOCK_BRAM
`define USE_FAST_BRAM

View file

@ -20,22 +20,22 @@ module VX_cache import VX_gpu_pkg::*; #(
parameter NUM_REQS = 4,
// Size of cache in bytes
parameter CACHE_SIZE = 4096,
parameter CACHE_SIZE = 32768,
// Size of line inside a bank in bytes
parameter LINE_SIZE = 64,
// Number of banks
parameter NUM_BANKS = 1,
parameter NUM_BANKS = 4,
// Number of associative ways
parameter NUM_WAYS = 1,
parameter NUM_WAYS = 4,
// Size of a word in bytes
parameter WORD_SIZE = `XLEN/8,
parameter WORD_SIZE = 16,
// Core Response Queue Size
parameter CRSQ_SIZE = 2,
parameter CRSQ_SIZE = 4,
// Miss Reserv Queue Knob
parameter MSHR_SIZE = 8,
parameter MSHR_SIZE = 16,
// Memory Response Queue Size
parameter MRSQ_SIZE = 0,
parameter MRSQ_SIZE = 4,
// Memory Request Queue Size
parameter MREQ_SIZE = 4,
@ -49,7 +49,7 @@ module VX_cache import VX_gpu_pkg::*; #(
parameter DIRTY_BYTES = 0,
// Replacement policy
parameter REPL_POLICY = `CS_REPL_CYCLIC,
parameter REPL_POLICY = `CS_REPL_CYCLIC,
// Request debug identifier
parameter UUID_WIDTH = 0,
@ -61,10 +61,10 @@ module VX_cache import VX_gpu_pkg::*; #(
parameter FLAGS_WIDTH = 0,
// Core response output register
parameter CORE_OUT_BUF = 0,
parameter CORE_OUT_BUF = 3,
// Memory request output register
parameter MEM_OUT_BUF = 0
parameter MEM_OUT_BUF = 3
) (
// PERF
`ifdef PERF_ENABLE

View file

@ -295,6 +295,8 @@ module VX_cache_bank #(
assign req_uuid_sel = '0;
end
wire [`CS_LINE_SEL_BITS-1:0] line_idx_sel = addr_sel[`CS_LINE_SEL_BITS-1:0];
wire is_init_sel = init_valid;
wire is_creq_sel = creq_enable || replay_enable;
wire is_fill_sel = fill_enable;
@ -364,6 +366,7 @@ module VX_cache_bank #(
.hit_way (tag_matches_st1),
.repl_valid (do_fill_st0 && ~pipe_stall),
.repl_line (line_idx_st0),
.repl_line_n(line_idx_sel),
.repl_way (victim_way_st0)
);
@ -430,7 +433,6 @@ module VX_cache_bank #(
// The r/w hazard is also not needed for next writethrough fill/flush to the same line.
// For reads or writeback fill/flush to the same line, we sill need the hazard
// because the data writeen in st1 cannot be read at the same time in st0 without extra forwarding logic.
wire [`CS_LINE_SEL_BITS-1:0] line_idx_sel = addr_sel[`CS_LINE_SEL_BITS-1:0];
wire is_write_sel = is_creq_sel && rw_sel;
wire is_same_line = (line_idx_sel == line_idx_st0);
always @(posedge clk) begin

View file

@ -268,7 +268,7 @@ module VX_cache_bypass #(
for (genvar i = 0; i < NUM_REQS; ++i) begin : g_core_rsp_in_valid
assign core_rsp_in_valid[i] = core_bus_out_if[i].rsp_valid || (is_mem_rsp_nc && rsp_idx == REQ_SEL_WIDTH'(i));
end
for (genvar i = 0; i < NUM_REQS; ++i) begin : g_core_rsp_in_ready
assign core_bus_out_if[i].rsp_ready = core_rsp_in_ready[i];
end

View file

@ -24,22 +24,22 @@ module VX_cache_cluster import VX_gpu_pkg::*; #(
parameter NUM_REQS = 4,
// Size of cache in bytes
parameter CACHE_SIZE = 16384,
parameter CACHE_SIZE = 32768,
// Size of line inside a bank in bytes
parameter LINE_SIZE = 64,
// Number of banks
parameter NUM_BANKS = 1,
parameter NUM_BANKS = 4,
// Number of associative ways
parameter NUM_WAYS = 4,
// Size of a word in bytes
parameter WORD_SIZE = 4,
parameter WORD_SIZE = 16,
// Core Response Queue Size
parameter CRSQ_SIZE = 2,
parameter CRSQ_SIZE = 4,
// Miss Reserv Queue Knob
parameter MSHR_SIZE = 8,
parameter MSHR_SIZE = 16,
// Memory Response Queue Size
parameter MRSQ_SIZE = 0,
parameter MRSQ_SIZE = 4,
// Memory Request Queue Size
parameter MREQ_SIZE = 4,
@ -53,7 +53,7 @@ module VX_cache_cluster import VX_gpu_pkg::*; #(
parameter DIRTY_BYTES = 0,
// Replacement policy
parameter REPL_POLICY = `CS_REPL_CYCLIC,
parameter REPL_POLICY = `CS_REPL_CYCLIC,
// Request debug identifier
parameter UUID_WIDTH = 0,
@ -68,10 +68,10 @@ module VX_cache_cluster import VX_gpu_pkg::*; #(
parameter NC_ENABLE = 0,
// Core response output buffer
parameter CORE_OUT_BUF = 0,
parameter CORE_OUT_BUF = 3,
// Memory request output buffer
parameter MEM_OUT_BUF = 0
parameter MEM_OUT_BUF = 3
) (
input wire clk,
input wire reset,

View file

@ -56,7 +56,7 @@ module VX_cache_data #(
`UNUSED_PARAM (WORD_SIZE)
`UNUSED_VAR (stall)
localparam BYTEENW = (WRITE_ENABLE != 0 || NUM_WAYS != 1) ? (LINE_SIZE * NUM_WAYS) : 1;
localparam BYTEENW = (WRITE_ENABLE != 0) ? LINE_SIZE : 1;
wire [NUM_WAYS-1:0][`CS_WORDS_PER_LINE-1:0][`CS_WORD_WIDTH-1:0] line_rdata;
@ -137,62 +137,51 @@ module VX_cache_data #(
assign evict_byteen = '0;
end
wire [NUM_WAYS-1:0][`CS_WORDS_PER_LINE-1:0][`CS_WORD_WIDTH-1:0] line_wdata;
wire [BYTEENW-1:0] line_wren;
wire line_write;
wire line_read;
for (genvar i = 0; i < NUM_WAYS; ++i) begin : g_data_store
wire [`CS_WORDS_PER_LINE-1:0][`CS_WORD_WIDTH-1:0] line_wdata;
wire [BYTEENW-1:0] line_wren;
if (BYTEENW != 1) begin : g_wdata
wire [NUM_WAYS-1:0][LINE_SIZE-1:0] line_wren_w;
for (genvar i = 0; i < NUM_WAYS; ++i) begin : g_ways
wire fill_way_en = (NUM_WAYS == 1) || evict_way[i];
if (WRITE_ENABLE != 0) begin : g_we
wire [`CS_WORDS_PER_LINE-1:0][WORD_SIZE-1:0] write_mask;
for (genvar j = 0; j < `CS_WORDS_PER_LINE; ++j) begin : g_write_mask
wire word_en = (`CS_WORDS_PER_LINE == 1) || (word_idx == j);
assign write_mask[j] = write_byteen & {WORD_SIZE{word_en}};
end
assign line_wdata[i] = (fill && fill_way_en) ? fill_data : {`CS_WORDS_PER_LINE{write_word}};
assign line_wren_w[i] = {LINE_SIZE{fill && fill_way_en}}
| ({LINE_SIZE{write && tag_matches[i]}} & write_mask);
end else begin : g_ro
`UNUSED_VAR (write)
`UNUSED_VAR (write_byteen)
`UNUSED_VAR (write_word)
`UNUSED_VAR (word_idx)
assign line_wdata[i] = fill_data;
assign line_wren_w[i] = {LINE_SIZE{fill_way_en}};
wire fill_way_en = (NUM_WAYS == 1) || evict_way[i];
if (WRITE_ENABLE != 0) begin : g_wdata
wire [`CS_WORDS_PER_LINE-1:0][WORD_SIZE-1:0] write_mask;
for (genvar j = 0; j < `CS_WORDS_PER_LINE; ++j) begin : g_write_mask
wire word_en = (`CS_WORDS_PER_LINE == 1) || (word_idx == j);
assign write_mask[j] = write_byteen & {WORD_SIZE{word_en}};
end
assign line_wdata = (fill && fill_way_en) ? fill_data : {`CS_WORDS_PER_LINE{write_word}};
assign line_wren = {LINE_SIZE{fill && fill_way_en}}
| ({LINE_SIZE{write && tag_matches[i]}} & write_mask);
end else begin : g_ro_wdata
`UNUSED_VAR (write)
`UNUSED_VAR (write_byteen)
`UNUSED_VAR (write_word)
`UNUSED_VAR (word_idx)
assign line_wdata = fill_data;
assign line_wren = fill_way_en;
end
assign line_wren = line_wren_w;
end else begin : g_ro_1w_wdata
`UNUSED_VAR (write)
`UNUSED_VAR (evict_way)
`UNUSED_VAR (write_byteen)
`UNUSED_VAR (write_word)
assign line_wdata = fill_data;
assign line_wren = 1'b1;
wire line_write = fill || (write && WRITE_ENABLE);
wire line_read = read || ((fill || flush) && WRITEBACK);
VX_sp_ram #(
.DATAW (`CS_LINE_WIDTH),
.SIZE (`CS_LINES_PER_BANK),
.WRENW (BYTEENW),
.OUT_REG (1)
) data_store (
.clk (clk),
.reset (reset),
.read (line_read),
.write (line_write),
.wren (line_wren),
.addr (line_idx),
.wdata (line_wdata),
.rdata (line_rdata[i])
);
end
assign line_write = fill || (write && WRITE_ENABLE);
assign line_read = read || ((fill || flush) && WRITEBACK);
VX_sp_ram #(
.DATAW (NUM_WAYS * `CS_LINE_WIDTH),
.SIZE (`CS_LINES_PER_BANK),
.WRENW (BYTEENW),
.OUT_REG (1)
) data_store (
.clk (clk),
.reset (reset),
.read (line_read),
.write (line_write),
.wren (line_wren),
.addr (line_idx),
.wdata (line_wdata),
.rdata (line_rdata)
);
wire [`LOG2UP(NUM_WAYS)-1:0] hit_way_idx;
VX_onehot_encoder #(
.N (NUM_WAYS)

View file

@ -99,6 +99,7 @@ module VX_cache_repl #(
input wire [`CS_LINE_SEL_BITS-1:0] hit_line,
input wire [NUM_WAYS-1:0] hit_way,
input wire repl_valid,
input wire [`CS_LINE_SEL_BITS-1:0] repl_line_n,
input wire [`CS_LINE_SEL_BITS-1:0] repl_line,
output wire [NUM_WAYS-1:0] repl_way
);
@ -110,6 +111,7 @@ module VX_cache_repl #(
if (REPL_POLICY == `CS_REPL_PLRU) begin : g_plru
// Pseudo Least Recently Used replacement policy
localparam LRU_WIDTH = `UP(NUM_WAYS-1);
localparam FORCE_BRAM = (LRU_WIDTH * `CS_LINES_PER_BANK) >= 1024;
wire [WAY_IDX_WIDTH-1:0] repl_way_idx;
wire [WAY_IDX_WIDTH-1:0] hit_way_idx;
@ -118,17 +120,18 @@ module VX_cache_repl #(
wire [LRU_WIDTH-1:0] plru_wmask;
VX_dp_ram #(
.DATAW (LRU_WIDTH),
.SIZE (`CS_LINES_PER_BANK),
.WRENW (LRU_WIDTH)
.DATAW (LRU_WIDTH),
.SIZE (`CS_LINES_PER_BANK),
.WRENW (LRU_WIDTH),
.OUT_REG (FORCE_BRAM)
) plru_store (
.clk (clk),
.reset (reset),
.read (repl_valid),
.read (FORCE_BRAM ? ~stall : repl_valid),
.write (hit_valid),
.wren (plru_wmask),
.waddr (hit_line),
.raddr (repl_line),
.raddr (FORCE_BRAM ? repl_line_n : repl_line),
.wdata (plru_wdata),
.rdata (plru_rdata)
);
@ -167,23 +170,28 @@ module VX_cache_repl #(
end else if (REPL_POLICY == `CS_REPL_CYCLIC) begin : g_cyclic
// Cyclic replacement policy
localparam CTR_WIDTH = $clog2(NUM_WAYS);
localparam FORCE_BRAM = (CTR_WIDTH * `CS_LINES_PER_BANK) >= 1024;
`UNUSED_VAR (hit_valid)
`UNUSED_VAR (hit_line)
`UNUSED_VAR (hit_way)
`UNUSED_VAR (repl_valid)
wire [`UP(CTR_WIDTH)-1:0] ctr_rdata;
wire [`UP(CTR_WIDTH)-1:0] ctr_wdata = ctr_rdata + 1;
VX_sp_ram #(
.DATAW (`UP(CTR_WIDTH)),
.SIZE (`CS_LINES_PER_BANK)
VX_dp_ram #(
.DATAW (`UP(CTR_WIDTH)),
.SIZE (`CS_LINES_PER_BANK),
.OUT_REG (FORCE_BRAM)
) ctr_store (
.clk (clk),
.reset (reset),
.read (repl_valid),
.read (FORCE_BRAM ? ~stall : repl_valid),
.write (repl_valid),
.wren (1'b1),
.addr (repl_line),
.raddr (FORCE_BRAM ? repl_line_n : repl_line),
.waddr (repl_line),
.wdata (ctr_wdata),
.rdata (ctr_rdata)
);
@ -202,6 +210,7 @@ module VX_cache_repl #(
`UNUSED_VAR (hit_way)
`UNUSED_VAR (repl_valid)
`UNUSED_VAR (repl_line)
`UNUSED_VAR (repl_line_n)
if (NUM_WAYS > 1) begin : g_repl_way
reg [NUM_WAYS-1:0] victim_way;
always @(posedge clk) begin

View file

@ -20,7 +20,7 @@ module VX_cache_top import VX_gpu_pkg::*; #(
parameter NUM_REQS = 4,
// Size of cache in bytes
parameter CACHE_SIZE = 16384,
parameter CACHE_SIZE = 32768,
// Size of line inside a bank in bytes
parameter LINE_SIZE = 64,
// Number of banks
@ -28,14 +28,14 @@ module VX_cache_top import VX_gpu_pkg::*; #(
// Number of associative ways
parameter NUM_WAYS = 4,
// Size of a word in bytes
parameter WORD_SIZE = 4,
parameter WORD_SIZE = 16,
// Core Response Queue Size
parameter CRSQ_SIZE = 2,
parameter CRSQ_SIZE = 4,
// Miss Reserv Queue Knob
parameter MSHR_SIZE = 16,
// Memory Response Queue Size
parameter MRSQ_SIZE = 0,
parameter MRSQ_SIZE = 4,
// Memory Request Queue Size
parameter MREQ_SIZE = 4,
@ -55,10 +55,10 @@ module VX_cache_top import VX_gpu_pkg::*; #(
parameter TAG_WIDTH = 16,
// Core response output buffer
parameter CORE_OUT_BUF = 2,
parameter CORE_OUT_BUF = 3,
// Memory request output buffer
parameter MEM_OUT_BUF = 2,
parameter MEM_OUT_BUF = 3,
parameter MEM_TAG_WIDTH = `CLOG2(MSHR_SIZE) + `CLOG2(NUM_BANKS)
) (

View file

@ -27,18 +27,18 @@ module VX_cache_wrap import VX_gpu_pkg::*; #(
// Size of line inside a bank in bytes
parameter LINE_SIZE = 64,
// Number of banks
parameter NUM_BANKS = 1,
parameter NUM_BANKS = 4,
// Number of associative ways
parameter NUM_WAYS = 1,
parameter NUM_WAYS = 4,
// Size of a word in bytes
parameter WORD_SIZE = 4,
parameter WORD_SIZE = 16,
// Core Response Queue Size
parameter CRSQ_SIZE = 2,
parameter CRSQ_SIZE = 4,
// Miss Reserv Queue Knob
parameter MSHR_SIZE = 8,
parameter MSHR_SIZE = 16,
// Memory Response Queue Size
parameter MRSQ_SIZE = 0,
parameter MRSQ_SIZE = 4,
// Memory Request Queue Size
parameter MREQ_SIZE = 4,
@ -52,7 +52,7 @@ module VX_cache_wrap import VX_gpu_pkg::*; #(
parameter DIRTY_BYTES = 0,
// Replacement policy
parameter REPL_POLICY = `CS_REPL_CYCLIC,
parameter REPL_POLICY = `CS_REPL_CYCLIC,
// Request debug identifier
parameter UUID_WIDTH = 0,
@ -70,10 +70,10 @@ module VX_cache_wrap import VX_gpu_pkg::*; #(
parameter PASSTHRU = 0,
// Core response output buffer
parameter CORE_OUT_BUF = 0,
parameter CORE_OUT_BUF = 3,
// Memory request output buffer
parameter MEM_OUT_BUF = 0
parameter MEM_OUT_BUF = 3
) (
input wire clk,

View file

@ -266,9 +266,9 @@ module VX_operands import VX_gpu_pkg::*; #(
VX_dp_ram #(
.DATAW (REGS_DATAW),
.SIZE (PER_BANK_REGS * PER_ISSUE_WARPS),
.OUT_REG (1),
.READ_ENABLE (1),
.WRENW (BYTEENW),
.OUT_REG (1),
.WRITE_MODE ("U"),
`ifdef GPR_RESET
.RESET_RAM (1),
`endif

View file

@ -24,7 +24,7 @@ module VX_dp_ram #(
parameter RW_ASSERT = 0,
parameter RESET_RAM = 0,
parameter RESET_OUT = 0,
parameter READ_ENABLE = 0,
parameter `STRING WRITE_MODE = "R", // R: read-first, W: write-first, N: no-change, U: undefined
parameter INIT_ENABLE = 0,
parameter INIT_FILE = "",
parameter [DATAW-1:0] INIT_VALUE = 0,
@ -41,7 +41,10 @@ module VX_dp_ram #(
output wire [DATAW-1:0] rdata
);
localparam WSELW = DATAW / WRENW;
localparam USE_BRAM = !LUTRAM && ((DATAW * SIZE) >= `MAX_LUTRAM);
`STATIC_ASSERT((WRENW * WSELW == DATAW), ("invalid parameter"))
`UNUSED_PARAM (RW_ASSERT)
`define RAM_INITIALIZATION \
if (INIT_ENABLE != 0) begin : g_init \
@ -56,187 +59,155 @@ module VX_dp_ram #(
end \
end
`define RAM_WREN_BLOCK_ALTERA(__we__) \
reg [WRENW-1:0][WSELW-1:0] ram [0:SIZE-1]; \
`RAM_INITIALIZATION \
always @(posedge clk) begin \
if (__we__) begin \
for (integer i = 0; i < WRENW; ++i) begin \
if (wren[i]) begin \
ram[waddr][i] <= wdata[i * WSELW +: WSELW]; \
end \
end \
end \
end
`define RAM_WREN_BLOCK_XILINX(__we__) \
reg [DATAW-1:0] ram [0:SIZE-1]; \
`RAM_INITIALIZATION \
always @(posedge clk) begin \
if (__we__) begin \
for (integer i = 0; i < WRENW; ++i) begin \
if (wren[i]) begin \
ram[waddr][i * WSELW +: WSELW] <= wdata[i * WSELW +: WSELW]; \
end \
end \
end \
end
`define RAM_WRITE_BLOCK(__we__) \
reg [DATAW-1:0] ram [0:SIZE-1]; \
`RAM_INITIALIZATION \
always @(posedge clk) begin \
if (__we__) begin \
ram[waddr] <= wdata; \
end \
end
`define RAM_READ_BLOCK_OUT_REG(__re__) \
always @(posedge clk) begin \
if (__re__) begin \
if (RESET_OUT && reset) begin \
rdata_r <= INIT_VALUE; \
end else begin \
rdata_r <= ram[raddr]; \
end \
end \
end
`UNUSED_PARAM (RW_ASSERT)
`UNUSED_VAR (read)
`UNUSED_VAR (wren)
`ifdef SYNTHESIS
`ifdef QUARTUS
localparam `STRING RAM_STYLE_VALUE = USE_BRAM ? "block" : (LUTRAM ? "MLAB, no_rw_check" : "");
localparam `STRING RAM_NO_RWCHECK_VALUE = NO_RWCHECK ? "-name add_pass_through_logic_to_inferred_rams off" : "";
`define RAM_ARRAY (* ramstyle = RAM_STYLE_VALUE *) reg [WRENW-1:0][WSELW-1:0] ram [0:SIZE-1];
`define RAM_WRITE for (integer i = 0; i < WRENW; ++i) begin \
if (wren[i]) begin \
ram[waddr][i] <= wdata[i * WSELW +: WSELW]; \
end \
end
`define RAM_NO_RWCHECK (* altera_attribute = RAM_NO_RWCHECK_VALUE *)
`else
localparam `STRING RAM_STYLE_VALUE = USE_BRAM ? "block" : (LUTRAM ? "distributed" : "");
localparam `STRING RAM_NO_RWCHECK_VALUE = NO_RWCHECK ? "no" : "";
`define RAM_ARRAY (* ram_style = RAM_STYLE_VALUE *) reg [DATAW-1:0] ram [0:SIZE-1];
`define RAM_WRITE for (integer i = 0; i < WRENW; ++i) begin \
if (wren[i]) begin \
ram[waddr][i * WSELW +: WSELW] <= wdata[i * WSELW +: WSELW]; \
end \
end
`define RAM_NO_RWCHECK (* rw_addr_collision = RAM_NO_RWCHECK_VALUE *)
`endif
if (OUT_REG) begin : g_out_reg
reg [DATAW-1:0] rdata_r;
if (READ_ENABLE) begin : g_readen
if (WRENW != 1) begin : g_writeen
`ifdef QUARTUS
if (LUTRAM != 0) begin : g_lutram
`USE_FAST_BRAM `RAM_WREN_BLOCK_ALTERA(write)
`RAM_READ_BLOCK_OUT_REG(read)
end else begin : g_no_lutram
`RAM_WREN_BLOCK_ALTERA(write)
`RAM_READ_BLOCK_OUT_REG(read)
if (WRITE_MODE == "R") begin : g_read_first
`RAM_ARRAY
`RAM_INITIALIZATION
always @(posedge clk) begin
if (write) begin
`RAM_WRITE
end
`else
// Not Quartus
if (LUTRAM != 0) begin : g_lutram
`USE_FAST_BRAM `RAM_WREN_BLOCK_XILINX(write)
`RAM_READ_BLOCK_OUT_REG(read)
end else begin : g_no_lutram
`RAM_WREN_BLOCK_XILINX(write)
`RAM_READ_BLOCK_OUT_REG(read)
end
`endif
end else begin : g_no_writeen
if (LUTRAM != 0) begin : g_lutram
`USE_FAST_BRAM `RAM_WRITE_BLOCK(write)
`RAM_READ_BLOCK_OUT_REG(read)
end else begin : g_no_lutram
`RAM_WRITE_BLOCK(write)
`RAM_READ_BLOCK_OUT_REG(read)
if (RESET_OUT && reset) begin
rdata_r <= INIT_VALUE;
end else if (read || write) begin
rdata_r <= ram[raddr];
end
end
end else begin : g_no_readen
if (WRENW != 1) begin : g_writeen
`ifdef QUARTUS
if (LUTRAM != 0) begin : g_lutram
`USE_FAST_BRAM `RAM_WREN_BLOCK_ALTERA(write)
`RAM_READ_BLOCK_OUT_REG(read || write)
end else begin : g_no_lutram
`RAM_WREN_BLOCK_ALTERA(write)
`RAM_READ_BLOCK_OUT_REG(read || write)
end else if (WRITE_MODE == "W") begin : g_write_first
`RAM_ARRAY
`RAM_INITIALIZATION
always @(posedge clk) begin
if (write) begin
`RAM_WRITE
end
`else
// Not Quartus
if (LUTRAM != 0) begin : g_lutram
`USE_FAST_BRAM `RAM_WREN_BLOCK_XILINX(write)
`RAM_READ_BLOCK_OUT_REG(read || write)
end else begin : g_no_lutram
`RAM_WREN_BLOCK_XILINX(write)
`RAM_READ_BLOCK_OUT_REG(read || write)
if (RESET_OUT && reset) begin
rdata_r <= INIT_VALUE;
end else if (read || write) begin
rdata_r = ram[raddr];
end
`endif
end else begin : g_no_writeen
if (LUTRAM != 0) begin : g_lutram
`USE_FAST_BRAM `RAM_WRITE_BLOCK(write)
`RAM_READ_BLOCK_OUT_REG(read || write)
end else begin : g_no_lutram
`RAM_WRITE_BLOCK(write)
`RAM_READ_BLOCK_OUT_REG(read || write)
end
end else if (WRITE_MODE == "N") begin : g_no_change
`RAM_ARRAY
`RAM_INITIALIZATION
always @(posedge clk) begin
if (write) begin
`RAM_WRITE
end
if (RESET_OUT && reset) begin
rdata_r <= INIT_VALUE;
end else if (read && ~write) begin
rdata_r <= ram[raddr];
end
end
end end else if (WRITE_MODE == "U") begin : g_undefined
`RAM_NO_RWCHECK `RAM_ARRAY
`RAM_INITIALIZATION
always @(posedge clk) begin
if (write) begin
`RAM_WRITE
end
if (RESET_OUT && reset) begin
rdata_r <= INIT_VALUE;
end else if (read) begin
rdata_r <= ram[raddr];
end
end
end else begin
`STATIC_ASSERT(0, ("invalid write mode: %s", WRITE_MODE))
end
else begin : g_no_out_reg
`UNUSED_VAR (read)
`RAM_NO_RWCHECK `RAM_ARRAY
`RAM_INITIALIZATION
always @(posedge clk) begin
if (write) begin
`RAM_WRITE
end
end
assign rdata = ram[raddr];
end
`else
// simulation
reg [DATAW-1:0] ram [0:SIZE-1];
`RAM_INITIALIZATION
wire [DATAW-1:0] ram_n;
for (genvar i = 0; i < WRENW; ++i) begin : g_ram_n
assign ram_n[i * WSELW +: WSELW] = wren[i] ? wdata[i * WSELW +: WSELW] : ram[waddr][i * WSELW +: WSELW];
end
always @(posedge clk) begin
if (RESET_RAM && reset) begin
for (integer i = 0; i < SIZE; ++i) begin
ram[i] <= DATAW'(INIT_VALUE);
end
end else begin
if (write) begin
ram[waddr] <= ram_n;
end
end
end
if (OUT_REG && WRITE_MODE == "R") begin : g_read_first
reg [DATAW-1:0] rdata_r;
always @(posedge clk) begin
if (RESET_OUT && reset) begin
rdata_r <= DATAW'(INIT_VALUE);
end else if (read || write) begin
rdata_r <= ram[raddr];
end
end
assign rdata = rdata_r;
end else if (OUT_REG && WRITE_MODE == "W") begin : g_read_first
reg [DATAW-1:0] rdata_r;
always @(posedge clk) begin
if (RESET_OUT && reset) begin
rdata_r <= DATAW'(INIT_VALUE);
end else if (read || write) begin
if (write && (raddr == waddr)) begin
rdata_r <= ram_n;
end else begin
rdata_r <= ram[raddr];
end
end
end
assign rdata = rdata_r;
end else begin : g_no_out_reg
`ifdef SYNTHESIS
if (WRENW > 1) begin : g_writeen
`ifdef QUARTUS
if (LUTRAM != 0) begin : g_lutram
`USE_FAST_BRAM `RAM_WREN_BLOCK_ALTERA(write)
assign rdata = ram[raddr];
end else begin : g_no_lutram
if (NO_RWCHECK != 0) begin : g_no_rwcheck
`NO_RW_RAM_CHECK `RAM_WREN_BLOCK_ALTERA(write)
assign rdata = ram[raddr];
end else begin : g_rwcheck
`RAM_WREN_BLOCK_ALTERA(write)
assign rdata = ram[raddr];
end
end
`else
// default synthesis
if (LUTRAM != 0) begin : g_lutram
`USE_FAST_BRAM `RAM_WREN_BLOCK_XILINX(write)
assign rdata = ram[raddr];
end else begin : g_no_lutram
if (NO_RWCHECK != 0) begin : g_no_rwcheck
`NO_RW_RAM_CHECK `RAM_WREN_BLOCK_XILINX(write)
assign rdata = ram[raddr];
end else begin : g_rwcheck
`RAM_WREN_BLOCK_XILINX(write)
assign rdata = ram[raddr];
end
end
`endif
end else begin : g_no_writeen
// (WRENW == 1)
if (LUTRAM != 0) begin : g_lutram
`USE_FAST_BRAM `RAM_WRITE_BLOCK(write)
assign rdata = ram[raddr];
end else begin : g_no_lutram
if (NO_RWCHECK != 0) begin : g_no_rwcheck
`NO_RW_RAM_CHECK `RAM_WRITE_BLOCK(write)
assign rdata = ram[raddr];
end else begin : g_rwcheck
`RAM_WRITE_BLOCK(write)
assign rdata = ram[raddr];
end
end
end
`else
// simulation
reg [DATAW-1:0] ram [0:SIZE-1];
`RAM_INITIALIZATION
wire [DATAW-1:0] ram_n;
for (genvar i = 0; i < WRENW; ++i) begin : g_ram_n
assign ram_n[i * WSELW +: WSELW] = ((WRENW == 1) | wren[i]) ? wdata[i * WSELW +: WSELW] : ram[waddr][i * WSELW +: WSELW];
end
end else if (OUT_REG && WRITE_MODE == "N") begin : g_read_first
reg [DATAW-1:0] rdata_r;
always @(posedge clk) begin
if (RESET_RAM && reset) begin
for (integer i = 0; i < SIZE; ++i) begin
ram[i] <= DATAW'(INIT_VALUE);
end
end else begin
if (write) begin
ram[waddr] <= ram_n;
end
if (RESET_OUT && reset) begin
rdata_r <= DATAW'(INIT_VALUE);
end else if (read && ~write) begin
rdata_r <= ram[raddr];
end
end
if (!LUTRAM && NO_RWCHECK) begin : g_rdata_no_bypass
assign rdata = rdata_r;
end else begin : g_async_or_undef
wire [DATAW-1:0] rdata_w;
if (USE_BRAM && NO_RWCHECK) begin : g_rdata_no_bypass
reg [DATAW-1:0] prev_data;
reg [ADDRW-1:0] prev_waddr;
reg prev_write;
@ -253,15 +224,29 @@ module VX_dp_ram #(
end
end
assign rdata = (prev_write && (prev_waddr == raddr)) ? prev_data : ram[raddr];
if (RW_ASSERT) begin : g_rw_assert
`RUNTIME_ASSERT(~read || (rdata == ram[raddr]), ("%t: read after write hazard", $time))
assign rdata_w = (prev_write && (prev_waddr == raddr)) ? prev_data : ram[raddr];
if (RW_ASSERT) begin : g_rw_asert
`RUNTIME_ASSERT(~read || (rdata_w == ram[raddr]), ("%t: read after write hazard", $time))
end
end else begin : g_rdata_with_bypass
assign rdata = ram[raddr];
assign rdata_w = ram[raddr];
end
if (OUT_REG) begin : g_out_reg
reg [DATAW-1:0] rdata_r;
always @(posedge clk) begin
if (RESET_OUT && reset) begin
rdata_r <= DATAW'(INIT_VALUE);
end else if (read) begin
rdata_r <= rdata_w;
end
end
assign rdata = rdata_r;
end else begin : g_no_out_reg
`UNUSED_VAR (read)
assign rdata = rdata_w;
end
`endif
end
`endif
endmodule
`TRACING_ON

View file

@ -16,11 +16,11 @@
`TRACING_OFF
module VX_fifo_queue #(
parameter DATAW = 1,
parameter DEPTH = 2,
parameter DEPTH = 1,
parameter ALM_FULL = (DEPTH - 1),
parameter ALM_EMPTY = 1,
parameter OUT_REG = 0,
parameter LUTRAM = 0,
parameter LUTRAM = ((DATAW * DEPTH) < `MAX_LUTRAM),
parameter SIZEW = `CLOG2(DEPTH+1)
) (
input wire clk,
@ -105,7 +105,8 @@ module VX_fifo_queue #(
.DATAW (DATAW),
.SIZE (DEPTH),
.LUTRAM (LUTRAM),
.OUT_REG(!LUTRAM)
.OUT_REG(!LUTRAM),
.WRITE_MODE("W")
) dp_ram (
.clk (clk),
.reset (reset),
@ -119,47 +120,17 @@ module VX_fifo_queue #(
);
if (OUT_REG != 0) begin : g_out_reg
reg [DATAW-1:0] data_out_r, data_out_n;
if (LUTRAM) begin : g_lutram
assign data_out_n = data_out_w;
end else begin : g_no_lutram
reg [DATAW-1:0] data_out_p;
reg rdw_hazard_r;
wire rdw_hazard = push && (wr_ptr_r == rd_ptr_w);
always @(posedge clk) begin
if (rdw_hazard) begin
data_out_p <= data_in;
end
rdw_hazard_r <= rdw_hazard;
end
assign data_out_n = rdw_hazard_r ? data_out_p : data_out_w;
end
reg [DATAW-1:0] data_out_r;
always @(posedge clk) begin
if (bypass) begin
data_out_r <= data_in;
end else if (pop) begin
data_out_r <= data_out_n;
data_out_r <= data_out_w;
end
end
assign data_out = data_out_r;
end else begin : g_no_out_reg
if (LUTRAM) begin : g_lutram
assign data_out = data_out_w;
end else begin : g_no_lutram
reg [DATAW-1:0] data_in_r;
reg bypass_r;
always @(posedge clk) begin
if (bypass) begin
data_in_r <= data_in;
end
bypass_r <= bypass;
end
assign data_out = bypass_r ? data_in_r : data_out_w;
end
assign data_out = data_out_w;
end
end

View file

@ -112,9 +112,7 @@ module VX_scope_tap #(
VX_dp_ram #(
.DATAW (IDLE_CTRW),
.SIZE (DEPTH),
.OUT_REG (1),
.READ_ENABLE (0),
.NO_RWCHECK (1)
.OUT_REG (1)
) delta_store (
.clk (clk),
.reset (reset),
@ -135,9 +133,7 @@ module VX_scope_tap #(
VX_dp_ram #(
.DATAW (DATAW),
.SIZE (DEPTH),
.OUT_REG (1),
.READ_ENABLE (0),
.NO_RWCHECK (1)
.OUT_REG (1)
) data_store (
.clk (clk),
.reset (reset),

View file

@ -24,7 +24,7 @@ module VX_sp_ram #(
parameter RW_ASSERT = 0,
parameter RESET_RAM = 0,
parameter RESET_OUT = 0,
parameter READ_ENABLE = 0,
parameter `STRING WRITE_MODE = "R", // R: read-first, W: write-first, N: no-change, U: undefined
parameter INIT_ENABLE = 0,
parameter INIT_FILE = "",
parameter [DATAW-1:0] INIT_VALUE = 0,
@ -49,7 +49,7 @@ module VX_sp_ram #(
.RW_ASSERT (RW_ASSERT),
.RESET_RAM (RESET_RAM),
.RESET_OUT (RESET_OUT),
.READ_ENABLE(READ_ENABLE),
.WRITE_MODE (WRITE_MODE),
.INIT_ENABLE(INIT_ENABLE),
.INIT_FILE (INIT_FILE),
.INIT_VALUE (INIT_VALUE),

View file

@ -166,9 +166,7 @@ module VX_local_mem import VX_gpu_pkg::*; #(
.DATAW (WORD_WIDTH),
.SIZE (WORDS_PER_BANK),
.WRENW (WORD_SIZE),
.OUT_REG (1),
.READ_ENABLE (0),
.NO_RWCHECK (1)
.OUT_REG (1)
) lmem_store (
.clk (clk),
.reset (reset),