mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-04 22:32:36 +00:00
- Introduced a new testbench for the AXI4 interconnect () to validate fault classification for decode and access errors. - Updated and to reflect changes in bus naming conventions. - Enhanced to include AXI4-Stream interface checks and validate stream data transfers. - Modified to integrate AXI4-Stream interfaces for improved DMA testing. - Added new Python tests () to verify AXI4 to RIBP burst bridge functionality and interconnect fault classification. - Updated existing tests to include AXI4 interfaces and ensure proper error handling and response validation. - Adjusted memory map generation and test setups to accommodate new AXI4 interface requirements.
304 lines
9.6 KiB
Systemverilog
304 lines
9.6 KiB
Systemverilog
// Copyright (c) 2023-2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
|
|
// retroSoC is licensed under Mulan PSL v2.
|
|
// You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
// You may obtain a copy of Mulan PSL v2 at:
|
|
// http://license.coscl.org.cn/MulanPSL2
|
|
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
// See the Mulan PSL v2 for more details.
|
|
|
|
`ifndef RIBP_DMA_DEF_SV
|
|
`define RIBP_DMA_DEF_SV
|
|
|
|
// verilog_format: off
|
|
`define RIBP_DMA_MODE 8'h00
|
|
`define RIBP_DMA_SRCADDR 8'h04
|
|
`define RIBP_DMA_SRCINCR 8'h08
|
|
`define RIBP_DMA_DSTADDR 8'h0C
|
|
`define RIBP_DMA_DSTINCR 8'h10
|
|
`define RIBP_DMA_XFERLEN 8'h14
|
|
`define RIBP_DMA_START 8'h18
|
|
`define RIBP_DMA_STOP 8'h1C
|
|
`define RIBP_DMA_RESET 8'h20
|
|
`define RIBP_DMA_STATUS 8'h24
|
|
`define RIBP_DMA_FSM 8'h28
|
|
`define RIBP_DMA_ERROR_STATUS 8'h2C
|
|
`define RIBP_DMA_ERROR_ADDR 8'h30
|
|
// verilog_format: on
|
|
|
|
interface dma_hw_trg_if ();
|
|
logic i2s_tx_proc;
|
|
logic i2s_rx_proc;
|
|
logic qspi_tx_proc;
|
|
logic qspi_rx_proc;
|
|
logic uart_tx_proc;
|
|
logic uart_rx_proc;
|
|
logic i2c0_tx_proc;
|
|
logic i2c0_rx_proc;
|
|
logic i2c1_tx_proc;
|
|
logic i2c1_rx_proc;
|
|
|
|
modport dut(
|
|
input i2s_tx_proc,
|
|
input i2s_rx_proc,
|
|
input qspi_tx_proc,
|
|
input qspi_rx_proc,
|
|
input uart_tx_proc,
|
|
input uart_rx_proc,
|
|
input i2c0_tx_proc,
|
|
input i2c0_rx_proc,
|
|
input i2c1_tx_proc,
|
|
input i2c1_rx_proc
|
|
);
|
|
endinterface
|
|
|
|
`endif
|
|
|
|
module ribp_dma (
|
|
// verilog_format: off
|
|
input logic clk_i,
|
|
input logic rst_n_i,
|
|
output logic dma_xfer_done_o,
|
|
dma_hw_trg_if.dut hw_trg,
|
|
ribp_if.slave ribp,
|
|
rib_if.master rib,
|
|
axi4_stream_if.source i2s_tx_axis,
|
|
axi4_stream_if.sink i2s_rx_axis,
|
|
axi4_stream_if.sink dvp_rx_axis
|
|
// verilog_format: on
|
|
);
|
|
|
|
logic s_ribp_wr_hdshk, s_ribp_rd_hdshk;
|
|
logic s_ribp_ready_d, s_ribp_ready_q;
|
|
logic s_ribp_rdata_en;
|
|
logic [31:0] s_ribp_rdata_d, s_ribp_rdata_q;
|
|
|
|
logic s_dma_mode_en;
|
|
logic [3:0] s_dma_mode_d, s_dma_mode_q;
|
|
logic s_dma_srcaddr_en;
|
|
logic [31:0] s_dma_srcaddr_d, s_dma_srcaddr_q;
|
|
logic s_dma_srcincr_en;
|
|
logic s_dma_srcincr_d, s_dma_srcincr_q;
|
|
logic s_dma_dstaddr_en;
|
|
logic [31:0] s_dma_dstaddr_d, s_dma_dstaddr_q;
|
|
logic s_dma_dstincr_en;
|
|
logic s_dma_dstincr_d, s_dma_dstincr_q;
|
|
logic s_dma_xferlen_en;
|
|
logic [31:0] s_dma_xferlen_d, s_dma_xferlen_q;
|
|
logic s_dma_status_d, s_dma_status_q;
|
|
logic s_dma_error_status_d, s_dma_error_status_q;
|
|
logic [2:0] s_dma_error_code_d, s_dma_error_code_q;
|
|
logic [31:0] s_dma_error_addr_d, s_dma_error_addr_q;
|
|
// common
|
|
logic s_xfer_start, s_xfer_stop, s_xfer_reset, s_xfer_done;
|
|
logic [ 1:0] s_xfer_fsm;
|
|
logic s_xfer_error;
|
|
logic [ 2:0] s_xfer_error_code;
|
|
logic [31:0] s_xfer_error_addr;
|
|
|
|
|
|
assign s_ribp_wr_hdshk = ribp.valid && (~s_ribp_ready_q) && (|ribp.wstrb);
|
|
assign s_ribp_rd_hdshk = ribp.valid && (~s_ribp_ready_q) && (~(|ribp.wstrb));
|
|
assign ribp.ready = s_ribp_ready_q;
|
|
assign ribp.resp_err = 1'b0;
|
|
assign ribp.rdata = s_ribp_rdata_q;
|
|
|
|
assign dma_xfer_done_o = s_dma_status_q;
|
|
|
|
|
|
assign s_dma_mode_en = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_DMA_MODE;
|
|
assign s_dma_mode_d = ribp.wdata[3:0];
|
|
dffer #(4) u_dma_mode_dffer (
|
|
.clk_i (clk_i),
|
|
.rst_n_i(rst_n_i),
|
|
.en_i (s_dma_mode_en),
|
|
.dat_i (s_dma_mode_d),
|
|
.dat_o (s_dma_mode_q)
|
|
);
|
|
|
|
|
|
assign s_dma_srcaddr_en = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_DMA_SRCADDR;
|
|
always_comb begin
|
|
s_dma_srcaddr_d = s_dma_srcaddr_q;
|
|
if (ribp.wstrb[0]) s_dma_srcaddr_d[7:0] = ribp.wdata[7:0];
|
|
if (ribp.wstrb[1]) s_dma_srcaddr_d[15:8] = ribp.wdata[15:8];
|
|
if (ribp.wstrb[2]) s_dma_srcaddr_d[23:16] = ribp.wdata[23:16];
|
|
if (ribp.wstrb[3]) s_dma_srcaddr_d[31:24] = ribp.wdata[31:24];
|
|
end
|
|
dffer #(32) u_dma_srcaddr_dffer (
|
|
.clk_i (clk_i),
|
|
.rst_n_i(rst_n_i),
|
|
.en_i (s_dma_srcaddr_en),
|
|
.dat_i (s_dma_srcaddr_d),
|
|
.dat_o (s_dma_srcaddr_q)
|
|
);
|
|
|
|
|
|
assign s_dma_srcincr_en = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_DMA_SRCINCR;
|
|
assign s_dma_srcincr_d = ribp.wdata[0];
|
|
dffer #(1) u_dma_srcincr_dffer (
|
|
.clk_i (clk_i),
|
|
.rst_n_i(rst_n_i),
|
|
.en_i (s_dma_srcincr_en),
|
|
.dat_i (s_dma_srcincr_d),
|
|
.dat_o (s_dma_srcincr_q)
|
|
);
|
|
|
|
|
|
assign s_dma_dstaddr_en = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_DMA_DSTADDR;
|
|
always_comb begin
|
|
s_dma_dstaddr_d = s_dma_dstaddr_q;
|
|
if (ribp.wstrb[0]) s_dma_dstaddr_d[7:0] = ribp.wdata[7:0];
|
|
if (ribp.wstrb[1]) s_dma_dstaddr_d[15:8] = ribp.wdata[15:8];
|
|
if (ribp.wstrb[2]) s_dma_dstaddr_d[23:16] = ribp.wdata[23:16];
|
|
if (ribp.wstrb[3]) s_dma_dstaddr_d[31:24] = ribp.wdata[31:24];
|
|
end
|
|
dffer #(32) u_dma_dstaddr_dffer (
|
|
.clk_i (clk_i),
|
|
.rst_n_i(rst_n_i),
|
|
.en_i (s_dma_dstaddr_en),
|
|
.dat_i (s_dma_dstaddr_d),
|
|
.dat_o (s_dma_dstaddr_q)
|
|
);
|
|
|
|
assign s_dma_dstincr_en = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_DMA_DSTINCR;
|
|
assign s_dma_dstincr_d = ribp.wdata[0];
|
|
dffer #(1) u_dma_dstincr_dffer (
|
|
.clk_i (clk_i),
|
|
.rst_n_i(rst_n_i),
|
|
.en_i (s_dma_dstincr_en),
|
|
.dat_i (s_dma_dstincr_d),
|
|
.dat_o (s_dma_dstincr_q)
|
|
);
|
|
|
|
assign s_dma_xferlen_en = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_DMA_XFERLEN;
|
|
always_comb begin
|
|
s_dma_xferlen_d = s_dma_xferlen_q;
|
|
if (ribp.wstrb[0]) s_dma_xferlen_d[7:0] = ribp.wdata[7:0];
|
|
if (ribp.wstrb[1]) s_dma_xferlen_d[15:8] = ribp.wdata[15:8];
|
|
if (ribp.wstrb[2]) s_dma_xferlen_d[23:16] = ribp.wdata[23:16];
|
|
if (ribp.wstrb[3]) s_dma_xferlen_d[31:24] = ribp.wdata[31:24];
|
|
end
|
|
dffer #(32) u_dma_xferlen_dffer (
|
|
.clk_i (clk_i),
|
|
.rst_n_i(rst_n_i),
|
|
.en_i (s_dma_xferlen_en),
|
|
.dat_i (s_dma_xferlen_d),
|
|
.dat_o (s_dma_xferlen_q)
|
|
);
|
|
|
|
|
|
assign s_xfer_start = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_DMA_START;
|
|
assign s_xfer_stop = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_DMA_STOP;
|
|
assign s_xfer_reset = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_DMA_RESET;
|
|
|
|
|
|
always_comb begin
|
|
s_dma_status_d = s_dma_status_q;
|
|
if (s_ribp_rd_hdshk && ribp.addr[7:0] == `RIBP_DMA_STATUS) begin
|
|
s_dma_status_d = '0;
|
|
end else if (s_xfer_done) begin
|
|
s_dma_status_d = 1'b1;
|
|
end
|
|
end
|
|
dffr #(1) u_dma_status_dffr (
|
|
.clk_i (clk_i),
|
|
.rst_n_i(rst_n_i),
|
|
.dat_i (s_dma_status_d),
|
|
.dat_o (s_dma_status_q)
|
|
);
|
|
|
|
always_comb begin
|
|
s_dma_error_status_d = s_dma_error_status_q;
|
|
if (s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_DMA_ERROR_STATUS && ribp.wstrb[0] &&
|
|
ribp.wdata[0]) begin
|
|
s_dma_error_status_d = 1'b0;
|
|
end else if (s_xfer_error) begin
|
|
s_dma_error_status_d = 1'b1;
|
|
end
|
|
end
|
|
dffr #(1) u_dma_error_status_dffr (
|
|
.clk_i (clk_i),
|
|
.rst_n_i(rst_n_i),
|
|
.dat_i (s_dma_error_status_d),
|
|
.dat_o (s_dma_error_status_q)
|
|
);
|
|
assign s_dma_error_code_d = s_xfer_error_code;
|
|
dffer #(3) u_dma_error_code_dffer (
|
|
.clk_i (clk_i),
|
|
.rst_n_i(rst_n_i),
|
|
.en_i (s_xfer_error),
|
|
.dat_i (s_dma_error_code_d),
|
|
.dat_o (s_dma_error_code_q)
|
|
);
|
|
assign s_dma_error_addr_d = s_xfer_error_addr;
|
|
dffer #(32) u_dma_error_addr_dffer (
|
|
.clk_i (clk_i),
|
|
.rst_n_i(rst_n_i),
|
|
.en_i (s_xfer_error),
|
|
.dat_i (s_dma_error_addr_d),
|
|
.dat_o (s_dma_error_addr_q)
|
|
);
|
|
|
|
|
|
assign s_ribp_ready_d = ribp.valid && (~s_ribp_ready_q);
|
|
dffr #(1) u_ribp_ready_dffr (
|
|
.clk_i (clk_i),
|
|
.rst_n_i(rst_n_i),
|
|
.dat_i (s_ribp_ready_d),
|
|
.dat_o (s_ribp_ready_q)
|
|
);
|
|
|
|
assign s_ribp_rdata_en = s_ribp_rd_hdshk;
|
|
always_comb begin
|
|
s_ribp_rdata_d = s_ribp_rdata_q;
|
|
unique case (ribp.addr[7:0])
|
|
`RIBP_DMA_MODE: s_ribp_rdata_d = {28'd0, s_dma_mode_q};
|
|
`RIBP_DMA_SRCADDR: s_ribp_rdata_d = s_dma_srcaddr_q;
|
|
`RIBP_DMA_SRCINCR: s_ribp_rdata_d = {31'd0, s_dma_srcincr_q};
|
|
`RIBP_DMA_DSTADDR: s_ribp_rdata_d = s_dma_dstaddr_q;
|
|
`RIBP_DMA_DSTINCR: s_ribp_rdata_d = {31'd0, s_dma_dstincr_q};
|
|
`RIBP_DMA_XFERLEN: s_ribp_rdata_d = s_dma_xferlen_q;
|
|
`RIBP_DMA_STATUS: s_ribp_rdata_d = {31'd0, s_dma_status_q};
|
|
`RIBP_DMA_FSM: s_ribp_rdata_d = {30'd0, s_xfer_fsm};
|
|
`RIBP_DMA_ERROR_STATUS: s_ribp_rdata_d = {28'd0, s_dma_error_code_q, s_dma_error_status_q};
|
|
`RIBP_DMA_ERROR_ADDR: s_ribp_rdata_d = s_dma_error_addr_q;
|
|
default: s_ribp_rdata_d = s_ribp_rdata_q;
|
|
endcase
|
|
end
|
|
dffer #(32) u_ribp_rdata_dffer (
|
|
.clk_i (clk_i),
|
|
.rst_n_i(rst_n_i),
|
|
.en_i (s_ribp_rdata_en),
|
|
.dat_i (s_ribp_rdata_d),
|
|
.dat_o (s_ribp_rdata_q)
|
|
);
|
|
|
|
|
|
dma_core u_dma_core (
|
|
.clk_i (clk_i),
|
|
.rst_n_i (rst_n_i),
|
|
.mode_i (s_dma_mode_q),
|
|
.srcaddr_i (s_dma_srcaddr_q),
|
|
.srcincr_i (s_dma_srcincr_q),
|
|
.dstaddr_i (s_dma_dstaddr_q),
|
|
.dstincr_i (s_dma_dstincr_q),
|
|
.xferlen_i (s_dma_xferlen_q),
|
|
.start_i (s_xfer_start),
|
|
.stop_i (s_xfer_stop),
|
|
.reset_i (s_xfer_reset),
|
|
.done_o (s_xfer_done),
|
|
.error_o (s_xfer_error),
|
|
.error_code_o(s_xfer_error_code),
|
|
.error_addr_o(s_xfer_error_addr),
|
|
.fsm_o (s_xfer_fsm),
|
|
.hw_trg (hw_trg),
|
|
.rib (rib),
|
|
.i2s_tx_axis (i2s_tx_axis),
|
|
.i2s_rx_axis (i2s_rx_axis),
|
|
.dvp_rx_axis (dvp_rx_axis)
|
|
);
|
|
|
|
endmodule
|