abstractaccelerator/Flow/design/el2_dma_ctrl.sv

745 lines
28 KiB
Systemverilog
Raw Normal View History

2022-05-10 21:06:26 +08:00
// SPDX-License-Identifier: Apache-2.0
// Copyright 2020 Western Digital Corporation or its affiliates.
//
// 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.
//********************************************************************************
// $Id$
//
// Function: Top level SWERV core file
// Comments:
//
//********************************************************************************
module el2_dma_ctrl #(
2022-05-23 22:16:04 +08:00
`include "el2_param.vh"
) (
input logic clk,
input logic free_clk,
input logic rst_l,
input logic dma_bus_clk_en, // slave bus clock enable
input logic clk_override,
input logic scan_mode,
// Debug signals
input logic [31:0] dbg_cmd_addr,
input logic [31:0] dbg_cmd_wrdata,
input logic dbg_cmd_valid,
input logic dbg_cmd_write, // 1: write command, 0: read_command
input logic [ 1:0] dbg_cmd_type, // 0:gpr 1:csr 2: memory
input logic [ 1:0] dbg_cmd_size, // size of the abstract mem access debug command
input logic dbg_dma_bubble, // Debug needs a bubble to send a valid
output logic dma_dbg_ready, // DMA is ready to accept debug request
output logic dma_dbg_cmd_done,
output logic dma_dbg_cmd_fail,
output logic [31:0] dma_dbg_rddata,
// Core side signals
output logic dma_dccm_req, // DMA dccm request (only one of dccm/iccm will be set)
output logic dma_iccm_req, // DMA iccm request
output logic [ 2:0] dma_mem_tag, // DMA Buffer entry number
output logic [31:0] dma_mem_addr, // DMA request address
output logic [ 2:0] dma_mem_sz, // DMA request size
output logic dma_mem_write, // DMA write to dccm/iccm
output logic [63:0] dma_mem_wdata, // DMA write data
input logic dccm_dma_rvalid, // dccm data valid for DMA read
input logic dccm_dma_ecc_error, // ECC error on DMA read
input logic [ 2:0] dccm_dma_rtag, // Tag of the DMA req
input logic [63:0] dccm_dma_rdata, // dccm data for DMA read
input logic iccm_dma_rvalid, // iccm data valid for DMA read
input logic iccm_dma_ecc_error, // ECC error on DMA read
input logic [ 2:0] iccm_dma_rtag, // Tag of the DMA req
input logic [63:0] iccm_dma_rdata, // iccm data for DMA read
output logic dma_active, // DMA is busy
output logic dma_dccm_stall_any, // stall dccm pipe (bubble) so that DMA can proceed
output logic dma_iccm_stall_any, // stall iccm pipe (bubble) so that DMA can proceed
input logic dccm_ready, // dccm ready to accept DMA request
input logic iccm_ready, // iccm ready to accept DMA request
input logic [2:0] dec_tlu_dma_qos_prty, // DMA QoS priority coming from MFDC [18:15]
// PMU signals
output logic dma_pmu_dccm_read,
output logic dma_pmu_dccm_write,
output logic dma_pmu_any_read,
output logic dma_pmu_any_write,
// AXI Write Channels
input logic dma_axi_awvalid,
output logic dma_axi_awready,
input logic [pt.DMA_BUS_TAG-1:0] dma_axi_awid,
input logic [ 31:0] dma_axi_awaddr,
input logic [ 2:0] dma_axi_awsize,
input logic dma_axi_wvalid,
output logic dma_axi_wready,
input logic [63:0] dma_axi_wdata,
input logic [ 7:0] dma_axi_wstrb,
output logic dma_axi_bvalid,
input logic dma_axi_bready,
output logic [ 1:0] dma_axi_bresp,
output logic [pt.DMA_BUS_TAG-1:0] dma_axi_bid,
// AXI Read Channels
input logic dma_axi_arvalid,
output logic dma_axi_arready,
input logic [pt.DMA_BUS_TAG-1:0] dma_axi_arid,
input logic [ 31:0] dma_axi_araddr,
input logic [ 2:0] dma_axi_arsize,
output logic dma_axi_rvalid,
input logic dma_axi_rready,
output logic [pt.DMA_BUS_TAG-1:0] dma_axi_rid,
output logic [ 63:0] dma_axi_rdata,
output logic [ 1:0] dma_axi_rresp,
output logic dma_axi_rlast
2022-05-10 21:06:26 +08:00
);
2022-05-23 22:16:04 +08:00
localparam DEPTH = pt.DMA_BUF_DEPTH;
localparam DEPTH_PTR = $clog2(DEPTH);
localparam NACK_COUNT = 7;
logic [DEPTH-1:0] fifo_valid;
logic [DEPTH-1:0][1:0] fifo_error;
logic [DEPTH-1:0] fifo_error_bus;
logic [DEPTH-1:0] fifo_rpend;
logic [DEPTH-1:0] fifo_done; // DMA trxn is done in core
logic [DEPTH-1:0] fifo_done_bus; // DMA trxn is done in core but synced to bus clock
logic [DEPTH-1:0][31:0] fifo_addr;
logic [DEPTH-1:0][2:0] fifo_sz;
logic [DEPTH-1:0][7:0] fifo_byteen;
logic [DEPTH-1:0] fifo_write;
logic [DEPTH-1:0] fifo_posted_write;
logic [DEPTH-1:0] fifo_dbg;
logic [DEPTH-1:0][63:0] fifo_data;
logic [DEPTH-1:0][pt.DMA_BUS_TAG-1:0] fifo_tag;
logic [DEPTH-1:0][pt.DMA_BUS_ID-1:0] fifo_mid;
logic [DEPTH-1:0][pt.DMA_BUS_PRTY-1:0] fifo_prty;
logic [DEPTH-1:0] fifo_cmd_en;
logic [DEPTH-1:0] fifo_data_en;
logic [DEPTH-1:0] fifo_pend_en;
logic [DEPTH-1:0] fifo_done_en;
logic [DEPTH-1:0] fifo_done_bus_en;
logic [DEPTH-1:0] fifo_error_en;
logic [DEPTH-1:0] fifo_error_bus_en;
logic [DEPTH-1:0] fifo_reset;
logic [DEPTH-1:0][1:0] fifo_error_in;
logic [DEPTH-1:0][63:0] fifo_data_in;
logic fifo_write_in;
logic fifo_posted_write_in;
logic fifo_dbg_in;
logic [31:0] fifo_addr_in;
logic [2:0] fifo_sz_in;
logic [7:0] fifo_byteen_in;
logic [DEPTH_PTR-1:0] RspPtr, NxtRspPtr;
logic [DEPTH_PTR-1:0] WrPtr, NxtWrPtr;
logic [DEPTH_PTR-1:0] RdPtr, NxtRdPtr;
logic WrPtrEn, RdPtrEn, RspPtrEn;
logic [ 1:0] dma_dbg_sz;
logic [ 1:0] dma_dbg_addr;
logic [31:0] dma_dbg_mem_rddata;
logic [31:0] dma_dbg_mem_wrdata;
logic dma_dbg_cmd_error;
logic dma_dbg_cmd_done_q;
logic fifo_full, fifo_full_spec, fifo_empty;
logic dma_address_error, dma_alignment_error;
logic [ 3:0] num_fifo_vld;
logic dma_mem_req;
logic [31:0] dma_mem_addr_int;
logic [ 2:0] dma_mem_sz_int;
logic [ 7:0] dma_mem_byteen;
logic dma_mem_addr_in_dccm;
logic dma_mem_addr_in_iccm;
logic dma_mem_addr_in_pic;
logic dma_mem_addr_in_pic_region_nc;
logic dma_mem_addr_in_dccm_region_nc;
logic dma_mem_addr_in_iccm_region_nc;
logic [2:0] dma_nack_count, dma_nack_count_d, dma_nack_count_csr;
logic dma_buffer_c1_clken;
logic dma_free_clken;
logic dma_buffer_c1_clk;
logic dma_free_clk;
logic dma_bus_clk;
logic bus_rsp_valid, bus_rsp_sent;
logic bus_cmd_valid, bus_cmd_sent;
logic bus_cmd_write, bus_cmd_posted_write;
logic [ 7:0] bus_cmd_byteen;
logic [ 2:0] bus_cmd_sz;
logic [ 31:0] bus_cmd_addr;
logic [ 63:0] bus_cmd_wdata;
logic [ pt.DMA_BUS_TAG-1:0] bus_cmd_tag;
logic [ pt.DMA_BUS_ID-1:0] bus_cmd_mid;
logic [pt.DMA_BUS_PRTY-1:0] bus_cmd_prty;
logic bus_posted_write_done;
logic fifo_full_spec_bus;
logic dbg_dma_bubble_bus;
logic stall_dma_in;
logic dma_fifo_ready;
logic wrbuf_en, wrbuf_data_en;
logic wrbuf_cmd_sent, wrbuf_rst, wrbuf_data_rst;
logic wrbuf_vld, wrbuf_data_vld;
logic [pt.DMA_BUS_TAG-1:0] wrbuf_tag;
logic [ 2:0] wrbuf_sz;
logic [ 31:0] wrbuf_addr;
logic [ 63:0] wrbuf_data;
logic [ 7:0] wrbuf_byteen;
logic rdbuf_en;
logic rdbuf_cmd_sent, rdbuf_rst;
logic rdbuf_vld;
logic [pt.DMA_BUS_TAG-1:0] rdbuf_tag;
logic [ 2:0] rdbuf_sz;
logic [ 31:0] rdbuf_addr;
logic axi_mstr_prty_in, axi_mstr_prty_en;
logic axi_mstr_priority;
logic axi_mstr_sel;
logic axi_rsp_valid, axi_rsp_sent;
logic axi_rsp_write;
logic [pt.DMA_BUS_TAG-1:0] axi_rsp_tag;
logic [ 1:0] axi_rsp_error;
logic [ 63:0] axi_rsp_rdata;
//------------------------LOGIC STARTS HERE---------------------------------
// FIFO inputs
assign fifo_addr_in[31:0] = dbg_cmd_valid ? dbg_cmd_addr[31:0] : bus_cmd_addr[31:0];
assign fifo_byteen_in[7:0] = {8{~dbg_cmd_valid}} & bus_cmd_byteen[7:0]; // Byte enable is used only for bus requests
assign fifo_sz_in[2:0] = dbg_cmd_valid ? {1'b0, dbg_cmd_size[1:0]} : bus_cmd_sz[2:0];
assign fifo_write_in = dbg_cmd_valid ? dbg_cmd_write : bus_cmd_write;
assign fifo_posted_write_in = ~dbg_cmd_valid & bus_cmd_posted_write;
assign fifo_dbg_in = dbg_cmd_valid;
for (genvar i = 0; i < DEPTH; i++) begin : GenFifo
assign fifo_cmd_en[i] = ((bus_cmd_sent & dma_bus_clk_en) | (dbg_cmd_valid & dbg_cmd_type[1])) & (i == WrPtr[DEPTH_PTR-1:0]);
assign fifo_data_en[i] = (((bus_cmd_sent & fifo_write_in & dma_bus_clk_en) | (dbg_cmd_valid & dbg_cmd_type[1] & dbg_cmd_write)) & (i == WrPtr[DEPTH_PTR-1:0])) |
2022-05-10 21:06:26 +08:00
((dma_address_error | dma_alignment_error) & (i == RdPtr[DEPTH_PTR-1:0])) |
(dccm_dma_rvalid & (i == DEPTH_PTR'(dccm_dma_rtag[2:0]))) |
(iccm_dma_rvalid & (i == DEPTH_PTR'(iccm_dma_rtag[2:0])));
2022-05-23 22:16:04 +08:00
assign fifo_pend_en[i] = (dma_dccm_req | dma_iccm_req) & ~dma_mem_write & (i == RdPtr[DEPTH_PTR-1:0]);
assign fifo_error_en[i] = ((dma_address_error | dma_alignment_error | dma_dbg_cmd_error) & (i == RdPtr[DEPTH_PTR-1:0])) |
2022-05-10 21:06:26 +08:00
((dccm_dma_rvalid & dccm_dma_ecc_error) & (i == DEPTH_PTR'(dccm_dma_rtag[2:0]))) |
((iccm_dma_rvalid & iccm_dma_ecc_error) & (i == DEPTH_PTR'(iccm_dma_rtag[2:0])));
2022-05-23 22:16:04 +08:00
assign fifo_error_bus_en[i] = (((|fifo_error_in[i][1:0]) & fifo_error_en[i]) | (|fifo_error[i])) & dma_bus_clk_en;
assign fifo_done_en[i] = ((|fifo_error[i] | fifo_error_en[i] | ((dma_dccm_req | dma_iccm_req) & dma_mem_write)) & (i == RdPtr[DEPTH_PTR-1:0])) |
2022-05-10 21:06:26 +08:00
(dccm_dma_rvalid & (i == DEPTH_PTR'(dccm_dma_rtag[2:0]))) |
(iccm_dma_rvalid & (i == DEPTH_PTR'(iccm_dma_rtag[2:0])));
2022-05-23 22:16:04 +08:00
assign fifo_done_bus_en[i] = (fifo_done_en[i] | fifo_done[i]) & dma_bus_clk_en;
assign fifo_reset[i] = (((bus_rsp_sent | bus_posted_write_done) & dma_bus_clk_en) | dma_dbg_cmd_done) & (i == RspPtr[DEPTH_PTR-1:0]);
assign fifo_error_in[i] = (dccm_dma_rvalid & (i == DEPTH_PTR'(dccm_dma_rtag[2:0]))) ? {1'b0,dccm_dma_ecc_error} : (iccm_dma_rvalid & (i == DEPTH_PTR'(iccm_dma_rtag[2:0]))) ? {1'b0,iccm_dma_ecc_error} :
2022-05-10 21:06:26 +08:00
{(dma_address_error | dma_alignment_error | dma_dbg_cmd_error), dma_alignment_error};
2022-05-23 22:16:04 +08:00
assign fifo_data_in[i] = (fifo_error_en[i] & (|fifo_error_in[i])) ? {32'b0,fifo_addr[i]} :
2022-05-10 21:06:26 +08:00
((dccm_dma_rvalid & (i == DEPTH_PTR'(dccm_dma_rtag[2:0]))) ? dccm_dma_rdata[63:0] : (iccm_dma_rvalid & (i == DEPTH_PTR'(iccm_dma_rtag[2:0]))) ? iccm_dma_rdata[63:0] :
(dbg_cmd_valid ? {2{dma_dbg_mem_wrdata[31:0]}} : bus_cmd_wdata[63:0]));
2022-05-23 22:16:04 +08:00
rvdffsc #(1) fifo_valid_dff (
.din(1'b1),
.dout(fifo_valid[i]),
.en(fifo_cmd_en[i]),
.clear(fifo_reset[i]),
.clk(dma_free_clk),
.*
);
rvdffsc #(2) fifo_error_dff (
.din(fifo_error_in[i]),
.dout(fifo_error[i]),
.en(fifo_error_en[i]),
.clear(fifo_reset[i]),
.clk(dma_free_clk),
.*
);
rvdffsc #(1) fifo_error_bus_dff (
.din(1'b1),
.dout(fifo_error_bus[i]),
.en(fifo_error_bus_en[i]),
.clear(fifo_reset[i]),
.clk(dma_free_clk),
.*
);
rvdffsc #(1) fifo_rpend_dff (
.din(1'b1),
.dout(fifo_rpend[i]),
.en(fifo_pend_en[i]),
.clear(fifo_reset[i]),
.clk(dma_free_clk),
.*
);
rvdffsc #(1) fifo_done_dff (
.din(1'b1),
.dout(fifo_done[i]),
.en(fifo_done_en[i]),
.clear(fifo_reset[i]),
.clk(dma_free_clk),
.*
);
rvdffsc #(1) fifo_done_bus_dff (
.din(1'b1),
.dout(fifo_done_bus[i]),
.en(fifo_done_bus_en[i]),
.clear(fifo_reset[i]),
.clk(dma_free_clk),
.*
);
rvdffe #(32) fifo_addr_dff (
.din (fifo_addr_in[31:0]),
.dout(fifo_addr[i]),
.en (fifo_cmd_en[i]),
.*
);
rvdffs #(3) fifo_sz_dff (
.din (fifo_sz_in[2:0]),
.dout(fifo_sz[i]),
.en (fifo_cmd_en[i]),
.clk (dma_buffer_c1_clk),
.*
);
rvdffs #(8) fifo_byteen_dff (
.din (fifo_byteen_in[7:0]),
.dout(fifo_byteen[i]),
.en (fifo_cmd_en[i]),
.clk (dma_buffer_c1_clk),
.*
);
rvdffs #(1) fifo_write_dff (
.din (fifo_write_in),
.dout(fifo_write[i]),
.en (fifo_cmd_en[i]),
.clk (dma_buffer_c1_clk),
.*
);
rvdffs #(1) fifo_posted_write_dff (
.din (fifo_posted_write_in),
.dout(fifo_posted_write[i]),
.en (fifo_cmd_en[i]),
.clk (dma_buffer_c1_clk),
.*
);
rvdffs #(1) fifo_dbg_dff (
.din (fifo_dbg_in),
.dout(fifo_dbg[i]),
.en (fifo_cmd_en[i]),
.clk (dma_buffer_c1_clk),
.*
);
rvdffe #(64) fifo_data_dff (
.din (fifo_data_in[i]),
.dout(fifo_data[i]),
.en (fifo_data_en[i]),
.*
);
rvdffs #(pt.DMA_BUS_TAG) fifo_tag_dff (
.din (bus_cmd_tag[pt.DMA_BUS_TAG-1:0]),
.dout(fifo_tag[i][pt.DMA_BUS_TAG-1:0]),
.en (fifo_cmd_en[i]),
.clk (dma_buffer_c1_clk),
.*
);
rvdffs #(pt.DMA_BUS_ID) fifo_mid_dff (
.din (bus_cmd_mid[pt.DMA_BUS_ID-1:0]),
.dout(fifo_mid[i][pt.DMA_BUS_ID-1:0]),
.en (fifo_cmd_en[i]),
.clk (dma_buffer_c1_clk),
.*
);
rvdffs #(pt.DMA_BUS_PRTY) fifo_prty_dff (
.din (bus_cmd_prty[pt.DMA_BUS_PRTY-1:0]),
.dout(fifo_prty[i][pt.DMA_BUS_PRTY-1:0]),
.en (fifo_cmd_en[i]),
.clk (dma_buffer_c1_clk),
.*
);
end
// Pointer logic
assign NxtWrPtr[DEPTH_PTR-1:0] = (WrPtr[DEPTH_PTR-1:0] == (DEPTH-1)) ? '0 : WrPtr[DEPTH_PTR-1:0] + 1'b1;
assign NxtRdPtr[DEPTH_PTR-1:0] = (RdPtr[DEPTH_PTR-1:0] == (DEPTH-1)) ? '0 : RdPtr[DEPTH_PTR-1:0] + 1'b1;
assign NxtRspPtr[DEPTH_PTR-1:0] = (RspPtr[DEPTH_PTR-1:0] == (DEPTH-1)) ? '0 : RspPtr[DEPTH_PTR-1:0] + 1'b1;
assign WrPtrEn = |fifo_cmd_en[DEPTH-1:0];
assign RdPtrEn = dma_dccm_req | dma_iccm_req | (dma_address_error | dma_alignment_error | dma_dbg_cmd_error);
assign RspPtrEn = (dma_dbg_cmd_done | (bus_rsp_sent | bus_posted_write_done) & dma_bus_clk_en);
rvdffs #(DEPTH_PTR) WrPtr_dff (
.din (NxtWrPtr[DEPTH_PTR-1:0]),
.dout(WrPtr[DEPTH_PTR-1:0]),
.en (WrPtrEn),
.clk (dma_free_clk),
.*
);
rvdffs #(DEPTH_PTR) RdPtr_dff (
.din (NxtRdPtr[DEPTH_PTR-1:0]),
.dout(RdPtr[DEPTH_PTR-1:0]),
.en (RdPtrEn),
.clk (dma_free_clk),
.*
);
rvdffs #(DEPTH_PTR) RspPtr_dff (
.din (NxtRspPtr[DEPTH_PTR-1:0]),
.dout(RspPtr[DEPTH_PTR-1:0]),
.en (RspPtrEn),
.clk (dma_free_clk),
.*
);
// Miscellaneous signals
assign fifo_full = fifo_full_spec_bus;
always_comb begin
num_fifo_vld[3:0] = {3'b0, bus_cmd_sent} - {3'b0, bus_rsp_sent};
for (int i = 0; i < DEPTH; i++) begin
num_fifo_vld[3:0] += {3'b0, fifo_valid[i]};
end
end
assign fifo_full_spec = (num_fifo_vld[3:0] >= DEPTH);
assign dma_fifo_ready = ~(fifo_full | dbg_dma_bubble_bus);
// Error logic
assign dma_address_error = fifo_valid[RdPtr] & ~fifo_done[RdPtr] & ~fifo_dbg[RdPtr] & (~(dma_mem_addr_in_dccm | dma_mem_addr_in_iccm)); // request not for ICCM or DCCM
assign dma_alignment_error = fifo_valid[RdPtr] & ~fifo_done[RdPtr] & ~fifo_dbg[RdPtr] & ~dma_address_error &
2022-05-10 21:06:26 +08:00
(((dma_mem_sz_int[2:0] == 3'h1) & dma_mem_addr_int[0]) | // HW size but unaligned
2022-05-23 22:16:04 +08:00
((dma_mem_sz_int[2:0] == 3'h2) & (|dma_mem_addr_int[1:0])) | // W size but unaligned
((dma_mem_sz_int[2:0] == 3'h3) & (|dma_mem_addr_int[2:0])) | // DW size but unaligned
(dma_mem_addr_in_iccm & ~((dma_mem_sz_int[1:0] == 2'b10) | (dma_mem_sz_int[1:0] == 2'b11))) | // ICCM access not word size
(dma_mem_addr_in_dccm & dma_mem_write & ~((dma_mem_sz_int[1:0] == 2'b10) | (dma_mem_sz_int[1:0] == 2'b11))) | // DCCM write not word size
(dma_mem_write & (dma_mem_sz_int[2:0] == 3'h2) & (dma_mem_byteen[dma_mem_addr_int[2:0]+:4] != 4'hf)) | // Write byte enables not aligned for word store
(dma_mem_write & (dma_mem_sz_int[2:0] == 3'h3) & ~((dma_mem_byteen[7:0] == 8'h0f) | (dma_mem_byteen[7:0] == 8'hf0) | (dma_mem_byteen[7:0] == 8'hff)))); // Write byte enables not aligned for dword store
//Dbg outputs
assign dma_dbg_ready = fifo_empty & dbg_dma_bubble;
assign dma_dbg_cmd_done = (fifo_valid[RspPtr] & fifo_dbg[RspPtr] & fifo_done[RspPtr]);
assign dma_dbg_cmd_fail = (|fifo_error[RspPtr] & dma_dbg_cmd_done);
assign dma_dbg_sz[1:0] = fifo_sz[RspPtr][1:0];
assign dma_dbg_addr[1:0] = fifo_addr[RspPtr][1:0];
assign dma_dbg_mem_rddata[31:0] = fifo_addr[RspPtr][2] ? fifo_data[RspPtr][63:32] : fifo_data[RspPtr][31:0];
assign dma_dbg_rddata[31:0] = ({32{(dma_dbg_sz[1:0] == 2'h0)}} & ((dma_dbg_mem_rddata[31:0] >> 8*dma_dbg_addr[1:0]) & 32'hff)) |
2022-05-10 21:06:26 +08:00
({32{(dma_dbg_sz[1:0] == 2'h1)}} & ((dma_dbg_mem_rddata[31:0] >> 16*dma_dbg_addr[1]) & 32'hffff)) |
({32{(dma_dbg_sz[1:0] == 2'h2)}} & dma_dbg_mem_rddata[31:0]);
2022-05-23 22:16:04 +08:00
assign dma_dbg_cmd_error = fifo_valid[RdPtr] & ~fifo_done[RdPtr] & fifo_dbg[RdPtr] &
2022-05-10 21:06:26 +08:00
((~(dma_mem_addr_in_dccm | dma_mem_addr_in_iccm | dma_mem_addr_in_pic)) | // Address outside of ICCM/DCCM/PIC
((dma_mem_addr_in_iccm | dma_mem_addr_in_pic) & (dma_mem_sz_int[1:0] != 2'b10))); // Only word accesses allowed for ICCM/PIC
2022-05-23 22:16:04 +08:00
assign dma_dbg_mem_wrdata[31:0] = ({32{dbg_cmd_size[1:0] == 2'h0}} & {4{dbg_cmd_wrdata[7:0]}}) |
2022-05-10 21:06:26 +08:00
({32{dbg_cmd_size[1:0] == 2'h1}} & {2{dbg_cmd_wrdata[15:0]}}) |
({32{dbg_cmd_size[1:0] == 2'h2}} & dbg_cmd_wrdata[31:0]);
2022-05-23 22:16:04 +08:00
// Block the decode if fifo full
assign dma_dccm_stall_any = dma_mem_req & (dma_mem_addr_in_dccm | dma_mem_addr_in_pic) & (dma_nack_count >= dma_nack_count_csr);
assign dma_iccm_stall_any = dma_mem_req & dma_mem_addr_in_iccm & (dma_nack_count >= dma_nack_count_csr);
2022-05-10 21:06:26 +08:00
2022-05-23 22:16:04 +08:00
// Used to indicate ready to debug
assign fifo_empty = ~((|(fifo_valid[DEPTH-1:0])) | bus_cmd_sent);
2022-05-10 21:06:26 +08:00
2022-05-23 22:16:04 +08:00
// Nack counter, stall the lsu pipe if 7 nacks
assign dma_nack_count_csr[2:0] = dec_tlu_dma_qos_prty[2:0];
assign dma_nack_count_d[2:0] = (dma_nack_count[2:0] >= dma_nack_count_csr[2:0]) ? ({3{~(dma_dccm_req | dma_iccm_req)}} & dma_nack_count[2:0]) :
2022-05-10 21:06:26 +08:00
(dma_mem_req & ~(dma_dccm_req | dma_iccm_req)) ? (dma_nack_count[2:0] + 1'b1) : 3'b0;
2022-05-23 22:16:04 +08:00
rvdffs #(3) nack_count_dff (
.din (dma_nack_count_d[2:0]),
.dout(dma_nack_count[2:0]),
.en (dma_mem_req),
.clk (dma_free_clk),
.*
);
// Core outputs
assign dma_mem_req = fifo_valid[RdPtr] & ~fifo_rpend[RdPtr] & ~fifo_done[RdPtr] & ~(dma_address_error | dma_alignment_error | dma_dbg_cmd_error);
assign dma_dccm_req = dma_mem_req & (dma_mem_addr_in_dccm | dma_mem_addr_in_pic) & dccm_ready;
assign dma_iccm_req = dma_mem_req & dma_mem_addr_in_iccm & iccm_ready;
assign dma_mem_tag[2:0] = 3'(RdPtr);
assign dma_mem_addr_int[31:0] = fifo_addr[RdPtr];
assign dma_mem_sz_int[2:0] = fifo_sz[RdPtr];
assign dma_mem_addr[31:0] = (dma_mem_write & ~fifo_dbg[RdPtr] & (dma_mem_byteen[7:0] == 8'hf0)) ? {dma_mem_addr_int[31:3],1'b1,dma_mem_addr_int[1:0]} : dma_mem_addr_int[31:0];
assign dma_mem_sz[2:0] = (dma_mem_write & ~fifo_dbg[RdPtr] & ((dma_mem_byteen[7:0] == 8'h0f) | (dma_mem_byteen[7:0] == 8'hf0))) ? 3'h2 : dma_mem_sz_int[2:0];
assign dma_mem_byteen[7:0] = fifo_byteen[RdPtr];
assign dma_mem_write = fifo_write[RdPtr];
assign dma_mem_wdata[63:0] = fifo_data[RdPtr];
// PMU outputs
assign dma_pmu_dccm_read = dma_dccm_req & ~dma_mem_write;
assign dma_pmu_dccm_write = dma_dccm_req & dma_mem_write;
assign dma_pmu_any_read = (dma_dccm_req | dma_iccm_req) & ~dma_mem_write;
assign dma_pmu_any_write = (dma_dccm_req | dma_iccm_req) & dma_mem_write;
// Address check dccm
if (pt.DCCM_ENABLE) begin : Gen_dccm_enable
rvrangecheck #(
.CCM_SADR(pt.DCCM_SADR),
.CCM_SIZE(pt.DCCM_SIZE)
) addr_dccm_rangecheck (
.addr(dma_mem_addr_int[31:0]),
.in_range(dma_mem_addr_in_dccm),
.in_region(dma_mem_addr_in_dccm_region_nc)
);
end else begin : Gen_dccm_disable
assign dma_mem_addr_in_dccm = '0;
assign dma_mem_addr_in_dccm_region_nc = '0;
end // else: !if(pt.ICCM_ENABLE)
// Address check iccm
if (pt.ICCM_ENABLE) begin : Gen_iccm_enable
rvrangecheck #(
.CCM_SADR(pt.ICCM_SADR),
.CCM_SIZE(pt.ICCM_SIZE)
) addr_iccm_rangecheck (
.addr(dma_mem_addr_int[31:0]),
.in_range(dma_mem_addr_in_iccm),
.in_region(dma_mem_addr_in_iccm_region_nc)
);
end else begin : Gen_iccm_disable
assign dma_mem_addr_in_iccm = '0;
assign dma_mem_addr_in_iccm_region_nc = '0;
end // else: !if(pt.ICCM_ENABLE)
// PIC memory address check
rvrangecheck #(
.CCM_SADR(pt.PIC_BASE_ADDR),
.CCM_SIZE(pt.PIC_SIZE)
) addr_pic_rangecheck (
2022-05-10 21:06:26 +08:00
.addr(dma_mem_addr_int[31:0]),
.in_range(dma_mem_addr_in_pic),
.in_region(dma_mem_addr_in_pic_region_nc)
2022-05-23 22:16:04 +08:00
);
// Inputs
2022-05-23 23:37:09 +08:00
rvdff #(1) fifo_full_bus_ff (
2022-05-23 22:16:04 +08:00
.din(fifo_full_spec),
.dout(fifo_full_spec_bus),
.clk(dma_bus_clk),
.*
);
2022-05-23 23:37:09 +08:00
rvdff #(1) dbg_dma_bubble_ff (
2022-05-23 22:16:04 +08:00
.din(dbg_dma_bubble),
.dout(dbg_dma_bubble_bus),
.clk(dma_bus_clk),
.*
);
rvdff #(1) dma_dbg_cmd_doneff (
.din (dma_dbg_cmd_done),
.dout(dma_dbg_cmd_done_q),
.clk (free_clk),
.*
);
// Clock Gating logic
assign dma_buffer_c1_clken = (bus_cmd_valid & dma_bus_clk_en) | dbg_cmd_valid | clk_override;
assign dma_free_clken = (bus_cmd_valid | bus_rsp_valid | dbg_cmd_valid | dma_dbg_cmd_done | dma_dbg_cmd_done_q | (|fifo_valid[DEPTH-1:0]) | clk_override);
rvoclkhdr dma_buffer_c1cgc (
.en(dma_buffer_c1_clken),
.l1clk(dma_buffer_c1_clk),
.*
);
rvoclkhdr dma_free_cgc (
.en(dma_free_clken),
.l1clk(dma_free_clk),
.*
);
rvclkhdr dma_bus_cgc (
.en(dma_bus_clk_en),
.l1clk(dma_bus_clk),
.*
);
// Write channel buffer
assign wrbuf_en = dma_axi_awvalid & dma_axi_awready;
assign wrbuf_data_en = dma_axi_wvalid & dma_axi_wready;
assign wrbuf_cmd_sent = bus_cmd_sent & bus_cmd_write;
assign wrbuf_rst = wrbuf_cmd_sent & ~wrbuf_en;
assign wrbuf_data_rst = wrbuf_cmd_sent & ~wrbuf_data_en;
2022-05-23 23:37:09 +08:00
rvdffsc #(
2022-05-23 22:16:04 +08:00
.WIDTH(1)
) wrbuf_vldff (
.din(1'b1),
.dout(wrbuf_vld),
.en(wrbuf_en),
.clear(wrbuf_rst),
.clk(dma_bus_clk),
.*
);
2022-05-23 23:37:09 +08:00
rvdffsc #(
2022-05-23 22:16:04 +08:00
.WIDTH(1)
) wrbuf_data_vldff (
.din(1'b1),
.dout(wrbuf_data_vld),
.en(wrbuf_data_en),
.clear(wrbuf_data_rst),
.clk(dma_bus_clk),
.*
);
2022-05-23 23:37:09 +08:00
rvdffs #(
2022-05-23 22:16:04 +08:00
.WIDTH(pt.DMA_BUS_TAG)
) wrbuf_tagff (
.din(dma_axi_awid[pt.DMA_BUS_TAG-1:0]),
.dout(wrbuf_tag[pt.DMA_BUS_TAG-1:0]),
.en(wrbuf_en),
.clk(dma_bus_clk),
.*
);
2022-05-23 23:37:09 +08:00
rvdffs #(
2022-05-23 22:16:04 +08:00
.WIDTH(3)
) wrbuf_szff (
.din(dma_axi_awsize[2:0]),
.dout(wrbuf_sz[2:0]),
.en(wrbuf_en),
.clk(dma_bus_clk),
.*
);
rvdffe #(
.WIDTH(32)
) wrbuf_addrff (
.din (dma_axi_awaddr[31:0]),
.dout(wrbuf_addr[31:0]),
.en (wrbuf_en & dma_bus_clk_en),
.*
);
rvdffe #(
.WIDTH(64)
) wrbuf_dataff (
.din (dma_axi_wdata[63:0]),
.dout(wrbuf_data[63:0]),
.en (wrbuf_data_en & dma_bus_clk_en),
.*
);
2022-05-23 23:37:09 +08:00
rvdffs #(
2022-05-23 22:16:04 +08:00
.WIDTH(8)
) wrbuf_byteenff (
.din(dma_axi_wstrb[7:0]),
.dout(wrbuf_byteen[7:0]),
.en(wrbuf_data_en),
.clk(dma_bus_clk),
.*
);
// Read channel buffer
assign rdbuf_en = dma_axi_arvalid & dma_axi_arready;
assign rdbuf_cmd_sent = bus_cmd_sent & ~bus_cmd_write;
assign rdbuf_rst = rdbuf_cmd_sent & ~rdbuf_en;
2022-05-23 23:37:09 +08:00
rvdffsc #(
2022-05-23 22:16:04 +08:00
.WIDTH(1)
) rdbuf_vldff (
.din(1'b1),
.dout(rdbuf_vld),
.en(rdbuf_en),
.clear(rdbuf_rst),
.clk(dma_bus_clk),
.*
);
2022-05-23 23:37:09 +08:00
rvdffs #(
2022-05-23 22:16:04 +08:00
.WIDTH(pt.DMA_BUS_TAG)
) rdbuf_tagff (
.din(dma_axi_arid[pt.DMA_BUS_TAG-1:0]),
.dout(rdbuf_tag[pt.DMA_BUS_TAG-1:0]),
.en(rdbuf_en),
.clk(dma_bus_clk),
.*
);
2022-05-23 23:37:09 +08:00
rvdffs #(
2022-05-23 22:16:04 +08:00
.WIDTH(3)
) rdbuf_szff (
.din(dma_axi_arsize[2:0]),
.dout(rdbuf_sz[2:0]),
.en(rdbuf_en),
.clk(dma_bus_clk),
.*
);
rvdffe #(
.WIDTH(32)
) rdbuf_addrff (
.din (dma_axi_araddr[31:0]),
.dout(rdbuf_addr[31:0]),
.en (rdbuf_en & dma_bus_clk_en),
.*
);
assign dma_axi_awready = ~(wrbuf_vld & ~wrbuf_cmd_sent);
assign dma_axi_wready = ~(wrbuf_data_vld & ~wrbuf_cmd_sent);
assign dma_axi_arready = ~(rdbuf_vld & ~rdbuf_cmd_sent);
//Generate a single request from read/write channel
assign bus_cmd_valid = (wrbuf_vld & wrbuf_data_vld) | rdbuf_vld;
assign bus_cmd_sent = bus_cmd_valid & dma_fifo_ready;
assign bus_cmd_write = axi_mstr_sel;
assign bus_cmd_posted_write = '0;
assign bus_cmd_addr[31:0] = axi_mstr_sel ? wrbuf_addr[31:0] : rdbuf_addr[31:0];
assign bus_cmd_sz[2:0] = axi_mstr_sel ? wrbuf_sz[2:0] : rdbuf_sz[2:0];
assign bus_cmd_wdata[63:0] = wrbuf_data[63:0];
assign bus_cmd_byteen[7:0] = wrbuf_byteen[7:0];
assign bus_cmd_tag[pt.DMA_BUS_TAG-1:0] = axi_mstr_sel ? wrbuf_tag[pt.DMA_BUS_TAG-1:0] : rdbuf_tag[pt.DMA_BUS_TAG-1:0];
assign bus_cmd_mid[pt.DMA_BUS_ID-1:0] = '0;
assign bus_cmd_prty[pt.DMA_BUS_PRTY-1:0] = '0;
// Sel=1 -> write has higher priority
assign axi_mstr_sel = (wrbuf_vld & wrbuf_data_vld & rdbuf_vld) ? axi_mstr_priority : (wrbuf_vld & wrbuf_data_vld);
assign axi_mstr_prty_in = ~axi_mstr_priority;
assign axi_mstr_prty_en = bus_cmd_sent;
2022-05-23 23:37:09 +08:00
rvdffs #(
2022-05-23 22:16:04 +08:00
.WIDTH(1)
) mstr_prtyff (
.din(axi_mstr_prty_in),
.dout(axi_mstr_priority),
.en(axi_mstr_prty_en),
.clk(dma_bus_clk),
.*
);
assign axi_rsp_valid = fifo_valid[RspPtr] & ~fifo_dbg[RspPtr] & fifo_done_bus[RspPtr];
assign axi_rsp_rdata[63:0] = fifo_data[RspPtr];
assign axi_rsp_write = fifo_write[RspPtr];
assign axi_rsp_error[1:0] = fifo_error[RspPtr][0] ? 2'b10 : (fifo_error[RspPtr][1] ? 2'b11 : 2'b0);
assign axi_rsp_tag[pt.DMA_BUS_TAG-1:0] = fifo_tag[RspPtr];
// AXI response channel signals
assign dma_axi_bvalid = axi_rsp_valid & axi_rsp_write;
assign dma_axi_bresp[1:0] = axi_rsp_error[1:0];
assign dma_axi_bid[pt.DMA_BUS_TAG-1:0] = axi_rsp_tag[pt.DMA_BUS_TAG-1:0];
assign dma_axi_rvalid = axi_rsp_valid & ~axi_rsp_write;
assign dma_axi_rresp[1:0] = axi_rsp_error;
assign dma_axi_rdata[63:0] = axi_rsp_rdata[63:0];
assign dma_axi_rlast = 1'b1;
assign dma_axi_rid[pt.DMA_BUS_TAG-1:0] = axi_rsp_tag[pt.DMA_BUS_TAG-1:0];
assign bus_posted_write_done = 1'b0;
assign bus_rsp_valid = (dma_axi_bvalid | dma_axi_rvalid);
assign bus_rsp_sent = (dma_axi_bvalid & dma_axi_bready) | (dma_axi_rvalid & dma_axi_rready);
assign dma_active = wrbuf_vld | rdbuf_vld | (|fifo_valid[DEPTH-1:0]);
endmodule // el2_dma_ctrl