mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-20 12:17:19 -04:00
Parameterization and other fixes for downstream project (#1950)
* Bender fixes and switch to `cva6_fifo_v3` * cfg: Fix verilator warnings * Bender: Fix yml * acc_dispatcher: Add `csr_addr_i` * parameterization: Fox AXI_USER_EN warning * wb_cache: Fix Verilator Lint warnings * cva6_fifo_v3: Add to Flist * parameterization: Address review concerns * Switch to `cva6_fifo_v3` * tracer: Remove tracer interface The interface made a bunch of problems with the typedefs so I've removed it. --------- Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
parent
f886713754
commit
38e8c059b2
21 changed files with 335 additions and 233 deletions
11
Bender.yml
11
Bender.yml
|
@ -17,9 +17,11 @@ dependencies:
|
|||
frozen: true
|
||||
|
||||
sources:
|
||||
- files:
|
||||
- include_dirs:
|
||||
- core/include
|
||||
files:
|
||||
- core/include/config_pkg.sv
|
||||
|
||||
- core/include/build_config_pkg.sv
|
||||
- target: cv64a6_imafdcv_sv39
|
||||
files:
|
||||
- core/include/cv64a6_imafdcv_sv39_config_pkg.sv
|
||||
|
@ -107,7 +109,6 @@ sources:
|
|||
# Packages
|
||||
- core/include/wt_cache_pkg.sv
|
||||
- core/include/std_cache_pkg.sv
|
||||
- core/include/acc_pkg.sv
|
||||
|
||||
# for all the below files use Flist.cva6 as baseline and also look at Makefile pd/synth
|
||||
# CVXIF
|
||||
|
@ -118,11 +119,12 @@ sources:
|
|||
- core/cvxif_example/cvxif_example_coprocessor.sv
|
||||
- core/cvxif_example/instr_decoder.sv
|
||||
|
||||
- core/cva6_rvfi_probes.sv
|
||||
- core/cva6_fifo_v3.sv
|
||||
# vendored deps
|
||||
# - include_dirs: [vendor/pulp-platform/common_cells/include/, vendor/pulp-platform/common_cells/src/]
|
||||
# files:
|
||||
# - vendor/pulp-platform/common_cells/src/cf_math_pkg.sv
|
||||
# - vendor/pulp-platform/common_cells/src/fifo_v3.sv
|
||||
# - vendor/pulp-platform/common_cells/src/lfsr.sv
|
||||
# - vendor/pulp-platform/common_cells/src/lzc.sv
|
||||
# - vendor/pulp-platform/common_cells/src/rr_arb_tree.sv
|
||||
|
@ -244,7 +246,6 @@ sources:
|
|||
# Tracer (behavioral code, not RTL)
|
||||
- core/include/instr_tracer_pkg.sv
|
||||
- common/local/util/instr_tracer.sv
|
||||
- common/local/util/instr_tracer_if.sv
|
||||
|
||||
# TODO target define FPGA target + verification etc
|
||||
# - target: test
|
||||
|
|
|
@ -161,7 +161,6 @@ vendor/openhwgroup/cvfpu/src/fpnew_top.sv
|
|||
core/pmp/src/pmp.sv
|
||||
core/pmp/src/pmp_entry.sv
|
||||
common/local/util/instr_tracer.sv
|
||||
common/local/util/instr_tracer_if.sv
|
||||
core/cvxif_example/cvxif_example_coprocessor.sv
|
||||
core/cvxif_example/instr_decoder.sv
|
||||
vendor/pulp-platform/common_cells/src/counter.sv
|
||||
|
|
1
Makefile
1
Makefile
|
@ -699,7 +699,6 @@ fpga_filter := $(addprefix $(root-dir), corev_apu/bootrom/bootrom.sv)
|
|||
fpga_filter += $(addprefix $(root-dir), core/include/instr_tracer_pkg.sv)
|
||||
fpga_filter += $(addprefix $(root-dir), src/util/ex_trace_item.sv)
|
||||
fpga_filter += $(addprefix $(root-dir), src/util/instr_trace_item.sv)
|
||||
fpga_filter += $(addprefix $(root-dir), common/local/util/instr_tracer_if.sv)
|
||||
fpga_filter += $(addprefix $(root-dir), common/local/util/instr_tracer.sv)
|
||||
fpga_filter += $(addprefix $(root-dir), vendor/pulp-platform/tech_cells_generic/src/rtl/tc_sram.sv)
|
||||
fpga_filter += $(addprefix $(root-dir), common/local/util/tc_sram_wrapper.sv)
|
||||
|
|
|
@ -22,9 +22,34 @@ module instr_tracer #(
|
|||
parameter type bp_resolve_t = logic,
|
||||
parameter type scoreboard_entry_t = logic,
|
||||
parameter type interrupts_t = logic,
|
||||
parameter type exception_t = logic,
|
||||
parameter interrupts_t INTERRUPTS = '0
|
||||
)(
|
||||
instr_tracer_if tracer_if,
|
||||
input logic pck,
|
||||
input logic rstn,
|
||||
input logic flush_unissued,
|
||||
input logic flush_all,
|
||||
input logic [31:0] instruction,
|
||||
input logic fetch_valid,
|
||||
input logic fetch_ack,
|
||||
input logic issue_ack, // issue acknowledged
|
||||
input scoreboard_entry_t issue_sbe, // issue scoreboard entry
|
||||
input logic [1:0][4:0] waddr, // WB stage
|
||||
input logic [1:0][63:0] wdata,
|
||||
input logic [1:0] we_gpr,
|
||||
input logic [1:0] we_fpr,
|
||||
input scoreboard_entry_t [1:0] commit_instr, // commit instruction
|
||||
input logic [1:0] commit_ack,
|
||||
input logic st_valid, // stores - address translation
|
||||
input logic [CVA6Cfg.PLEN-1:0] st_paddr,
|
||||
input logic ld_valid, // loads
|
||||
input logic ld_kill,
|
||||
input logic [CVA6Cfg.PLEN-1:0] ld_paddr,
|
||||
input bp_resolve_t resolve_branch, // misprediction
|
||||
input exception_t commit_exception,
|
||||
input riscv::priv_lvl_t priv_lvl, // current privilege level
|
||||
input logic debug_mode,
|
||||
|
||||
input logic[CVA6Cfg.XLEN-1:0] hart_id_i
|
||||
);
|
||||
|
||||
|
@ -34,7 +59,7 @@ module instr_tracer #(
|
|||
logic [31:0] issue_queue [$];
|
||||
// issue scoreboard entries
|
||||
scoreboard_entry_t issue_sbe_queue [$];
|
||||
scoreboard_entry_t issue_sbe;
|
||||
scoreboard_entry_t issue_sbe_item;
|
||||
// store resolved branches, get (mis-)predictions
|
||||
bp_resolve_t bp [$];
|
||||
// shadow copy of the register files
|
||||
|
@ -69,7 +94,7 @@ module instr_tracer #(
|
|||
forever begin
|
||||
automatic bp_resolve_t bp_instruction = '0;
|
||||
// new cycle, we are only interested if reset is de-asserted
|
||||
@(tracer_if.pck) if (tracer_if.pck.rstn !== 1'b1) begin
|
||||
@(pck) if (rstn !== 1'b1) begin
|
||||
flush();
|
||||
continue;
|
||||
end
|
||||
|
@ -81,8 +106,8 @@ module instr_tracer #(
|
|||
// Instruction Decode
|
||||
// -------------------
|
||||
// we are decoding an instruction
|
||||
if (tracer_if.pck.fetch_valid && tracer_if.pck.fetch_ack) begin
|
||||
decode_instruction = tracer_if.pck.instruction;
|
||||
if (fetch_valid && fetch_ack) begin
|
||||
decode_instruction = instruction;
|
||||
decode_queue.push_back(decode_instruction);
|
||||
end
|
||||
// -------------------
|
||||
|
@ -90,85 +115,85 @@ module instr_tracer #(
|
|||
// -------------------
|
||||
// we got a new issue ack, so put the element from the decode queue to
|
||||
// the issue queue
|
||||
if (tracer_if.pck.issue_ack && !tracer_if.pck.flush_unissued) begin
|
||||
if (issue_ack && !flush_unissued) begin
|
||||
issue_instruction = decode_queue.pop_front();
|
||||
issue_queue.push_back(issue_instruction);
|
||||
// also save the scoreboard entry to a separate issue queue
|
||||
issue_sbe_queue.push_back(scoreboard_entry_t'(tracer_if.pck.issue_sbe));
|
||||
issue_sbe_queue.push_back(scoreboard_entry_t'(issue_sbe));
|
||||
end
|
||||
|
||||
// --------------------
|
||||
// Address Translation
|
||||
// --------------------
|
||||
if (tracer_if.pck.st_valid) begin
|
||||
store_mapping.push_back(tracer_if.pck.st_paddr);
|
||||
if (st_valid) begin
|
||||
store_mapping.push_back(st_paddr);
|
||||
end
|
||||
|
||||
if (tracer_if.pck.ld_valid && !tracer_if.pck.ld_kill) begin
|
||||
load_mapping.push_back(tracer_if.pck.ld_paddr);
|
||||
if (ld_valid && !ld_kill) begin
|
||||
load_mapping.push_back(ld_paddr);
|
||||
end
|
||||
// ----------------------
|
||||
// Store predictions
|
||||
// ----------------------
|
||||
if (tracer_if.pck.resolve_branch.valid) begin
|
||||
bp.push_back(tracer_if.pck.resolve_branch);
|
||||
if (resolve_branch.valid) begin
|
||||
bp.push_back(resolve_branch);
|
||||
end
|
||||
// --------------
|
||||
// Commit
|
||||
// --------------
|
||||
// we are committing an instruction
|
||||
for (int i = 0; i < 2; i++) begin
|
||||
if (tracer_if.pck.commit_ack[i]) begin
|
||||
commit_instruction = scoreboard_entry_t'(tracer_if.pck.commit_instr[i]);
|
||||
if (commit_ack[i]) begin
|
||||
commit_instruction = scoreboard_entry_t'(commit_instr[i]);
|
||||
issue_commit_instruction = issue_queue.pop_front();
|
||||
issue_sbe = issue_sbe_queue.pop_front();
|
||||
issue_sbe_item = issue_sbe_queue.pop_front();
|
||||
// check if the instruction retiring is a load or store, get the physical address accordingly
|
||||
if (tracer_if.pck.commit_instr[i].fu == ariane_pkg::LOAD)
|
||||
if (commit_instr[i].fu == ariane_pkg::LOAD)
|
||||
address_mapping = load_mapping.pop_front();
|
||||
else if (tracer_if.pck.commit_instr[i].fu == ariane_pkg::STORE)
|
||||
else if (commit_instr[i].fu == ariane_pkg::STORE)
|
||||
address_mapping = store_mapping.pop_front();
|
||||
|
||||
if (tracer_if.pck.commit_instr[i].fu == ariane_pkg::CTRL_FLOW)
|
||||
if (commit_instr[i].fu == ariane_pkg::CTRL_FLOW)
|
||||
bp_instruction = bp.pop_front();
|
||||
// the scoreboards issue entry still contains the immediate value as a result
|
||||
// check if the write back is valid, if not we need to source the result from the register file
|
||||
// as the most recent version of this register will be there.
|
||||
if (tracer_if.pck.we_gpr[i] || tracer_if.pck.we_fpr[i]) begin
|
||||
printInstr(issue_sbe, issue_commit_instruction, tracer_if.pck.wdata[i], address_mapping, tracer_if.pck.priv_lvl, tracer_if.pck.debug_mode, bp_instruction);
|
||||
if (we_gpr[i] || we_fpr[i]) begin
|
||||
printInstr(issue_sbe_item, issue_commit_instruction, wdata[i], address_mapping, priv_lvl, debug_mode, bp_instruction);
|
||||
end else if (ariane_pkg::is_rd_fpr(commit_instruction.op)) begin
|
||||
printInstr(issue_sbe, issue_commit_instruction, fp_reg_file[commit_instruction.rd], address_mapping, tracer_if.pck.priv_lvl, tracer_if.pck.debug_mode, bp_instruction);
|
||||
printInstr(issue_sbe_item, issue_commit_instruction, fp_reg_file[commit_instruction.rd], address_mapping, priv_lvl, debug_mode, bp_instruction);
|
||||
end else begin
|
||||
printInstr(issue_sbe, issue_commit_instruction, gp_reg_file[commit_instruction.rd], address_mapping, tracer_if.pck.priv_lvl, tracer_if.pck.debug_mode, bp_instruction);
|
||||
printInstr(issue_sbe_item, issue_commit_instruction, gp_reg_file[commit_instruction.rd], address_mapping, priv_lvl, debug_mode, bp_instruction);
|
||||
end
|
||||
end
|
||||
end
|
||||
// --------------
|
||||
// Exceptions
|
||||
// --------------
|
||||
if (tracer_if.pck.exception.valid && !(tracer_if.pck.debug_mode && tracer_if.pck.exception.cause == riscv::BREAKPOINT)) begin
|
||||
if (commit_exception.valid && !(debug_mode && commit_exception.cause == riscv::BREAKPOINT)) begin
|
||||
// print exception
|
||||
printException(tracer_if.pck.commit_instr[0].pc, tracer_if.pck.exception.cause, tracer_if.pck.exception.tval);
|
||||
printException(commit_instr[0].pc, commit_exception.cause, commit_exception.tval);
|
||||
end
|
||||
// ----------------------
|
||||
// Commit Registers
|
||||
// ----------------------
|
||||
// update shadow reg files here
|
||||
for (int i = 0; i < 2; i++) begin
|
||||
if (tracer_if.pck.we_gpr[i] && tracer_if.pck.waddr[i] != 5'b0) begin
|
||||
gp_reg_file[tracer_if.pck.waddr[i]] = tracer_if.pck.wdata[i];
|
||||
end else if (tracer_if.pck.we_fpr[i]) begin
|
||||
fp_reg_file[tracer_if.pck.waddr[i]] = tracer_if.pck.wdata[i];
|
||||
if (we_gpr[i] && waddr[i] != 5'b0) begin
|
||||
gp_reg_file[waddr[i]] = wdata[i];
|
||||
end else if (we_fpr[i]) begin
|
||||
fp_reg_file[waddr[i]] = wdata[i];
|
||||
end
|
||||
end
|
||||
// --------------
|
||||
// Flush Signals
|
||||
// --------------
|
||||
// flush un-issued instructions
|
||||
if (tracer_if.pck.flush_unissued) begin
|
||||
if (flush_unissued) begin
|
||||
flushDecode();
|
||||
end
|
||||
// flush whole pipeline
|
||||
if (tracer_if.pck.flush) begin
|
||||
if (flush_all) begin
|
||||
flush();
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// 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.
|
||||
//
|
||||
// Author: Florian Zaruba, ETH Zurich
|
||||
// Date: 16.05.2017
|
||||
// Description: Instruction Tracer Interface
|
||||
|
||||
`ifndef VERILATOR
|
||||
`ifndef INSTR_TRACER_IF_SV
|
||||
`define INSTR_TRACER_IF_SV
|
||||
interface instr_tracer_if #(
|
||||
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
|
||||
parameter type bp_resolve_t = logic,
|
||||
parameter type exception_t = logic,
|
||||
parameter type scoreboard_entry_t = logic
|
||||
)(
|
||||
input clk
|
||||
);
|
||||
|
||||
logic rstn;
|
||||
logic flush_unissued;
|
||||
logic flush;
|
||||
// Decode
|
||||
logic [31:0] instruction;
|
||||
logic fetch_valid;
|
||||
logic fetch_ack;
|
||||
// Issue stage
|
||||
logic issue_ack; // issue acknowledged
|
||||
scoreboard_entry_t issue_sbe; // issue scoreboard entry
|
||||
// WB stage
|
||||
logic [1:0][4:0] waddr;
|
||||
logic [1:0][63:0] wdata;
|
||||
logic [1:0] we_gpr;
|
||||
logic [1:0] we_fpr;
|
||||
// commit stage
|
||||
scoreboard_entry_t [1:0] commit_instr; // commit instruction
|
||||
logic [1:0] commit_ack;
|
||||
// address translation
|
||||
// stores
|
||||
logic st_valid;
|
||||
logic [CVA6Cfg.PLEN-1:0] st_paddr;
|
||||
// loads
|
||||
logic ld_valid;
|
||||
logic ld_kill;
|
||||
logic [CVA6Cfg.PLEN-1:0] ld_paddr;
|
||||
// misprediction
|
||||
bp_resolve_t resolve_branch;
|
||||
// exceptions
|
||||
exception_t exception;
|
||||
// current privilege level
|
||||
riscv::priv_lvl_t priv_lvl;
|
||||
logic debug_mode;
|
||||
// the tracer just has a passive interface we do not drive anything with it
|
||||
|
||||
//pragma translate_off
|
||||
clocking pck @(posedge clk);
|
||||
input rstn, flush_unissued, flush, instruction, fetch_valid, fetch_ack, issue_ack, issue_sbe, waddr,
|
||||
st_valid, st_paddr, ld_valid, ld_kill, ld_paddr, resolve_branch,
|
||||
wdata, we_gpr, we_fpr, commit_instr, commit_ack, exception, priv_lvl, debug_mode;
|
||||
endclocking
|
||||
//pragma translate_on
|
||||
|
||||
endinterface
|
||||
`endif
|
||||
`endif
|
|
@ -133,6 +133,7 @@ ${CVA6_REPO_DIR}/core/commit_stage.sv
|
|||
${CVA6_REPO_DIR}/core/axi_shim.sv
|
||||
${CVA6_REPO_DIR}/core/cva6_accel_first_pass_decoder_stub.sv
|
||||
${CVA6_REPO_DIR}/core/acc_dispatcher.sv
|
||||
${CVA6_REPO_DIR}/core/cva6_fifo_v3.sv
|
||||
|
||||
// What is "frontend"?
|
||||
${CVA6_REPO_DIR}/core/frontend/btb.sv
|
||||
|
@ -178,7 +179,6 @@ ${CVA6_REPO_DIR}/core/pmp/src/pmp.sv
|
|||
${CVA6_REPO_DIR}/core/pmp/src/pmp_entry.sv
|
||||
|
||||
// Tracer (behavioral code, not RTL)
|
||||
${CVA6_REPO_DIR}/common/local/util/instr_tracer_if.sv
|
||||
${CVA6_REPO_DIR}/common/local/util/instr_tracer.sv
|
||||
${CVA6_REPO_DIR}/common/local/util/tc_sram_wrapper.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/tech_cells_generic/src/rtl/tc_sram.sv
|
||||
|
|
|
@ -90,6 +90,7 @@ module acc_dispatcher
|
|||
input dcache_req_i_t [2:0] dcache_req_ports_i,
|
||||
// Interface with the controller
|
||||
output logic ctrl_halt_o,
|
||||
input logic [11:0] csr_addr_i,
|
||||
input logic flush_unissued_instr_i,
|
||||
input logic flush_ex_i,
|
||||
output logic flush_pipeline_o,
|
||||
|
@ -165,7 +166,7 @@ module acc_dispatcher
|
|||
|
||||
assign acc_data = acc_valid_ex_o ? fu_data_i : '0;
|
||||
|
||||
fifo_v3 #(
|
||||
cva6_fifo_v3 #(
|
||||
.DEPTH (InstructionQueueDepth),
|
||||
.FALL_THROUGH(1'b1),
|
||||
.dtype (fu_data_t),
|
||||
|
|
|
@ -62,7 +62,7 @@ module amo_buffer #(
|
|||
// e.g.: it is not speculative anymore
|
||||
assign flush_amo_buffer = flush_i & !amo_valid_commit_i;
|
||||
|
||||
fifo_v3 #(
|
||||
cva6_fifo_v3 #(
|
||||
.DEPTH (1),
|
||||
.dtype (amo_op_t),
|
||||
.FPGA_EN(CVA6Cfg.FpgaEn)
|
||||
|
|
|
@ -433,6 +433,9 @@ module cache_ctrl
|
|||
state_d = IDLE;
|
||||
end
|
||||
end
|
||||
|
||||
default:;
|
||||
|
||||
endcase
|
||||
|
||||
if (req_port_i.kill_req) begin
|
||||
|
|
|
@ -160,6 +160,10 @@ module miss_handler
|
|||
ariane_pkg::amo_t amo_op;
|
||||
logic [ 63:0] amo_operand_b;
|
||||
|
||||
// 32b request
|
||||
logic [31:0] halfword;
|
||||
logic [$clog2(CVA6Cfg.DCACHE_LINE_WIDTH)-1:0] cl_offset;
|
||||
|
||||
// ------------------------------
|
||||
// Cache Management
|
||||
// ------------------------------
|
||||
|
@ -221,6 +225,9 @@ module miss_handler
|
|||
amo_resp_o.result = '0;
|
||||
amo_operand_b = '0;
|
||||
|
||||
halfword = '0;
|
||||
cl_offset = '0;
|
||||
|
||||
case (state_q)
|
||||
|
||||
IDLE: begin
|
||||
|
@ -303,7 +310,6 @@ module miss_handler
|
|||
// ~> replace the cacheline
|
||||
SAVE_CACHELINE: begin
|
||||
// calculate cacheline offset
|
||||
automatic logic [$clog2(CVA6Cfg.DCACHE_LINE_WIDTH)-1:0] cl_offset;
|
||||
cl_offset = mshr_q.addr[CVA6Cfg.DCACHE_OFFSET_WIDTH-1:3] << 6;
|
||||
// we've got a valid response from refill unit
|
||||
if (valid_miss_fsm) begin
|
||||
|
@ -474,8 +480,6 @@ module miss_handler
|
|||
amo_resp_o.ack = 1'b1;
|
||||
// Request is assumed to be still valid (ack not granted yet)
|
||||
if (amo_req_i.size == 2'b10) begin
|
||||
// 32b request
|
||||
logic [31:0] halfword;
|
||||
if (amo_req_i.operand_a[2:0] == '0) begin
|
||||
// 64b aligned -> activate lower 4 byte lanes
|
||||
halfword = amo_bypass_rsp.rdata[31:0];
|
||||
|
@ -491,6 +495,8 @@ module miss_handler
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
default:;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
|
|
@ -179,7 +179,7 @@ module std_cache_subsystem
|
|||
end
|
||||
|
||||
// W Channel
|
||||
fifo_v3 #(
|
||||
cva6_fifo_v3 #(
|
||||
.DATA_WIDTH (2),
|
||||
// we can have a maximum of 4 oustanding transactions as each port is blocking
|
||||
.DEPTH (4),
|
||||
|
|
|
@ -310,7 +310,7 @@ module wt_axi_adapter
|
|||
end
|
||||
end
|
||||
|
||||
fifo_v3 #(
|
||||
cva6_fifo_v3 #(
|
||||
.dtype (icache_req_t),
|
||||
.DEPTH (ReqFifoDepth),
|
||||
.FPGA_EN(CVA6Cfg.FpgaEn)
|
||||
|
@ -328,7 +328,7 @@ module wt_axi_adapter
|
|||
.pop_i (arb_ack[0])
|
||||
);
|
||||
|
||||
fifo_v3 #(
|
||||
cva6_fifo_v3 #(
|
||||
.dtype (dcache_req_t),
|
||||
.DEPTH (ReqFifoDepth),
|
||||
.FPGA_EN(CVA6Cfg.FpgaEn)
|
||||
|
@ -353,7 +353,7 @@ module wt_axi_adapter
|
|||
logic icache_rtrn_rd_en, dcache_rtrn_rd_en;
|
||||
logic icache_rtrn_vld_d, icache_rtrn_vld_q, dcache_rtrn_vld_d, dcache_rtrn_vld_q;
|
||||
|
||||
fifo_v3 #(
|
||||
cva6_fifo_v3 #(
|
||||
.DATA_WIDTH(CVA6Cfg.MEM_TID_WIDTH),
|
||||
.DEPTH (MetaFifoDepth),
|
||||
.FPGA_EN (CVA6Cfg.FpgaEn)
|
||||
|
@ -371,7 +371,7 @@ module wt_axi_adapter
|
|||
.pop_i (icache_rtrn_vld_d)
|
||||
);
|
||||
|
||||
fifo_v3 #(
|
||||
cva6_fifo_v3 #(
|
||||
.DATA_WIDTH(CVA6Cfg.MEM_TID_WIDTH),
|
||||
.DEPTH (MetaFifoDepth),
|
||||
.FPGA_EN (CVA6Cfg.FpgaEn)
|
||||
|
@ -389,7 +389,7 @@ module wt_axi_adapter
|
|||
.pop_i (dcache_rd_pop)
|
||||
);
|
||||
|
||||
fifo_v3 #(
|
||||
cva6_fifo_v3 #(
|
||||
.DATA_WIDTH(CVA6Cfg.MEM_TID_WIDTH),
|
||||
.DEPTH (MetaFifoDepth),
|
||||
.FPGA_EN (CVA6Cfg.FpgaEn)
|
||||
|
@ -419,7 +419,7 @@ module wt_axi_adapter
|
|||
assign axi_wr_rdy = ~b_full;
|
||||
assign b_push = axi_wr_valid & axi_wr_rdy;
|
||||
|
||||
fifo_v3 #(
|
||||
cva6_fifo_v3 #(
|
||||
.DATA_WIDTH (CVA6Cfg.AxiIdWidth + 1),
|
||||
.DEPTH (MetaFifoDepth),
|
||||
.FALL_THROUGH(1'b1),
|
||||
|
|
|
@ -299,7 +299,7 @@ module wt_dcache_wbuffer
|
|||
///////////////////////////////////////////////////////
|
||||
|
||||
// TODO: todo: make this fall through if timing permits it
|
||||
fifo_v3 #(
|
||||
cva6_fifo_v3 #(
|
||||
.FALL_THROUGH(1'b0),
|
||||
.DATA_WIDTH ($clog2(CVA6Cfg.DCACHE_MAX_TX)),
|
||||
.DEPTH (CVA6Cfg.DCACHE_MAX_TX),
|
||||
|
|
74
core/cva6.sv
74
core/cva6.sv
|
@ -1407,6 +1407,7 @@ module cva6
|
|||
.acc_no_st_pending_i (no_st_pending_commit),
|
||||
.dcache_req_ports_i (dcache_req_ports_ex_cache),
|
||||
.ctrl_halt_o (halt_acc_ctrl),
|
||||
.csr_addr_i (csr_addr_ex_csr),
|
||||
.acc_dcache_req_ports_o(dcache_req_ports_acc_cache),
|
||||
.acc_dcache_req_ports_i(dcache_req_ports_cache_acc),
|
||||
.inval_ready_i (inval_ready),
|
||||
|
@ -1503,59 +1504,40 @@ module cva6
|
|||
`endif // PITON_ARIANE
|
||||
|
||||
`ifndef VERILATOR
|
||||
instr_tracer_if #(
|
||||
.CVA6Cfg(CVA6Cfg),
|
||||
.bp_resolve_t(bp_resolve_t),
|
||||
.exception_t(exception_t),
|
||||
.scoreboard_entry_t(scoreboard_entry_t)
|
||||
) tracer_if (
|
||||
clk_i
|
||||
);
|
||||
// assign instruction tracer interface
|
||||
// control signals
|
||||
assign tracer_if.rstn = rst_ni;
|
||||
assign tracer_if.flush_unissued = flush_unissued_instr_ctrl_id;
|
||||
assign tracer_if.flush = flush_ctrl_ex;
|
||||
// fetch
|
||||
assign tracer_if.instruction = id_stage_i.fetch_entry_i.instruction;
|
||||
assign tracer_if.fetch_valid = id_stage_i.fetch_entry_valid_i;
|
||||
assign tracer_if.fetch_ack = id_stage_i.fetch_entry_ready_o;
|
||||
// Issue
|
||||
assign tracer_if.issue_ack = issue_stage_i.i_scoreboard.issue_ack_i;
|
||||
assign tracer_if.issue_sbe = issue_stage_i.i_scoreboard.issue_instr_o;
|
||||
// write-back
|
||||
assign tracer_if.waddr = waddr_commit_id;
|
||||
assign tracer_if.wdata = wdata_commit_id;
|
||||
assign tracer_if.we_gpr = we_gpr_commit_id;
|
||||
assign tracer_if.we_fpr = we_fpr_commit_id;
|
||||
// commit
|
||||
assign tracer_if.commit_instr = commit_instr_id_commit;
|
||||
assign tracer_if.commit_ack = commit_ack;
|
||||
// branch predict
|
||||
assign tracer_if.resolve_branch = resolved_branch;
|
||||
// address translation
|
||||
// stores
|
||||
assign tracer_if.st_valid = ex_stage_i.lsu_i.i_store_unit.store_buffer_i.valid_i;
|
||||
assign tracer_if.st_paddr = ex_stage_i.lsu_i.i_store_unit.store_buffer_i.paddr_i;
|
||||
// loads
|
||||
assign tracer_if.ld_valid = ex_stage_i.lsu_i.i_load_unit.req_port_o.tag_valid;
|
||||
assign tracer_if.ld_kill = ex_stage_i.lsu_i.i_load_unit.req_port_o.kill_req;
|
||||
assign tracer_if.ld_paddr = ex_stage_i.lsu_i.i_load_unit.paddr_i;
|
||||
// exceptions
|
||||
assign tracer_if.exception = commit_stage_i.exception_o;
|
||||
// assign current privilege level
|
||||
assign tracer_if.priv_lvl = priv_lvl;
|
||||
assign tracer_if.debug_mode = debug_mode;
|
||||
|
||||
instr_tracer #(
|
||||
.CVA6Cfg(CVA6Cfg),
|
||||
.bp_resolve_t(bp_resolve_t),
|
||||
.scoreboard_entry_t(scoreboard_entry_t),
|
||||
.interrupts_t(interrupts_t),
|
||||
.exception_t(exception_t),
|
||||
.INTERRUPTS(INTERRUPTS)
|
||||
) instr_tracer_i (
|
||||
.tracer_if(tracer_if),
|
||||
.hart_id_i
|
||||
// .tracer_if(tracer_if),
|
||||
.pck (clk_i),
|
||||
.rstn (rst_ni),
|
||||
.flush_unissued (flush_unissued_instr_ctrl_id),
|
||||
.flush_all (flush_ctrl_ex),
|
||||
.instruction (id_stage_i.fetch_entry_i.instruction),
|
||||
.fetch_valid (id_stage_i.fetch_entry_valid_i),
|
||||
.fetch_ack (id_stage_i.fetch_entry_ready_o),
|
||||
.issue_ack (issue_stage_i.i_scoreboard.issue_ack_i),
|
||||
.issue_sbe (issue_stage_i.i_scoreboard.issue_instr_o),
|
||||
.waddr (waddr_commit_id),
|
||||
.wdata (wdata_commit_id),
|
||||
.we_gpr (we_gpr_commit_id),
|
||||
.we_fpr (we_fpr_commit_id),
|
||||
.commit_instr (commit_instr_id_commit),
|
||||
.commit_ack (commit_ack),
|
||||
.st_valid (ex_stage_i.lsu_i.i_store_unit.store_buffer_i.valid_i),
|
||||
.st_paddr (ex_stage_i.lsu_i.i_store_unit.store_buffer_i.paddr_i),
|
||||
.ld_valid (ex_stage_i.lsu_i.i_load_unit.req_port_o.tag_valid),
|
||||
.ld_kill (ex_stage_i.lsu_i.i_load_unit.req_port_o.kill_req),
|
||||
.ld_paddr (ex_stage_i.lsu_i.i_load_unit.paddr_i),
|
||||
.resolve_branch (resolved_branch),
|
||||
.commit_exception (commit_stage_i.exception_o),
|
||||
.priv_lvl (priv_lvl),
|
||||
.debug_mode (debug_mode),
|
||||
.hart_id_i (hart_id_i)
|
||||
);
|
||||
|
||||
// mock tracer for Verilator, to be used with spike-dasm
|
||||
|
|
192
core/cva6_fifo_v3.sv
Normal file
192
core/cva6_fifo_v3.sv
Normal file
|
@ -0,0 +1,192 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// 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.
|
||||
|
||||
// Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
|
||||
|
||||
module cva6_fifo_v3 #(
|
||||
parameter bit FALL_THROUGH = 1'b0, // fifo is in fall-through mode
|
||||
parameter int unsigned DATA_WIDTH = 32, // default data width if the fifo is of type logic
|
||||
parameter int unsigned DEPTH = 8, // depth can be arbitrary from 0 to 2**32
|
||||
parameter type dtype = logic [DATA_WIDTH-1:0],
|
||||
parameter bit FPGA_EN = 1'b0,
|
||||
// DO NOT OVERWRITE THIS PARAMETER
|
||||
parameter int unsigned ADDR_DEPTH = (DEPTH > 1) ? $clog2(DEPTH) : 1
|
||||
)(
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
input logic flush_i, // flush the queue
|
||||
input logic testmode_i, // test_mode to bypass clock gating
|
||||
// status flags
|
||||
output logic full_o, // queue is full
|
||||
output logic empty_o, // queue is empty
|
||||
output logic [ADDR_DEPTH-1:0] usage_o, // fill pointer
|
||||
// as long as the queue is not full we can push new data
|
||||
input dtype data_i, // data to push into the queue
|
||||
input logic push_i, // data is valid and can be pushed to the queue
|
||||
// as long as the queue is not empty we can pop new elements
|
||||
output dtype data_o, // output data
|
||||
input logic pop_i // pop head from queue
|
||||
);
|
||||
// local parameter
|
||||
// FIFO depth - handle the case of pass-through, synthesizer will do constant propagation
|
||||
localparam int unsigned FifoDepth = (DEPTH > 0) ? DEPTH : 1;
|
||||
// clock gating control
|
||||
logic gate_clock;
|
||||
// pointer to the read and write section of the queue
|
||||
logic [ADDR_DEPTH - 1:0] read_pointer_n, read_pointer_q, write_pointer_n, write_pointer_q;
|
||||
// keep a counter to keep track of the current queue status
|
||||
// this integer will be truncated by the synthesis tool
|
||||
logic [ADDR_DEPTH:0] status_cnt_n, status_cnt_q;
|
||||
// actual memory
|
||||
dtype [FifoDepth - 1:0] mem_n, mem_q;
|
||||
|
||||
// fifo ram signals for fpga target
|
||||
logic fifo_ram_we;
|
||||
logic [ADDR_DEPTH-1:0] fifo_ram_read_address;
|
||||
logic [ADDR_DEPTH-1:0] fifo_ram_write_address;
|
||||
logic [$bits(dtype)-1:0] fifo_ram_wdata;
|
||||
logic [$bits(dtype)-1:0] fifo_ram_rdata;
|
||||
|
||||
assign usage_o = status_cnt_q[ADDR_DEPTH-1:0];
|
||||
|
||||
if (DEPTH == 0) begin : gen_pass_through
|
||||
assign empty_o = ~push_i;
|
||||
assign full_o = ~pop_i;
|
||||
end else begin : gen_fifo
|
||||
assign full_o = (status_cnt_q == FifoDepth[ADDR_DEPTH:0]);
|
||||
assign empty_o = (status_cnt_q == 0) & ~(FALL_THROUGH & push_i);
|
||||
end
|
||||
// status flags
|
||||
|
||||
// read and write queue logic
|
||||
always_comb begin : read_write_comb
|
||||
// default assignment
|
||||
read_pointer_n = read_pointer_q;
|
||||
write_pointer_n = write_pointer_q;
|
||||
status_cnt_n = status_cnt_q;
|
||||
if (FPGA_EN) begin
|
||||
fifo_ram_we = '0;
|
||||
fifo_ram_read_address = read_pointer_q;
|
||||
fifo_ram_write_address = '0;
|
||||
fifo_ram_wdata = '0;
|
||||
data_o = (DEPTH == 0) ? data_i : fifo_ram_rdata;
|
||||
end else begin
|
||||
data_o = (DEPTH == 0) ? data_i : mem_q[read_pointer_q];
|
||||
mem_n = mem_q;
|
||||
gate_clock = 1'b1;
|
||||
end
|
||||
|
||||
// push a new element to the queue
|
||||
if (push_i && ~full_o) begin
|
||||
if (FPGA_EN) begin
|
||||
fifo_ram_we = 1'b1;
|
||||
fifo_ram_write_address = write_pointer_q;
|
||||
fifo_ram_wdata = data_i;
|
||||
end else begin
|
||||
// push the data onto the queue
|
||||
mem_n[write_pointer_q] = data_i;
|
||||
// un-gate the clock, we want to write something
|
||||
gate_clock = 1'b0;
|
||||
end
|
||||
|
||||
// increment the write counter
|
||||
if (write_pointer_q == FifoDepth[ADDR_DEPTH-1:0] - 1)
|
||||
write_pointer_n = '0;
|
||||
else
|
||||
write_pointer_n = write_pointer_q + 1;
|
||||
// increment the overall counter
|
||||
status_cnt_n = status_cnt_q + 1;
|
||||
end
|
||||
|
||||
if (pop_i && ~empty_o) begin
|
||||
// read from the queue is a default assignment
|
||||
// but increment the read pointer...
|
||||
if (read_pointer_n == FifoDepth[ADDR_DEPTH-1:0] - 1)
|
||||
read_pointer_n = '0;
|
||||
else
|
||||
read_pointer_n = read_pointer_q + 1;
|
||||
// ... and decrement the overall count
|
||||
status_cnt_n = status_cnt_q - 1;
|
||||
end
|
||||
|
||||
// keep the count pointer stable if we push and pop at the same time
|
||||
if (push_i && pop_i && ~full_o && ~empty_o)
|
||||
status_cnt_n = status_cnt_q;
|
||||
|
||||
// FIFO is in pass through mode -> do not change the pointers
|
||||
if (FALL_THROUGH && (status_cnt_q == 0) && push_i) begin
|
||||
data_o = data_i;
|
||||
if (pop_i) begin
|
||||
status_cnt_n = status_cnt_q;
|
||||
read_pointer_n = read_pointer_q;
|
||||
write_pointer_n = write_pointer_q;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// sequential process
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if(~rst_ni) begin
|
||||
read_pointer_q <= '0;
|
||||
write_pointer_q <= '0;
|
||||
status_cnt_q <= '0;
|
||||
end else begin
|
||||
if (flush_i) begin
|
||||
read_pointer_q <= '0;
|
||||
write_pointer_q <= '0;
|
||||
status_cnt_q <= '0;
|
||||
end else begin
|
||||
read_pointer_q <= read_pointer_n;
|
||||
write_pointer_q <= write_pointer_n;
|
||||
status_cnt_q <= status_cnt_n;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (FPGA_EN) begin : gen_fpga_queue
|
||||
AsyncDpRam #(
|
||||
.ADDR_WIDTH (ADDR_DEPTH),
|
||||
.DATA_DEPTH (DEPTH),
|
||||
.DATA_WIDTH ($bits(dtype))
|
||||
) fifo_ram (
|
||||
.Clk_CI ( clk_i ),
|
||||
.WrEn_SI ( fifo_ram_we ),
|
||||
.RdAddr_DI ( fifo_ram_read_address ),
|
||||
.WrAddr_DI ( fifo_ram_write_address ),
|
||||
.WrData_DI ( fifo_ram_wdata ),
|
||||
.RdData_DO ( fifo_ram_rdata )
|
||||
);
|
||||
end else begin : gen_asic_queue
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if(~rst_ni) begin
|
||||
mem_q <= '0;
|
||||
end else if (!gate_clock) begin
|
||||
mem_q <= mem_n;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// pragma translate_off
|
||||
`ifndef VERILATOR
|
||||
initial begin
|
||||
assert (DEPTH > 0) else $error("DEPTH must be greater than 0.");
|
||||
end
|
||||
|
||||
full_write : assert property(
|
||||
@(posedge clk_i) disable iff (~rst_ni) (full_o |-> ~push_i))
|
||||
else $fatal (1, "Trying to push new data although the FIFO is full.");
|
||||
|
||||
empty_read : assert property(
|
||||
@(posedge clk_i) disable iff (~rst_ni) (empty_o |-> ~pop_i))
|
||||
else $fatal (1, "Trying to pop data although the FIFO is empty.");
|
||||
`endif
|
||||
// pragma translate_on
|
||||
|
||||
endmodule // fifo_v3
|
|
@ -110,7 +110,7 @@ module cvxif_example_coprocessor
|
|||
end
|
||||
end
|
||||
|
||||
fifo_v3 #(
|
||||
cva6_fifo_v3 #(
|
||||
.FALL_THROUGH(1), //data_o ready and pop in the same cycle
|
||||
.DATA_WIDTH (64),
|
||||
.DEPTH (8),
|
||||
|
|
|
@ -411,7 +411,7 @@ ariane_pkg::FETCH_FIFO_DEPTH
|
|||
for (genvar i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin : gen_instr_fifo
|
||||
// Make sure we don't save any instructions if we couldn't save the address
|
||||
assign push_instr_fifo[i] = push_instr[i] & ~address_overflow;
|
||||
fifo_v3 #(
|
||||
cva6_fifo_v3 #(
|
||||
.DEPTH (ariane_pkg::FETCH_FIFO_DEPTH),
|
||||
.dtype (instr_data_t),
|
||||
.FPGA_EN(CVA6Cfg.FpgaEn)
|
||||
|
@ -439,7 +439,7 @@ ariane_pkg::FETCH_FIFO_DEPTH
|
|||
end
|
||||
end
|
||||
|
||||
fifo_v3 #(
|
||||
cva6_fifo_v3 #(
|
||||
.DEPTH (ariane_pkg::FETCH_FIFO_DEPTH), // TODO(zarubaf): Fork out to separate param
|
||||
.DATA_WIDTH(CVA6Cfg.VLEN),
|
||||
.FPGA_EN (CVA6Cfg.FpgaEn)
|
||||
|
|
|
@ -196,10 +196,12 @@ module id_stage #(
|
|||
// ------------------
|
||||
// Pipeline Register
|
||||
// ------------------
|
||||
assign issue_entry_o = issue_q.sbe;
|
||||
assign issue_entry_valid_o = issue_q.valid;
|
||||
assign is_ctrl_flow_o = issue_q.is_ctrl_flow;
|
||||
assign orig_instr_o = issue_q.orig_instr;
|
||||
always_comb begin
|
||||
issue_entry_o = issue_q.sbe;
|
||||
issue_entry_valid_o = issue_q.valid;
|
||||
is_ctrl_flow_o = issue_q.is_ctrl_flow;
|
||||
orig_instr_o = issue_q.orig_instr;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
issue_n = issue_q;
|
||||
|
|
|
@ -102,7 +102,7 @@ package build_config_pkg;
|
|||
cfg.CachedRegionLength = CVA6Cfg.CachedRegionLength;
|
||||
cfg.MaxOutstandingStores = CVA6Cfg.MaxOutstandingStores;
|
||||
cfg.DebugEn = CVA6Cfg.DebugEn;
|
||||
cfg.NonIdemPotenceEn = CVA6Cfg.NrNonIdempotentRules && CVA6Cfg.NonIdempotentLength;
|
||||
cfg.NonIdemPotenceEn = (CVA6Cfg.NrNonIdempotentRules > 0) && (CVA6Cfg.NonIdempotentLength > 0);
|
||||
cfg.AxiBurstWriteEn = CVA6Cfg.AxiBurstWriteEn;
|
||||
|
||||
cfg.ICACHE_SET_ASSOC = CVA6Cfg.IcacheSetAssoc;
|
||||
|
|
|
@ -270,7 +270,7 @@ package config_pkg;
|
|||
int unsigned DATA_USER_EN;
|
||||
int unsigned FETCH_USER_WIDTH;
|
||||
int unsigned FETCH_USER_EN;
|
||||
int unsigned AXI_USER_EN;
|
||||
bit AXI_USER_EN;
|
||||
|
||||
int unsigned FETCH_WIDTH;
|
||||
int unsigned INSTR_PER_FETCH;
|
||||
|
@ -288,7 +288,7 @@ package config_pkg;
|
|||
|
||||
/// Empty configuration to sanity check proper parameter passing. Whenever
|
||||
/// you develop a module that resides within the core, assign this constant.
|
||||
localparam cva6_cfg_t cva6_cfg_empty = '0;
|
||||
localparam cva6_cfg_t cva6_cfg_empty = cva6_cfg_t'(0);
|
||||
|
||||
/// Utility function being called to check parameters. Not all values make
|
||||
/// sense for all parameters, here is the place to sanity check them.
|
||||
|
|
70
vendor/pulp-platform/common_cells/src/fifo_v3.sv
vendored
70
vendor/pulp-platform/common_cells/src/fifo_v3.sv
vendored
|
@ -15,7 +15,6 @@ module fifo_v3 #(
|
|||
parameter int unsigned DATA_WIDTH = 32, // default data width if the fifo is of type logic
|
||||
parameter int unsigned DEPTH = 8, // depth can be arbitrary from 0 to 2**32
|
||||
parameter type dtype = logic [DATA_WIDTH-1:0],
|
||||
parameter bit FPGA_EN = 1'b0,
|
||||
// DO NOT OVERWRITE THIS PARAMETER
|
||||
parameter int unsigned ADDR_DEPTH = (DEPTH > 1) ? $clog2(DEPTH) : 1
|
||||
)(
|
||||
|
@ -47,13 +46,6 @@ module fifo_v3 #(
|
|||
// actual memory
|
||||
dtype [FifoDepth - 1:0] mem_n, mem_q;
|
||||
|
||||
// fifo ram signals for fpga target
|
||||
logic fifo_ram_we;
|
||||
logic [ADDR_DEPTH-1:0] fifo_ram_read_address;
|
||||
logic [ADDR_DEPTH-1:0] fifo_ram_write_address;
|
||||
logic [$bits(dtype)-1:0] fifo_ram_wdata;
|
||||
logic [$bits(dtype)-1:0] fifo_ram_rdata;
|
||||
|
||||
assign usage_o = status_cnt_q[ADDR_DEPTH-1:0];
|
||||
|
||||
if (DEPTH == 0) begin : gen_pass_through
|
||||
|
@ -71,32 +63,18 @@ module fifo_v3 #(
|
|||
read_pointer_n = read_pointer_q;
|
||||
write_pointer_n = write_pointer_q;
|
||||
status_cnt_n = status_cnt_q;
|
||||
if (FPGA_EN) begin
|
||||
fifo_ram_we = '0;
|
||||
fifo_ram_read_address = read_pointer_q;
|
||||
fifo_ram_write_address = '0;
|
||||
fifo_ram_wdata = '0;
|
||||
data_o = (DEPTH == 0) ? data_i : fifo_ram_rdata;
|
||||
end else begin
|
||||
data_o = (DEPTH == 0) ? data_i : mem_q[read_pointer_q];
|
||||
mem_n = mem_q;
|
||||
gate_clock = 1'b1;
|
||||
end
|
||||
data_o = (DEPTH == 0) ? data_i : mem_q[read_pointer_q];
|
||||
mem_n = mem_q;
|
||||
gate_clock = 1'b1;
|
||||
|
||||
// push a new element to the queue
|
||||
if (push_i && ~full_o) begin
|
||||
if (FPGA_EN) begin
|
||||
fifo_ram_we = 1'b1;
|
||||
fifo_ram_write_address = write_pointer_q;
|
||||
fifo_ram_wdata = data_i;
|
||||
end else begin
|
||||
// push the data onto the queue
|
||||
mem_n[write_pointer_q] = data_i;
|
||||
// un-gate the clock, we want to write something
|
||||
gate_clock = 1'b0;
|
||||
end
|
||||
|
||||
// push the data onto the queue
|
||||
mem_n[write_pointer_q] = data_i;
|
||||
// un-gate the clock, we want to write something
|
||||
gate_clock = 1'b0;
|
||||
// increment the write counter
|
||||
// this is dead code when DEPTH is a power of two
|
||||
if (write_pointer_q == FifoDepth[ADDR_DEPTH-1:0] - 1)
|
||||
write_pointer_n = '0;
|
||||
else
|
||||
|
@ -108,6 +86,7 @@ module fifo_v3 #(
|
|||
if (pop_i && ~empty_o) begin
|
||||
// read from the queue is a default assignment
|
||||
// but increment the read pointer...
|
||||
// this is dead code when DEPTH is a power of two
|
||||
if (read_pointer_n == FifoDepth[ADDR_DEPTH-1:0] - 1)
|
||||
read_pointer_n = '0;
|
||||
else
|
||||
|
@ -150,31 +129,16 @@ module fifo_v3 #(
|
|||
end
|
||||
end
|
||||
|
||||
if (FPGA_EN) begin : gen_fpga_queue
|
||||
AsyncDpRam #(
|
||||
.ADDR_WIDTH (ADDR_DEPTH),
|
||||
.DATA_DEPTH (DEPTH),
|
||||
.DATA_WIDTH ($bits(dtype))
|
||||
) fifo_ram (
|
||||
.Clk_CI ( clk_i ),
|
||||
.WrEn_SI ( fifo_ram_we ),
|
||||
.RdAddr_DI ( fifo_ram_read_address ),
|
||||
.WrAddr_DI ( fifo_ram_write_address ),
|
||||
.WrData_DI ( fifo_ram_wdata ),
|
||||
.RdData_DO ( fifo_ram_rdata )
|
||||
);
|
||||
end else begin : gen_asic_queue
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if(~rst_ni) begin
|
||||
mem_q <= '0;
|
||||
end else if (!gate_clock) begin
|
||||
mem_q <= mem_n;
|
||||
end
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if(~rst_ni) begin
|
||||
mem_q <= '0;
|
||||
end else if (!gate_clock) begin
|
||||
mem_q <= mem_n;
|
||||
end
|
||||
end
|
||||
|
||||
// pragma translate_off
|
||||
`ifndef VERILATOR
|
||||
`ifndef SYNTHESIS
|
||||
`ifndef COMMON_CELLS_ASSERTS_OFF
|
||||
initial begin
|
||||
assert (DEPTH > 0) else $error("DEPTH must be greater than 0.");
|
||||
end
|
||||
|
@ -187,6 +151,6 @@ module fifo_v3 #(
|
|||
@(posedge clk_i) disable iff (~rst_ni) (empty_o |-> ~pop_i))
|
||||
else $fatal (1, "Trying to pop data although the FIFO is empty.");
|
||||
`endif
|
||||
// pragma translate_on
|
||||
`endif
|
||||
|
||||
endmodule // fifo_v3
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue