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

Subversion Repositories xulalx25soc

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

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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