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

Subversion Repositories wb_lpc

[/] [wb_lpc/] [trunk/] [rtl/] [verilog/] [wb_lpc_host.v] - Blame information for rev 15

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

Line No. Rev Author Line
1 3 hharte
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3 15 hharte
////  $Id: wb_lpc_host.v,v 1.3 2008-07-22 13:46:42 hharte Exp $   ////
4 3 hharte
////  wb_lpc_host.v - Wishbone Slave to LPC Host 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 5 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
module wb_lpc_host(clk_i, nrst_i, wbs_adr_i, wbs_dat_o, wbs_dat_i, wbs_sel_i, wbs_tga_i, wbs_we_i,
55 5 hharte
                   wbs_stb_i, wbs_cyc_i, wbs_ack_o,
56
                   dma_chan_i, dma_tc_i,
57
                   lframe_o, lad_i, lad_o, lad_oe
58 3 hharte
);
59 5 hharte
    // Wishbone Slave Interface
60
    input              clk_i;
61
    input              nrst_i;             // Active low reset.
62
    input       [31:0] wbs_adr_i;
63
    output      [31:0] wbs_dat_o;
64
    input       [31:0] wbs_dat_i;
65
    input       [3:0]  wbs_sel_i;
66
    input       [1:0]  wbs_tga_i;
67
    input              wbs_we_i;
68
    input              wbs_stb_i;
69
    input              wbs_cyc_i;
70
    output reg         wbs_ack_o;
71
 
72
    // LPC Master Interface
73
    output reg        lframe_o;     // LPC Frame output (active high)
74
    output reg        lad_oe;       // LPC AD Output Enable
75
    input       [3:0] lad_i;        // LPC AD Input Bus
76
    output reg  [3:0] lad_o;        // LPC AD Output Bus
77 3 hharte
 
78 5 hharte
    // DMA-Specific sideband signals
79
    input       [2:0] dma_chan_i;   // DMA Channel
80
    input             dma_tc_i;     // DMA Terminal Count
81 3 hharte
 
82 5 hharte
    reg         [12:0] state;       // Current state
83
    reg         [2:0] adr_cnt;      // Address nibbe counter
84
    reg         [3:0] dat_cnt;      // Data nibble counter
85
    reg         [2:0] xfr_len;      // Number of nibbls for transfer
86
    wire        [2:0] byte_cnt = dat_cnt[3:1];  // Byte Counter
87
    wire              nibble_cnt = dat_cnt[0];    // Nibble counter
88
    reg         [31:0] lpc_dat_i;           // Temporary storage for input word.
89 3 hharte
 
90 5 hharte
    //
91
    // generate wishbone register signals
92
    wire wbs_acc = wbs_cyc_i & wbs_stb_i;    // Wishbone access
93
    wire wbs_wr  = wbs_acc & wbs_we_i;       // Wishbone write access
94 3 hharte
 
95 5 hharte
    // Memory Cycle (tga== 1'b00) is bit 2=1 for LPC Cycle Type.
96
    wire    mem_xfr = (wbs_tga_i == `WB_TGA_MEM);
97
    wire    dma_xfr = (wbs_tga_i == `WB_TGA_DMA);
98
    wire    fw_xfr  = (wbs_tga_i == `WB_TGA_FW);
99
 
100
    assign wbs_dat_o[31:0] = lpc_dat_i;
101 3 hharte
 
102 5 hharte
    always @(posedge clk_i or negedge nrst_i)
103
        if(~nrst_i)
104
        begin
105
            state <= `LPC_ST_IDLE;
106
            lframe_o <= 1'b0;
107
            wbs_ack_o <= 1'b0;
108
            lad_oe <= 1'b0;
109
            lad_o <= 4'b0;
110
            adr_cnt <= 3'b0;
111
            dat_cnt <= 4'h0;
112
            xfr_len <= 3'b000;
113
            lpc_dat_i <= 32'h00000000;
114
        end
115
        else begin
116
            case(state)
117
                `LPC_ST_IDLE:
118
                    begin
119
                        wbs_ack_o <= 1'b0;
120
                        lframe_o <= 1'b0;
121
                        dat_cnt <= 4'h0;
122 3 hharte
 
123 5 hharte
                        if(wbs_acc)     // Wishbone access starts LPC transaction
124
                            state <= `LPC_ST_START;
125
                        else
126
                            state <= `LPC_ST_IDLE;
127
                    end
128
                `LPC_ST_START:
129
                    begin
130
                        lframe_o <= 1'b1;
131
                        if(~fw_xfr) begin       // For Memory and I/O Cycles
132
                            lad_o   <= `LPC_START;
133
                            state   <= `LPC_ST_CYCTYP;
134
                        end
135
                        else begin              // Firmware Read and Write Cycles
136
                            if(wbs_wr)
137
                                lad_o <= `LPC_FW_WRITE;
138
                            else
139
                                lad_o <= `LPC_FW_READ;
140
 
141
                            state   <= `LPC_ST_ADDR;
142
                        end
143
                        lad_oe  <= 1'b1;
144
                        adr_cnt <= ((mem_xfr | fw_xfr) ? 3'b000 : 3'b100);
145
                    end
146
                `LPC_ST_CYCTYP:
147
                    begin
148
                        lframe_o    <= 1'b0;
149
                        lad_oe  <= 1'b1;
150 3 hharte
 
151 5 hharte
                        if(~dma_xfr)
152
                            begin
153
                                lad_o   <= {1'b0,mem_xfr,wbs_wr,1'b0};      // Cycle Type/Direction for I/O or MEM
154
                                state       <= `LPC_ST_ADDR;
155
                            end
156
                        else // it is DMA
157
                            begin
158
                                lad_o   <= {1'b1,1'b0,~wbs_wr,1'b0};        // Cycle Type/Direction for DMA, r/w is inverted for DMA
159
                                state       <= `LPC_ST_CHAN;
160
                            end
161
                    end
162
                `LPC_ST_ADDR:   // Output four nubbles of address.
163
                    begin
164
                        lframe_o <= 1'b0;       // In case we came here from a Firmware cycle, which skips CYCTYP.
165
 
166
                        // The LPC Bus Address is sent across the bus a nibble at a time;
167
                        // however, the most significant nibble is sent first.  For firmware and
168 15 hharte
                        // memory cycles, the address is 32-bits.  Actually, for firmware accesses,
169 5 hharte
                        // the most significant nibble is known as the IDSEL field.  For I/O,
170
                        // the address is only 16-bits wide.
171
                        case(adr_cnt)
172
                            3'h0:
173
                                lad_o <= wbs_adr_i[31:28];
174
                            3'h1:
175
                                lad_o <= wbs_adr_i[27:24];
176
                            3'h2:
177
                                lad_o <= wbs_adr_i[23:20];
178
                            3'h3:
179
                                lad_o <= wbs_adr_i[19:16];
180
                            3'h4:
181
                                lad_o <= wbs_adr_i[15:12];
182
                            3'h5:
183
                                lad_o <= wbs_adr_i[11:8];
184
                            3'h6:
185
                                lad_o <= wbs_adr_i[7:4];
186
                            3'h7:
187
                                lad_o <= wbs_adr_i[3:0];
188
                        endcase
189
 
190
                        adr_cnt <= adr_cnt + 1;
191
 
192
                        if(adr_cnt == 4'h7) // Last address nibble.
193
                            begin
194
                                if(~fw_xfr)
195
                                    if(wbs_wr)
196
                                        state <= `LPC_ST_H_DATA;
197
                                    else
198
                                        state <= `LPC_ST_H_TAR1;
199
                                else    // For firmware read/write, we need to transfer the MSIZE nibble
200
                                    state <= `LPC_ST_SIZE;
201
                            end
202
                        else
203
                            state <= `LPC_ST_ADDR;
204
 
205
                        lad_oe  <= 1'b1;
206
                        xfr_len     <= 3'b001;      // One Byte Transfer
207
                    end
208
                `LPC_ST_CHAN:
209
                    begin
210
                        lad_o   <= {dma_tc_i, dma_chan_i};
211
                        state <= `LPC_ST_SIZE;
212
                    end
213
                `LPC_ST_SIZE:
214
                    begin
215
                        case(wbs_sel_i)
216
                            `WB_SEL_BYTE:
217
                                begin
218
                                    xfr_len <= 3'b001;
219
                                    lad_o <= 4'h0;
220
                                end
221
                            `WB_SEL_SHORT:
222
                                begin
223
                                    xfr_len <= 3'b010;
224
                                    lad_o <= 4'h1;
225
                                end
226
                            `WB_SEL_WORD:
227
                                begin
228
                                    xfr_len <= 3'b100;
229
                                    if(fw_xfr)              // Firmware transfer uses '2' for 4-byte transfer.
230
                                        lad_o <= 4'h2;
231
                                    else                    // DMA uses '3' for 4-byte transfer.
232
                                        lad_o <= 4'h3;
233
                                end
234
                            default:
235
                                begin
236
                                    xfr_len <= 3'b001;
237
                                    lad_o <= 4'h0;
238
                                end
239
                        endcase
240
                        if(wbs_wr)
241
                            state <= `LPC_ST_H_DATA;
242
                        else
243
                            state <= `LPC_ST_H_TAR1;
244
                    end
245 3 hharte
 
246 5 hharte
                `LPC_ST_H_DATA:
247
                    begin
248
                        lad_oe  <= 1'b1;
249
                        case(dat_cnt)   // We only support a single byte for I/O.
250
                            4'h0:
251
                                lad_o <= wbs_dat_i[3:0];
252
                            4'h1:
253
                                lad_o <= wbs_dat_i[7:4];
254
                            4'h2:
255
                                lad_o <= wbs_dat_i[11:8];
256
                            4'h3:
257
                                lad_o <= wbs_dat_i[15:12];
258
                            4'h4:
259
                                lad_o <= wbs_dat_i[19:16];
260
                            4'h5:
261
                                lad_o <= wbs_dat_i[23:20];
262
                            4'h6:
263
                                lad_o <= wbs_dat_i[27:24];
264
                            4'h7:
265
                                lad_o <= wbs_dat_i[31:28];
266
                            default:
267
                                lad_o <= 4'hx;
268
                        endcase
269
 
270
                        dat_cnt <= dat_cnt + 1;
271
 
272
                        if(nibble_cnt == 1'b1) // end of byte
273
                            begin
274 15 hharte
                                if((fw_xfr) && (byte_cnt != xfr_len-1)) // Firmware transfer does not have TAR between bytes.
275
                                    state <= `LPC_ST_H_DATA;
276
                                else
277
                                    state <= `LPC_ST_H_TAR1;
278 5 hharte
                            end
279
                        else
280
                            state <= `LPC_ST_H_DATA;
281
                    end
282
 
283
                `LPC_ST_H_TAR1:
284
                    begin
285
                        lad_o <= 4'b1111;       // Drive LAD high
286
                        lad_oe <= 1'b1;
287
                        state <= `LPC_ST_H_TAR2;
288
                    end
289
                `LPC_ST_H_TAR2:
290
                    begin
291
                        lad_oe <= 1'b0;     // float LAD
292
                        state <= `LPC_ST_SYNC;
293
                    end
294
                `LPC_ST_SYNC:
295
                    begin
296
                        lad_oe <= 1'b0;     // float LAD
297
                        if(lad_i == `LPC_SYNC_READY) begin
298
                            if(wbs_wr) begin
299
                                state <= `LPC_ST_P_TAR1;
300
                            end
301
                            else
302
                                state <= `LPC_ST_P_DATA;
303
                            end
304
                        else
305
                            state <= `LPC_ST_SYNC;
306
                    end
307
 
308
                `LPC_ST_P_DATA:
309
                    begin
310
                        case(dat_cnt)
311
                            4'h0:
312
                                lpc_dat_i[3:0] <= lad_i;
313
                            4'h1:
314
                                lpc_dat_i[7:4] <= lad_i;
315
                            4'h2:
316
                                lpc_dat_i[11:8] <= lad_i;
317
                            4'h3:
318
                                lpc_dat_i[15:12] <= lad_i;
319
                            4'h4:
320
                                lpc_dat_i[19:16] <= lad_i;
321
                            4'h5:
322
                                lpc_dat_i[23:20] <= lad_i;
323
                            4'h6:
324
                                lpc_dat_i[27:24] <= lad_i;
325
                            4'h7:
326
                                lpc_dat_i[31:28] <= lad_i;
327
                        endcase
328
 
329
                        dat_cnt <= dat_cnt + 1;
330
 
331
                        if(nibble_cnt == 1'b1)          // Byte transfer complete
332
                            if (byte_cnt == xfr_len-1)  // End of data transfer phase
333
                                state <= `LPC_ST_P_TAR1;
334 15 hharte
                            else begin
335
                                if(fw_xfr) // Firmware transfer does not have TAR between bytes.
336
                                    state <= `LPC_ST_P_DATA;
337
                                else
338
                                    state <= `LPC_ST_SYNC;
339
                            end
340 5 hharte
                        else                            // Go to next nibble
341
                            state <= `LPC_ST_P_DATA;
342
                    end
343
                `LPC_ST_P_TAR1:
344
                    begin
345
                        lad_oe <= 1'b0;
346
                        if(byte_cnt == xfr_len) begin
347
                            state <= `LPC_ST_WB_RETIRE;
348
                            wbs_ack_o <= wbs_acc;
349
                        end
350
                        else begin
351
                            if(wbs_wr) begin    // DMA READ (Host to Peripheral)
352
                                state <= `LPC_ST_H_DATA;
353
                            end
354
                            else begin  // unhandled READ case
355
                                state <= `LPC_ST_IDLE;
356
                            end
357
                        end
358
                    end
359
                `LPC_ST_WB_RETIRE:
360
                    begin
361
                        wbs_ack_o <= 1'b0;
362
                        if(wbs_acc) begin
363
                            state <= `LPC_ST_WB_RETIRE;
364
                        end
365
                        else begin
366
                            state <= `LPC_ST_IDLE;
367
                        end
368
                    end
369
            endcase
370
        end
371 3 hharte
 
372
endmodule
373
 
374 5 hharte
 

powered by: WebSVN 2.1.0

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