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 20

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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