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 |