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 6

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

Line No. Rev Author Line
1 3 hharte
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3 6 hharte
////  $Id: wb_lpc_periph.v,v 1.2 2008-03-05 05:50:59 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 6 hharte
                     wbm_stb_o, wbm_cyc_o, wbm_ack_i,
57
                     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 3 hharte
 
74 6 hharte
    // LPC Slave Interface
75
    input              lframe_i;    // LPC Frame input (active high)
76
    output reg         lad_oe;      // LPC AD Output Enable
77
    input        [3:0] lad_i;       // LPC AD Input Bus
78
    output reg   [3:0] lad_o;       // LPC AD Output Bus
79 3 hharte
 
80 6 hharte
    // DMA-Specific sideband signals
81
    output       [2:0] dma_chan_o;  // DMA Channel
82
    output             dma_tc_o;    // DMA Terminal Count
83 3 hharte
 
84 6 hharte
    reg         [12:0] state;       // Current state
85
    reg          [2:0] adr_cnt;     // Address nibble counter
86
    reg          [3:0] dat_cnt;     // Data nibble counter
87
    wire         [2:0] byte_cnt = dat_cnt[3:1];  // Byte counter
88
    wire               nibble_cnt = dat_cnt[0];  // Nibble counter
89 3 hharte
 
90 6 hharte
    reg         [31:0] lpc_dat_i;   // Temporary storage for input data.
91
    reg          [3:0] start_type;  // Type of LPC start cycle
92
    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 6 hharte
    assign dma_chan_o = dma_chan;
100
    assign dma_tc_o = dma_tc;
101
 
102
    always @(posedge clk_i or negedge nrst_i)
103
        if(~nrst_i)
104
        begin
105
            state <= `LPC_ST_IDLE;
106
            wbm_adr_o <= 16'h0000;
107
            wbm_dat_o <= 32'h00000000;
108
            wbm_sel_o <= 4'b0000;
109
            wbm_tga_o <= `WB_TGA_MEM;
110
            wbm_we_o <= 1'b0;
111
            wbm_stb_o <= 1'b0;
112
            wbm_cyc_o <= 1'b0;
113
            lad_oe <= 1'b0;
114
            lad_o <= 8'hFF;
115
            lpc_dat_i <= 32'h00;
116
            start_type <= 4'b0000;
117
            wbm_tga_o <= `WB_TGA_MEM;
118
            mem_xfr <= 1'b0;
119
            dma_xfr <= 1'b0;
120
            fw_xfr <= 1'b0;
121
            xfr_len <= 3'b000;
122
            dma_tc <= 1'b0;
123
            dma_chan <= 3'b000;
124
        end
125
        else begin
126
            case(state)
127
                `LPC_ST_IDLE:
128
                    begin
129
                        dat_cnt <= 4'h0;
130
                        if(lframe_i)
131
                            begin
132
                                start_type <= lad_i;
133
                                wbm_sel_o <= 4'b0000;
134
                                wbm_stb_o <= 1'b0;
135
                                wbm_cyc_o <= 1'b0;
136
                                lad_oe <= 1'b0;
137
                                xfr_len <= 3'b001;
138
 
139
                                if(lad_i == `LPC_START) begin
140
                                    state <= `LPC_ST_CYCTYP;
141
                                    wbm_we_o <= 1'b0;
142
                                    fw_xfr <= 1'b0;
143
                                end
144
                                else if (lad_i == `LPC_FW_READ) begin
145
                                    state <= `LPC_ST_ADDR;
146
                                    wbm_we_o <= 1'b0;
147
                                    adr_cnt <= 3'b000;
148
                                    fw_xfr <= 1'b1;
149
                                    wbm_tga_o <= `WB_TGA_FW;
150
                                end
151
                                else if (lad_i == `LPC_FW_WRITE) begin
152
                                    state <= `LPC_ST_ADDR;
153
                                    wbm_we_o <= 1'b1;
154
                                    adr_cnt <= 3'b000;
155
                                    fw_xfr <= 1'b1;
156
                                    wbm_tga_o <= `WB_TGA_FW;
157
                                end
158
                                else
159
                                    state <= `LPC_ST_IDLE;
160
                            end
161
                        else
162
                            state <= `LPC_ST_IDLE;
163
                    end
164
                `LPC_ST_CYCTYP:
165
                    begin
166
                        wbm_we_o <= (lad_i[3] ? ~lad_i[1] : lad_i[1]);  // Invert we_o if we are doing DMA.
167
                        mem_xfr <= lad_i[2];
168
                        dma_xfr <= lad_i[3];
169
                        adr_cnt <= (lad_i[2] ? 3'b000 : 3'b100);
170
                        if(lad_i[3]) // dma_xfr)
171
                            wbm_tga_o <= `WB_TGA_DMA;
172
                        else if(lad_i[2]) //mem_xfr)
173
                            wbm_tga_o <= `WB_TGA_MEM;
174
                        else
175
                            wbm_tga_o <= `WB_TGA_IO;
176
 
177
                        if(lad_i[3]) //dma_xfr)
178
                            begin
179
                                state <= `LPC_ST_CHAN;
180
                            end
181
                        else
182
                            begin
183
                                state <= `LPC_ST_ADDR;
184
                            end
185
                    end
186
                `LPC_ST_ADDR:
187
                    begin
188
                        case(adr_cnt)
189
                            3'h0:
190
                                wbm_adr_o[31:28] <= lad_i;
191
                            3'h1:
192
                                wbm_adr_o[27:24] <= lad_i;
193
                            3'h2:
194
                                wbm_adr_o[23:20] <= lad_i;
195
                            3'h3:
196
                                wbm_adr_o[19:16] <= lad_i;
197
                            3'h4:
198
                                wbm_adr_o[15:12] <= lad_i;
199
                            3'h5:
200
                                wbm_adr_o[11:8] <= lad_i;
201
                            3'h6:
202
                                wbm_adr_o[7:4] <= lad_i;
203
                            3'h7:
204
                                wbm_adr_o[3:0] <= lad_i;
205
                        endcase
206
 
207
                        adr_cnt <= adr_cnt + 1;
208
 
209
                        if(adr_cnt == 3'h7) // Last address nibble.
210
                            begin
211
                                if(~fw_xfr)
212
                                    if(wbm_we_o)
213
                                        state <= `LPC_ST_H_DATA;
214
                                    else
215
                                        state <= `LPC_ST_H_TAR1;
216
                                else    // For firmware read/write, we need to read the MSIZE nibble
217
                                    state <= `LPC_ST_SIZE;
218
                            end
219
                        else
220
                            state <= `LPC_ST_ADDR;
221
                    end
222
                `LPC_ST_CHAN:
223
                    begin
224
                        wbm_adr_o <= 32'h00000000;      // Address lines not used for DMA.
225
                        dma_tc <= lad_i[3];
226
                        dma_chan <= lad_i[2:0];
227
                        state <= `LPC_ST_SIZE;
228
                    end
229
                `LPC_ST_SIZE:
230
                    begin
231
                        case(lad_i)
232
                            4'h0:
233
                                begin
234
                                    xfr_len <= 3'b001;
235
                                    wbm_sel_o <= `WB_SEL_BYTE;
236
                                end
237
                            4'h1:
238
                                begin
239
                                    xfr_len <= 3'b010;
240
                                    wbm_sel_o <= `WB_SEL_SHORT;
241
                                end
242
                            4'h2:           // Firmware transfer uses '2' for 4-byte transfer.
243
                                begin
244
                                    xfr_len <= 3'b100;
245
                                    wbm_sel_o <= `WB_SEL_WORD;
246
                                end
247
                            4'h3:           // DMA uses '3' for 4-byte transfer.
248
                                begin
249
                                    xfr_len <= 3'b100;
250
                                    wbm_sel_o <= `WB_SEL_WORD;
251
                                end
252
                            default:
253
                                begin
254
                                    xfr_len <= 3'b001;
255
                                    wbm_sel_o <= 4'b0000;
256
                                end
257
                        endcase
258
                        if(wbm_we_o)
259
                            state <= `LPC_ST_H_DATA;
260
                        else
261
                            state <= `LPC_ST_H_TAR1;
262
                    end
263
                `LPC_ST_H_DATA:
264
                    begin
265
                        case(dat_cnt)
266
                            4'h0:
267
                                wbm_dat_o[3:0] <= lad_i;
268
                            4'h1:
269
                                wbm_dat_o[7:4] <= lad_i;
270
                            4'h2:
271
                                wbm_dat_o[11:8] <= lad_i;
272
                            4'h3:
273
                                wbm_dat_o[15:12] <= lad_i;
274
                            4'h4:
275
                                wbm_dat_o[19:16] <= lad_i;
276
                            4'h5:
277
                                wbm_dat_o[23:20] <= lad_i;
278
                            4'h6:
279
                                wbm_dat_o[27:24] <= lad_i;
280
                            4'h7:
281
                                wbm_dat_o[31:28] <= lad_i;
282
                        endcase
283
 
284
                        dat_cnt <= dat_cnt + 1;
285
 
286
                        if(nibble_cnt == 1'b1) // end of byte
287
                            begin
288
                                state <= `LPC_ST_H_TAR1;
289
                            end
290
                        else
291
                            state <= `LPC_ST_H_DATA;
292
 
293
                    end
294
 
295
                `LPC_ST_H_TAR1:
296
                    begin
297
                        if(((byte_cnt == xfr_len) & wbm_we_o) | ((byte_cnt == 0) & ~wbm_we_o))
298
                        begin
299
                            wbm_stb_o <= 1'b1;
300
                            wbm_cyc_o <= 1'b1;
301
                        end
302
                        state <= `LPC_ST_H_TAR2;
303
                    end
304
                `LPC_ST_H_TAR2:
305
                    begin
306
                        state <= `LPC_ST_SYNC;
307
                        lad_oe <= 1'b1;     // start driving LAD
308
                        lad_o <= `LPC_SYNC_SWAIT;
309
                    end
310
                `LPC_ST_SYNC:
311
                    begin
312
                        lad_oe <= 1'b1;     // start driving LAD
313
                        if(((byte_cnt == xfr_len) & wbm_we_o) | ((byte_cnt == 0) & ~wbm_we_o)) begin
314
                            if(wbm_ack_i)
315
                                begin
316
                                    lad_o <= `LPC_SYNC_READY;   // Ready
317
                                    wbm_stb_o <= 1'b0;  // End Wishbone cycle.
318
                                    wbm_cyc_o <= 1'b0;
319
                                    if(wbm_we_o)
320
                                        state <= `LPC_ST_P_TAR1;
321
                                    else
322
                                        begin
323
                                            lpc_dat_i <= wbm_dat_i[31:0];
324
                                            state <= `LPC_ST_P_DATA;
325
                                        end
326
                                end
327
                            else
328
                                begin
329
                                    state <= `LPC_ST_SYNC;
330
                                    lad_o <= `LPC_SYNC_SWAIT;
331
                                end
332
                            end
333
                        else begin  // Multi-byte transfer, just ack right away.
334
                            lad_o <= `LPC_SYNC_READY;   // Ready
335
                            if(wbm_we_o)
336
                                state <= `LPC_ST_P_TAR1;
337
                            else
338
                                state <= `LPC_ST_P_DATA;
339
                            end
340
                        end
341
 
342
                `LPC_ST_P_DATA:
343
                    begin
344
                        case(dat_cnt)
345
                            4'h0:
346
                                lad_o <= lpc_dat_i[3:0];
347
                            4'h1:
348
                                lad_o <= lpc_dat_i[7:4];
349
                            4'h2:
350
                                lad_o <= lpc_dat_i[11:8];
351
                            4'h3:
352
                                lad_o <= lpc_dat_i[15:12];
353
                            4'h4:
354
                                lad_o <= lpc_dat_i[19:16];
355
                            4'h5:
356
                                lad_o <= lpc_dat_i[23:20];
357
                            4'h6:
358
                                lad_o <= lpc_dat_i[27:24];
359
                            4'h7:
360
                                lad_o <= lpc_dat_i[31:28];
361
                        endcase
362
 
363
                        dat_cnt <= dat_cnt + 1;
364
 
365
                        if(nibble_cnt == 1'b1)  // Byte transfer complete
366
                            if (byte_cnt == xfr_len-1) // Byte transfer complete
367
                                state <= `LPC_ST_P_TAR1;
368
                            else
369
                                state <= `LPC_ST_SYNC;
370
                        else
371
                            state <= `LPC_ST_P_DATA;
372
 
373
                        lad_oe <= 1'b1;
374
                    end
375
                `LPC_ST_P_TAR1:
376
                    begin
377
                        lad_oe <= 1'b1;
378
                        lad_o <= 4'hF;
379
                        state <= `LPC_ST_P_TAR2;
380
                    end
381
                `LPC_ST_P_TAR2:
382
                    begin
383
                        lad_oe <= 1'b0;     // float LAD
384
                        if(byte_cnt == xfr_len) begin
385
                            state <= `LPC_ST_IDLE;
386
                        end
387
                        else begin
388
                            if(wbm_we_o) begin  // DMA READ (Host to Peripheral)
389
                                state <= `LPC_ST_P_WAIT1;
390
                            end
391
                            else begin  // unhandled READ case
392
                                state <= `LPC_ST_IDLE;
393
                            end
394
                        end
395 3 hharte
 
396 6 hharte
                    end
397
                    `LPC_ST_P_WAIT1:
398
                         state <= `LPC_ST_H_DATA;
399
            endcase
400
        end
401 3 hharte
 
402
endmodule
403
 
404 6 hharte
 

powered by: WebSVN 2.1.0

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