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

Subversion Repositories openarty

[/] [openarty/] [trunk/] [rtl/] [wbuexec.v] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    wbuexec.v
4
//
5
// Project:     FPGA library
6
//
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
`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
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
        output  wire            o_busy;
54
        // Wishbone outputs
55
        output  reg             o_wb_cyc;
56
        output  reg             o_wb_stb;
57
        output  reg             o_wb_we;
58
        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
        // output       wire            o_dbg;
66
 
67
 
68
        wire    w_accept, w_eow, w_newwr, w_new_err;
69
        // wire w_newad, w_newrd;
70
        assign  w_accept = (i_stb)&&(~o_busy);
71
        // assign       w_newad  = (w_accept)&&(i_codword[35:34] == 2'b00);
72
        assign  w_newwr  = (w_accept)&&(i_codword[35:34] == 2'b01);
73
        assign  w_eow    = (w_accept)&&(i_codword[35:30] == 6'h2e);
74
        // assign       w_newrd  = (w_accept)&&(i_codword[35:34] == 2'b11);
75
        wire    [31:0]   w_cod_data;
76
        assign  w_cod_data={ i_codword[32:31], i_codword[29:0] };
77
        assign  w_new_err = ((w_accept)
78
                                &&(i_codword[35:33] != 3'h3)
79
                                &&(i_codword[35:30] != 6'h2e));
80
 
81
        reg     [2:0]    wb_state;
82
        reg     [9:0]    r_acks_needed, r_len;
83
        reg     r_inc, r_new_addr, last_read_request, last_ack, zero_acks;
84
        reg     single_read_request;
85
 
86
        initial r_new_addr = 1'b1;
87
        initial wb_state = `WB_IDLE;
88
        initial o_stb = 1'b0;
89
        always @(posedge i_clk)
90
                if (i_rst)
91
                begin
92
                        wb_state <= `WB_IDLE;
93
                        o_stb <= 1'b1;
94
                        o_codword <= { 6'h3, i_wb_data[29:0] }; // BUS Reset
95
                        o_wb_cyc <= 1'b0;
96
                        o_wb_stb <= 1'b0;
97
                end else case(wb_state)
98
                `WB_IDLE: begin
99
                        o_wb_cyc <= 1'b0;
100
                        o_wb_stb <= 1'b0;
101
                        // Now output codewords while we're idle,
102
                        //    ... unless we get an address command (later).
103
                        o_stb    <= 1'b0;
104
 
105
                        // The new instruction.  The following
106
                        // don't matter if we're not running,
107
                        // so set them any time in this state,
108
                        // and if we move then they'll still be
109
                        // set right.
110
                        //
111
                        // Increment addresses?
112
                        r_inc <= i_codword[30];
113
                        // Will this be a write?
114
                        o_wb_we <= (~i_codword[35]);
115
                        //
116
                        // Our next codeword will be the new address (if there
117
                        // is one).  Set it here.  The o_stb line will determine
118
                        // if this codeword is actually sent out.
119
                        //
120
                        o_codword <= { 4'h2, o_wb_addr };
121
                        o_wb_we <= (i_codword[35:34] != 2'b11);
122
                        //
123
                        // The output data is a don't care, unless we are
124
                        // starting a write.  Hence, let's always set it as
125
                        // though we were about to start a write.
126
                        //
127
                        o_wb_data <= w_cod_data;
128
                        //
129
                        if (i_stb)
130
                        begin
131
                                // Default is not to send any codewords
132
                                // Do we need to broadcast a new address?
133
                                // r_new_addr <= 1'b0;
134
                                // 
135
                                casez(i_codword[35:32])
136
                                4'b0000: begin // Set a new (arbitrary) address
137
                                        // r_new_addr <= 1'b1;
138
                                        o_wb_addr <= i_codword[31:0]; //w_cod_data
139
                                        end
140
                                4'b001?: begin // Set a new relative address
141
                                        // r_new_addr <= 1'b1;
142
                                        o_wb_addr <= o_wb_addr // + w_cod_data;
143
 
144
                                                + { i_codword[32:31], i_codword[29:0] };
145
                                        end
146
                                4'b01??: begin // Start a write transaction,
147
                                        // address is alrdy set
148
                                        // r_new_addr <= 1'b1;
149
                                        wb_state <= `WB_WRITE_REQUEST;
150
                                        o_wb_cyc <= 1'b1;
151
                                        o_wb_stb <= 1'b1;
152
                                        end
153
                                4'b11??: begin // Start a vector read
154
                                        // Address is already set ...
155
                                        // This also depends upon the decoder working
156
                                        if (r_new_addr)
157
                                                o_stb <= 1'b1;
158
                                        wb_state <= `WB_READ_REQUEST;
159
                                        o_wb_cyc <= 1'b1;
160
                                        o_wb_stb <= 1'b1;
161
                                        end
162
                                default:
163
                                        ;
164
                                endcase
165
                        end end
166
                `WB_READ_REQUEST: begin
167
                        o_wb_cyc <= 1'b1;
168
                        o_wb_stb <= 1'b1;
169
 
170
                        if (i_wb_err)
171
                                wb_state <= `WB_IDLE;
172
 
173
                        o_stb <= (i_wb_err)||(i_wb_ack);
174
 
175
                        if (i_wb_err) // Bus Error
176
                                o_codword <= { 6'h5, i_wb_data[29:0] };
177
                        else // Read data on ack
178
                                o_codword <= { 3'h7, i_wb_data[31:30], r_inc,
179
                                        i_wb_data[29:0] };
180
 
181
                        if ((r_inc)&&(~i_wb_stall))
182
                                o_wb_addr <= o_wb_addr + 32'h001;
183
 
184
 
185
                        if (~i_wb_stall) // Deal with the strobe line
186
                        begin // Strobe was accepted, busy should be '1' here
187
                                if ((single_read_request)||(last_read_request)) // (r_len != 0) // read
188
                                begin
189
                                        wb_state <= `WB_ACK;
190
                                        o_wb_stb <= 1'b0;
191
                                end
192
                        end end
193
                `WB_WRITE_REQUEST: begin
194
                        o_wb_cyc <= 1'b1;
195
                        o_wb_stb <= 1'b1;
196
                        //
197
 
198
                        if (i_wb_err) // Bus Err
199
                                o_codword <= { 6'h5, i_wb_data[29:0] };
200
                        else // Write acknowledgement
201
                                o_codword <= { 6'h2, i_wb_data[29:0] };
202
 
203
                        if ((r_inc)&&(~i_wb_stall))
204
                                o_wb_addr <= o_wb_addr + 32'h001;
205
 
206
                        o_stb <= (i_wb_err)||(~i_wb_stall);
207
 
208
                        // Don't need to worry about accepting anything new
209
                        // here, since we'll always be busy while in this state.
210
                        // Hence, we cannot accept new write requests.
211
                        //
212
 
213
                        if (i_wb_err)
214
                        begin
215
                                wb_state <= `WB_FLUSH_WRITE_REQUESTS;
216
                                //
217
                                o_wb_cyc <= 1'b0;
218
                                o_wb_stb <= 1'b0;
219
                        end else if (~i_wb_stall)
220
                        begin
221
                                wb_state <= `WB_WAIT_ON_NEXT_WRITE;
222
                                o_wb_stb <= 1'b0;
223
                        end end
224
                `WB_ACK: begin
225
                        o_wb_cyc <= 1'b1;
226
                        o_wb_stb <= 1'b0;
227
                        //
228
                        // No strobes are being sent out.  No further
229
                        // bus transactions are requested.  We only need
230
                        // to finish processing the last one(s) by waiting
231
                        // for (and recording?) their acks.
232
                        //
233
                        // Process acknowledgements
234
                        if (i_wb_err) // Bus error
235
                                o_codword <= { 6'h5, i_wb_data[29:0] };
236
                        else // Read data
237
                                o_codword <= { 3'h7, i_wb_data[31:30], r_inc,
238
                                        i_wb_data[29:0] };
239
 
240
                        // Return a read result, or (possibly) an error
241
                        // notification
242
                        o_stb <= (((i_wb_ack)&&(~o_wb_we)) || (i_wb_err));
243
 
244
                        if (((last_ack)&&(i_wb_ack))||(zero_acks)||(i_wb_err))
245
                        begin
246
                                o_wb_cyc <= 1'b0;
247
                                wb_state <= `WB_IDLE;
248
                        end end
249
                `WB_WAIT_ON_NEXT_WRITE: begin
250
 
251
                        o_codword <= { 6'h5, i_wb_data[29:0] };
252
                        o_stb <= (i_wb_err)||(w_new_err);
253
 
254
                        o_wb_data <= w_cod_data;
255
                        o_wb_cyc <= 1'b1;
256
                        o_wb_stb <= 1'b0;
257
 
258
                        if (w_new_err) // Something other than a write or EOW
259
                        begin
260
                                o_wb_cyc <= 1'b0;
261
                                wb_state <= `WB_IDLE;
262
                        end else if (i_wb_err) // Bus returns an error
263
                        begin
264
                                o_wb_cyc <= 1'b0;
265
                                wb_state <= `WB_FLUSH_WRITE_REQUESTS;
266
                        end
267
                        else if (w_newwr) // Need to make a new write request
268
                        begin
269
                                wb_state <= `WB_WRITE_REQUEST;
270
                                o_wb_stb <= 1'b1;
271
                        end
272
                        else if (w_eow) // All done writing, wait for last ack
273
                                wb_state <= `WB_ACK;
274
                        end
275
                `WB_FLUSH_WRITE_REQUESTS: begin
276
                        // We come in here after an error within a write
277
                        // We need to wait until the command cycle finishes
278
                        // issuing all its write commands before we can go back
279
                        // to idle.
280
                        //
281
                        // In the off chance that we are in here in error, or
282
                        // out of sync, we'll transition to WB_IDLE and just
283
                        // issue a second error token.
284
 
285
                        o_wb_cyc <= 1'b0;
286
                        o_wb_stb <= 1'b0;
287
                        o_codword <= { 6'h5, i_wb_data[29:0] };
288
                        o_stb <= (w_new_err);
289
 
290
                        if ((w_eow)||(w_new_err))
291
                                wb_state <= `WB_IDLE;
292
                        end
293
                default: begin
294
                        o_stb <= 1'b1;
295
                        o_codword <= { 6'h3, i_wb_data[29:0] };
296
                        wb_state <= `WB_IDLE;
297
                        o_wb_cyc <= 1'b0;
298
                        o_wb_stb <= 1'b0;
299
                        end
300
                endcase
301
 
302
        assign o_busy = (wb_state != `WB_IDLE)
303
                        &&(wb_state != `WB_WAIT_ON_NEXT_WRITE)
304
                        &&(wb_state != `WB_FLUSH_WRITE_REQUESTS);
305
        //assign o_wb_cyc = (wb_state == `WB_READ_REQUEST)
306
                        //||(wb_state == `WB_WRITE_REQUEST)
307
                        //||(wb_state == `WB_ACK)
308
                        //||(wb_state == `WB_WAIT_ON_NEXT_WRITE);
309
        //assign o_wb_stb = (wb_state == `WB_READ_REQUEST)
310
        //                      ||(wb_state == `WB_WRITE_REQUEST);
311
 
312
        always @(posedge i_clk)
313
                if (i_rst)
314
                        r_new_addr <= 1'b1;
315
                else if ((~o_wb_cyc)&&(i_stb)&&(~i_codword[35]))
316
                        r_new_addr <= 1'b1;
317
                else if (o_wb_cyc)
318
                        r_new_addr <= 1'b0;
319
 
320
        always @(posedge i_clk)
321
                if (~o_wb_cyc)
322
                        r_acks_needed <= 10'h00; // (i_codword[35])?i_codword[9:0]:10'h00;
323
                else if ((o_wb_stb)&&(~i_wb_stall)&&(~i_wb_ack))
324
                        r_acks_needed <= r_acks_needed + 10'h01;
325
                else if (((~o_wb_stb)||(i_wb_stall))&&(i_wb_ack))
326
                        r_acks_needed <= r_acks_needed - 10'h01;
327
 
328
        always @(posedge i_clk)
329
                last_ack <= (~o_wb_stb)&&(r_acks_needed == 10'h01)
330
                                ||(o_wb_stb)&&(r_acks_needed == 10'h00);
331
 
332
        always @(posedge i_clk)
333
                zero_acks <= (~o_wb_stb)&&(r_acks_needed == 10'h00);
334
 
335
        always @(posedge i_clk)
336
                if (~o_wb_stb) // (~o_wb_cyc)&&(i_codword[35:34] == 2'b11))
337
                        r_len <= i_codword[9:0];
338
                else if ((o_wb_stb)&&(~i_wb_stall)&&(|r_len))
339
                        r_len <= r_len - 10'h01;
340
 
341
        always @(posedge i_clk)
342
        begin
343
                single_read_request <= (~o_wb_cyc)&&(i_codword[9:0] == 10'h01);
344
                // When there is one read request left, it will be the last one
345
                // will be the last one
346
                last_read_request <= (o_wb_stb)&&(r_len[9:2] == 8'h00)
347
                        &&((~r_len[1])
348
                                ||((~r_len[0])&&(~i_wb_stall)));
349
        end
350
 
351
        /*
352
        reg     [5:0]   count;
353
        always @(posedge i_clk)
354
                if (~o_wb_cyc)
355
                        count <= 0;
356
                else
357
                        count <= count+1;
358
        assign o_dbg = (count > 6'd10);
359
        */
360
        // assign       o_dbg = (wb_state == `WB_ACK);
361
 
362
endmodule

powered by: WebSVN 2.1.0

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