Subversion Repositories ngs

Rev

Rev 97 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
97 lvd 1
// part of NeoGS project (c) 2008-2013 NedoPC
2 lvd 2
 
3
// dma sequencer
4
 
5
/*
6
 
7
input interface of every DMA end-user
8
 
9
clocks: ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^
10
reqN    _______/```````````\______________/`````````````````\______________/``````````````````
11
ackN    ________________/``\_____________________________/``\____________________/``\__/``\__/
12
doneN   _________________________/``\_____________________________/``\______________/``\__/``\
13
rnwN    -------/```````````\--------------\_________________/--------------/````````\_____/```
14
adrwdN  -------< read addr >--------------< write addr&data >--------------< rdaddr X wra X rd
15
rdN     -------------------------<dd>-----------------------------------------------<dd>------
16
 
17
 
18
sequencing algorithm is round-robin with fixed initial prioritizing when multiple requests appear simultaneously while
19
everything was idle
20
 
21
*/
22
 
23
 
24
module dma_sequencer(
25
 
26
        input wire clk,
27
        input wire rst_n,
28
 
29
        // dma requests connection
30
        //
31
        input wire req0,
32
        input wire req1,
33
        input wire req2,
34
        input wire req3,
35
 
62 lvd 36
        input wire [21:0] addr0,
37
        input wire [21:0] addr1,
38
        input wire [21:0] addr2,
39
        input wire [21:0] addr3,
2 lvd 40
 
41
        input wire rnw0,
42
        input wire rnw1,
43
        input wire rnw2,
44
        input wire rnw3,
45
 
46
        input wire [7:0] wd0,
47
        input wire [7:0] wd1,
48
        input wire [7:0] wd2,
49
        input wire [7:0] wd3,
50
 
51
 
52
        output wire ack0,
53
        output wire ack1,
54
        output wire ack2,
55
        output wire ack3,
56
 
57
        output wire end0,
58
        output wire end1,
59
        output wire end2,
60
        output wire end3,
61
 
62
//      dma controller connection
63
        output wire        dma_req,
62 lvd 64
        output wire [21:0] dma_addr,
2 lvd 65
        output wire        dma_rnw,
66
        output wire  [7:0] dma_wd,
67
 
68
        input  wire        dma_ack,
69
        input  wire        dma_end
70
);
71
        localparam DEVNUM = 4;
72
 
73
 
74
 
75
        wire [DEVNUM-1:0] reqs;
62 lvd 76
        wire       [21:0] addrs [0:DEVNUM-1];
2 lvd 77
        wire [DEVNUM-1:0] rnws;
78
        wire        [7:0] wds   [0:DEVNUM-1];
79
        wire [DEVNUM-1:0] acks;
80
        wire [DEVNUM-1:0] ends;
81
 
82
 
83
        // aggregate signals for brewity
84
        assign reqs[DEVNUM-1:0] = {req3,req2,req1,req0};
85
        assign addrs[0] = addr0;
86
        assign addrs[1] = addr1;
87
        assign addrs[2] = addr2;
88
        assign addrs[3] = addr3;
89
        assign rnws[DEVNUM-1:0] = {rnw3,rnw2,rnw1,rnw0};
90
        assign wds[0] = wd0;
91
        assign wds[1] = wd1;
92
        assign wds[2] = wd2;
93
        assign wds[3] = wd3;
94
        assign {ack3,ack2,ack1,ack0} = acks[DEVNUM-1:0];
95
        assign {end3,end2,end1,end0} = ends[DEVNUM-1:0];
96
 
97
 
98
 
99
 
100
 
101
        reg  [DEVNUM-1:0] cur_input_mux;  // which current input is muxed to the DMA  (input=req,ack,addr,wd)
102
        reg  [DEVNUM-1:0] cur_output_mux; // which current output is muxed to the DMA (output=end)
103
 
104
        wire [DEVNUM-1:0] next_input_mux;
105
 
106
        reg busy;
107
 
108
 
109
        always @(posedge clk, negedge rst_n)
110
        begin
111
                if( !rst_n )
112
                        busy = 1'b0;
113
                else // posedge clk
114
                begin
115
                        if( !busy )
116
                                busy <= |reqs;
117
                        else // busy
118
                                busy <= dma_req;
119
                end
120
        end
121
 
122
 
123
        always @(posedge clk, negedge rst_n)
124
        begin
125
                if( !rst_n )
126
                begin
97 lvd 127
                        cur_input_mux  = {DEVNUM{1'b0}}; // to remove static priority selection after idle -- have here 'd1!
2 lvd 128
                end
129
                else // posedge clk
130
                begin
131
                        if( (!busy) || dma_ack ) // idle or dma acknoledges data receive
132
                        begin
133
                                cur_input_mux <= next_input_mux;
134
                        end
135
                end
136
        end
137
 
138
        rr_arbiter #( .DEVNUM(DEVNUM) ) rr_arbiter(
139
                .reqs(reqs),
140
                .prev( cur_input_mux),
141
                .next(next_input_mux)
142
        );
143
 
144
 
145
 
146
        // output mux should follow input after dma_ack
147
        //
148
        always @(posedge clk, negedge rst_n)
149
        begin
150
                if( !rst_n )
151
                begin
152
                        cur_output_mux = {DEVNUM{1'b0}};
153
                end
154
                else // posedge clk
155
                begin
156
                        if( dma_ack )
157
                                cur_output_mux <= cur_input_mux;
158
                end
159
        end
160
 
161
 
162
 
163
 
164
 
165
        // actual muxing of input data
166
        //
167
        wor         int_dma_req;  // wor is to do easily decoded AND-OR muxes
168
        wor  [20:0] int_dma_addr; //
169
        wand        int_dma_rnw;  // this is WAND to have it 1 in idle
170
        wor   [7:0] int_dma_wd;   //
171
        //
172
        genvar i;
173
        generate
174
                for(i=0;i<DEVNUM;i=i+1)
175
                begin : mux_dma_inputs
176
 
177
                        assign int_dma_req  =     cur_input_mux[i]   &  reqs[i]; // wired OR happens!
178
                        assign int_dma_addr = {21{cur_input_mux[i]}} & addrs[i]; //
179
                        assign int_dma_rnw  =   (~cur_input_mux[i])  |  rnws[i]; // wired AND...
180
                        assign int_dma_wd   =  {8{cur_input_mux[i]}} &   wds[i]; //
181
                end
182
        endgenerate
183
        //
184
        // output data to dma controller
185
        //
186
        assign dma_req  = int_dma_req;
187
        assign dma_addr = int_dma_addr;
188
        assign dma_rnw  = int_dma_rnw;
189
        assign dma_wd   = int_dma_wd;
190
 
191
        // actual de-muxing of output data from dma controller
192
        //
193
        assign acks = cur_input_mux  & {DEVNUM{dma_ack}};
194
        assign ends = cur_output_mux & {DEVNUM{dma_end}};
195
 
196
endmodule
197
 
198
 
199
 
200
 
201
 
202
 
203
// round-robin arbiter
204
module rr_arbiter(
205
        /*input  wire [DEVNUM-1:0]*/ reqs,
206
        /*input  wire [DEVNUM-1:0]*/ prev,
207
 
208
        /*output wire [DEVNUM-1:0]*/ next
209
);
210
        parameter DEVNUM=4;
211
 
212
 
213
        input  wire [DEVNUM-1:0] reqs;
214
        input  wire [DEVNUM-1:0] prev;
215
 
216
        output wire [DEVNUM-1:0] next;
217
 
218
 
219
 
220
        genvar i;
221
 
222
 
223
 
224
        // arbitration if there was previous actives
225
        //
226
        wire [DEVNUM-1:0] loop;
227
        wire [DEVNUM-1:0] next_arb;
228
 
229
        generate
230
                for(i=0;i<DEVNUM;i=i+1)
231
                begin : gen_forwarders
232
 
233
                        if( i==0 )
234
                                rr_fwd forwarder( .prev(prev[i]),
235
                                                  .req(reqs[i]),
236
                                                  .next(next_arb[i]),
237
                                                  .loop_in(loop[DEVNUM-1]),
238
                                                  .loop_out(loop[i]) );
239
                        else
240
                                rr_fwd forwarder( .prev(prev[i]),
241
                                                  .req(reqs[i]),
242
                                                  .next(next_arb[i]),
243
                                                  .loop_in(loop[i-1]),
244
                                                  .loop_out(loop[i]) );
245
                end
246
        endgenerate
247
 
248
 
249
        // arbitration if there was no actives prior to requests
250
        //
251
        wire  [DEVNUM-1:0] next_empty;
252
 
253
        generate
254
                for(i=0;i<DEVNUM;i=i+1)
255
                begin : pri_enc
256
                        if( i==0 )
257
                        begin : pri_zero
258
                                assign next_empty[0] = reqs[0];
259
                        end
260
                        else
261
                        begin : pri_nonzero
262
                                assign next_empty[i] = reqs[i] & ( ~|reqs[i-1:0] );
263
                        end
264
                end
265
        endgenerate
266
 
267
 
268
        // select between prev-busy and prev-free cases
269
        assign next = ( prev ) ? next_arb : next_empty;
270
 
271
endmodule
272
 
273
 
274
// round-robin request forwarder (1 bit)
275
module rr_fwd(
276
        input  wire prev,  // who was arbitrated last time (one-hot)
277
        input  wire req,   // who are requesting
278
        output reg  next, // who will be next
279
 
280
        input  wire loop_in, // for internal arbitration
281
        output reg  loop_out //
282
);
283
 
284
        always @*
285
        begin
286
                if( prev )
287
                begin
288
                        loop_out = 1'b1;
289
                end
290
                else //!prev
291
                begin
292
                        loop_out = req ? 1'b0 : loop_in;
293
                end
294
        end
295
 
296
        always @*
297
        begin
298
                next = req ? loop_in : 1'b0;
299
        end
300
 
301
endmodule