mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-04 22:32:36 +00:00
- Updated NMI interface references from to in multiple files for consistency. - Added a new script to convert UART performance records into structured JSON format. - Enhanced the README documentation to include details about the new performance log parser. - Implemented tests for the new performance log parser to ensure correct functionality. - Added new test cases for DMA error handling and SDRAM data integrity to improve coverage. - Updated existing test cases to accommodate changes in the NMI interface and added performance metrics. - Refactored bus fault testbench to include fault code checks and improved error handling. - Adjusted memory map generation and pin mapping tests to reflect recent changes in RTL structure.
283 lines
7.8 KiB
Systemverilog
283 lines
7.8 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.
|
|
|
|
`include "soc_nmi_defs.svh"
|
|
|
|
module dma_core (
|
|
// verilog_format: off
|
|
input logic clk_i,
|
|
input logic rst_n_i,
|
|
input logic [2:0] mode_i,
|
|
input logic [31:0] srcaddr_i,
|
|
input logic srcincr_i,
|
|
input logic [31:0] dstaddr_i,
|
|
input logic dstincr_i,
|
|
input logic [31:0] xferlen_i,
|
|
input logic start_i,
|
|
input logic stop_i,
|
|
input logic reset_i,
|
|
output logic done_o,
|
|
output logic error_o,
|
|
output logic [2:0] error_code_o,
|
|
output logic [31:0] error_addr_o,
|
|
output logic [1:0] fsm_o,
|
|
dma_hw_trg_if.dut hw_trg,
|
|
soc_nmi_if.master nmi
|
|
// verilog_format: on
|
|
);
|
|
|
|
// mode val
|
|
// 7-5: resv
|
|
// 4: xpi rx fifo trg
|
|
// 3: xpi tx fifo trg
|
|
// 2: i2s rx fifo trg
|
|
// 1: i2s tx fifo trg
|
|
// 0: sft trg
|
|
localparam SFT_TRG = 3'd0;
|
|
localparam HWT_I2S_TX_TRG = 3'd1;
|
|
localparam HWT_I2S_RX_TRG = 3'd2;
|
|
localparam HWT_QSPI_TX_TRG = 3'd3;
|
|
localparam HWT_QSPI_RX_TRG = 3'd4;
|
|
|
|
localparam FSM_IDLE = 2'd0;
|
|
localparam FSM_XFER = 2'd1;
|
|
localparam FSM_DONE = 2'd2;
|
|
|
|
logic [1:0] s_fsm_d, s_fsm_q;
|
|
logic [31:0] s_xfer_cnt_d, s_xfer_cnt_q;
|
|
logic [31:0] s_src_addr_d, s_src_addr_q;
|
|
logic [31:0] s_dst_addr_d, s_dst_addr_q;
|
|
logic [31:0] s_rd_data_d, s_rd_data_q;
|
|
logic s_xfer_type_d, s_xfer_type_q; // 0: rd 1: wr
|
|
logic s_xfer_done_d, s_xfer_done_q;
|
|
logic s_ctrl_stop_d, s_ctrl_stop_q;
|
|
// Registered NMI master outputs
|
|
logic s_nmi_valid_d, s_nmi_valid_q;
|
|
logic [31:0] s_nmi_addr_d, s_nmi_addr_q;
|
|
logic [31:0] s_nmi_wdata_d, s_nmi_wdata_q;
|
|
logic [3:0] s_nmi_wstrb_d, s_nmi_wstrb_q;
|
|
|
|
assign fsm_o = s_fsm_q;
|
|
assign nmi.valid = s_nmi_valid_q;
|
|
assign nmi.addr = s_nmi_addr_q;
|
|
assign nmi.wdata = s_nmi_wdata_q;
|
|
assign nmi.wstrb = s_nmi_wstrb_q;
|
|
always_comb begin
|
|
s_fsm_d = s_fsm_q;
|
|
s_src_addr_d = s_src_addr_q;
|
|
s_dst_addr_d = s_dst_addr_q;
|
|
s_rd_data_d = s_rd_data_q;
|
|
s_xfer_cnt_d = s_xfer_cnt_q;
|
|
s_xfer_type_d = s_xfer_type_q;
|
|
s_xfer_done_d = s_xfer_done_q;
|
|
// nmi if (registered outputs)
|
|
s_nmi_valid_d = '0;
|
|
s_nmi_addr_d = s_nmi_addr_q;
|
|
s_nmi_wdata_d = s_nmi_wdata_q;
|
|
s_nmi_wstrb_d = '0;
|
|
// common
|
|
done_o = '0;
|
|
error_o = 1'b0;
|
|
error_code_o = `SOC_NMI_RESP_OK;
|
|
error_addr_o = s_nmi_addr_q;
|
|
unique case (s_fsm_q)
|
|
FSM_IDLE: begin
|
|
if (start_i) begin
|
|
s_fsm_d = FSM_XFER;
|
|
s_src_addr_d = srcaddr_i;
|
|
s_dst_addr_d = dstaddr_i;
|
|
s_xfer_cnt_d = '0;
|
|
s_xfer_type_d = 1'b0;
|
|
s_xfer_done_d = 1'b1;
|
|
end
|
|
end
|
|
FSM_XFER: begin
|
|
if (~s_ctrl_stop_q) begin
|
|
if (~s_xfer_type_q) begin
|
|
unique case (mode_i)
|
|
HWT_I2S_RX_TRG: begin
|
|
if (~hw_trg.i2s_rx_proc && s_xfer_done_q) s_nmi_valid_d = 1'b0;
|
|
else s_nmi_valid_d = 1'b1;
|
|
end
|
|
HWT_QSPI_RX_TRG: begin
|
|
if (~hw_trg.qspi_rx_proc && s_xfer_done_q) s_nmi_valid_d = 1'b0;
|
|
else s_nmi_valid_d = 1'b1;
|
|
end
|
|
default: s_nmi_valid_d = 1'b1;
|
|
endcase
|
|
s_nmi_addr_d = s_src_addr_q;
|
|
if (nmi.valid && nmi.ready) begin
|
|
s_nmi_valid_d = 1'b0;
|
|
if (nmi.resp_err) begin
|
|
s_fsm_d = FSM_IDLE;
|
|
error_o = 1'b1;
|
|
error_code_o = nmi.resp_code;
|
|
end else begin
|
|
s_xfer_type_d = 1'b1;
|
|
s_xfer_done_d = 1'b1;
|
|
s_rd_data_d = nmi.rdata;
|
|
end
|
|
end else if (nmi.valid) begin
|
|
s_xfer_done_d = 1'b0;
|
|
end
|
|
end else begin
|
|
unique case (mode_i)
|
|
HWT_I2S_TX_TRG: begin
|
|
if (~hw_trg.i2s_tx_proc && s_xfer_done_q) s_nmi_valid_d = 1'b0;
|
|
else s_nmi_valid_d = 1'b1;
|
|
end
|
|
HWT_QSPI_TX_TRG: begin
|
|
if (~hw_trg.qspi_tx_proc && s_xfer_done_q) s_nmi_valid_d = 1'b0;
|
|
else s_nmi_valid_d = 1'b1;
|
|
end
|
|
default: s_nmi_valid_d = 1'b1;
|
|
endcase
|
|
s_nmi_addr_d = s_dst_addr_q;
|
|
s_nmi_wdata_d = s_rd_data_q;
|
|
s_nmi_wstrb_d = '1;
|
|
if (nmi.valid && nmi.ready) begin
|
|
s_nmi_valid_d = 1'b0;
|
|
if (nmi.resp_err) begin
|
|
s_fsm_d = FSM_IDLE;
|
|
error_o = 1'b1;
|
|
error_code_o = nmi.resp_code;
|
|
end else begin
|
|
s_xfer_type_d = 1'b0;
|
|
s_xfer_done_d = 1'b1;
|
|
// when src rd+wr xfer done
|
|
if ((s_xfer_cnt_q + 32'd1) == xferlen_i) begin
|
|
s_xfer_cnt_d = '0;
|
|
s_fsm_d = FSM_DONE;
|
|
end else begin
|
|
s_xfer_cnt_d = s_xfer_cnt_q + 1'b1;
|
|
if (srcincr_i) s_src_addr_d = s_src_addr_q + 32'd4;
|
|
if (dstincr_i) s_dst_addr_d = s_dst_addr_q + 32'd4;
|
|
end
|
|
end
|
|
end else if (nmi.valid) s_xfer_done_d = 1'b0;
|
|
end
|
|
end else begin
|
|
if (reset_i) s_fsm_d = FSM_IDLE;
|
|
end
|
|
end
|
|
FSM_DONE: begin
|
|
done_o = 1'b1;
|
|
s_fsm_d = FSM_IDLE;
|
|
end
|
|
default: begin
|
|
s_fsm_d = s_fsm_q;
|
|
s_src_addr_d = s_src_addr_q;
|
|
s_dst_addr_d = s_dst_addr_q;
|
|
s_rd_data_d = s_rd_data_q;
|
|
s_xfer_cnt_d = s_xfer_cnt_q;
|
|
s_xfer_type_d = s_xfer_type_q;
|
|
s_xfer_done_d = s_xfer_done_q;
|
|
// nmi if
|
|
s_nmi_valid_d = '0;
|
|
s_nmi_addr_d = '0;
|
|
s_nmi_wdata_d = '0;
|
|
s_nmi_wstrb_d = '0;
|
|
// common
|
|
done_o = '0;
|
|
error_o = 1'b0;
|
|
error_code_o = `SOC_NMI_RESP_OK;
|
|
error_addr_o = s_nmi_addr_q;
|
|
end
|
|
endcase
|
|
end
|
|
dffr #(2) u_fsm_dffr (
|
|
clk_i,
|
|
rst_n_i,
|
|
s_fsm_d,
|
|
s_fsm_q
|
|
);
|
|
|
|
dffr #(32) u_xfer_cnt_dffr (
|
|
clk_i,
|
|
rst_n_i,
|
|
s_xfer_cnt_d,
|
|
s_xfer_cnt_q
|
|
);
|
|
|
|
dffr #(32) u_src_addr_dffr (
|
|
clk_i,
|
|
rst_n_i,
|
|
s_src_addr_d,
|
|
s_src_addr_q
|
|
);
|
|
|
|
dffr #(32) u_dst_addr_dffr (
|
|
clk_i,
|
|
rst_n_i,
|
|
s_dst_addr_d,
|
|
s_dst_addr_q
|
|
);
|
|
|
|
dffr #(32) u_rd_data_dffr (
|
|
clk_i,
|
|
rst_n_i,
|
|
s_rd_data_d,
|
|
s_rd_data_q
|
|
);
|
|
|
|
dffr #(1) u_xfer_type_dffr (
|
|
clk_i,
|
|
rst_n_i,
|
|
s_xfer_type_d,
|
|
s_xfer_type_q
|
|
);
|
|
|
|
dffr #(1) u_xfer_done_dffr (
|
|
clk_i,
|
|
rst_n_i,
|
|
s_xfer_done_d,
|
|
s_xfer_done_q
|
|
);
|
|
|
|
// control the xfer
|
|
always_comb begin
|
|
s_ctrl_stop_d = s_ctrl_stop_q;
|
|
if (stop_i) s_ctrl_stop_d = ~s_ctrl_stop_q;
|
|
end
|
|
dffr #(1) u_ctrl_stop_dffr (
|
|
clk_i,
|
|
rst_n_i,
|
|
s_ctrl_stop_d,
|
|
s_ctrl_stop_q
|
|
);
|
|
|
|
// Registered NMI master outputs
|
|
dffr #(1) u_nmi_valid_dffr (
|
|
clk_i,
|
|
rst_n_i,
|
|
s_nmi_valid_d,
|
|
s_nmi_valid_q
|
|
);
|
|
dffr #(32) u_nmi_addr_dffr (
|
|
clk_i,
|
|
rst_n_i,
|
|
s_nmi_addr_d,
|
|
s_nmi_addr_q
|
|
);
|
|
dffr #(32) u_nmi_wdata_dffr (
|
|
clk_i,
|
|
rst_n_i,
|
|
s_nmi_wdata_d,
|
|
s_nmi_wdata_q
|
|
);
|
|
dffr #(4) u_nmi_wstrb_dffr (
|
|
clk_i,
|
|
rst_n_i,
|
|
s_nmi_wstrb_d,
|
|
s_nmi_wstrb_q
|
|
);
|
|
|
|
endmodule
|