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

Subversion Repositories wb_size_bridge

[/] [wb_size_bridge/] [trunk/] [src/] [wb_size_bridge.v] - Blame information for rev 4

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

Line No. Rev Author Line
1 4 qaztronic
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
//// Copyright (C) 2009 Authors and OPENCORES.ORG                 ////
4
////                                                              ////
5
//// This source file may be used and distributed without         ////
6
//// restriction provided that this copyright statement is not    ////
7
//// removed from the file and that any derivative work contains  ////
8
//// the original copyright notice and the associated disclaimer. ////
9
////                                                              ////
10
//// This source file is free software; you can redistribute it   ////
11
//// and/or modify it under the terms of the GNU Lesser General   ////
12
//// Public License as published by the Free Software Foundation; ////
13
//// either version 2.1 of the License, or (at your option) any   ////
14
//// later version.                                               ////
15
////                                                              ////
16
//// This source is distributed in the hope that it will be       ////
17
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
18
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
19
//// PURPOSE.  See the GNU Lesser General Public License for more ////
20
//// details.                                                     ////
21
////                                                              ////
22
//// You should have received a copy of the GNU Lesser General    ////
23
//// Public License along with this source; if not, download it   ////
24
//// from http://www.opencores.org/lgpl.shtml                     ////
25
////                                                              ////
26
//////////////////////////////////////////////////////////////////////
27
 
28
`timescale 1ns/10ps
29
 
30
 
31
module wb_size_bridge(
32
                        input         wb_hi_clk_i,
33
                        input         wb_hi_rst_i,
34
                        output [31:0] wb_hi_dat_o,
35
                        input  [31:0] wb_hi_dat_i,
36
                        input  [31:0] wb_hi_adr_i,
37
                        input         wb_hi_cyc_i,
38
                        input         wb_hi_stb_i,
39
                        input         wb_hi_we_i,
40
                        input  [3:0]  wb_hi_sel_i,
41
                        output        wb_hi_ack_o,
42
                        output        wb_hi_err_o,
43
                        output        wb_hi_rty_o,
44
 
45
                        output        wb_lo_clk_o,
46
                        output        wb_lo_rst_o,
47
                        input  [15:0] wb_lo_dat_i,
48
                        output [15:0] wb_lo_dat_o,
49
                        output [31:0] wb_lo_adr_o,
50
                        output        wb_lo_cyc_o,
51
                        output        wb_lo_stb_o,
52
                        output        wb_lo_we_o,
53
                        output [1:0]  wb_lo_sel_o,
54
                        input         wb_lo_ack_i,
55
                        input         wb_lo_err_i,
56
                        input         wb_lo_rty_i,
57
 
58
                        input         lo_byte_if_i
59
                      );
60
 
61
  // --------------------------------------------------------------------
62
  //  state machine encoder
63
  reg [2:0] state_enc;
64
 
65
  wire state_enc_3_more_chunks  = state_enc[2];
66
  wire state_enc_1_more_chunks  = state_enc[1];
67
  wire state_enc_error          = state_enc[0];
68
 
69
  always @(*)
70
    case( { lo_byte_if_i, wb_hi_sel_i } )
71
      5'b1_0001:  state_enc = { 1'b0, 1'b0, 1'b0 };
72
      5'b1_0010:  state_enc = { 1'b0, 1'b0, 1'b0 };
73
      5'b1_0100:  state_enc = { 1'b0, 1'b0, 1'b0 };
74
      5'b1_1000:  state_enc = { 1'b0, 1'b0, 1'b0 };
75
      5'b1_0011:  state_enc = { 1'b0, 1'b1, 1'b0 };
76
      5'b1_1100:  state_enc = { 1'b0, 1'b1, 1'b0 };
77
      5'b1_1111:  state_enc = { 1'b1, 1'b0, 1'b0 };
78
      5'b0_0001:  state_enc = { 1'b0, 1'b0, 1'b0 };
79
      5'b0_0010:  state_enc = { 1'b0, 1'b0, 1'b0 };
80
      5'b0_0100:  state_enc = { 1'b0, 1'b0, 1'b0 };
81
      5'b0_1000:  state_enc = { 1'b0, 1'b0, 1'b0 };
82
      5'b0_0011:  state_enc = { 1'b0, 1'b0, 1'b0 };
83
      5'b0_1100:  state_enc = { 1'b0, 1'b0, 1'b0 };
84
      5'b0_1111:  state_enc = { 1'b0, 1'b1, 1'b0 };
85
      default:   state_enc = { 1'b0, 1'b0, 1'b1 };
86
    endcase
87
 
88
 
89
  // --------------------------------------------------------------------
90
  //  state machine
91
 
92
  localparam   STATE_DONT_CARE     = 4'b????;
93
  localparam   STATE_PASS_THROUGH  = 4'b0001;
94
  localparam   STATE_1_MORE_CHUNK  = 4'b0010;
95
  localparam   STATE_2_MORE_CHUNK  = 4'b0100;
96
  localparam   STATE_3_MORE_CHUNK  = 4'b1000;
97
 
98
  reg [3:0] state;
99
  reg [3:0] next_state;
100
 
101
  always @(posedge wb_hi_clk_i or posedge wb_hi_rst_i)
102
    if(wb_hi_rst_i)
103
      state <= STATE_PASS_THROUGH;
104
    else
105
      state <= next_state;
106
 
107
  always @(*)
108
    case( state )
109
      STATE_PASS_THROUGH: if( state_enc_1_more_chunks & wb_lo_ack_i & wb_hi_stb_i & wb_hi_cyc_i )
110
                            next_state = STATE_1_MORE_CHUNK;
111
                          else if( state_enc_3_more_chunks & wb_lo_ack_i & wb_hi_stb_i & wb_hi_cyc_i )
112
                            next_state = STATE_3_MORE_CHUNK;
113
                          else
114
                            next_state = STATE_PASS_THROUGH;
115
 
116
      STATE_3_MORE_CHUNK: if( wb_lo_ack_i )
117
                            next_state = STATE_2_MORE_CHUNK;
118
                          else
119
                            next_state = STATE_3_MORE_CHUNK;
120
 
121
      STATE_2_MORE_CHUNK: if( wb_lo_ack_i )
122
                            next_state = STATE_1_MORE_CHUNK;
123
                          else
124
                            next_state = STATE_2_MORE_CHUNK;
125
 
126
      STATE_1_MORE_CHUNK: if( wb_lo_ack_i )
127
                            next_state = STATE_PASS_THROUGH;
128
                          else
129
                            next_state = STATE_1_MORE_CHUNK;
130
 
131
      default:            next_state = STATE_PASS_THROUGH;
132
    endcase
133
 
134
 
135
  // --------------------------------------------------------------------
136
  //  byte enable & select
137
  reg [3:0] byte_enable;
138
  localparam   BYTE_N_ENABLED  = 4'b0000;
139
  localparam   BYTE_0_ENABLED  = 4'b0001;
140
  localparam   BYTE_1_ENABLED  = 4'b0010;
141
  localparam   BYTE_2_ENABLED  = 4'b0100;
142
  localparam   BYTE_3_ENABLED  = 4'b1000;
143
 
144
  reg [1:0] byte_select;
145
  localparam   BYTE_0_SELECTED  = 2'b00;
146
  localparam   BYTE_1_SELECTED  = 2'b01;
147
  localparam   BYTE_2_SELECTED  = 2'b10;
148
  localparam   BYTE_3_SELECTED  = 2'b11;
149
  localparam   BYTE_X_SELECTED  = 2'b??;
150
 
151
  always @(*)
152
    casez( { lo_byte_if_i, wb_hi_sel_i, state } )
153
      { 1'b1, 4'b0001, STATE_PASS_THROUGH }:  byte_enable = BYTE_0_ENABLED;
154
      { 1'b1, 4'b0010, STATE_PASS_THROUGH }:  byte_enable = BYTE_1_ENABLED;
155
      { 1'b1, 4'b0100, STATE_PASS_THROUGH }:  byte_enable = BYTE_2_ENABLED;
156
      { 1'b1, 4'b1000, STATE_PASS_THROUGH }:  byte_enable = BYTE_3_ENABLED;
157
 
158
      { 1'b1, 4'b0011, STATE_PASS_THROUGH }:  byte_enable = BYTE_0_ENABLED;
159
      { 1'b1, 4'b0011, STATE_1_MORE_CHUNK }:  byte_enable = BYTE_1_ENABLED;
160
 
161
      { 1'b1, 4'b1100, STATE_PASS_THROUGH }:  byte_enable = BYTE_2_ENABLED;
162
      { 1'b1, 4'b1100, STATE_1_MORE_CHUNK }:  byte_enable = BYTE_3_ENABLED;
163
 
164
      { 1'b1, 4'b1111, STATE_PASS_THROUGH }:  byte_enable = BYTE_0_ENABLED;
165
      { 1'b1, 4'b1111, STATE_3_MORE_CHUNK }:  byte_enable = BYTE_1_ENABLED;
166
      { 1'b1, 4'b1111, STATE_2_MORE_CHUNK }:  byte_enable = BYTE_2_ENABLED;
167
      { 1'b1, 4'b1111, STATE_1_MORE_CHUNK }:  byte_enable = BYTE_3_ENABLED;
168
 
169
      { 1'b0, 4'b????, STATE_DONT_CARE }:     byte_enable = BYTE_N_ENABLED;
170
      default:                                byte_enable = BYTE_N_ENABLED;
171
    endcase
172
 
173
  always @(*)
174
    case( byte_enable )
175
      BYTE_0_ENABLED:  byte_select = BYTE_0_SELECTED;
176
      BYTE_1_ENABLED:  byte_select = BYTE_1_SELECTED;
177
      BYTE_2_ENABLED:  byte_select = BYTE_2_SELECTED;
178
      BYTE_3_ENABLED:  byte_select = BYTE_3_SELECTED;
179
      default:  byte_select = 2'bxx;
180
    endcase
181
 
182
 
183
  // --------------------------------------------------------------------
184
  //  word enable & select
185
  reg [1:0] word_enable;
186
  localparam   WORD_N_ENABLED  = 2'b00;
187
  localparam   WORD_0_ENABLED  = 2'b01;
188
  localparam   WORD_1_ENABLED  = 2'b10;
189
 
190
  reg word_select;
191
  localparam   WORD_0_SELECTED  = 1'b0;
192
  localparam   WORD_1_SELECTED  = 1'b1;
193
  localparam   WORD_X_SELECTED  = 1'b?;
194
 
195
  always @(*)
196
    casez( { lo_byte_if_i, wb_hi_sel_i, state } )
197
      { 1'b0, 4'b0011, STATE_PASS_THROUGH }:  word_enable = WORD_0_ENABLED;
198
      { 1'b0, 4'b1100, STATE_PASS_THROUGH }:  word_enable = WORD_1_ENABLED;
199
      { 1'b0, 4'b0001, STATE_PASS_THROUGH }:  word_enable = WORD_0_ENABLED;
200
      { 1'b0, 4'b0010, STATE_PASS_THROUGH }:  word_enable = WORD_0_ENABLED;
201
      { 1'b0, 4'b0100, STATE_PASS_THROUGH }:  word_enable = WORD_1_ENABLED;
202
      { 1'b0, 4'b1000, STATE_PASS_THROUGH }:  word_enable = WORD_1_ENABLED;
203
 
204
      { 1'b0, 4'b1111, STATE_PASS_THROUGH }:  word_enable = WORD_0_ENABLED;
205
      { 1'b0, 4'b1111, STATE_1_MORE_CHUNK }:  word_enable = WORD_1_ENABLED;
206
 
207
      { 1'b1, 4'b????, STATE_DONT_CARE }:     word_enable = WORD_N_ENABLED;
208
      default:                                word_enable = WORD_N_ENABLED;
209
    endcase
210
 
211
  always @(*)
212
    case( word_enable )
213
      WORD_0_ENABLED: word_select = WORD_0_SELECTED;
214
      WORD_1_ENABLED: word_select = WORD_1_SELECTED;
215
      default:        word_select = 1'bx;
216
    endcase
217
 
218
 
219
  // --------------------------------------------------------------------
220
  //  write mux
221
  reg [1:0] byte_write_mux_enc;
222
 
223
  always @(*)
224
    casez( {lo_byte_if_i, byte_select, word_select} )
225
      { 1'b1, BYTE_0_SELECTED, WORD_X_SELECTED }: byte_write_mux_enc = 2'b00;
226
      { 1'b1, BYTE_1_SELECTED, WORD_X_SELECTED }: byte_write_mux_enc = 2'b01;
227
      { 1'b1, BYTE_2_SELECTED, WORD_X_SELECTED }: byte_write_mux_enc = 2'b10;
228
      { 1'b1, BYTE_3_SELECTED, WORD_X_SELECTED }: byte_write_mux_enc = 2'b11;
229
      { 1'b0, BYTE_X_SELECTED, WORD_0_SELECTED }: byte_write_mux_enc = 2'b00;
230
      { 1'b0, BYTE_X_SELECTED, WORD_1_SELECTED }: byte_write_mux_enc = 2'b10;
231
      default:                                    byte_write_mux_enc = 2'b00;
232
    endcase
233
 
234
  reg [7:0] byte_write_mux;
235
 
236
  always @(*)
237
    case( byte_write_mux_enc )
238
      2'b00:    byte_write_mux = wb_hi_dat_i[7:0];
239
      2'b01:    byte_write_mux = wb_hi_dat_i[15:8];
240
      2'b10:    byte_write_mux = wb_hi_dat_i[23:16];
241
      2'b11:    byte_write_mux = wb_hi_dat_i[31:24];
242
      default:  byte_write_mux = wb_hi_dat_i[7:0];
243
    endcase
244
 
245
  reg [7:0] word_write_mux;
246
 
247
  always @(*)
248
    case( word_select )
249
      WORD_0_SELECTED:  word_write_mux = wb_hi_dat_i[15:8];
250
      WORD_1_SELECTED:  word_write_mux = wb_hi_dat_i[31:24];
251
      default:          word_write_mux = wb_hi_dat_i[15:8];
252
    endcase
253
 
254
 
255
  // --------------------------------------------------------------------
256
  //  read buffer & bypass mux 
257
 
258
  // low side input mux
259
  wire [7:0] read_word_lo_mux = wb_lo_dat_i[7:0];
260
  wire [7:0] read_word_hi_mux = ( word_enable[0] | word_enable[1] )? wb_lo_dat_i[15:8] : wb_lo_dat_i[7:0];
261
 
262
  reg [31:0] read_buffer;
263
 
264
  wire read_buffer_0_enable = (byte_enable[0] | word_enable[0]) & ~wb_hi_we_i;
265
  wire read_buffer_1_enable = (byte_enable[1] | word_enable[0]) & ~wb_hi_we_i;
266
  wire read_buffer_2_enable = (byte_enable[2] | word_enable[1]) & ~wb_hi_we_i;
267
  wire read_buffer_3_enable = (byte_enable[3] | word_enable[1]) & ~wb_hi_we_i;
268
 
269
  always @(posedge wb_hi_clk_i)
270
    if( read_buffer_0_enable )
271
      read_buffer[7:0] <= read_word_lo_mux;
272
 
273
  always @(posedge wb_hi_clk_i)
274
    if( read_buffer_1_enable )
275
      read_buffer[15:8] <= read_word_hi_mux;
276
 
277
  always @(posedge wb_hi_clk_i)
278
    if( read_buffer_2_enable )
279
      read_buffer[23:16] <= read_word_lo_mux;
280
 
281
  always @(posedge wb_hi_clk_i)
282
    if( read_buffer_3_enable )
283
      read_buffer[31:24] <= read_word_hi_mux;
284
 
285
  wire [31:0] read_buffer_mux;
286
 
287
  // bypass read mux
288
  assign read_buffer_mux[7:0]   = read_buffer_0_enable ? read_word_lo_mux : read_buffer[7:0];
289
  assign read_buffer_mux[15:8]  = read_buffer_1_enable ? read_word_hi_mux : read_buffer[15:8];
290
  assign read_buffer_mux[23:16] = read_buffer_2_enable ? read_word_lo_mux : read_buffer[23:16];
291
  assign read_buffer_mux[31:24] = read_buffer_3_enable ? read_word_hi_mux : read_buffer[31:24];
292
 
293
 
294
  // --------------------------------------------------------------------
295
  //  misc logic
296
  wire [1:0] lo_addr_bits;
297
  assign lo_addr_bits = ( |byte_enable ) ? byte_select : { word_select, 1'b0 };
298
 
299
  wire all_done = ( ~(|state_enc) & (state == STATE_PASS_THROUGH) ) |
300
                  ( |state_enc & (state == STATE_1_MORE_CHUNK) );
301
 
302
  reg [1:0] wb_lo_sel_r;
303
  always @(*)
304
    casez( { lo_byte_if_i, wb_hi_sel_i, state } )
305
      { 1'b0, 4'b0001, STATE_PASS_THROUGH }:  wb_lo_sel_r = 2'b01;
306
      { 1'b0, 4'b0010, STATE_PASS_THROUGH }:  wb_lo_sel_r = 2'b10;
307
      { 1'b0, 4'b0100, STATE_PASS_THROUGH }:  wb_lo_sel_r = 2'b01;
308
      { 1'b0, 4'b1000, STATE_PASS_THROUGH }:  wb_lo_sel_r = 2'b10;
309
      default:                                wb_lo_sel_r = 2'b11;
310
    endcase
311
 
312
 
313
 
314
  // --------------------------------------------------------------------
315
  //  output port assignments
316
  assign wb_hi_dat_o = read_buffer_mux;
317
  assign wb_hi_err_o = (wb_lo_err_i | state_enc_error) & wb_hi_stb_i & wb_hi_cyc_i;
318
  assign wb_hi_rty_o = wb_lo_rty_i;
319
  assign wb_hi_ack_o = all_done & wb_hi_stb_i & wb_hi_cyc_i & wb_lo_ack_i;
320
 
321
  assign wb_lo_adr_o = { wb_hi_adr_i[31:2], lo_addr_bits };
322
  assign wb_lo_clk_o = wb_hi_clk_i;
323
  assign wb_lo_rst_o = wb_hi_rst_i;
324
  assign wb_lo_cyc_o = wb_hi_cyc_i;
325
  assign wb_lo_stb_o = wb_hi_stb_i;
326
  assign wb_lo_we_o  = wb_hi_we_i & wb_hi_stb_i & wb_hi_cyc_i;
327
  assign wb_lo_dat_o = {word_write_mux, byte_write_mux};
328
  assign wb_lo_sel_o = wb_lo_sel_r;
329
 
330
 
331
endmodule
332
 
333
 

powered by: WebSVN 2.1.0

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