Skip to content

Commit

Permalink
First pass - AXI DMA
Browse files Browse the repository at this point in the history
  • Loading branch information
calebofearth committed Jul 25, 2024
1 parent b811e1d commit 0a58401
Show file tree
Hide file tree
Showing 10 changed files with 2,041 additions and 1,475 deletions.
635 changes: 635 additions & 0 deletions src/axi/rtl/axi_dma_ctrl.sv

Large diffs are not rendered by default.

271 changes: 126 additions & 145 deletions src/axi/rtl/axi_dma_reg.rdl

Large diffs are not rendered by default.

1,324 changes: 470 additions & 854 deletions src/axi/rtl/axi_dma_reg.sv

Large diffs are not rendered by default.

84 changes: 39 additions & 45 deletions src/axi/rtl/axi_dma_reg_pkg.sv

Large diffs are not rendered by default.

688 changes: 257 additions & 431 deletions src/axi/rtl/axi_dma_reg_uvm.sv

Large diffs are not rendered by default.

57 changes: 57 additions & 0 deletions src/axi/rtl/axi_dma_req_if.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// SPDX-License-Identifier: Apache-2.0
//
// 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.
//
// Description:
// Signals for internal transaction requests inside the Caliptra DMA
// hardware assist block
// Does not include any datapath signals (data, strb, user)
// as these flow separately through the FIFO.
//

interface axi_dma_req_if #(parameter AW = 32) (input logic clk, input logic rst_n);

import axi_pkg::*;

logic valid;
logic ready;
logic [AW-1:0] addr;
logic [AXI_LEN_BC_WIDTH-1:0] byte_len; // Byte count, max value per AXI spec
logic fixed;
logic lock;
logic resp_valid;
logic [$bits(axi_resp_e)-1:0] resp;

modport src (
output valid,
input ready,
output addr,
output len,
output fixed,
output lock,
input resp_valid,
input resp
);

modport snk (
input valid,
output ready,
input addr,
input len,
input fixed,
input lock,
output resp_valid,
output resp
);

endinterface
76 changes: 76 additions & 0 deletions src/axi/rtl/axi_dma_top.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// SPDX-License-Identifier: Apache-2.0
//
// 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.
//
// Description:
// Top wrapper on AXI4 Manager (DMA) block
//

module axi_dma_top import axi_pkg::*; #(
parameter AW = 64,
parameter DW = 32, // Data Width
BC = DW/8, // Byte Count
BW = $clog2(BC), // Byte count Width
parameter UW = 32, // User Width
parameter IW = 1, // ID Width
ID_NUM = 1 << IW // Don't override
)(
input clk,
input rst_n,

// SOC_IFC Internal Signaling
input mbox_lock,
input sha_lock,

// AXI INF
axi_if.w_mgr m_axi_wr,
axi_if.r_mgr m_axi_rd,

// Component INF
input dv,
input var soc_ifc_req_t req_data,
output hold,
output [SOC_IFC_DATA_W-1:0] rdata,
output error

);

// --------------------------------------- //
// Imports //
// --------------------------------------- //

// --------------------------------------- //
// Localparams/Typedefs //
// --------------------------------------- //

// --------------------------------------- //
// Signals //
// --------------------------------------- //

// --------------------------------------- //
// Control State Machine //
// --------------------------------------- //

// --------------------------------------- //
// AXI Manager Read Channel //
// --------------------------------------- //

// --------------------------------------- //
// AXI Manager Write Channel //
// --------------------------------------- //

// --------------------------------------- //
// Assertions //
// --------------------------------------- //

endmodule
188 changes: 188 additions & 0 deletions src/axi/rtl/axi_mgr_rd.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
// SPDX-License-Identifier: Apache-2.0
//
// 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.
//
// Description:
// Generic AXI4 manager component for read channel. Accepts requests from
// FSM logic, converts the request to legal AXI4 handshake, and forwards
// return data via a FIFO interface.
//

module axi_mgr_rd import axi_pkg::*; #(
parameter AW = 32,
parameter DW = 32,
BC = DW/8, // Byte Count
BW = $clog2(BC), // Byte count Width
parameter UW = 32,
parameter IW = 1,
ID_NUM = 1 << IW
) (
input clk,
input rst_n,

// AXI INF
axi_if.r_mgr m_axi_if,

// REQ INF
axi_dma_req_if.snk req_if,

// FIFO INF
input ready_i,
output valid_o,
output [DW-1:0] data_o
);

// --------------------------------------- //
// Imports //
// --------------------------------------- //


// --------------------------------------- //
// Localparams/Typedefs //
// --------------------------------------- //
// Transaction context
typedef struct packed {
logic [AW-1:0] addr;
logic fixed;
logic [AXI_LEN_WIDTH-1:0] len;
logic lock;
} req_ctx_t;


// --------------------------------------- //
// Signals //
// --------------------------------------- //
req_ctx_t req_ctx;
req_ctx_t axi_ctx;
logic axi_ctx_valid;
logic axi_ctx_ready;
logic axi_ctx_sent;

logic txn_active;
logic txn_final_beat;


// --------------------------------------- //
// Request Context //
// --------------------------------------- //

always_comb begin
req_ctx.addr = req_if.addr;
req_ctx.fixed = req_if.fixed;
req_ctx.len = req_if.byte_len[BW+:AXI_LEN_WIDTH];
req_ctx.lock = req_if.lock;
end

// Buffer the incoming request, but send it out over Address channel immediately
// to allow multiple in-flight transactions (reduce bubbles between bursts).
// The contents of the skidbuffer will inform the tracker for the next data
// burst once the address channel request is sent.
skidbuffer #(
.OPT_LOWPOWER (0 ),
.OPT_OUTREG (0 ),
//
.OPT_PASSTHROUGH(0 ),
.DW ($bits(req_ctx_t)),
.OPT_INITIAL (1'b1)
) i_ctx_skd (
.i_clk (clk ),
.i_reset(!rst_n ),
.i_valid(req_if.valid ),
.o_ready(req_if.ready ),
.i_data (req_ctx ),
.o_valid(axi_ctx_valid ),
.i_ready(axi_ctx_ready ),
.o_data (axi_ctx )
);

always_ff@(posedge clk or negedge rst_n) begin
if (!rst_n) begin
axi_ctx_sent = 1'b0;
end
else if (axi_ctx_valid && axi_ctx_ready) begin
axi_ctx_sent = 1'b0;
end
else if (m_axi_if.arvalid && m_axi_if.arready) begin
axi_ctx_sent = 1'b1;
end
end

always_comb begin
m_axi_if.arvalid = axi_ctx_valid && !axi_ctx_sent;
m_axi_if.araddr = axi_ctx.addr;
m_axi_if.arburst = axi_ctx.fixed ? AXI_BURST_FIXED : AXI_BURST_INCR;
m_axi_if.arsize = BW;
m_axi_if.arlen = axi_ctx.len;
m_axi_if.aruser = '0; // TODO ?
m_axi_if.arid = IW'(0);
m_axi_if.arlock = axi_ctx.lock;
end

axi_ctx_ready = (!txn_active || txn_final_beat) &&
(m_axi_if.arready || axi_ctx_sent);


// --------------------------------------- //
// Datapath //
// --------------------------------------- //
always_ff@(posedge clk or negedge rst_n) begin
if (!rst_n) begin
txn_active <= 1'b0;
end
else if (axi_ctx_valid && axi_ctx_ready) begin
txn_active <= 1'b1;
end
else if (txn_final_beat) begin
txn_active <= 1'b0;
end
end

always_comb txn_final_beat = m_axi_if.rvalid && m_axi_if.rready && m_axi_if.rlast;
always_comb m_axi_if.rready = txn_active && ready_i;

always_comb begin
valid_o = m_axi_if.rvalid && m_axi_if.rready;
data_o = m_axi_if.rdata;
end

always_ff@(posedge clk or negedge rst_n) begin
if (!rst_n) begin
req_if.resp <= AXI_RESP_OKAY;
req_if.resp_valid <= 1'b0;
end
// Accumulate status codes...
// TODO what if ERROR is interleaved with EXOKAY?
else if (m_axi_if.rvalid && m_axi_if.rready) begin
req_if.resp <= req_if.resp | m_axi_if.rresp;
req_if.resp_valid <= m_axi_if.rlast;
end
else if (axi_ctx_valid && axi_ctx_ready) begin
req_if.resp <= AXI_RESP_OKAY;
req_if.resp_valid <= 1'b0;
end
else begin
req_if.resp <= req_if.resp;
req_if.resp_valid <= 1'b0;
end
end

// --------------------------------------- //
// Assertions //
// --------------------------------------- //
`FIXME_ASSERT(req.valid && addr + len <= 4096)
`FIXME_ASSERT(req_if.byte_len[11:10] == 2'b00)
`FIXME_ASSERT(req_if.rvalid && txn_active)
`FIXME_ASSERT_NEVER(fixme_valid_and_ready && ready_i, "Received data with no space in FIFO! Is the FSM credit calculation wrong?")


endmodule
Loading

0 comments on commit 0a58401

Please sign in to comment.