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

Subversion Repositories openarty

[/] [openarty/] [trunk/] [rtl/] [wbicapetwo.v] - Blame information for rev 30

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 dgisselq
////////////////////////////////////////////////////////////////////////////////
2 3 dgisselq
//
3
// Filename:    wbicapetwo.v
4
//
5
// Project:     Wishbone to ICAPE2 interface conversion
6
//
7
// Purpose:     This routine maps the configuration registers of a 7-series
8
//              Xilinx part onto register addresses on a wishbone bus interface
9
//              via the ICAPE2 access port to those parts.  The big thing this
10
//              captures is the timing and handshaking required to read and
11
//              write registers from the configuration interface.
12
//
13
//              As an example of what can be done, writing a 32'h00f to
14
//              local address 5'h4 sends the IPROG command to the FPGA, causing
15
//              it to immediately reconfigure itself.
16
//
17
//              As another example, the warm boot start address is located
18
//              in register 5'h10.  Writing to this address, followed by
19
//              issuing the IPROG command just mentioned will cause the
20
//              FPGA to configure from that warm boot start address.
21
// 
22
//              For more details on the configuration interface, the registers
23
//              in question, their meanings and what they do, please see
24
//              User's Guide 470, the "7 Series FPGAs Configuration" User
25
//              Guide.
26
//
27
// Notes:       This module supports both reads and writes from the ICAPE2
28
//              interface.  These follow the following pattern.
29
//
30
//      For writes:
31
//              (Idle)  0xffffffff      (Dummy)
32
//              (CS/W)  0x20000000      NOOP
33
//              (CS/W)  0xaa995566      SYNC WORD
34
//              (CS/W)  0x20000000      NOOP
35
//              (CS/W)  0x20000000      NOOP
36
//              (CS/W)  ...             Write command
37
//              (CS/W)  ...             Write value, from Wishbone bus
38
//              (CS/W)  0x20000000      NOOP
39
//              (CS/W)  0x20000000      NOOP
40
//              (CS/W)  0x30008001      Write to CMD register (address 4)
41
//              (CS/W)  0x0000000d      DESYNC command
42
//              (CS/W)  0x20000000      NOOP
43
//              (CS/W)  0x20000000      NOOP
44
//              (Idle)
45
//
46
//      and for reads:
47
//              (Idle)  0xffffffff      (Dummy)
48
//              (CS/W)  0x20000000      NOOP
49
//              (CS/W)  0xaa995566      SYNC WORD
50
//              (CS/W)  0x20000000      NOOP
51
//              (CS/W)  0x20000000      NOOP
52
//              (CS/W)  ...             Read command
53
//              (CS/W)  0x20000000      NOOP
54
//              (CS/W)  0x20000000      NOOP
55
//              (Idle)  0x20000000      (Idle the interface again, so we can rd)
56
//              (CS/R)  0x20000000      (Wait)
57
//              (CS/R)  0x20000000      (Wait)
58
//              (CS/R)  0x20000000      (Wait)
59
//              (CS/R)  0x20000000      (Wait)
60
//              (Idle)  0x20000000      (Idle the interface before writing)
61
//              (CS/W)  0x20000000      NOOP
62
//              (CS/W)  0x20000000      NOOP
63
//              (CS/W)  0x30008001      Write to CMD register (address 4)
64
//              (CS/W)  0x0000000d      DESYNC command
65
//              (CS/W)  0x20000000      NOOP
66
//              (CS/W)  0x20000000      NOOP
67
//              (Idle)
68
// Creator:     Dan Gisselquist, Ph.D.
69
//              Gisselquist Technology, LLC
70
//
71 30 dgisselq
////////////////////////////////////////////////////////////////////////////////
72 3 dgisselq
//
73 30 dgisselq
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
74 3 dgisselq
//
75
// This program is free software (firmware): you can redistribute it and/or
76
// modify it under the terms of  the GNU General Public License as published
77
// by the Free Software Foundation, either version 3 of the License, or (at
78
// your option) any later version.
79
//
80
// This program is distributed in the hope that it will be useful, but WITHOUT
81
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
82
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
83
// for more details.
84
//
85
// License:     GPL, v3, as defined and found on www.gnu.org,
86
//              http://www.gnu.org/licenses/gpl.html
87
//
88
//
89 30 dgisselq
////////////////////////////////////////////////////////////////////////////////
90 3 dgisselq
//
91 30 dgisselq
//
92 3 dgisselq
`define MBOOT_IDLE      5'h00
93
`define MBOOT_START     5'h01
94
`define MBOOT_READ      5'h06
95
`define MBOOT_WRITE     5'h0f
96
`define MBOOT_DESYNC    5'h11
97
module  wbicapetwo(i_clk,
98
                i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
99 13 dgisselq
                        o_wb_ack, o_wb_stall, o_wb_data, o_dbg);
100 25 dgisselq
        parameter       LGDIV = 3; /// Log of the clock divide
101 3 dgisselq
        input                   i_clk;
102
        // Wishbone inputs
103
        input                   i_wb_cyc, i_wb_stb, i_wb_we;
104
        input           [4:0]    i_wb_addr;
105
        input           [31:0]   i_wb_data;
106
        // Wishbone outputs
107
        output  reg             o_wb_ack, o_wb_stall;
108
        output  reg     [31:0]   o_wb_data;
109 13 dgisselq
        // Debugging output
110
        output  wire    [31:0]   o_dbg;
111 3 dgisselq
        // ICAPE2 interface signals
112
        //      These are kept internal to this block ...
113
 
114
        reg             wb_req, r_we;
115
        reg     [31:0]   r_data;
116
        reg     [4:0]    r_addr;
117
 
118 25 dgisselq
 
119 13 dgisselq
        reg             clk_stb, clk_stall;
120
        wire            slow_clk;
121
 
122 25 dgisselq
        generate
123
        if (LGDIV <= 1)
124 13 dgisselq
        begin
125 25 dgisselq
                reg             r_slow_clk;
126
                always @(posedge i_clk)
127
                begin
128
                        r_slow_clk  <= (slow_clk + 1'b1);
129
                        // We'll move on the positive edge of the clock,
130
                        // so therefore clk_stb must be true one clock before
131
                        // that, so we test for it one clock before that.
132
                        clk_stb   <= (slow_clk == 1'b1);
133
                        // CLK_STALL is set to true two clocks before any
134
                        // cycle that will, by necessity, stall.
135
                        clk_stall <= (slow_clk != 1'b0); //True all but 1ckcycle
136
                end
137 13 dgisselq
 
138 25 dgisselq
                assign  slow_clk = r_slow_clk;
139
        end else begin
140
                reg     [(LGDIV-1):0]    slow_clk_counter;
141
 
142
                always @(posedge i_clk)
143
                begin
144
                        slow_clk_counter  <= slow_clk_counter + 1'b1;
145
                        // We'll move on the positive edge of the clock, so therefore
146
                        // clk_stb must be true one clock before that, so we test for
147
                        // it one clock before that.
148
                        clk_stb   <= (slow_clk_counter=={{(LGDIV){1'b1}},1'b0});
149
                        // CLK_STALL is set to true two clocks before any cycle that
150
                        // will, by necessity, stall.
151
                        clk_stall <= (slow_clk_counter!={{(LGDIV){1'b0}},1'b1});
152
                end
153
 
154
                assign  slow_clk = slow_clk_counter[(LGDIV-1)];
155
        end endgenerate
156
 
157 3 dgisselq
        reg     [31:0]   cfg_in;
158
        reg             cfg_cs_n, cfg_rdwrn;
159
        wire    [31:0]   cfg_out;
160
        reg     [4:0]    state;
161
        initial state = `MBOOT_IDLE;
162
        initial cfg_cs_n = 1'b1;
163
        always @(posedge i_clk)
164
        begin
165 13 dgisselq
                // In general, o_wb_ack is always zero.  The exceptions to this
166
                // will be handled individually below.
167 3 dgisselq
                o_wb_ack <= 1'b0;
168 13 dgisselq
                // We can simplify our logic a touch by always setting
169
                // o_wb_data.  It will only be examined if o_wb_ack
170
                // is also true, so this is okay.
171
                o_wb_data <= cfg_out;
172
 
173 3 dgisselq
                // Turn any request "off", so that it will not be ack'd, if
174
                // the wb_cyc line is ever lowered.
175
                wb_req <= wb_req & i_wb_cyc;
176 13 dgisselq
                o_wb_stall <= (state != `MBOOT_IDLE)||(clk_stall);
177
                if (clk_stb)
178 3 dgisselq
                begin
179
                        state <= state + 5'h01;
180
                        case(state)
181
                        `MBOOT_IDLE: begin
182
                                cfg_cs_n <= 1'b1;
183
                                cfg_rdwrn <= 1'b1;
184
                                cfg_in <= 32'hffffffff; // Dummy word
185
 
186
                                state <= `MBOOT_IDLE;
187
 
188
                                o_wb_ack <= 1'b0;
189
 
190
                                r_addr <= i_wb_addr;
191
                                r_data <= i_wb_data;
192
                                r_we   <= i_wb_we;
193 13 dgisselq
                                if(i_wb_stb) // &&(!o_wb_stall)
194 3 dgisselq
                                begin
195
                                        state <= `MBOOT_START;
196
                                        wb_req <= 1'b1;
197
                                        //
198
                                        o_wb_ack <= 1'b0;
199
                                end end
200 13 dgisselq
                        `MBOOT_START: begin
201
                                cfg_in <= 32'hffffffff; // NOOP
202
                                cfg_cs_n <= 1'b1;
203
                                end
204 3 dgisselq
                        5'h02: begin
205
                                cfg_cs_n <= 1'b0; // Activate interface
206
                                cfg_rdwrn <= 1'b0;
207
                                cfg_in <= 32'h20000000; // NOOP
208
                                end
209 13 dgisselq
                        5'h03: begin
210
                                cfg_in <= 32'haa995566; // Sync word
211
                                cfg_cs_n <= 1'b0;
212
                                end
213
                        5'h04: begin
214
                                cfg_in <= 32'h20000000; // NOOP
215
                                cfg_cs_n <= 1'b0;
216
                                end
217 3 dgisselq
                        5'h05: begin
218
                                cfg_in <= 32'h20000000; // NOOP
219
                                state <= (r_we) ? `MBOOT_WRITE : `MBOOT_READ;
220 13 dgisselq
                                cfg_cs_n <= 1'b0;
221 3 dgisselq
                                end
222 13 dgisselq
                        `MBOOT_READ: begin
223
                                cfg_cs_n <= 1'b0;
224
                                cfg_in <= { 8'h28, 6'h0, r_addr, 13'h001 };
225
                                end
226
                        5'h07: begin
227
                                cfg_cs_n <= 1'b0;
228
                                cfg_in <= 32'h20000000; // NOOP
229
                                end
230
                        5'h08: begin
231
                                cfg_cs_n <= 1'b0;
232
                                cfg_in <= 32'h20000000; // NOOP
233
                                end
234 3 dgisselq
                        5'h09: begin // Idle the interface before the read cycle
235
                                cfg_cs_n <= 1'b1;
236
                                cfg_rdwrn <= 1'b1;
237
                                cfg_in <= 32'h20000000; // NOOP
238
                                end
239
                        5'h0a: begin // Re-activate the interface and wait 3 cycles
240
                                cfg_cs_n <= 1'b0;
241
                                cfg_rdwrn <= 1'b1;
242
                                cfg_in <= 32'h20000000; // NOOP
243
                                end
244 13 dgisselq
                        5'h0b: begin // ... still waiting, cycle two
245 3 dgisselq
                                cfg_in <= 32'h20000000; // NOOP
246 13 dgisselq
                                cfg_cs_n <= 1'b0;
247
                                end
248
                        5'h0c: begin // ... still waiting, cycle three
249 3 dgisselq
                                cfg_in <= 32'h20000000; // NOOP
250 13 dgisselq
                                cfg_cs_n <= 1'b0;
251
                                end
252
                        5'h0d: begin // ... still waiting, cycle four
253 3 dgisselq
                                cfg_in <= 32'h20000000; // NOOP
254 13 dgisselq
                                cfg_cs_n <= 1'b0;
255
                                end
256 3 dgisselq
                        5'h0e: begin // and now our answer is there
257
                                cfg_cs_n <= 1'b1;
258
                                cfg_rdwrn <= 1'b1;
259
                                cfg_in <= 32'h20000000; // NOOP
260
                                //
261
                                // Wishbone return
262
                                o_wb_ack <= wb_req;
263 13 dgisselq
                                // o_wb_data <= cfg_out; // Independent of state
264 3 dgisselq
                                wb_req <= 1'b0;
265
                                //
266
                                state <= `MBOOT_DESYNC;
267
                                end
268 13 dgisselq
                        `MBOOT_WRITE: begin
269
                                // Issue a write command to the given address
270 3 dgisselq
                                cfg_in <= { 8'h30, 6'h0, r_addr, 13'h001 };
271 13 dgisselq
                                cfg_cs_n <= 1'b0;
272
                                end
273
                        5'h10: begin
274
                                cfg_in <= r_data;       // Write the value
275
                                cfg_cs_n <= 1'b0;
276
                                end
277 3 dgisselq
                        `MBOOT_DESYNC: begin
278
                                cfg_cs_n <= 1'b0;
279
                                cfg_rdwrn <= 1'b0;
280
                                cfg_in <= 32'h20000000; // 1st NOOP
281
                                end
282 13 dgisselq
                        5'h12: begin
283
                                cfg_cs_n <= 1'b0;
284
                                cfg_in <= 32'h20000000; // 2nd NOOP
285
                                end
286
                        5'h13: begin
287
                                cfg_cs_n <= 1'b0;
288
                                cfg_in <= 32'h30008001; // Write to CMD register
289
                                end
290
                        5'h14: begin
291
                                cfg_cs_n <= 1'b0;
292
                                cfg_in <= 32'h0000000d; // DESYNC command
293
                                end
294
                        5'h15: begin
295
                                cfg_cs_n <= 1'b0;
296
                                cfg_in <= 32'h20000000; // NOOP
297
                                end
298
                        5'h16: begin
299
                                cfg_cs_n <= 1'b0;
300
                                cfg_in <= 32'h20000000; // NOOP
301
                                end
302 3 dgisselq
                        5'h17: begin
303
                                // Acknowledge the bus transaction, it is now complete
304
                                o_wb_ack <= wb_req;
305
                                wb_req <= 1'b0;
306
                                //
307
                                cfg_cs_n <= 1'b1;
308
                                cfg_rdwrn <= 1'b0;
309
                                cfg_in <= 32'hffffffff; // DUMMY
310
                                //
311
                                state <= `MBOOT_IDLE;
312
                                end
313
                        default: begin
314 13 dgisselq
                                wb_req <= 1'b0;
315 3 dgisselq
                                cfg_cs_n <= 1'b1;
316
                                cfg_rdwrn <= 1'b0;
317
                                state <= `MBOOT_IDLE;
318
                                cfg_in <= 32'hffffffff; // DUMMY WORD
319
                                end
320
                        endcase
321
                end
322
        end
323
 
324
        genvar  k;
325
        //
326
        // The data registers to the ICAPE2 interface are bit swapped within
327
        // each byte.  Thus, in order to read from or write to the interface,
328
        // we need to bit swap the bits in each byte.  These next lines
329
        // accomplish that for both the input and output ports.
330
        //
331
        wire    [31:0]   bit_swapped_cfg_in;
332
        generate
333
        for(k=0; k<8; k=k+1)
334
        begin
335
                assign bit_swapped_cfg_in[   k] = cfg_in[   7-k];
336
                assign bit_swapped_cfg_in[ 8+k] = cfg_in[ 8+7-k];
337
                assign bit_swapped_cfg_in[16+k] = cfg_in[16+7-k];
338
                assign bit_swapped_cfg_in[24+k] = cfg_in[24+7-k];
339
        end endgenerate
340
 
341
        wire    [31:0]   bit_swapped_cfg_out;
342
        generate
343
        for(k=0; k<8; k=k+1)
344
        begin
345
                assign cfg_out[   k] = bit_swapped_cfg_out[   7-k];
346
                assign cfg_out[ 8+k] = bit_swapped_cfg_out[ 8+7-k];
347
                assign cfg_out[16+k] = bit_swapped_cfg_out[16+7-k];
348
                assign cfg_out[24+k] = bit_swapped_cfg_out[24+7-k];
349
        end endgenerate
350
 
351
        ICAPE2 #(.ICAP_WIDTH("X32")) reconfig(.CLK(slow_clk),
352
                        .CSIB(cfg_cs_n), .RDWRB(cfg_rdwrn),
353
                        .I(bit_swapped_cfg_in), .O(bit_swapped_cfg_out));
354 13 dgisselq
 
355
        assign o_dbg = {
356
`ifdef  DIVIDE_BY_FOUR
357
                slow_clk_counter, clk_stb, clk_stall,
358
`else
359
                1'b0, slow_clk, clk_stb, clk_stall,
360
`endif
361
                i_wb_stb, o_wb_ack, cfg_cs_n, cfg_rdwrn,
362
                o_wb_stall, state, 2'h0,
363
                        cfg_in[7:0],
364
                        cfg_out[7:0] };
365
 
366 3 dgisselq
endmodule

powered by: WebSVN 2.1.0

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