// modelling dma_sequencer.v together with dma_access.v
 
 
 
module tb_dma2;
 
 
 
 
 
   parameter DEVNUM = 4;
 
 
 
 
 
   integer i,j,k;
 
 
 
 
 
   tri1 iorq_n,mreq_n,rd_n,wr_n;
 
   reg clk,rst_n;
 
   wire busrq_n,busak_n;
 
   trireg [15:0] zaddr;
 
   tri  [7:0] zdata;
 
 
 
 
 
   wire dma_req,dma_rnw;
 
   wire dma_ack,dma_end;
 
   wire dma_busynready;
 
 
 
   wire [20:0] dma_addr;
 
   wire  [7:0] dma_wd;
 
   wire  [7:0] dma_rd;
 
 
 
   reg  [DEVNUM:1] req;
 
   reg  [DEVNUM:1] rnw;
 
   wire [DEVNUM:1] done;
 
   wire [DEVNUM:1] ack;
 
 
 
   reg [20:0] addr[1:DEVNUM];
 
   reg  [7:0]   wd[1:DEVNUM];
 
   reg  [7:0]   rd;
 
 
 
 
 
 
 
   wire mem_dma_bus;
 
   wire [15:0] mem_dma_addr;
 
   wire [7:0] mem_dma_wd;
 
   wire [7:0] mem_dma_rd;
 
   wire mem_dma_rnw;
 
   wire mem_dma_oe;
 
   wire mem_dma_we;
 
 
 
 
 
 
 
   T80a z80( .RESET_n(rst_n),
 
             .CLK_n(clk),
 
             .WAIT_n(1'b1),
 
             .INT_n(1'b1),
 
             .NMI_n(1'b1),
 
             .MREQ_n(mreq_n),
 
             .IORQ_n(iorq_n),
 
             .RD_n(rd_n),
 
             .WR_n(wr_n),
 
             .BUSRQ_n(busrq_n),
 
             .BUSAK_n(busak_n),
 
             .A(zaddr),
 
             .D(zdata) );
 
 
 
 
 
 
 
   rom myrom( .addr(zaddr),
 
              .data(zdata),
 
              .ce_n( (zaddr<16'h8000)?(mreq_n|rd_n):1'b1 ) );
 
 
 
 
 
   assign zaddr = mem_dma_bus ? mem_dma_addr[15:0] : 16'hZZZZ;
 
 
 
   assign zdata = (mem_dma_bus&(!mem_dma_rnw)) ? mem_dma_wd : 8'hZZ;
 
   assign mem_dma_rd = zdata;
 
 
 
   ram myram( .addr(zaddr),
 
              .data(zdata),
 
              .ce_n( (zaddr>=16'h8000)?1'b0:1'b1 ),
 
              .oe_n( mem_dma_bus ? mem_dma_oe : (mreq_n|rd_n) ),
 
              .we_n( mem_dma_bus ? mem_dma_we : (mreq_n|wr_n) ) );
 
 
 
 
 
   dma_sequencer myseq( .clk(clk),
 
                        .rst_n(rst_n),
 
 
 
                        .addr(addr),
 
                        .wd(wd),
 
                        .rd(rd),
 
                        .req(req),
 
                        .rnw(rnw),
 
                        .ack(ack),
 
                        .done(done),
 
 
 
                        .dma_req(dma_req),
 
                        .dma_rnw(dma_rnw),
 
                        .dma_ack(dma_ack),
 
                        .dma_end(dma_end),
 
                        .dma_addr(dma_addr),
 
                        .dma_wd(dma_wd),
 
                        .dma_rd(dma_rd) );
 
 
 
 
 
   dma_access mydma( .dma_req(dma_req),
 
                     .dma_rnw(dma_rnw),
 
                     .dma_ack(dma_ack),
 
                     .dma_end(dma_end),
 
                     .dma_addr(dma_addr),
 
                     .dma_wd(dma_wd),
 
                     .dma_busynready(dma_busynready),
 
 
 
                     .mem_dma_rd(zdata),
 
                     .mem_dma_wd(mem_dma_wd),
 
                     .mem_dma_bus(mem_dma_bus),
 
                     .mem_dma_addr(mem_dma_addr),
 
                     .mem_dma_rnw(mem_dma_rnw),
 
                     .mem_dma_oe(mem_dma_oe),
 
                     .mem_dma_we(mem_dma_we),
 
 
 
                     .clk(clk),
 
                     .rst_n(rst_n),
 
                     .busrq_n(busrq_n),
 
                     .busak_n(busak_n) );
 
 
 
 
 
 
 
        reg start  [1:DEVNUM];
 
        reg rnw_in [1:DEVNUM];
 
        wire inprogress [1:DEVNUM];
 
 
 
 
 
 
 
        generate
 
                genvar gv;
 
                for(gv=1;gv<=DEVNUM;gv=gv+1)
 
                begin : dmaers
 
                        dmaer g( .clk(clk), .rst_n(rst_n),
 
                                 .start(start[gv]),
 
                                 .rnw_in(rnw_in[gv]),
 
                                 .inprogress(inprogress[gv]),
 
                                 .req(req[gv]),
 
                                 .rnw(rnw[gv]),
 
                                 .ack(ack[gv]),
 
                                 .done(done[gv]) );
 
                end
 
        endgenerate
 
 
 
 
 
 
 
 
 
        initial
 
        begin
 
                clk <= 1'b0;
 
            forever #40 clk <= ~clk;
 
        end
 
 
 
 
 
        initial
 
        begin
 
                rst_n <= 1'b0;
 
 
 
                for(i=1;i<=DEVNUM;i=i+1)
 
                begin
 
                        start[i] <= 1'b0;
 
                        rnw_in[i] <= 1'b1;
 
                end
 
 
 
 
 
                @(posedge clk);
 
                @(posedge clk);
 
                @(posedge clk);
 
                rst_n <= 1'b1;
 
                @(posedge clk);
 
 
 
 
 
 
 
 
 
/*              start[1] <= 1'b1;
 
                @(posedge ack[1]);
 
                start[1] <= 1'b0;
 
 
 
                @(negedge inprogress[1]);
 
*/
 
                repeat (5) @(posedge clk);
 
 
 
 
 
 
 
                rnw_in[1] = 1'b1;
 
                rnw_in[2] = 1'b0;
 
                start[1] = 1'b1;
 
                start[2] = 1'b1;
 
 
 
                fork
 
                begin
 
                        @(posedge ack[1]);
 
                        start[1] <= 1'b0;
 
                end
 
                begin
 
                        @(posedge ack[2]);
 
                        start[2] <= 1'b0;
 
                end
 
                join
 
 
 
 
 
//              $stop;
 
 
 
 
 
 
 
        end
 
 
 
 
 
 
 
 
 
endmodule
 
 
 
 
 
 
 
 
 
module dmaer(
 
 
 
        input clk,
 
        input rst_n,
 
 
 
        input start,
 
        input rnw_in,
 
 
 
        output reg inprogress,
 
 
 
        output reg req,
 
        output reg rnw,
 
        input      ack,
 
        input      done
 
);
 
 
 
 
 
        initial
 
        begin
 
                inprogress = 1'b0;
 
                req        = 1'b0;
 
                rnw        = 1'b1;
 
        end
 
 
 
 
 
        always @(negedge rst_n)
 
        begin
 
                disable main_loop;
 
 
 
                req <= 1'b0;
 
                rnw <= 1'b1;
 
                inprogress <= 1'b0;
 
        end
 
 
 
 
 
        always
 
        begin : main_loop
 
 
 
                wait(rst_n);
 
 
 
                wait(start);
 
 
 
              begin : dma_loop
 
                        forever
 
                        begin
 
                                inprogress <= 1'b1;
 
                                rnw <= rnw_in;
 
                                req <= 1'b1;
 
 
 
                                @(negedge ack);
 
                                if( !start ) disable dma_loop;
 
                        end
 
                end
 
 
 
                req <= 1'b0;
 
                wait(done);/*@(posedge done);*/
 
                inprogress <= 1'b0;
 
        end
 
 
 
 
 
 
 
endmodule