If there is code that needs to be modified between "// START MODIFICATION AREA" and "// END MODIFICATION AREA", please make the necessary changes in accordance with the attached specifications to enhance its completeness.

<<<StartOfFile:DMAC/RTL/DMAC_CFG.sv>>>
module DMAC_CFG
(
    input wire clk,
    input wire rst_n, // _n means active low
    // AMBA APB interface
    input wire psel_i,
    input wire penable_i,
    input wire [11:0] paddr_i,
    input wire pwrite_i,
    input wire [31:0] pwdata_i,
    output reg pready_o,
    output reg [31:0] prdata_o,
    output reg pslverr_o,
    // configuration registers
    output reg [31:0] src_addr_o,
    output reg [31:0] dst_addr_o,
    output reg [15:0] byte_len_o,
    output wire start_o,
    input wire done_i
);
    // Configuration register to read/write
    reg [31:0] src_addr;
    reg [31:0] dst_addr;
    reg [15:0] byte_len;
    //----------------------------------------------------------
    // Write
    //----------------------------------------------------------
    // an APB write occurs when PSEL & PENABLE & PWRITE
    // clk : __--__--__--__--__--__--__--__--__--__--
    // psel : ___--------_____________________________
    // penable : _______----_____________________________
    // pwrite : ___--------_____________________________
    // wren : _______----_____________________________
    //
    // DMA start command must be asserted when APB writes 1 to the DMA_CMD
    // register
    // clk : __--__--__--__--__--__--__--__--__--__--
    // psel : ___--------_____________________________
    // penable : _______----_____________________________
    // pwrite : ___--------_____________________________
    // paddr : |DMA_CMD|
    // pwdata : | 1 |
    // start : _______----_____________________________
    wire wren = psel_i & penable_i & pwrite_i;
    always_ff @(posedge clk) begin
        if (!rst_n) begin
            src_addr <= 32'd0;
            dst_addr <= 32'd0;
            byte_len <= 16'd0;
        end
        else if (wren) begin
            case (paddr_i)
                'h100: src_addr <= pwdata_i[31:0];
                'h104: dst_addr <= pwdata_i[31:0];
                'h108: byte_len <= pwdata_i[15:0];
            endcase
        end
    end
    wire start = wren & (paddr_i=='h10C) & pwdata_i[0];
    //----------------------------------------------------------
    // READ
    //----------------------------------------------------------
    // an APB read occurs when PSEL & PENABLE & !PWRITE
    // To make read data a direct output from register,
    // this code shall buffer the muxed read data into a register
    // in the SETUP cycle (PSEL & !PENABLE)
    // clk : __--__--__--__--__--__--__--__--__--__--
    // psel : ___--------_____________________________
    // penable : _______----_____________________________
    // pwrite : ________________________________________
    // reg update : ___----_________________________________
    // prdata : |DATA
    reg [31:0] rdata;
    always_ff @(posedge clk) begin
        if (!rst_n) begin
            rdata <= 32'd0;
        end
        else if (psel_i & !penable_i & !pwrite_i) begin // in the setup cycle in the APB state diagram
            case (paddr_i)
                'h0: rdata <= 32'h0001_2024;
                'h100: rdata <= src_addr;
                'h104: rdata <= dst_addr;
                'h108: rdata <= {16'd0, byte_len};
                'h110: rdata <= {31'd0, done_i};
                default: rdata <= 32'd0;
            endcase
        end
    end
    // output assignments
    assign pready_o = 1'b1;
    assign prdata_o = rdata;
    assign pslverr_o = 1'b0;
    assign src_addr_o = src_addr;
    assign dst_addr_o = dst_addr;
    assign byte_len_o = byte_len;
    assign start_o = start;
endmodule
<<<EndOfFile:DMAC/RTL/DMAC_CFG.sv>>>
<<<StartOfFile:DMAC/RTL/DMAC_ENGINE.sv>>>
module DMAC_ENGINE
(
    input wire clk,
    input wire rst_n, // _n means active low
    // configuration registers
    input wire [31:0] src_addr_i,
    input wire [31:0] dst_addr_i,
    input wire [15:0] byte_len_i,
    input wire start_i,
    output wire done_o,
    // AMBA AXI interface (AW channel)
    output wire [3:0] awid_o,
    output wire [31:0] awaddr_o,
    output wire [3:0] awlen_o,
    output wire [2:0] awsize_o,
    output wire [1:0] awburst_o,
    output wire awvalid_o,
    input wire awready_i,
    // AMBA AXI interface (W channel)
    output wire [3:0] wid_o,
    output wire [31:0] wdata_o,
    output wire [3:0] wstrb_o,
    output wire wlast_o,
    output wire wvalid_o,
    input wire wready_i,
    // AMBA AXI interface (B channel)
    input wire [3:0] bid_i,
    input wire [1:0] bresp_i,
    input wire bvalid_i,
    output wire bready_o,
    // AMBA AXI interface (AR channel)
    output wire [3:0] arid_o,
    output wire [31:0] araddr_o,
    output wire [3:0] arlen_o,
    output wire [2:0] arsize_o,
    output wire [1:0] arburst_o,
    output wire arvalid_o,
    input wire arready_i,
    // AMBA AXI interface (R channel)
    input wire [3:0] rid_i,
    input wire [31:0] rdata_i,
    input wire [1:0] rresp_i,
    input wire rlast_i,
    input wire rvalid_i,
    output wire rready_o
);
    // mnemonics for state values
    localparam S_IDLE = 3'd0,
                                S_RREQ = 3'd1,
                                S_RDATA = 3'd2,
                                S_WREQ = 3'd3,
                                S_WDATA = 3'd4;
    reg [2:0] state, state_n;
    reg [31:0] src_addr, src_addr_n;
    reg [31:0] dst_addr, dst_addr_n;
    reg [15:0] cnt, cnt_n;
    reg [31:0] data_buf, data_buf_n;
    reg arvalid,
                                rready,
                                awvalid,
                                wvalid,
                                done;
    // it's desirable to code registers in a simple way
    always_ff @(posedge clk) begin
        if (!rst_n) begin
            state <= S_IDLE;
            src_addr <= 32'd0;
            dst_addr <= 32'd0;
            cnt <= 16'd0;
            data_buf <= 32'd0;
        end
        else begin
            state <= state_n;
            src_addr <= src_addr_n;
            dst_addr <= dst_addr_n;
            cnt <= cnt_n;
            data_buf <= data_buf_n;
        end
    end
    // this block programs output values and next register values
    // based on states.
    always_comb begin
        state_n = state;
        src_addr_n = src_addr;
        dst_addr_n = dst_addr;
        cnt_n = cnt;
        data_buf_n = data_buf;
        arvalid = 1'b0;
        rready = 1'b0;
        awvalid = 1'b0;
        wvalid = 1'b0;
        done = 1'b0;
        case (state)
            // START MODIFICATION AREA
            S_IDLE: begin
                done = 1'b1; // DMA operation is not ongoing
                if (start_i && (byte_len_i != 0)) begin
                    src_addr_n = src_addr_i;
                    dst_addr_n = dst_addr_i;
                    cnt_n = byte_len_i >> 2; // Adjust for the data width
                    state_n = S_RREQ;
                end
            end

            S_RREQ: begin
                arvalid = 1'b1;
                if (arready_i) begin
                    src_addr_n = src_addr + 4; // Prepare for the next address
                    state_n = S_RDATA;
                end
            end

            S_RDATA: begin
                rready = 1'b1;
                if (rvalid_i) begin
                    data_buf_n = rdata_i;
                    state_n = S_WREQ;
                end
            end

            S_WREQ: begin
                awvalid = 1'b1;
                if (awready_i) begin
                    dst_addr_n = dst_addr + 4;
                    cnt_n = cnt - 1;
                    state_n = S_WDATA;
                end
            end

            S_WDATA: begin
                wvalid = 1'b1;
                if (wready_i) begin
                    if (cnt != 0) begin
                        state_n = S_RREQ;
                    end
                    else begin
                        state_n = S_IDLE;
                    end
                end
            end
            // END MODIFICATION AREA
        endcase
    end
    // Output assigments
    assign done_o = done;
    assign awid_o = 4'd0;
    assign awaddr_o = dst_addr;
    assign awlen_o = 4'd0; // 1-burst
    assign awsize_o = 3'b010; // 4 bytes per transfer
    assign awburst_o = 2'b01; // incremental
    assign awvalid_o = awvalid;
    assign wid_o = 4'd0;
    assign wdata_o = data_buf;
    assign wstrb_o = 4'b1111; // all bytes within 4 byte are valid
    assign wlast_o = 1'b1;
    assign wvalid_o = wvalid;
    assign bready_o = 1'b1;
    assign araddr_o = src_addr;
    assign arid_o = 4'd0;
    assign arlen_o = 4'd0; // 1-burst
    assign arsize_o = 3'b010; // 4 bytes per transfer
    assign arburst_o = 2'b01; // incremental
    assign arvalid_o = arvalid;
    assign rready_o = rready;
endmodule
<<<EndOfFile:DMAC/RTL/DMAC_ENGINE.sv>>>
<<<StartOfFile:DMAC/RTL/DMAC_TOP.sv>>>
module DMAC_TOP
(
    input wire clk,
    input wire rst_n, // _n means active low
    // AMBA APB interface
    input wire psel_i,
    input wire penable_i,
    input wire [11:0] paddr_i,
    input wire pwrite_i,
    input wire [31:0] pwdata_i,
    output reg pready_o,
    output reg [31:0] prdata_o,
    output reg pslverr_o,
    // AMBA AXI interface (AW channel)
    output wire [3:0] awid_o,
    output wire [31:0] awaddr_o,
    output wire [3:0] awlen_o,
    output wire [2:0] awsize_o,
    output wire [1:0] awburst_o,
    output wire awvalid_o,
    input wire awready_i,
    // AMBA AXI interface (AW channel)
    output wire [3:0] wid_o,
    output wire [31:0] wdata_o,
    output wire [3:0] wstrb_o,
    output wire wlast_o,
    output wire wvalid_o,
    input wire wready_i,
    // AMBA AXI interface (B channel)
    input wire [3:0] bid_i,
    input wire [1:0] bresp_i,
    input wire bvalid_i,
    output wire bready_o,
    // AMBA AXI interface (AR channel)
    output wire [3:0] arid_o,
    output wire [31:0] araddr_o,
    output wire [3:0] arlen_o,
    output wire [2:0] arsize_o,
    output wire [1:0] arburst_o,
    output wire arvalid_o,
    input wire arready_i,
    // AMBA AXI interface (R channel)
    input wire [3:0] rid_i,
    input wire [31:0] rdata_i,
    input wire [1:0] rresp_i,
    input wire rlast_i,
    input wire rvalid_i,
    output wire rready_o
);
    wire [31:0] src_addr;
    wire [31:0] dst_addr;
    wire [15:0] byte_len;
    wire start;
    wire done;
    DMAC_CFG u_cfg(
        .clk (clk),
        .rst_n (rst_n),
        // AMBA APB interface
        .psel_i (psel_i),
        .penable_i (penable_i),
        .paddr_i (paddr_i),
        .pwrite_i (pwrite_i),
        .pwdata_i (pwdata_i),
        .pready_o (pready_o),
        .prdata_o (prdata_o),
        .pslverr_o (pslverr_o),
        .src_addr_o (src_addr),
        .dst_addr_o (dst_addr),
        .byte_len_o (byte_len),
        .start_o (start),
        .done_i (done)
    );
    DMAC_ENGINE u_engine(
        .clk (clk),
        .rst_n (rst_n),
        // configuration registers
        .src_addr_i (src_addr),
        .dst_addr_i (dst_addr),
        .byte_len_i (byte_len),
        .start_i (start),
        .done_o (done),
        // AMBA AXI interface (AW channel)
        .awid_o (awid_o),
        .awaddr_o (awaddr_o),
        .awlen_o (awlen_o),
        .awsize_o (awsize_o),
        .awburst_o (awburst_o),
        .awvalid_o (awvalid_o),
        .awready_i (awready_i),
        // AMBA AXI interface (W channel)
        .wid_o (wid_o),
        .wdata_o (wdata_o),
        .wstrb_o (wstrb_o),
        .wlast_o (wlast_o),
        .wvalid_o (wvalid_o),
        .wready_i (wready_i),
        // AMBA AXI interface (B channel)
        .bid_i (bid_i),
        .bresp_i (bresp_i),
        .bvalid_i (bvalid_i),
        .bready_o (bready_o),
        // AMBA AXI interface (AR channel)
        .arid_o (arid_o),
        .araddr_o (araddr_o),
        .arlen_o (arlen_o),
        .arsize_o (arsize_o),
        .arburst_o (arburst_o),
        .arvalid_o (arvalid_o),
        .arready_i (arready_i),
        // AMBA AXI interface (R channel)
        .rid_i (rid_i),
        .rdata_i (rdata_i),
        .rresp_i (rresp_i),
        .rlast_i (rlast_i),
        .rvalid_i (rvalid_i),
        .rready_o (rready_o)
    );
endmodule
<<<EndOfFile:DMAC/RTL/DMAC_TOP.sv>>>
<<<StartOfFile:DMAC/RTL/filelist.f>>>
-sverilog \$LAB_PATH/RTL/DMAC_TOP.sv
-sverilog \$LAB_PATH/RTL/DMAC_CFG.sv
-sverilog \$LAB_PATH/RTL/DMAC_ENGINE.sv
<<<EndOfFile:DMAC/RTL/filelist.f>>>
<<<StartOfFile:DMAC/SIM/TB/AXI_INTF.sv>>>
`include "../TB/AXI_TYPEDEF.svh"
interface AXI_AW_CH
#(
    parameter ADDR_WIDTH = `AXI_ADDR_WIDTH,
    parameter ID_WIDTH = `AXI_ID_WIDTH
 )
(
    input clk
);
    logic awvalid;
    logic awready;
    logic [ID_WIDTH-1:0] awid;
    logic [ADDR_WIDTH-1:0] awaddr;
    logic [3:0] awlen;
    logic [2:0] awsize;
    logic [1:0] awburst;
endinterface
interface AXI_W_CH
#(
    parameter DATA_WIDTH = `AXI_DATA_WIDTH,
    parameter ID_WIDTH = `AXI_ID_WIDTH
 )
(
    input clk
);
    logic wvalid;
    logic wready;
    logic [ID_WIDTH-1:0] wid;
    logic [DATA_WIDTH-1:0] wdata;
    logic [DATA_WIDTH/8-1:0] wstrb;
    logic wlast;
endinterface
interface AXI_B_CH
#(
    parameter ID_WIDTH = `AXI_ID_WIDTH
 )
(
    input clk
);
    logic bvalid;
    logic bready;
    logic [ID_WIDTH-1:0] bid;
    logic [1:0] bresp;
endinterface
interface AXI_AR_CH
#(
    parameter ADDR_WIDTH = `AXI_ADDR_WIDTH,
    parameter ID_WIDTH = `AXI_ID_WIDTH
 )
(
    input clk
);
    logic arvalid;
    logic arready;
    logic [ID_WIDTH-1:0] arid;
    logic [ADDR_WIDTH-1:0] araddr;
    logic [3:0] arlen;
    logic [2:0] arsize;
    logic [1:0] arburst;
endinterface
interface AXI_R_CH
#(
    parameter DATA_WIDTH = `AXI_DATA_WIDTH,
    parameter ID_WIDTH = `AXI_ID_WIDTH
 )
(
    input clk
);
    logic rvalid;
    logic rready;
    logic [ID_WIDTH-1:0] rid;
    logic [DATA_WIDTH-1:0] rdata;
    logic [1:0] rresp;
    logic rlast;
endinterface
interface APB (
    input clk
);
    logic psel;
    logic penable;
    logic [31:0] paddr;
    logic pwrite;
    logic [31:0] pwdata;
    logic pready;
    logic [31:0] prdata;
    logic pslverr;
    modport master (
        input clk,
        input pready, prdata, pslverr,
        output psel, penable, paddr, pwrite, pwdata
    );
    task init();
        psel = 1'b0;
        penable = 1'b0;
        paddr = 32'd0;
        pwrite = 1'b0;
        pwdata = 32'd0;
    endtask
    task write(input int addr,
               input int data);
        #1
        psel = 1'b1;
        penable = 1'b0;
        paddr = addr;
        pwrite = 1'b1;
        pwdata = data;
        @(posedge clk);
        #1
        penable = 1'b1;
        @(posedge clk);
        while (pready==1'b0) begin
            @(posedge clk);
        end
        psel = 1'b0;
        penable = 1'b0;
        paddr = 'hX;
        pwrite = 1'bx;
        pwdata = 'hX;
    endtask
    task read(input int addr,
              output int data);
        #1
        psel = 1'b1;
        penable = 1'b0;
        paddr = addr;
        pwrite = 1'b0;
        pwdata = 'hX;
        @(posedge clk);
        #1
        penable = 1'b1;
        @(posedge clk);
        while (pready==1'b0) begin
            @(posedge clk);
        end
        data = prdata;
        psel = 1'b0;
        penable = 1'b0;
        paddr = 'hX;
        pwrite = 1'bx;
        pwdata = 'hX;
    endtask
endinterface
<<<EndOfFile:DMAC/SIM/TB/AXI_INTF.sv>>>
<<<StartOfFile:DMAC/SIM/TB/AXI_SLAVE.sv>>>
`include "../TB/AXI_TYPEDEF.svh"
module AXI_SLAVE
#(
    parameter ADDR_WIDTH = 16,
    parameter DATA_WIDTH = `AXI_DATA_WIDTH,
    parameter ID_WIDTH = `AXI_ID_WIDTH,
    parameter AWREADY_DELAY = 1,
    parameter ARREADY_DELAY = 1,
    parameter AR2R_DELAY = 50
)
(
    input wire clk,
    input wire rst_n, // _n means active low
    AXI_AW_CH aw_ch,
    AXI_W_CH w_ch,
    AXI_B_CH b_ch,
    AXI_AR_CH ar_ch,
    AXI_R_CH r_ch
);
    localparam DATA_DEPTH = 1<<ADDR_WIDTH;
    logic [7:0] mem[DATA_DEPTH];
    function void write_byte(int addr, input bit [7:0] wdata);
        mem[addr] = wdata;
    endfunction
    function void write_word(int addr, input bit [31:0] wdata);
        for (int i=0; i<4; i++) begin
            write_byte(addr+i, wdata[8*i +: 8]); // [i*8+7:i*8]
        end
    endfunction
    function bit [7:0] read_byte(int addr);
        read_byte = mem[addr];
    endfunction
    function bit [31:0] read_word(int addr);
        for (int i=0; i<4; i++) begin
            read_word[8*i +: 8] = read_byte(addr+i);// [i*8+7:i*8]
        end
    endfunction
    //----------------------------------------------------------
    // write channels (AW, W, B)
    //----------------------------------------------------------
    localparam logic [1:0] S_W_IDLE = 0,
                                S_W_AWREADY = 1,
                                S_W_BURST = 2,
                                S_W_RESP = 3;
    logic [1:0] wstate, wstate_n;
    logic [7:0] wcnt, wcnt_n;
    logic [ADDR_WIDTH-1:0] waddr, waddr_n;
    logic [ID_WIDTH-1:0] wid, wid_n;
    logic [3:0] wlen, wlen_n;
    always_ff @(posedge clk)
        if (!rst_n) begin
            wstate <= S_W_IDLE;
            wcnt <= 8'd0;
            waddr <= {ADDR_WIDTH{1'b0}};
            wid <= {ID_WIDTH{1'b0}};
            wlen <= 4'd0;
        end
        else begin
            wstate <= wstate_n;
            wcnt <= wcnt_n;
            waddr <= waddr_n;
            wid <= wid_n;
            wlen <= wlen_n;
        end
    always @(*) begin
        wstate_n = wstate;
        wcnt_n = wcnt;
        waddr_n = waddr;
        wid_n = wid;
        wlen_n = wlen;
        aw_ch.awready = 1'b0;
        w_ch.wready = 1'b0;
        b_ch.bvalid = 1'b0;
        case (wstate)
            S_W_IDLE: begin
                if (aw_ch.awvalid) begin
                    if (AWREADY_DELAY == 0) begin
                        waddr_n = aw_ch.awaddr;
                        wid_n = aw_ch.awid;
                        wlen_n = aw_ch.awlen;
                        aw_ch.awready = 1'b1;
                        wstate_n = S_W_BURST;
                    end
                    else begin
                        wcnt_n = AWREADY_DELAY-1;
                        wstate_n = S_W_AWREADY;
                    end
                end
            end
            S_W_AWREADY: begin
                if (wcnt==0) begin
                    waddr_n = aw_ch.awaddr;
                    wid_n = aw_ch.awid;
                    wlen_n = aw_ch.awlen;
                    aw_ch.awready = 1'b1;
                    wstate_n = S_W_BURST;
                end
                else begin
                    wcnt_n = wcnt - 8'd1;
                end
            end
            S_W_BURST: begin
                w_ch.wready = 1'b1;
                if (w_ch.wvalid) begin
                    for (int i=0; i<DATA_WIDTH/8; i++) begin
                        write_byte(waddr + i, w_ch.wdata[i*8 +: 8]); // [i*8+7:i*8]
                    end
                    waddr_n = waddr + (DATA_WIDTH/8);
                    if (wlen==4'd0) begin
                        if (w_ch.wlast!=1'b1) begin
                            \$display("WLAST mismatch");
                            @(posedge clk);
                            \$finish;
                        end
                        wstate_n = S_W_RESP;
                    end
                    else begin
                        wlen_n = wlen - 4'd1;
                    end
                end
            end
            S_W_RESP: begin
                b_ch.bvalid = 1'b1;
                if (b_ch.bready) begin
                    wstate_n = S_W_IDLE;
                end
            end
        endcase
    end
    //----------------------------------------------------------
    // read channel (AR, R)
    //----------------------------------------------------------
    localparam logic [1:0] S_R_IDLE = 0,
                                S_R_ARREADY = 1,
                                S_R_DELAY = 2,
                                S_R_BURST = 3;
    logic [1:0] rstate, rstate_n;
    logic [7:0] rcnt, rcnt_n;
    logic [ADDR_WIDTH-1:0] raddr, raddr_n;
    logic [ID_WIDTH-1:0] rid, rid_n;
    logic [3:0] rlen, rlen_n;
    always_ff @(posedge clk)
        if (!rst_n) begin
            rstate <= S_R_IDLE;
            rcnt <= 8'd0;
            raddr <= {ADDR_WIDTH{1'b0}};
            rid <= {ID_WIDTH{1'b0}};
            rlen <= 4'd0;
        end
        else begin
            rstate <= rstate_n;
            rcnt <= rcnt_n;
            raddr <= raddr_n;
            rid <= rid_n;
            rlen <= rlen_n;
        end
    always_comb begin
        rstate_n = rstate;
        rcnt_n = rcnt;
        raddr_n = raddr;
        rid_n = rid;
        rlen_n = rlen;
        ar_ch.arready = 1'b0;
        r_ch.rvalid = 1'b0;
        r_ch.rlast = 1'b0;
        case (rstate)
            S_R_IDLE: begin
                if (ar_ch.arvalid) begin
                    if (ARREADY_DELAY == 0) begin
                        raddr_n = ar_ch.araddr;
                        rid_n = ar_ch.arid;
                        rlen_n = ar_ch.arlen;
                        ar_ch.arready = 1'b1;
                        rcnt_n = AR2R_DELAY - 1;
                        rstate_n = S_R_DELAY;
                    end
                    else begin
                        rcnt_n = ARREADY_DELAY-1;
                        rstate_n = S_R_ARREADY;
                    end
                end
            end
            S_R_ARREADY: begin
                if (rcnt==0) begin
                    raddr_n = ar_ch.araddr;
                    rid_n = ar_ch.arid;
                    rlen_n = ar_ch.arlen;
                    ar_ch.arready = 1'b1;
                    rcnt_n = AR2R_DELAY - 1;
                    rstate_n = S_R_DELAY;
                end
                else begin
                    rcnt_n = rcnt - 8'd1;
                end
            end
            S_R_DELAY: begin
                if (rcnt==0) begin
                    rstate_n = S_R_BURST;
                end
                else begin
                    rcnt_n = rcnt - 8'd1;
                end
            end
            S_R_BURST: begin
                r_ch.rvalid = 1'b1;
                r_ch.rlast = (rlen==4'd0);
                for (int i=0; i<DATA_WIDTH/8; i++) begin
                    r_ch.rdata[i*8 +: 8] = read_byte(raddr + i); // [i*8+7:i*8]
                end
                if (r_ch.rready) begin
                    raddr_n = raddr + (DATA_WIDTH/8);
                    if (rlen==4'd0) begin
                        rstate_n = S_R_IDLE;
                    end
                    else begin
                        rlen_n = rlen - 4'd1;
                    end
                end
            end
        endcase
    end
    // output assignments
    assign b_ch.bid = wid;
    assign b_ch.bresp = 2'd0;
    assign r_ch.rid = rid;
    assign r_ch.rresp = 2'd0;
endmodule
<<<EndOfFile:DMAC/SIM/TB/AXI_SLAVE.sv>>>
<<<StartOfFile:DMAC/SIM/TB/AXI_TYPEDEF.svh>>>
`ifndef __AXI_TYPEDEF_SVH__
`define __AXI_TYPEDEF_SVH__
`define AXI_ADDR_WIDTH 32
`define AXI_DATA_WIDTH 32
`define AXI_ID_WIDTH 4
`endif /* __AXI_TYPEDEF_SVH__ */
<<<EndOfFile:DMAC/SIM/TB/AXI_TYPEDEF.svh>>>
<<<StartOfFile:DMAC/SIM/TB/DMAC_TOP_TB.sv>>>
`define IP_VER 32'h000
`define SRC_ADDR 32'h100
`define DST_ADDR 32'h104
`define LEN_ADDR 32'h108
`define STAT_ADDR 32'h110
`define START_ADDR 32'h10c
`define TIMEOUT_CYCLE 50000000
module DMAC_TOP_TB ();
    reg clk;
    reg rst_n;
    // clock generation
    initial begin
        clk = 1'b0;
        forever #10 clk = !clk;
    end
    // reset generation
    initial begin
        rst_n = 1'b0; // active at time 0
        repeat (3) @(posedge clk); // after 3 cycles,
        rst_n = 1'b1; // release the reset
    end
    // enable waveform dump
    initial begin
        \$dumpvars(0, u_DUT);
        \$dumpfile("dump.vcd");
    end
 // timeout
 initial begin
  #`TIMEOUT_CYCLE \$display("Timeout!");
  \$finish;
 end
    APB apb_if (.clk(clk));
    AXI_AW_CH aw_ch (.clk(clk));
    AXI_W_CH w_ch (.clk(clk));
    AXI_B_CH b_ch (.clk(clk));
    AXI_AR_CH ar_ch (.clk(clk));
    AXI_R_CH r_ch (.clk(clk));
    task test_init();
        int data;
        apb_if.init();
        @(posedge rst_n); // wait for a release of the reset
        repeat (10) @(posedge clk); // wait another 10 cycles
        apb_if.read(`IP_VER, data);
        \$display("---------------------------------------------------");
        \$display("IP version: %x", data);
        \$display("---------------------------------------------------");
        \$display("---------------------------------------------------");
        \$display("Reset value test");
        \$display("---------------------------------------------------");
        apb_if.read(`SRC_ADDR, data);
        if (data===0)
            \$display("DMA_SRC(pass): %x", data);
        else begin
            \$display("DMA_SRC(fail): %x", data);
            @(posedge clk);
            \$finish;
        end
        apb_if.read(`DST_ADDR, data);
        if (data===0)
            \$display("DMA_DST(pass): %x", data);
        else begin
            \$display("DMA_DST(fail): %x", data);
            @(posedge clk);
            \$finish;
        end
        apb_if.read(`LEN_ADDR, data);
        if (data===0)
            \$display("DMA_LEN(pass): %x", data);
        else begin
            \$display("DMA_LEN(fail): %x", data);
            @(posedge clk);
            \$finish;
        end
        apb_if.read(`STAT_ADDR, data);
        if (data===1)
            \$display("DMA_STATUS(pass): %x", data);
        else begin
            \$display("DMA_STATUS(fail): %x", data);
            @(posedge clk);
            \$finish;
        end
    endtask
    task test_dma(input int src, input int dst, input int len);
        int data;
        int word;
        realtime elapsed_time;
        \$display("---------------------------------------------------");
        \$display("Load data to memory");
        \$display("---------------------------------------------------");
        for (int i=src; i<(src+len); i=i+4) begin
            word = \$random;
            u_mem.write_word(i, word);
        end
        \$display("---------------------------------------------------");
        \$display("Configuration test");
        \$display("---------------------------------------------------");
        apb_if.write(`SRC_ADDR, src);
        apb_if.read(`SRC_ADDR, data);
        if (data===src)
            \$display("DMA_SRC(pass): %x", data);
        else begin
            \$display("DMA_SRC(fail): %x", data);
            @(posedge clk);
            \$finish;
        end
        apb_if.write(`DST_ADDR, dst);
        apb_if.read(`DST_ADDR, data);
        if (data===dst)
            \$display("DMA_DST(pass): %x", data);
        else begin
            \$display("DMA_DST(fail): %x", data);
            @(posedge clk);
            \$finish;
        end
        apb_if.write(`LEN_ADDR, len);
        apb_if.read(`LEN_ADDR, data);
        if (data===len)
            \$display("DMA_LEN(pass): %x", data);
        else begin
            \$display("DMA_LEN(fail): %x", data);
            @(posedge clk);
            \$finish;
        end
        \$display("---------------------------------------------------");
        \$display("DMA start");
        \$display("---------------------------------------------------");
        apb_if.write(`START_ADDR, 32'h1);
        elapsed_time = \$realtime;
        \$display("---------------------------------------------------");
        \$display("Wait for a DMA completion");
        \$display("---------------------------------------------------");
        data = 0;
        while (data!=1) begin
            apb_if.read(`STAT_ADDR, data);
            repeat (100) @(posedge clk);
        end
        @(posedge clk);
        elapsed_time = \$realtime - elapsed_time;
        \$timeformat(-9, 0, " ns", 10);
        \$display("Elapsed time for DMA: %t", elapsed_time);
        \$display("---------------------------------------------------");
        \$display("DMA completed");
        \$display("---------------------------------------------------");
        repeat (len) @(posedge clk); // to make sure data is written
        \$display("---------------------------------------------------");
        \$display("verify data");
        \$display("---------------------------------------------------");
        for (int i=0; i<len; i=i+4) begin
            logic [31:0] src_word;
            logic [31:0] dst_word;
            src_word = u_mem.read_word(src+i);
            dst_word = u_mem.read_word(dst+i);
            if (src_word!==dst_word) begin
                \$display("Mismatch! (src:%x @%x, dst:%x @%x", src_word, src+i, dst_word, dst+i);
            end
        end
    endtask
    int src,
                    dst,
                    len;
    // main
    initial begin
        test_init();
        \$display("===================================================");
        \$display("================== First trial ====================");
        \$display("===================================================");
        src = 'h0000_1000;
        dst = 'h0000_2000;
        len = 'h0100;
        test_dma(src, dst, len);
        \$display("===================================================");
        \$display("================= Second trial ====================");
        \$display("===================================================");
        src = 'h1234_1234;
        dst = 'hABCD_ABCD;
        len = 'hFF00;
        test_dma(src, dst, len);
        \$display("===================================================");
        \$display("================== Third trial ====================");
        \$display("===================================================");
        src = 'hDEFE_C8ED;
        dst = 'h1234_1234;
        len = 'h0040;
        test_dma(src, dst, len);
        \$display("===================================================");
        \$display("================= Fourth trial ====================");
        \$display("===================================================");
        src = 'h0101_0101;
        dst = 'h1010_1010;
        len = 'h2480;
        test_dma(src, dst, len);
        \$display("===================================================");
        \$display("================== Fifth trial ====================");
        \$display("===================================================");
        src = 'h0000_2000;
        dst = 'h0000_4000;
        len = 'h0200;
        test_dma(src, dst, len);
        \$finish;
    end
    AXI_SLAVE u_mem (
        .clk (clk),
        .rst_n (rst_n),
        .aw_ch (aw_ch),
        .w_ch (w_ch),
        .b_ch (b_ch),
        .ar_ch (ar_ch),
        .r_ch (r_ch)
    );
    DMAC_TOP u_DUT (
        .clk (clk),
        .rst_n (rst_n),
        // APB interface
        .psel_i (apb_if.psel),
        .penable_i (apb_if.penable),
        .paddr_i (apb_if.paddr[11:0]),
        .pwrite_i (apb_if.pwrite),
        .pwdata_i (apb_if.pwdata),
        .pready_o (apb_if.pready),
        .prdata_o (apb_if.prdata),
        .pslverr_o (apb_if.pslverr),
        // AXI AW channel
        .awid_o (aw_ch.awid),
        .awaddr_o (aw_ch.awaddr),
        .awlen_o (aw_ch.awlen),
        .awsize_o (aw_ch.awsize),
        .awburst_o (aw_ch.awburst),
        .awvalid_o (aw_ch.awvalid),
        .awready_i (aw_ch.awready),
        // AXI W channel
        .wid_o (w_ch.wid),
        .wdata_o (w_ch.wdata),
        .wstrb_o (w_ch.wstrb),
        .wlast_o (w_ch.wlast),
        .wvalid_o (w_ch.wvalid),
        .wready_i (w_ch.wready),
        // AXI B channel
        .bid_i (b_ch.bid),
        .bresp_i (b_ch.bresp),
        .bvalid_i (b_ch.bvalid),
        .bready_o (b_ch.bready),
        // AXI AR channel
        .arid_o (ar_ch.arid),
        .araddr_o (ar_ch.araddr),
        .arlen_o (ar_ch.arlen),
        .arsize_o (ar_ch.arsize),
        .arburst_o (ar_ch.arburst),
        .arvalid_o (ar_ch.arvalid),
        .arready_i (ar_ch.arready),
        // AXI R channel
        .rid_i (r_ch.rid),
        .rdata_i (r_ch.rdata),
        .rresp_i (r_ch.rresp),
        .rlast_i (r_ch.rlast),
        .rvalid_i (r_ch.rvalid),
        .rready_o (r_ch.rready)
    );
endmodule
<<<EndOfFile:DMAC/SIM/TB/DMAC_TOP_TB.sv>>>
<<<StartOfFile:DMAC/SIM/TB/FIFO.sv>>>
module FIFO
#(
    parameter DATA_WIDTH = 32,
    parameter DATA_DEPTH_LG2= 4,
    parameter ALMOST_FULL = (1<<DATA_DEPTH_LG2)-1,
    parameter ALMOST_EMPTY = 1
 )
(
    input wire clk,
    input wire rst_n,
    // push interface
    output wire full_o,
    output wire afull_o, // almost full
    input wire wren_i,
    input wire [DATA_WIDTH-1:0] wdata_i,
    // pop interface
    output wire empty_o,
    output wire aempty_o, // almost empty
    input wire rden_i,
    output wire [DATA_WIDTH-1:0] rdata_o
);
localparam DATA_DEPTH = (1<<DATA_DEPTH_LG2);
localparam PTR_WIDTH = DATA_DEPTH_LG2+1;
reg [DATA_WIDTH-1:0][DATA_DEPTH] data;
reg [PTR_WIDTH-1:0] wrptr, wrptr_n,
                                rdptr, rdptr_n;
                                cnt, cnt_n;
always @(posedge clk)
    if (!rst_n) begin
        wrptr <= 'd0;
        rdptr <= 'd0;
        cnt <= 'd0;
    end
    else begin
        wrptr <= wrptr_n;
        rdptr <= rdptr_n;
        cnt <= cnt_n;
    end
always_comb begin
    wrptr_n = wrptr;
    rdptr_n = rdptr;
    cnt_n = cnt;
    if (wren_i) begin
        wrptr_n = wrptr + 'd1;
        cnt_n = cnt + 'd1;
    end
    if (rden_i) begin
        rdptr_n = rdptr + 'd1;
        // must be cnt_n to cover simultaneous wren and rden
        cnt_n = cnt_n - 'd1;
    end
end
always @(posedge clk)
    if (!rst_n) begin
        for (int i=0; i<DATA_DEPTH; i++) begin
            data[i] <= 'd0;
        end
    end
    else begin
        if (wren_i) begin
            data[wrptr] <= wdata_i;
        end
    end
assign full_o = (cnt==DATA_DEPTH);
assign afull_o = (cnt==ALMOST_FULL);
assign empty_o = (cnt=='d0);
assign aempty_o = (cnt==ALMOST_EMPTY);
assign rdata_o = data[rdptr];
endmodule
<<<EndOfFile:DMAC/SIM/TB/FIFO.sv>>>
<<<StartOfFile:DMAC/SIM/TB/filelist.f>>>
\$LAB_PATH/SIM/TB/timescale.v
\$LAB_PATH/SIM/TB/AXI_INTF.sv
\$LAB_PATH/SIM/TB/AXI_SLAVE.sv
\$LAB_PATH/SIM/TB/DMAC_TOP_TB.sv
<<<EndOfFile:DMAC/SIM/TB/filelist.f>>>
<<<StartOfFile:DMAC/SIM/TB/timescale.v>>>
`timescale 1ns/1ps
<<<EndOfFile:DMAC/SIM/TB/timescale.v>>>




Direct Memory Access (DMA) Controller
Design Document V1.0

1 Overview
This document specifies the design and implementation of a Direct Memory Access Controller (DMAC) as a part of System-on-a-Chip (SoC). The main purpose of this DMAC design is to integrate into SoC for exchange a large volume of data between memory and peripherals at high speed. The proposed DMAC works on ARM’s Advanced Microcontroller Bus Architecture (AMBA) specification. The DMAC provides an AMBA APB interface to configure the IP, and an AMBA AXI interface to transfer data.

2 Architecture Specification
2.1 General Description
Some applications require transferring a volume of data between memory and peripherals without any modification on data. In software, it is commonly served by executing the memcpy library function in C, C++ or other languages. In C, the function has the following interface and copies len bytes from the object pointed by src to the object pointed by dst: void* memcpy(void* dst, const void* src, size_t len).
While a pure software-based implementation of memcpy transfers data using CPU instructions, DMA does not use expensive CPU cycles but uses a hardware engine (DMAC) for the transfer. This can significantly speed up data transfers and allows using CPU for other jobs.
2.2 Usage Constraints
Below describe constraints in utilizing DMAC v1.
-The src and dst addresses are physical addresses.
-The src and dst addresses must be a multiple of 4.
-The len must be a multiple of 4.
-The maximum len is 0xFFFF
-Source and destination ranges must not overlap.
2.3 Programming Model
Software can use the following sequence to transfer data using DMAC.
-1.Write the source address to DMA_SRC register
-2.Write the destination address to DMA_DST register
-3.Write length to DMA_LEN register
-4.Write 1 to bit[0] of DMA_CMD register
-5.Wait until DMA_STATUS register has bit[0] as 1.

2.4 Register Map
In order to control DMAC, software can configure the following registers.
+--------+------------+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---+---+---+---+---+---+---+---+---+-------+
| Offset | Reg Name | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+--------+------------+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---+---+---+---+---+---+---+---+---+-------+
| 0x00 | DMA_VER | version |
+--------+------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| 0x04~0xFC | Reserved |
+--------+------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| 0x100 | DMA_SRC | start_addr |
+--------+------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| 0x104 | DMA_DST | start_addr |
+--------+------------+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+-------------------------------------------------------------------------+
| 0x108 | DMA_LEN | | | | | | | | | | | | | | | | | byte_len |
+--------+------------+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---+---+---+---+---+---+---+---+---+-------+
| 0x10C | DMA_CMD | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | start |
+--------+------------+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---+---+---+---+---+---+---+---+---+-------+
| 0x110 | DMA_STATUS | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | done |
+--------+------------+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---+---+---+---+---+---+---+---+---+-------+

2.4.1 DMA VERSION
| Field name | Bit range | R/W | Reset value | Desciption |
|------------|-----------|-----|-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| version | [31:0] | R | 0x0001_2024 | The version of this DMA controller. The upper 16 bits represent the major version. The lower 16 bits represent the released year of the version. This document describes behaviors of major version 1. |

2.4.2 DMA_SRC
| Field name | Bit range | R/W | Reset value | Desciption |
|------------|-----------|-----|-------------|------------------------------------|
| start_addr | [31:0] | R/W | 0x0000_0000 | start address of the source range. |

2.4.3 DMA_DST
| Field name | Bit range | R/W | Reset value | Desciption |
|------------|-----------|-----|-------------|-----------------------------------------|
| start_addr | [31:0] | R/W | 0x0000_0000 | start address of the destination range. |

2.4.4 DMA_LEN
| Field name | Bit range | R/W | Reset value | Desciption |
|------------|-----------|-----|-------------|-----------------------------------------------------------------------|
| byte_len | [15:0] | R/W | 0x0000 | Number of bytes to be transferred from the source to the destination. |

2.4.5 DMA_CMD Field
| Field name | Bit range | R/W | Reset value | Desciption |
|------------|-----------|-----|-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| start | [0] | W | N/A | Writing 1 to this field will initiate a DMA transfer based on DMA_SRC, DMA_DST, and DMA_LEN registers. Software must not write 1 when there’s an on-going transfer. Writing 0 to this field does not affect operation |

2.4.6 DMA_STATUS
| Field name | Bit range | R/W | Reset value | Desciption |
|------------|-----------|-----|-------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| done | [0] | R | 1 | This field is 1 when there’s no on-going DMA transfer. Software must wait this field to be 1 for a completion of a transfer. Software must not initiate a DMA transfer when this field is 0. |

3 Micro-architecture v1.1 Specification
This section describes microarchitecture of a simple DMAC. It reads data from memory, buffers the data, and write the data into memory. It repeats this procedure until it completes transferring the specified number of bytes.
For simplicity, it read/writes one-cycle data (4 bytes) at a time (in other words, burst-1 transfers). For simplicity, this microarchitecture does not consider write responses from the AXI interface. Later versions will support burst transfers and write responses.

3.1 External Interface
DMAC v1.1 has the following external interfaces to communicate with other hardware IPs.
-AMBA APB interface for configuration
-AMBA AXI interface for data transfer

The image you’ve uploaded is a diagram showing the on-chip interconnect of a computer system. Here’s a detailed description:
The diagram illustrates how the CPU core, memory, and DMAC (Direct Memory Access Controller) are connected through an on-chip interconnect.
The connections also include specific interfaces like Config interface (APB) and Data interface (AXI).
“CPU core” is a box on the left side connected to the central “On-chip interconnect” cloud shape with a bidirectional arrow.
Below the “CPU core,” there’s another box labeled “Memory,” also connected to the “On-chip interconnect” with a bidirectional arrow.
On the right side, there’s a box labeled “DMAC” connected to both “Config interface (APB)” and “Data interface (AXI)” which are in turn connected to the central “On-chip interconnect” with bidirectional arrows.
The arrows indicate that data can flow in both directions between these components.

3.2 Block Diagram
DMAC v1.1 has the following blocks inside.

The diagram is divided into three main blocks labeled “DMAC_TOP,” “DMAC_CFG,” and “DMAC_ENGINE.”
“clk” and “rst” are inputs to the “DMAC_TOP” block.
An arrow labeled “APB” connects the “DMAC_TOP” block to the “DMAC_CFG” block.
Another arrow labeled “AXI” connects both the “DMAC_TOP” and “DMAC_CFG” blocks to the “DMAC_ENGINE” block.
Inside the “DMAC_ENGINE” block, there are four internal components labeled as follows:
SRC_ADDR
DST_ADDR
CNT
DATA BUF
There’s also a small circular graph with nodes labeled 0 to 3 inside this block.
This diagram is likely used to illustrate the flow of data or control signals between these components in a Direct Memory Access Controller configuration. Please let me know if you need more information!

3.3 Configuration Register (lab2)
This block receives read/write requests from the APB and configures the registers describes in Section 2.4.

3.4 Finite State Machine (lab3)
DMA engine utilizes the following state machine to control operations.

The diagram contains five blue circles representing different states: IDLE, RREQ, RDATA, WREQ, and WDATA.
Arrows connect these circles indicating the flow from one state to another.
Each arrow has text annotations that describe the conditions for transitioning from one state to another. For example, transitioning from IDLE to RREQ requires writing 1 to DMA_CMD & LEN!=0, and copying DMA_SRC/DST/LEN.
There are also annotations on the state circles themselves, such as “done=1” on IDLE and “AWVALID=1” on WDATA.

+-------+--------------------------------------------+------------+-----------------------------------------------------------+----------------------------------------+
| State | Major outputs | Next State | Next state transition condition | Notes |
| +---------+--------+---------+--------+------+ | | |
| | ARVALID | RREADY | AWVALID | WVALID | done | | | |
+-------+---------+--------+---------+--------+------+------------+-----------------------------------------------------------+----------------------------------------+
| IDLE | 0 | 0 | 0 | 0 | 1 | RREQ | (DMA_CMD.start is written as 1) and (DMA_LEN.byte_len!=0) | On moving out, |
| | | | | | | | | - Copy DMA_SRC to SRC_ADDR. |
| | | | | | | | | - Copy DMA_DST to DST_ADDR |
| | | | | | | | | - Copy DMA_LEN to the internal counter |
+-------+---------+--------+---------+--------+------+------------+-----------------------------------------------------------+----------------------------------------+
| RREQ | 1 | 0 | 0 | 0 | 0 | RDATA | ARREADY=1 | On moving out, |
| | | | | | | | | - Increment ARADDR by 4 |
+-------+---------+--------+---------+--------+------+------------+-----------------------------------------------------------+----------------------------------------+
| RDATA | 0 | 1 | 0 | 0 | 0 | WREQ | RVALID=1 | On moving out, |
| | | | | | | | | - Buffer RDATA into the data buffer |
+-------+---------+--------+---------+--------+------+------------+-----------------------------------------------------------+----------------------------------------+
| WREQ | 0 | 0 | 1 | 0 | 0 | WDATA | AWREADY=1 | On moving out, |
| | | | | | | | | - Increment AWADDR by 4 |
| | | | | | | | | - Decrement the internal counter by 4 |
+-------+---------+--------+---------+--------+------+------------+-----------------------------------------------------------+----------------------------------------+
| WDATA | 0 | 0 | 0 | 1 | 0 | RREQ | (WREADY=1) & (counter!=0) | |
| | | | | | +------------+-----------------------------------------------------------+----------------------------------------+
| | | | | | | IDLE | (WREADY=1) & (counter==0) | |
+-------+---------+--------+---------+--------+------+------------+-----------------------------------------------------------+----------------------------------------+



The diagram contains horizontal lines representing different signals or data paths labeled as “clk”, “state”, “write to CMD”, “AR*”, “R*”, “AW*” and “W*”.
Each line has different states represented by segments of varying lengths; these include labels like “IDLE”, “RREQ”, “RDATA”, “WREQ”, “WDATA”.
Vertical dashed lines indicate transitions between these states.
There are three rectangular boxes labeled as ‘SRC’, ‘DST’, and ‘DATA’ connected to the waveform lines indicating sources, destinations, or data types associated with those specific points in time.
Numbers from 0 to 16 are marked at the bottom of the image indicating time intervals or clock cycles.

{ "signal": [
    { "name": "clk", "wave": "p....|.........." },
    { "name": "state", "wave": "2.3.4|..5.6.2...", "data": ["IDLE", "RREQ", "RDATA", "WREQ", "WDATA", "IDLE"] },
    { "name": "write to CMD", "wave": "010..|..........", "data": ["1"] },
    {},
    [ "AR ch",
        { "name": "ARVALID(out)", "wave": "0.1.0|..........", "data": ["SRC"] },
        { "name": "ARADDR(out)", "wave": "x.3.x|..........", "data": ["SRC"] },
        { "name": "ARLEN(out)", "wave": "2....|..........", "data": ["0"] },
        { "name": "ARREADY(in)", "wave": "0..10|.........." },
    ],
    [ "R ch",
        { "name": "RREADY(out)", "wave": "0...1|..0......." },
        { "name": "RVALID(in)", "wave": "0....|.10......." },
        { "name": "RDATA(in)", "wave": "x....|.4x.......", "data": ["DATA"] },
    ],
    [ "AW ch",
        { "name": "AWVALID(out)", "wave": "0....|..1.0....." },
        { "name": "AWADDR(out)", "wave": "x....|..5.x.....", "data": ["DST"] },
        { "name": "AWLEN(out)", "wave": "2....|..........", "data": ["0"] },
        { "name": "AWREADY(in)", "wave": "0....|...10....." },
    ],
    [ "W ch",
        { "name": "WVALID(out)", "wave": "0....|....1.0..." },
        { "name": "WDATA(out)", "wave": "x....|....4.x...", "data": ["DATA"] },
        { "name": "WREADY(in)", "wave": "0....|.....10..." }
    ]
  ],
    "head" : {
    "tick" : "0"
    },
     "foot" : {
     "tick" : "0"
     }
  }
그림 1. DMA operation with microarchitecture v1.1

4 Micro-architecture v1.2 Specification (lab4)
A problem with microarchitecture v1.1 is that it reads/writes data one-by-one. As memory read takes some time, DMAC v1.1 will suffer from poor performance with a long memory read latency (그림 2). We will improve the microarchitecture to transfer a burst of data to minimize performance degradation.

{ "signal": [
    { "name": "clk", "wave": "p....|.................." },
    { "name": "state", "wave": "2.3.4|..5.6.3.4|..5.6.3.", "data": ["IDLE", "RREQ", "RDATA", "WREQ", "WDATA", "RREQ", "RDATA", "WREQ", "WDATA", "RREQ"] },
    { "name": "write to CMD", "wave": "010..|.........|........", "data": ["1"] },
    {},
    [ "AR ch",
        { "name": "ARVALID(out)", "wave": "0.1.0|......1.0|......1.", "data": ["SRC"] },
        { "name": "ARADDR(out)", "wave": "x.3.x|......3.x|......3.", "data": ["SRC", "SRC+4", "SRC+8"] },
        { "name": "ARLEN(out)", "wave": "2....|.........|........", "data": ["0"] },
        { "name": "ARREADY(in)", "wave": "0..10|.......10|.......1" },
    ],
    [ "R ch",
        { "name": "RREADY(out)", "wave": "0...1|..0.....1|..0....." },
        { "name": "RVALID(in)", "wave": "0....|.10......|.10....." },
        { "name": "RDATA(in)", "wave": "x....|.4x......|.4x.....", "data": ["DATA", "DATA"] },
    ],
    [ "AW ch",
        { "name": "AWVALID(out)", "wave": "0....|..1.0....|..1.0..." },
        { "name": "AWADDR(out)", "wave": "x....|..5.x....|..5.x...", "data": ["DST", "DST+4"] },
        { "name": "AWLEN(out)", "wave": "2....|.........|........", "data": ["0"] },
        { "name": "AWREADY(in)", "wave": "0....|...10....|...10..." },
    ],
    [ "W ch",
        { "name": "WVALID(out)", "wave": "0....|....1.0..|....1.0." },
        { "name": "WDATA(out)", "wave": "x....|....4.x..|....4.x.", "data": ["DATA", "DATA"] },
        { "name": "WREADY(in)", "wave": "0....|.....10..|.....10." }
    ]
  ],
    "head" : {
    "tick" : "0"
    },
     "foot" : {
     "tick" : "0"
     }
  }
그림 2. DMA operation with microarchitecture 1.1. At a time, it transfers single burst of data

In Microarchitecture version 2, DMAC transfers up to 16 cycles of data with a single access. This can significantly reduce execution time by transferring data in bursts (그림 3).