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

Subversion Repositories wb_lpc

[/] [wb_lpc/] [trunk/] [rtl/] [verilog/] [wb_lpc_periph.v] - Blame information for rev 20

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 hharte
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3 17 hharte
////  $Id: wb_lpc_periph.v,v 1.4 2008-07-26 19:15:32 hharte Exp $ ////
4 3 hharte
////  wb_lpc_periph.v - LPC Peripheral to Wishbone Master Bridge  ////
5
////                                                              ////
6
////  This file is part of the Wishbone LPC Bridge project        ////
7
////  http://www.opencores.org/projects/wb_lpc/                   ////
8
////                                                              ////
9
////  Author:                                                     ////
10
////      - Howard M. Harte (hharte@opencores.org)                ////
11
////                                                              ////
12
//////////////////////////////////////////////////////////////////////
13
////                                                              ////
14
//// Copyright (C) 2008 Howard M. Harte                           ////
15
////                                                              ////
16
//// This source file may be used and distributed without         ////
17
//// restriction provided that this copyright statement is not    ////
18
//// removed from the file and that any derivative work contains  ////
19
//// the original copyright notice and the associated disclaimer. ////
20
////                                                              ////
21
//// This source file is free software; you can redistribute it   ////
22
//// and/or modify it under the terms of the GNU Lesser General   ////
23
//// Public License as published by the Free Software Foundation; ////
24
//// either version 2.1 of the License, or (at your option) any   ////
25
//// later version.                                               ////
26
////                                                              ////
27
//// This source is distributed in the hope that it will be       ////
28
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
29
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
30
//// PURPOSE.  See the GNU Lesser General Public License for more ////
31
//// details.                                                     ////
32
////                                                              ////
33
//// You should have received a copy of the GNU Lesser General    ////
34
//// Public License along with this source; if not, download it   ////
35
//// from http://www.opencores.org/lgpl.shtml                     ////
36
////                                                              ////
37
//////////////////////////////////////////////////////////////////////
38
 
39
`timescale 1 ns / 1 ns
40
 
41
`include "../../rtl/verilog/wb_lpc_defines.v"
42
 
43 6 hharte
//              I/O Write       I/O Read        DMA Read        DMA Write
44
//                                                          
45
//  States - 1. H Start         H Start         H Start         H Start
46
//           2. H CYCTYPE+DIR   H CYCTYPE+DIR   H CYCTYPE+DIR   H CYCTYPE+DIR
47
//           3. H Addr (4)      H Addr (4)      H CHAN+TC       H CHAN+TC
48
//                                              H SIZE          H SIZE
49
//           4. H Data (2)      H TAR  (2)    +-H DATA (2)      H TAR  (2)
50
//           5. H TAR  (2)      P SYNC (1+)   | H TAR  (2)    +-P SYNC (1+)
51
//           6. P SYNC (1+)     P DATA (2)    | H SYNC (1+)   +-P DATA (2)
52
//           7. P TAR  (2)      P TAR  (2)    +-P TAR  (2)      P TAR
53
//                                                          
54 3 hharte
 
55
module wb_lpc_periph(clk_i, nrst_i, wbm_adr_o, wbm_dat_o, wbm_dat_i, wbm_sel_o, wbm_tga_o, wbm_we_o,
56 17 hharte
                     wbm_stb_o, wbm_cyc_o, wbm_ack_i, wbm_err_i,
57 6 hharte
                     dma_chan_o, dma_tc_o,
58
                     lframe_i, lad_i, lad_o, lad_oe
59 3 hharte
);
60
 
61 6 hharte
    // Wishbone Master Interface
62
    input              clk_i;
63
    input              nrst_i;
64
    output reg  [31:0] wbm_adr_o;
65
    output reg  [31:0] wbm_dat_o;
66
    input       [31:0] wbm_dat_i;
67
    output reg   [3:0] wbm_sel_o;
68
    output reg   [1:0] wbm_tga_o;
69
    output reg         wbm_we_o;
70
    output reg         wbm_stb_o;
71
    output reg         wbm_cyc_o;
72
    input              wbm_ack_i;
73 17 hharte
    input              wbm_err_i;
74 3 hharte
 
75 6 hharte
    // LPC Slave Interface
76
    input              lframe_i;    // LPC Frame input (active high)
77
    output reg         lad_oe;      // LPC AD Output Enable
78
    input        [3:0] lad_i;       // LPC AD Input Bus
79
    output reg   [3:0] lad_o;       // LPC AD Output Bus
80 3 hharte
 
81 6 hharte
    // DMA-Specific sideband signals
82
    output       [2:0] dma_chan_o;  // DMA Channel
83
    output             dma_tc_o;    // DMA Terminal Count
84 3 hharte
 
85 17 hharte
    reg         [13:0] state;       // Current state
86 6 hharte
    reg          [2:0] adr_cnt;     // Address nibble counter
87
    reg          [3:0] dat_cnt;     // Data nibble counter
88
    wire         [2:0] byte_cnt = dat_cnt[3:1];  // Byte counter
89
    wire               nibble_cnt = dat_cnt[0];  // Nibble counter
90 3 hharte
 
91 17 hharte
    reg         [31:0] lpc_dat_i;   // Temporary storage for LPC input data.
92 6 hharte
    reg                mem_xfr;     // LPC Memory Transfer (not I/O)
93
    reg                dma_xfr;     // LPC DMA Transfer
94
    reg                fw_xfr;      // LPC Firmware memory read/write
95
    reg          [2:0] xfr_len;     // Number of nibbls for transfer
96
    reg                dma_tc;      // DMA Terminal Count
97
    reg          [2:0] dma_chan;    // DMA Channel
98 3 hharte
 
99 17 hharte
    // These buffer enough state to delay the start of the next Wishbone cycle
100
    // until the previous Firmware Write has completed.
101
    reg         [31:0] lpc_adr_reg; // Temporary storage for address received on LPC bus.
102
    reg         [31:0] lpc_dat_o;   // Temporary storage for LPC output data.
103
    reg                lpc_write;   // Holds current LPC transfer direction
104
    reg          [1:0] lpc_tga_o;
105
    reg                got_ack;     // Set when ack has been received from wbm
106
 
107 6 hharte
    assign dma_chan_o = dma_chan;
108
    assign dma_tc_o = dma_tc;
109
 
110
    always @(posedge clk_i or negedge nrst_i)
111 17 hharte
    begin
112 6 hharte
        if(~nrst_i)
113
        begin
114
            state <= `LPC_ST_IDLE;
115 17 hharte
            lpc_adr_reg <= 32'h00000000;
116
            lpc_dat_o <= 32'h00000000;
117
            lpc_write <= 1'b0;
118
            lpc_tga_o <= `WB_TGA_MEM;
119 6 hharte
            lad_oe <= 1'b0;
120
            lad_o <= 8'hFF;
121 17 hharte
            lpc_dat_i <= 32'h00000000;
122 6 hharte
            mem_xfr <= 1'b0;
123
            dma_xfr <= 1'b0;
124
            fw_xfr <= 1'b0;
125
            xfr_len <= 3'b000;
126
            dma_tc <= 1'b0;
127
            dma_chan <= 3'b000;
128
        end
129
        else begin
130
            case(state)
131
                `LPC_ST_IDLE:
132
                    begin
133
                        dat_cnt <= 4'h0;
134 17 hharte
                        if(lframe_i) begin
135
                            lad_oe <= 1'b0;
136
                            xfr_len <= 3'b001;
137 6 hharte
 
138 17 hharte
                            if(lad_i == `LPC_START) begin
139
                                state <= `LPC_ST_CYCTYP;
140
                                lpc_write <= 1'b0;
141
                                fw_xfr <= 1'b0;
142 6 hharte
                            end
143 17 hharte
                            else if ((lad_i == `LPC_FW_WRITE) || (lad_i == `LPC_FW_READ)) begin
144
                                state <= `LPC_ST_ADDR;
145
                                lpc_write <= (lad_i == `LPC_FW_WRITE) ? 1'b1 : 1'b0;
146
                                adr_cnt <= 3'b000;
147
                                fw_xfr <= 1'b1;
148
                                dma_xfr <= 1'b0;
149
                                lpc_tga_o <= `WB_TGA_FW;
150
                            end
151
                            else
152
                                state <= `LPC_ST_IDLE;
153
                        end
154 6 hharte
                        else
155
                            state <= `LPC_ST_IDLE;
156
                    end
157
                `LPC_ST_CYCTYP:
158
                    begin
159 17 hharte
                        lpc_write <= (lad_i[3] ? ~lad_i[1] : lad_i[1]);  // Invert we_o if we are doing DMA.
160 6 hharte
                        adr_cnt <= (lad_i[2] ? 3'b000 : 3'b100);
161 17 hharte
                        if(lad_i[3]) begin // dma_xfr
162
                            lpc_tga_o <= `WB_TGA_DMA;
163
                            dma_xfr <= 1'b1;
164
                            mem_xfr <= 1'b0;
165
                            state <= `LPC_ST_CHAN;
166
                        end
167
                        else if(lad_i[2]) begin // mem_xfr
168
                            lpc_tga_o <= `WB_TGA_MEM;
169
                            dma_xfr <= 1'b0;
170
                            mem_xfr <= 1'b1;
171
                            state <= `LPC_ST_ADDR;
172
                        end
173
                        else begin
174
                            lpc_tga_o <= `WB_TGA_IO;
175
                            dma_xfr <= 1'b0;
176
                            mem_xfr <= 1'b0;
177
                            state <= `LPC_ST_ADDR;
178
                        end
179 6 hharte
                    end
180
                `LPC_ST_ADDR:
181
                    begin
182
                        case(adr_cnt)
183 17 hharte
                            3'h0: lpc_adr_reg[31:28] <= lad_i;
184
                            3'h1: lpc_adr_reg[27:24] <= lad_i;
185
                            3'h2: lpc_adr_reg[23:20] <= lad_i;
186
                            3'h3: lpc_adr_reg[19:16] <= lad_i;
187
                            3'h4: lpc_adr_reg[15:12] <= lad_i;
188
                            3'h5: lpc_adr_reg[11: 8] <= lad_i;
189
                            3'h6: lpc_adr_reg[ 7: 4] <= lad_i;
190
                            3'h7: lpc_adr_reg[ 3: 0] <= lad_i;
191 6 hharte
                        endcase
192
 
193
                        adr_cnt <= adr_cnt + 1;
194
 
195
                        if(adr_cnt == 3'h7) // Last address nibble.
196
                            begin
197
                                if(~fw_xfr)
198 17 hharte
                                    if(lpc_write)
199 6 hharte
                                        state <= `LPC_ST_H_DATA;
200
                                    else
201
                                        state <= `LPC_ST_H_TAR1;
202
                                else    // For firmware read/write, we need to read the MSIZE nibble
203
                                    state <= `LPC_ST_SIZE;
204
                            end
205
                        else
206
                            state <= `LPC_ST_ADDR;
207
                    end
208
                `LPC_ST_CHAN:
209
                    begin
210 17 hharte
                        lpc_adr_reg <= 32'h00000000;      // Address lines not used for DMA.
211 6 hharte
                        dma_tc <= lad_i[3];
212
                        dma_chan <= lad_i[2:0];
213
                        state <= `LPC_ST_SIZE;
214
                    end
215
                `LPC_ST_SIZE:
216
                    begin
217
                        case(lad_i)
218 17 hharte
                            4'h0:    xfr_len <= 3'b001;
219
                            4'h1:    xfr_len <= 3'b010;
220
                            4'h2:    xfr_len <= 3'b100;   // Firmware transfer uses '2' for 4-byte transfer.
221
                            4'h3:    xfr_len <= 3'b100;   // DMA uses '3' for 4-byte transfer.
222
                            default: xfr_len <= 3'b001;
223 6 hharte
                        endcase
224 17 hharte
                        if(lpc_write)
225 6 hharte
                            state <= `LPC_ST_H_DATA;
226
                        else
227
                            state <= `LPC_ST_H_TAR1;
228
                    end
229
                `LPC_ST_H_DATA:
230
                    begin
231
                        case(dat_cnt)
232 17 hharte
                            4'h0: lpc_dat_o[ 3: 0] <= lad_i;
233
                            4'h1: lpc_dat_o[ 7: 4] <= lad_i;
234
                            4'h2: lpc_dat_o[11: 8] <= lad_i;
235
                            4'h3: lpc_dat_o[15:12] <= lad_i;
236
                            4'h4: lpc_dat_o[19:16] <= lad_i;
237
                            4'h5: lpc_dat_o[23:20] <= lad_i;
238
                            4'h6: lpc_dat_o[27:24] <= lad_i;
239
                            4'h7: lpc_dat_o[31:28] <= lad_i;
240 6 hharte
                        endcase
241
 
242
                        dat_cnt <= dat_cnt + 1;
243
 
244
                        if(nibble_cnt == 1'b1) // end of byte
245
                            begin
246 15 hharte
                                if((fw_xfr) && (byte_cnt != xfr_len-1)) // Firmware transfer does not have TAR between bytes.
247
                                    state <= `LPC_ST_H_DATA;
248
                                                                                  else
249
                                    state <= `LPC_ST_H_TAR1;
250 6 hharte
                            end
251
                        else
252
                            state <= `LPC_ST_H_DATA;
253
 
254
                    end
255
 
256
                `LPC_ST_H_TAR1:
257
                    begin
258 17 hharte
                        // It is ok to start the Wishbone Cycle, done below...
259 6 hharte
                        state <= `LPC_ST_H_TAR2;
260
                    end
261
                `LPC_ST_H_TAR2:
262
                    begin
263 17 hharte
                        state <= (fw_xfr & lpc_write) ? `LPC_ST_FWW_SYNC : `LPC_ST_SYNC;
264
                        lad_o <= (fw_xfr & lpc_write) ? `LPC_SYNC_READY : `LPC_SYNC_SWAIT;
265 6 hharte
                        lad_oe <= 1'b1;     // start driving LAD
266
                    end
267
                `LPC_ST_SYNC:
268
                    begin
269
                        lad_oe <= 1'b1;     // start driving LAD
270 17 hharte
                        // First byte of WB read, last byte of WB write
271
                        if(((byte_cnt == xfr_len) & lpc_write) | ((byte_cnt == 0) & ~lpc_write)) begin
272
                            // Errors can not be signalled for Firmware Memory accesses according to the spec.
273
                            if((wbm_err_i) && (~fw_xfr)) begin
274
                                dat_cnt <= { xfr_len, 1'b1 }; // Abort remainder of transfer
275
                                lad_o <= `LPC_SYNC_ERROR;   // Bus error
276
                                state <= `LPC_ST_P_TAR1;
277
                            end else if(got_ack) begin
278
                                if(lpc_write) begin
279 6 hharte
                                    lad_o <= `LPC_SYNC_READY;   // Ready
280 17 hharte
                                    state <= `LPC_ST_P_TAR1;
281 6 hharte
                                end
282 17 hharte
                                else begin
283
                                    // READY+MORE for multi-byte DMA, except the final byte.
284
                                    // For non-DMA cycles, only READY
285
                                    lad_o <= (((xfr_len == 1) & ~lpc_write) || (~dma_xfr)) ? `LPC_SYNC_READY : `LPC_SYNC_MORE;
286
                                    state <= `LPC_ST_P_DATA;
287 6 hharte
                                end
288
                            end
289 17 hharte
                            else begin
290
                                state <= `LPC_ST_SYNC;
291
                                lad_o <= `LPC_SYNC_SWAIT;
292
                            end
293
                        end
294 6 hharte
                        else begin  // Multi-byte transfer, just ack right away.
295 17 hharte
                            if(lpc_write) begin
296
                                lad_o <= (dma_xfr) ? `LPC_SYNC_MORE : `LPC_SYNC_READY;
297 6 hharte
                                state <= `LPC_ST_P_TAR1;
298 17 hharte
                            end
299
                                                                         else begin
300
                                lad_o <= ((byte_cnt == xfr_len-1) || (~dma_xfr)) ? `LPC_SYNC_READY : `LPC_SYNC_MORE;   // Ready-More                                                                     
301 6 hharte
                                state <= `LPC_ST_P_DATA;
302
                            end
303
                        end
304 17 hharte
                    end
305
                `LPC_ST_FWW_SYNC:       // Firmware write requires a special SYNC without wait-states.
306
                    begin
307
                        lad_o <= 4'hF;
308
                        state <= `LPC_ST_P_TAR2;
309
                    end
310 6 hharte
 
311
                `LPC_ST_P_DATA:
312
                    begin
313
                        case(dat_cnt)
314 17 hharte
                            4'h0: lad_o <= lpc_dat_i[ 3: 0];
315
                            4'h1: lad_o <= lpc_dat_i[ 7: 4];
316
                            4'h2: lad_o <= lpc_dat_i[11: 8];
317
                            4'h3: lad_o <= lpc_dat_i[15:12];
318
                            4'h4: lad_o <= lpc_dat_i[19:16];
319
                            4'h5: lad_o <= lpc_dat_i[23:20];
320
                            4'h6: lad_o <= lpc_dat_i[27:24];
321
                            4'h7: lad_o <= lpc_dat_i[31:28];
322 6 hharte
                        endcase
323
 
324
                        dat_cnt <= dat_cnt + 1;
325
 
326
                        if(nibble_cnt == 1'b1)  // Byte transfer complete
327
                            if (byte_cnt == xfr_len-1) // Byte transfer complete
328
                                state <= `LPC_ST_P_TAR1;
329 15 hharte
                            else begin
330
                                if(fw_xfr) // Firmware transfer does not have TAR between bytes.
331
                                    state <= `LPC_ST_P_DATA;
332
                                else
333
                                    state <= `LPC_ST_SYNC;
334
                            end
335 6 hharte
                        else
336
                            state <= `LPC_ST_P_DATA;
337
 
338
                        lad_oe <= 1'b1;
339
                    end
340
                `LPC_ST_P_TAR1:
341
                    begin
342
                        lad_oe <= 1'b1;
343
                        lad_o <= 4'hF;
344
                        state <= `LPC_ST_P_TAR2;
345
                    end
346
                `LPC_ST_P_TAR2:
347
                    begin
348
                        lad_oe <= 1'b0;     // float LAD
349
                        if(byte_cnt == xfr_len) begin
350
                            state <= `LPC_ST_IDLE;
351
                        end
352
                        else begin
353 17 hharte
                            if(lpc_write) begin  // DMA READ (Host to Peripheral)
354 6 hharte
                                state <= `LPC_ST_P_WAIT1;
355
                            end
356
                            else begin  // unhandled READ case
357
                                state <= `LPC_ST_IDLE;
358
                            end
359
                        end
360 3 hharte
 
361 6 hharte
                    end
362
                    `LPC_ST_P_WAIT1:
363
                         state <= `LPC_ST_H_DATA;
364
            endcase
365
        end
366 3 hharte
 
367 17 hharte
// The goal here is to split the Wishbone cycle handling out of the main state-machine
368
// so it can run independently.  This is needed so that in the case of a firmware write,
369
// where the FLASH requires wait-states (which are not allowed for FW write according to
370
// the LPC Specification.)  In this case, since the FLASH cannot insert wait-states,
371
// a subsequent LPC operation (which must not be another FW Write) will insert wait-
372
// states before starting the next Wishbone master cycle.
373
//
374
// The only reason that I can think of for the LPC spec to mandate that Firmware Writes
375
// must not insert wait-states is that since FLASH writes can take a very long time,
376
// the LPC spec disallowed them to force LPC FLASH programming software to use polling
377
// to determine when the write is complete rather than inserting a bunch of wait-states,
378
// which would use up too much LPC bus bandwidth, and block other requests from getting
379
// through.
380
//
381
        if(~nrst_i)
382
        begin
383
            wbm_adr_o <= 32'h00000000;
384
            wbm_dat_o <= 32'h00000000;
385
            wbm_stb_o <= 1'b0;
386
            wbm_cyc_o <= 1'b0;
387
            wbm_we_o <= 1'b0;
388
            wbm_sel_o <= 4'b0000;
389
            wbm_tga_o <= `WB_TGA_MEM;
390
            got_ack <= 1'b0;
391
        end
392
        else begin
393
            if ((state == `LPC_ST_H_TAR1) && (((byte_cnt == xfr_len) & lpc_write) | ((byte_cnt == 0) & ~lpc_write)))
394
            begin
395
                // Start Wishbone Cycle
396
                wbm_stb_o <= 1'b1;
397
                wbm_cyc_o <= 1'b1;
398
                wbm_adr_o <= lpc_adr_reg;
399
                wbm_dat_o <= lpc_dat_o;
400
                wbm_we_o <= lpc_write;
401
                wbm_tga_o <= lpc_tga_o;
402
                got_ack <= 1'b0;
403
                case(xfr_len)
404
                    3'h0: wbm_sel_o <= `WB_SEL_BYTE;
405
                    3'h2: wbm_sel_o <= `WB_SEL_SHORT;
406
                    3'h4: wbm_sel_o <= `WB_SEL_WORD;
407
                endcase
408
            end
409
            else if((wbm_stb_o == 1'b1) && (wbm_ack_i == 1'b1)) begin
410
                // End Wishbone Cycle
411
                wbm_stb_o <= 1'b0;
412
                wbm_cyc_o <= 1'b0;
413
                wbm_we_o <= 1'b0;
414
                got_ack <= 1'b1;
415
                if(~wbm_we_o) begin
416
                    lpc_dat_i <= wbm_dat_i;
417
                end
418
             end
419
        end
420
    end
421 3 hharte
endmodule
422
 
423 6 hharte
 

powered by: WebSVN 2.1.0

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