// part of NeoGS project
 
//
 
// (c) NedoPC 2007-2008
 
//
 
// modelling is in tb_dma2.*
 
 
 
module dma_sequencer(
 
 
 
        clk,
 
        rst_n,
 
 
 
        addr,
 
        wd,
 
 
 
        rd,
 
 
 
        req,
 
        rnw,
 
        ack,
 
        done,
 
 
 
        dma_req,
 
        dma_addr,
 
        dma_rnw,
 
        dma_wd,
 
        dma_rd,
 
 
 
        dma_ack,
 
        dma_end
 
);
 
 
 
        parameter DEVNUM = 4;
 
 
 
 
 
        input clk;
 
        input rst_n;
 
 
 
 
 
        input       [20:0] addr [1:DEVNUM];
 
        input        [7:0] wd   [1:DEVNUM];
 
 
 
        output reg   [7:0] rd;
 
 
 
        input              [DEVNUM:1] req;
 
        input              [DEVNUM:1] rnw;
 
 
 
        output reg         dma_req;
 
        output reg         dma_rnw;
 
        output reg  [20:0] dma_addr;
 
        output reg   [7:0] dma_wd;
 
        input        [7:0] dma_rd;
 
 
 
        input              dma_ack;
 
        input              dma_end;
 
 
 
 
 
 
 
        output reg [DEVNUM:1] ack;
 
        output reg [DEVNUM:1] done;
 
 
 
        reg [DEVNUM:1] muxbeg;
 
        reg [DEVNUM:1] muxend;
 
        reg [DEVNUM:1] muxend_in;
 
 
 
        reg [DEVNUM:1] pri_in;
 
        reg [DEVNUM:1] pri_out;
 
 
 
 
 
 
 
 
 
 
 
        integer i;
 
 
 
        always @*
 
                for(i=1;i<=DEVNUM;i=i+1)
 
                begin
 
                        pri_in[i]  = (i==1) ? pri_out[DEVNUM] : pri_out[i-1];
 
                        pri_out[i] = ( pri_in[i] & (~req[i]) ) | muxend[i];
 
 
 
                        muxbeg[i]    = pri_in[i] & req[i];
 
                        muxend_in[i] = muxbeg[i] & dma_ack;
 
                end
 
 
 
        always @(posedge clk, negedge rst_n)
 
        begin
 
                if( !rst_n )
 
                begin
 
                        muxend[1] <= 1'b1;
 
                        for(i=2;i<=DEVNUM;i=i+1)
 
                                muxend[i] <= 1'b0;
 
                end
 
                else if( dma_ack )
 
                begin
 
                        for(i=1;i<=DEVNUM;i=i+1)
 
                                muxend[i] <= muxend_in[i];
 
                end
 
        end
 
 
 
 
 
 
 
 
 
 
 
        always @*
 
        begin
 
                rd = dma_rd;
 
 
 
                dma_req = 1'b0;
 
                for(i=1;i<=DEVNUM;i=i+1)
 
                        dma_req = dma_req | req[i];
 
 
 
                dma_wd = 8'd0;
 
                for(i=1;i<=DEVNUM;i=i+1)
 
                        dma_wd = dma_wd | ( (muxbeg[i]==1'b1) ? wd[i] : 8'd0 );
 
 
 
                dma_addr = 21'd0;
 
                for(i=1;i<=DEVNUM;i=i+1)
 
                        dma_addr = dma_addr | ( (muxbeg[i]==1'b1) ? addr[i] : 21'd0 );
 
 
 
                dma_rnw = 1'b0;
 
                for(i=1;i<=DEVNUM;i=i+1)
 
                        dma_rnw = dma_rnw | ( (muxbeg[i]==1'b1) ? rnw[i] : 1'b0 );
 
 
 
 
 
                for(i=1;i<=DEVNUM;i=i+1)
 
                        ack[i] = (muxbeg[i]==1'b1) ? dma_ack : 1'b0;
 
 
 
                for(i=1;i<=DEVNUM;i=i+1)
 
                        done[i] = (muxend[i]==1'b1) ? dma_end : 1'b0;
 
 
 
        end
 
 
 
 
 
 
 
 
 
 
 
endmodule