Rev 61 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | lvd | 1 | // part of NeoGS project |
2 | // |
||
3 | // (c) NedoPC 2007-2008 |
||
4 | // |
||
5 | // modelling is in tb_dma1.* |
||
6 | // look also at dma_access.png |
||
7 | |||
8 | module dma_access( |
||
9 | |||
10 | input clk, |
||
11 | |||
12 | input rst_n, |
||
13 | |||
14 | |||
15 | input dma_req, // DMA request |
||
62 | lvd | 16 | input [21:0] dma_addr, // DMA address (2mb) |
2 | lvd | 17 | input dma_rnw, // DMA READ/nWRITE |
18 | input [7:0] dma_wd, // DMA data to write |
||
19 | output reg [7:0] dma_rd, // DMA data just read |
||
20 | |||
21 | output reg dma_busynready, // DMA BUSY/nREADY |
||
22 | output reg dma_ack, // positive pulse as dma_busynready goes high |
||
23 | output reg dma_end, // positive pulse as dma_busynready goes low |
||
24 | |||
25 | output wire mem_dma_bus, // DMA taking over the bus |
||
62 | lvd | 26 | output wire [21:0] mem_dma_addr, // DMA address going to the bus |
2 | lvd | 27 | output wire [7:0] mem_dma_wd, // DMA data going to the bus |
28 | input [7:0] mem_dma_rd, // DMA data going from the bus |
||
29 | output wire mem_dma_rnw, // DMA bus direction (1=read, 0=write) |
||
30 | output reg mem_dma_oe, // DMA read strobe going to the bus |
||
31 | output reg mem_dma_we, // DMA write pulse going to the bus |
||
32 | |||
33 | |||
34 | output reg busrq_n, // CPU signals |
||
35 | input busak_n // control |
||
36 | ); |
||
37 | |||
38 | reg dma_bus; |
||
39 | |||
62 | lvd | 40 | reg [21:0] int_dma_addr; |
2 | lvd | 41 | reg int_dma_rnw; |
42 | reg [7:0] int_dma_wd; |
||
43 | wire [7:0] int_dma_rd; |
||
44 | |||
45 | assign mem_dma_bus = dma_bus; |
||
46 | assign mem_dma_addr = int_dma_addr; |
||
47 | assign mem_dma_wd = int_dma_wd; |
||
48 | assign mem_dma_rnw = int_dma_rnw; |
||
49 | assign int_dma_rd = mem_dma_rd; |
||
50 | |||
51 | |||
52 | |||
53 | localparam IDLE = 0; |
||
54 | localparam START = 1; |
||
55 | localparam WACK = 2; |
||
56 | localparam READ1 = 3; |
||
57 | localparam READ2 = 4; |
||
58 | localparam WRITE1 = 5; |
||
59 | localparam WRITE2 = 6; |
||
60 | |||
61 | |||
62 | reg [3:0] state; |
||
63 | reg [3:0] next_state; |
||
64 | |||
65 | |||
66 | |||
67 | |||
68 | // for simulation purposes |
||
69 | initial |
||
70 | begin |
||
71 | state <= IDLE; |
||
72 | busrq_n <= 1'b1; |
||
73 | mem_dma_oe <= 1'b1; |
||
74 | mem_dma_we <= 1'b1; |
||
75 | end |
||
76 | |||
77 | |||
78 | // FSM |
||
79 | always @(posedge clk, negedge rst_n) |
||
80 | begin |
||
81 | if( !rst_n ) |
||
82 | state <= IDLE; |
||
83 | else |
||
84 | state <= next_state; |
||
85 | end |
||
86 | |||
87 | |||
88 | always @* |
||
89 | begin |
||
90 | case( state ) |
||
91 | ////////////////////////////////////////////////////////////////////////////////////////// |
||
92 | IDLE: |
||
93 | begin |
||
94 | if( dma_req==1'b1 ) |
||
95 | next_state <= START; |
||
96 | else |
||
97 | next_state <= IDLE; |
||
98 | end |
||
99 | ////////////////////////////////////////////////////////////////////////////////////////// |
||
100 | START: |
||
101 | begin |
||
102 | next_state <= WACK; |
||
103 | end |
||
104 | ////////////////////////////////////////////////////////////////////////////////////////// |
||
105 | WACK: |
||
106 | begin |
||
107 | if( busak_n == 1'b1 ) ///// ACHTUNG WARNING!!! probably use here registered busak? |
||
108 | next_state <= WACK; |
||
109 | else // busak_n == 1'b0 |
||
110 | begin |
||
111 | if( int_dma_rnw == 1'b1 ) // read |
||
112 | next_state <= READ1; |
||
113 | else // int_dma_rnw == 1'b0 - write |
||
114 | next_state <= WRITE1; |
||
115 | end |
||
116 | end |
||
117 | ////////////////////////////////////////////////////////////////////////////////////////// |
||
118 | READ1: |
||
119 | begin |
||
120 | next_state <= READ2; |
||
121 | end |
||
122 | ////////////////////////////////////////////////////////////////////////////////////////// |
||
123 | READ2: |
||
124 | begin |
||
125 | if( dma_req == 1'b0 ) |
||
126 | next_state <= IDLE; |
||
127 | else // dma_req == 1'b1 |
||
128 | begin |
||
129 | if( dma_rnw == 1'b1 ) // next is read |
||
130 | next_state <= READ1; |
||
131 | else // dma_rnw == 1'b0 - next is write |
||
132 | next_state <= WRITE1; |
||
133 | end |
||
134 | end |
||
135 | ////////////////////////////////////////////////////////////////////////////////////////// |
||
136 | WRITE1: |
||
137 | begin |
||
138 | next_state <= WRITE2; |
||
139 | end |
||
140 | ////////////////////////////////////////////////////////////////////////////////////////// |
||
141 | WRITE2: |
||
142 | begin |
||
143 | if( dma_req == 1'b0 ) |
||
144 | next_state <= IDLE; |
||
145 | else // dma_req == 1'b1 |
||
146 | begin |
||
147 | if( dma_rnw == 1'b1 ) // next is read |
||
148 | next_state <= READ1; |
||
149 | else // dma_rnw == 1'b0 - next is write |
||
150 | next_state <= WRITE1; |
||
151 | end |
||
152 | end |
||
153 | ////////////////////////////////////////////////////////////////////////////////////////// |
||
154 | endcase |
||
155 | end |
||
156 | |||
157 | |||
158 | always @(posedge clk, negedge rst_n) |
||
159 | begin |
||
160 | if( !rst_n ) |
||
161 | begin |
||
162 | busrq_n <= 1'b1; |
||
163 | dma_busynready <= 1'b0; |
||
164 | dma_ack <= 1'b0; |
||
165 | dma_end <= 1'b0; |
||
166 | dma_bus <= 1'b0; |
||
167 | mem_dma_oe <= 1'b1; |
||
168 | end |
||
169 | else case( next_state ) |
||
170 | ////////////////////////////////////////////////////////////////////////////////////////// |
||
171 | IDLE: |
||
172 | begin |
||
173 | dma_end <= 1'b0; |
||
174 | |||
175 | busrq_n <= 1'b1; |
||
176 | dma_bus <= 1'b0; |
||
177 | mem_dma_oe <= 1'b1; |
||
178 | end |
||
179 | ////////////////////////////////////////////////////////////////////////////////////////// |
||
180 | START: |
||
181 | begin |
||
182 | // dma_bus <= 1'b0; // if rst=0>1 and dma_ack=1 --> ??? is this really needed? |
||
183 | |||
184 | |||
185 | busrq_n <= 1'b0; |
||
186 | |||
187 | dma_busynready <= 1'b1; |
||
188 | dma_ack <= 1'b1; |
||
189 | |||
190 | int_dma_rnw <= dma_rnw; |
||
191 | int_dma_addr <= dma_addr; |
||
192 | int_dma_wd <= dma_wd; |
||
193 | end |
||
194 | ////////////////////////////////////////////////////////////////////////////////////////// |
||
195 | WACK: |
||
196 | begin |
||
197 | dma_ack <= 1'b0; |
||
198 | end |
||
199 | ////////////////////////////////////////////////////////////////////////////////////////// |
||
200 | READ1: |
||
201 | begin |
||
202 | dma_bus <= 1'b1; // take over the bus |
||
203 | mem_dma_oe <= 1'b0; |
||
204 | if( dma_busynready == 1'b0 ) // if we are here from READ2 or WRITE2 |
||
205 | begin |
||
206 | dma_busynready <= 1'b1; |
||
207 | dma_ack <= 1'b1; |
||
208 | dma_end <= 1'b0; |
||
209 | int_dma_rnw <= 1'b1; |
||
210 | int_dma_addr <= dma_addr; |
||
211 | end |
||
212 | end |
||
213 | ////////////////////////////////////////////////////////////////////////////////////////// |
||
214 | READ2: |
||
215 | begin |
||
216 | dma_busynready <= 1'b0; |
||
217 | dma_ack <= 1'b0; |
||
218 | dma_end <= 1'b1; |
||
219 | dma_rd <= int_dma_rd; |
||
220 | end |
||
221 | ////////////////////////////////////////////////////////////////////////////////////////// |
||
222 | WRITE1: |
||
223 | begin |
||
224 | dma_bus <= 1'b1; // take over the bus |
||
225 | mem_dma_oe <= 1'b1; |
||
226 | |||
227 | if( dma_busynready == 1'b0 ) // from READ2 or WRITE2 |
||
228 | begin |
||
229 | dma_busynready <= 1'b1; |
||
230 | dma_ack <= 1'b1; |
||
231 | dma_end <= 1'b0; |
||
232 | int_dma_rnw <= 1'b0; |
||
233 | int_dma_addr <= dma_addr; |
||
234 | int_dma_wd <= dma_wd; |
||
235 | end |
||
236 | end |
||
237 | ////////////////////////////////////////////////////////////////////////////////////////// |
||
238 | WRITE2: |
||
239 | begin |
||
240 | dma_busynready <= 1'b0; |
||
241 | dma_ack <= 1'b0; |
||
242 | dma_end <= 1'b1; |
||
243 | end |
||
244 | ////////////////////////////////////////////////////////////////////////////////////////// |
||
245 | endcase |
||
246 | end |
||
247 | |||
248 | |||
249 | |||
250 | |||
251 | // mem_dma_we generator |
||
252 | |||
253 | always @(negedge clk,negedge rst_n) |
||
254 | begin |
||
255 | if( !rst_n ) |
||
256 | mem_dma_we <= 1'b1; |
||
257 | else |
||
258 | begin |
||
259 | if( dma_bus ) |
||
260 | begin |
||
261 | if( !int_dma_rnw ) |
||
262 | mem_dma_we <= ~mem_dma_we; |
||
263 | end |
||
264 | else |
||
265 | mem_dma_we <= 1'b1; |
||
266 | end |
||
267 | end |
||
268 | |||
269 | |||
270 | endmodule |
||
271 |