OpenCores
URL https://opencores.org/ocsvn/xulalx25soc/xulalx25soc/trunk

Subversion Repositories xulalx25soc

[/] [xulalx25soc/] [trunk/] [rtl/] [wbuexec.v] - Blame information for rev 109

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    wbuexec.v
4
//
5 109 dgisselq
// Project:     FPGA library
6 2 dgisselq
//
7
// Purpose:     This is the part of the USB-JTAG to wishbone conversion that
8
//              actually conducts a wishbone transaction.  Transactions are
9
//      requested via codewords that come in, and the results recorded on
10
//      codewords that are sent out.  Compression and/or decompression, coding
11
//      etc. all take place external to this routine.
12
//
13
//
14
// Creator:     Dan Gisselquist, Ph.D.
15
//              Gisselquist Technology, LLC
16
//
17
////////////////////////////////////////////////////////////////////////////////
18
//
19
// Copyright (C) 2015, Gisselquist Technology, LLC
20
//
21
// This program is free software (firmware): you can redistribute it and/or
22
// modify it under the terms of  the GNU General Public License as published
23
// by the Free Software Foundation, either version 3 of the License, or (at
24
// your option) any later version.
25
//
26
// This program is distributed in the hope that it will be useful, but WITHOUT
27
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
28
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
29
// for more details.
30
//
31
// License:     GPL, v3, as defined and found on www.gnu.org,
32
//              http://www.gnu.org/licenses/gpl.html
33
//
34
//
35
////////////////////////////////////////////////////////////////////////////////
36
//
37
//
38 59 dgisselq
`define WB_IDLE                 3'b000
39
`define WB_READ_REQUEST         3'b001
40
`define WB_WRITE_REQUEST        3'b010
41
`define WB_ACK                  3'b011
42
`define WB_WAIT_ON_NEXT_WRITE   3'b100
43
`define WB_FLUSH_WRITE_REQUESTS 3'b101
44
 
45 2 dgisselq
module  wbuexec(i_clk, i_rst, i_stb, i_codword, o_busy,
46
                o_wb_cyc, o_wb_stb, o_wb_we, o_wb_addr, o_wb_data,
47
                        i_wb_ack, i_wb_stall, i_wb_err, i_wb_data,
48
                o_stb, o_codword);
49
        input                   i_clk, i_rst;
50
        // The command inputs
51
        input                   i_stb;
52
        input           [35:0]   i_codword;
53 59 dgisselq
        output  wire            o_busy;
54 2 dgisselq
        // Wishbone outputs
55 109 dgisselq
        output  reg             o_wb_cyc;
56
        output  reg             o_wb_stb;
57 59 dgisselq
        output  reg             o_wb_we;
58 2 dgisselq
        output  reg     [31:0]   o_wb_addr, o_wb_data;
59
        // Wishbone inputs
60
        input                   i_wb_ack, i_wb_stall, i_wb_err;
61
        input           [31:0]   i_wb_data;
62
        // And our codeword outputs
63
        output  reg             o_stb;
64
        output  reg     [35:0]   o_codword;
65
 
66
 
67
        wire    w_accept, w_eow, w_newwr, w_new_err;
68
        // wire w_newad, w_newrd;
69
        assign  w_accept = (i_stb)&&(~o_busy);
70
        // assign       w_newad  = (w_accept)&&(i_codword[35:34] == 2'b00);
71
        assign  w_newwr  = (w_accept)&&(i_codword[35:34] == 2'b01);
72
        assign  w_eow    = (w_accept)&&(i_codword[35:30] == 6'h2e);
73
        // assign       w_newrd  = (w_accept)&&(i_codword[35:34] == 2'b11);
74
        wire    [31:0]   w_cod_data;
75
        assign  w_cod_data={ i_codword[32:31], i_codword[29:0] };
76
        assign  w_new_err = ((w_accept)
77 59 dgisselq
                                &&(i_codword[35:33] != 3'h3)
78 2 dgisselq
                                &&(i_codword[35:30] != 6'h2e));
79
 
80 59 dgisselq
        reg     [2:0]    wb_state;
81 2 dgisselq
        reg     [9:0]    r_acks_needed, r_len;
82 59 dgisselq
        reg     r_inc, r_new_addr, last_read_request, last_ack, zero_acks;
83 109 dgisselq
        reg     single_read_request;
84 2 dgisselq
 
85
        initial r_new_addr = 1'b1;
86 59 dgisselq
        initial wb_state = `WB_IDLE;
87
        initial o_stb = 1'b0;
88 2 dgisselq
        always @(posedge i_clk)
89
                if (i_rst)
90
                begin
91 59 dgisselq
                        wb_state <= `WB_IDLE;
92 2 dgisselq
                        o_stb <= 1'b1;
93 109 dgisselq
                        o_codword <= { 6'h3, i_wb_data[29:0] }; // BUS Reset
94
                        o_wb_cyc <= 1'b0;
95
                        o_wb_stb <= 1'b0;
96 59 dgisselq
                end else case(wb_state)
97
                `WB_IDLE: begin
98 109 dgisselq
                        o_wb_cyc <= 1'b0;
99
                        o_wb_stb <= 1'b0;
100 59 dgisselq
                        // Now output codewords while we're idle,
101
                        //    ... unless we get an address command (later).
102
                        o_stb    <= 1'b0;
103 2 dgisselq
 
104 59 dgisselq
                        // The new instruction.  The following
105
                        // don't matter if we're not running,
106
                        // so set them any time in this state,
107
                        // and if we move then they'll still be
108
                        // set right.
109
                        //
110
                        // Increment addresses?
111
                        r_inc <= i_codword[30];
112
                        // Will this be a write?
113
                        o_wb_we <= (~i_codword[35]);
114
                        //
115
                        // Our next codeword will be the new address (if there
116
                        // is one).  Set it here.  The o_stb line will determine
117
                        // if this codeword is actually sent out.
118
                        //
119
                        o_codword <= { 4'h2, o_wb_addr };
120
                        o_wb_we <= (i_codword[35:34] != 2'b11);
121
                        //
122
                        // The output data is a don't care, unless we are
123
                        // starting a write.  Hence, let's always set it as
124
                        // though we were about to start a write.
125
                        //
126
                        o_wb_data <= w_cod_data;
127
                        //
128
                        if (i_stb)
129 2 dgisselq
                        begin
130 59 dgisselq
                                // Default is not to send any codewords
131
                                // Do we need to broadcast a new address?
132
                                // r_new_addr <= 1'b0;
133
                                // 
134
                                casez(i_codword[35:32])
135
                                4'b0000: begin // Set a new (arbitrary) address
136 109 dgisselq
                                        // r_new_addr <= 1'b1;
137
                                        o_wb_addr <= i_codword[31:0]; //w_cod_data
138 59 dgisselq
                                        end
139
                                4'b001?: begin // Set a new relative address
140 109 dgisselq
                                        // r_new_addr <= 1'b1;
141
                                        o_wb_addr <= o_wb_addr // + w_cod_data;
142
 
143 59 dgisselq
                                                + { i_codword[32:31], i_codword[29:0] };
144
                                        end
145
                                4'b01??: begin // Start a write transaction,
146
                                        // address is alrdy set
147 109 dgisselq
                                        // r_new_addr <= 1'b1;
148 59 dgisselq
                                        wb_state <= `WB_WRITE_REQUEST;
149 109 dgisselq
                                        o_wb_cyc <= 1'b1;
150
                                        o_wb_stb <= 1'b1;
151 59 dgisselq
                                        end
152
                                4'b11??: begin // Start a vector read
153
                                        // Address is already set ...
154
                                        // This also depends upon the decoder working
155
                                        if (r_new_addr)
156
                                                o_stb <= 1'b1;
157
                                        wb_state <= `WB_READ_REQUEST;
158 109 dgisselq
                                        o_wb_cyc <= 1'b1;
159
                                        o_wb_stb <= 1'b1;
160 59 dgisselq
                                        end
161
                                default:
162
                                        ;
163
                                endcase
164
                        end end
165
                `WB_READ_REQUEST: begin
166 109 dgisselq
                        o_wb_cyc <= 1'b1;
167
                        o_wb_stb <= 1'b1;
168 59 dgisselq
 
169
                        if (i_wb_err)
170
                                wb_state <= `WB_IDLE;
171
 
172
                        o_stb <= (i_wb_err)||(i_wb_ack);
173
 
174 109 dgisselq
                        if (i_wb_err) // Bus Error
175 59 dgisselq
                                o_codword <= { 6'h5, i_wb_data[29:0] };
176 109 dgisselq
                        else // Read data on ack
177 59 dgisselq
                                o_codword <= { 3'h7, i_wb_data[31:30], r_inc,
178
                                        i_wb_data[29:0] };
179
 
180
                        if ((r_inc)&&(~i_wb_stall))
181
                                o_wb_addr <= o_wb_addr + 32'h001;
182
 
183
 
184
                        if (~i_wb_stall) // Deal with the strobe line
185 2 dgisselq
                        begin // Strobe was accepted, busy should be '1' here
186 109 dgisselq
                                if ((single_read_request)||(last_read_request)) // (r_len != 0) // read
187
                                begin
188 59 dgisselq
                                        wb_state <= `WB_ACK;
189 109 dgisselq
                                        o_wb_stb <= 1'b0;
190
                                end
191 59 dgisselq
                        end end
192
                `WB_WRITE_REQUEST: begin
193 109 dgisselq
                        o_wb_cyc <= 1'b1;
194
                        o_wb_stb <= 1'b1;
195
                        //
196 2 dgisselq
 
197 109 dgisselq
                        if (i_wb_err) // Bus Err
198 59 dgisselq
                                o_codword <= { 6'h5, i_wb_data[29:0] };
199 109 dgisselq
                        else // Write acknowledgement
200 59 dgisselq
                                o_codword <= { 6'h2, i_wb_data[29:0] };
201 2 dgisselq
 
202 59 dgisselq
                        if ((r_inc)&&(~i_wb_stall))
203
                                o_wb_addr <= o_wb_addr + 32'h001;
204 2 dgisselq
 
205 59 dgisselq
                        o_stb <= (i_wb_err)||(~i_wb_stall);
206 2 dgisselq
 
207 59 dgisselq
                        // Don't need to worry about accepting anything new
208
                        // here, since we'll always be busy while in this state.
209
                        // Hence, we cannot accept new write requests.
210
                        //
211 2 dgisselq
 
212 59 dgisselq
                        if (i_wb_err)
213
                        begin
214
                                wb_state <= `WB_FLUSH_WRITE_REQUESTS;
215
                                //
216 109 dgisselq
                                o_wb_cyc <= 1'b0;
217
                                o_wb_stb <= 1'b0;
218 59 dgisselq
                        end else if (~i_wb_stall)
219 109 dgisselq
                        begin
220 59 dgisselq
                                wb_state <= `WB_WAIT_ON_NEXT_WRITE;
221 109 dgisselq
                                o_wb_stb <= 1'b0;
222
                        end end
223 59 dgisselq
                `WB_ACK: begin
224 109 dgisselq
                        o_wb_cyc <= 1'b1;
225
                        o_wb_stb <= 1'b0;
226 2 dgisselq
                        //
227 59 dgisselq
                        // No strobes are being sent out.  No further
228
                        // bus transactions are requested.  We only need
229
                        // to finish processing the last one(s) by waiting
230
                        // for (and recording?) their acks.
231 2 dgisselq
                        //
232 59 dgisselq
                        // Process acknowledgements
233 109 dgisselq
                        if (i_wb_err) // Bus error
234 59 dgisselq
                                o_codword <= { 6'h5, i_wb_data[29:0] };
235 109 dgisselq
                        else // Read data
236 59 dgisselq
                                o_codword <= { 3'h7, i_wb_data[31:30], r_inc,
237 2 dgisselq
                                        i_wb_data[29:0] };
238
 
239 59 dgisselq
                        // Return a read result, or (possibly) an error
240
                        // notification
241
                        o_stb <= (((i_wb_ack)&&(~o_wb_we)) || (i_wb_err));
242
 
243
                        if (((last_ack)&&(i_wb_ack))||(zero_acks)||(i_wb_err))
244 109 dgisselq
                        begin
245
                                o_wb_cyc <= 1'b0;
246 59 dgisselq
                                wb_state <= `WB_IDLE;
247 109 dgisselq
                        end end
248 59 dgisselq
                `WB_WAIT_ON_NEXT_WRITE: begin
249 2 dgisselq
 
250 59 dgisselq
                        o_codword <= { 6'h5, i_wb_data[29:0] };
251
                        o_stb <= (i_wb_err)||(w_new_err);
252
 
253
                        o_wb_data <= w_cod_data;
254 109 dgisselq
                        o_wb_cyc <= 1'b1;
255
                        o_wb_stb <= 1'b0;
256 59 dgisselq
 
257
                        if (w_new_err) // Something other than a write or EOW
258 109 dgisselq
                        begin
259
                                o_wb_cyc <= 1'b0;
260 59 dgisselq
                                wb_state <= `WB_IDLE;
261 109 dgisselq
                        end else if (i_wb_err) // Bus returns an error
262
                        begin
263
                                o_wb_cyc <= 1'b0;
264 59 dgisselq
                                wb_state <= `WB_FLUSH_WRITE_REQUESTS;
265 109 dgisselq
                        end
266 59 dgisselq
                        else if (w_newwr) // Need to make a new write request
267 109 dgisselq
                        begin
268 59 dgisselq
                                wb_state <= `WB_WRITE_REQUEST;
269 109 dgisselq
                                o_wb_stb <= 1'b1;
270
                        end
271 59 dgisselq
                        else if (w_eow) // All done writing, wait for last ack
272
                                wb_state <= `WB_ACK;
273 2 dgisselq
                        end
274 59 dgisselq
                `WB_FLUSH_WRITE_REQUESTS: begin
275
                        // We come in here after an error within a write
276
                        // We need to wait until the command cycle finishes
277
                        // issuing all its write commands before we can go back
278
                        // to idle.
279
                        //
280
                        // In the off chance that we are in here in error, or
281
                        // out of sync, we'll transition to WB_IDLE and just
282
                        // issue a second error token.
283 2 dgisselq
 
284 109 dgisselq
                        o_wb_cyc <= 1'b0;
285
                        o_wb_stb <= 1'b0;
286 59 dgisselq
                        o_codword <= { 6'h5, i_wb_data[29:0] };
287
                        o_stb <= (w_new_err);
288
 
289
                        if ((w_eow)||(w_new_err))
290
                                wb_state <= `WB_IDLE;
291
                        end
292
                default: begin
293
                        o_stb <= 1'b1;
294
                        o_codword <= { 6'h3, i_wb_data[29:0] };
295
                        wb_state <= `WB_IDLE;
296 109 dgisselq
                        o_wb_cyc <= 1'b0;
297
                        o_wb_stb <= 1'b0;
298 59 dgisselq
                        end
299
                endcase
300
 
301
        assign o_busy = (wb_state != `WB_IDLE)
302
                        &&(wb_state != `WB_WAIT_ON_NEXT_WRITE)
303
                        &&(wb_state != `WB_FLUSH_WRITE_REQUESTS);
304 109 dgisselq
        //assign o_wb_cyc = (wb_state == `WB_READ_REQUEST)
305
                        //||(wb_state == `WB_WRITE_REQUEST)
306
                        //||(wb_state == `WB_ACK)
307
                        //||(wb_state == `WB_WAIT_ON_NEXT_WRITE);
308
        //assign o_wb_stb = (wb_state == `WB_READ_REQUEST)
309
        //                      ||(wb_state == `WB_WRITE_REQUEST);
310 59 dgisselq
 
311
        always @(posedge i_clk)
312 109 dgisselq
                if (i_rst)
313
                        r_new_addr <= 1'b1;
314
                else if ((~o_wb_cyc)&&(i_stb)&&(~i_codword[35]))
315
                        r_new_addr <= 1'b1;
316
                else if (o_wb_cyc)
317
                        r_new_addr <= 1'b0;
318
 
319
        always @(posedge i_clk)
320
                if (~o_wb_cyc)
321 59 dgisselq
                        r_acks_needed <= 10'h00; // (i_codword[35])?i_codword[9:0]:10'h00;
322
                else if ((o_wb_stb)&&(~i_wb_stall)&&(~i_wb_ack))
323
                        r_acks_needed <= r_acks_needed + 10'h01;
324
                else if (((~o_wb_stb)||(i_wb_stall))&&(i_wb_ack))
325
                        r_acks_needed <= r_acks_needed - 10'h01;
326
 
327
        always @(posedge i_clk)
328 109 dgisselq
                last_ack <= (~o_wb_stb)&&(r_acks_needed == 10'h01)
329
                                ||(o_wb_stb)&&(r_acks_needed == 10'h00);
330 59 dgisselq
 
331
        always @(posedge i_clk)
332
                zero_acks <= (~o_wb_stb)&&(r_acks_needed == 10'h00);
333
 
334
        always @(posedge i_clk)
335 109 dgisselq
                if (~o_wb_cyc) // &&(i_codword[35:34] == 2'b11))
336
                        r_len <= i_codword[9:0];
337 59 dgisselq
                else if ((o_wb_stb)&&(~i_wb_stall)&&(|r_len))
338
                        r_len <= r_len - 10'h01;
339
 
340
        always @(posedge i_clk)
341 109 dgisselq
        begin
342
                single_read_request <= (~o_wb_cyc)&&(i_codword[9:0] == 10'h01);
343
                // When there is one read request left, it will be the last one
344
                // will be the last one
345
                last_read_request <= (o_wb_stb)&&(r_len[9:2] == 8'h00)
346
                        &&((~r_len[1])
347
                                ||((~r_len[0])&&(~i_wb_stall)));
348
        end
349 59 dgisselq
 
350 2 dgisselq
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.