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

Subversion Repositories qaz_libs

[/] [qaz_libs/] [trunk/] [axi4_stream_lib/] [src/] [axis_downsizer.sv] - Blame information for rev 35

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 31 qaztronic
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
//// Copyright (C) 2015 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
module
29
  axis_downsizer
30
  #(
31
    N,              // data bus width in bytes
32
    I = 1,          // TID width
33
    D = 1,          // TDEST width
34
    U,              // TUSER width
35
    S,              // tdata size divisor
36
    USE_TSTRB = 0,  //  set to 1 to enable, 0 to disable
37
    USE_TKEEP = 0,  //  set to 1 to enable, 0 to disable
38
    BYTES_PER_TUSER //  bytes per tuser bit. Set to 0 for transfer based.
39
  )
40
  (
41
    axis_if axis_in,
42
    axis_if axis_out,
43
    input   aclk,
44
    input   aresetn
45
  );
46
 
47
// --------------------------------------------------------------------
48
// synthesis translate_off
49
  initial
50
  begin
51
    a_divisor: assert(S > 1) else $fatal;
52
    a_tdata_mod: assert(N % S == 0) else $fatal;
53
    a_tstrb_unsuported: assert(USE_TSTRB == 0) else $fatal;
54
    a_tkeep_unsuported: assert(USE_TKEEP == 0) else $fatal;
55
    a_bytes_per_tuser: assert((BYTES_PER_TUSER == 0) | (N % BYTES_PER_TUSER == 0)) else $fatal;
56
    a_tuser: assert((BYTES_PER_TUSER == 0) | (U % S == 0)) else $fatal;
57
  end
58
// synthesis translate_on
59
// --------------------------------------------------------------------
60
 
61
 
62
  // --------------------------------------------------------------------
63
  //
64
  localparam M_A = $clog2(S);
65
  localparam M_D = 2 ** M_A;
66
  localparam M_NW = (N*8)/ S;
67
  localparam M_UW = U / S;
68
 
69
 
70
  // --------------------------------------------------------------------
71
  //
72
  localparam U_OUT = (BYTES_PER_TUSER == 0) ? U : U / (N / BYTES_PER_TUSER);
73
  axis_if #(.N(N/S), .U(U_OUT)) axis_downsizer_bus(.*);
74
 
75
 
76
  // --------------------------------------------------------------------
77
  //
78
  wire almost_last_word;
79
 
80
 
81
  //---------------------------------------------------
82
  //  state machine binary definitions
83
  enum reg [2:0]
84
    {
85
      GET_WORD_IN   = 3'b001,
86
      MUX_WORD_OUT  = 3'b010,
87
      LAST_WORD_OUT = 3'b100
88
    } state, next_state;
89
 
90
 
91
  //---------------------------------------------------
92
  //  state machine flop
93
  always_ff @(posedge aclk)
94
    if(~aresetn)
95
      state <= GET_WORD_IN;
96
    else
97
      state <= next_state;
98
 
99
 
100
  //---------------------------------------------------
101
  //  state machine
102
  always_comb
103
    case(state)
104
      GET_WORD_IN:          if(axis_in.tvalid)
105
                              next_state <= MUX_WORD_OUT;
106
                            else
107
                              next_state <= GET_WORD_IN;
108
 
109
      MUX_WORD_OUT:         if(almost_last_word & axis_downsizer_bus.tready)
110
                              next_state <= LAST_WORD_OUT;
111
                            else
112
                              next_state <= MUX_WORD_OUT;
113
 
114
      LAST_WORD_OUT:        if(~axis_downsizer_bus.tready)
115
                              next_state <= LAST_WORD_OUT;
116
                            else if(axis_in.tvalid)
117
                              next_state <= MUX_WORD_OUT;
118
                            else
119
                              next_state <= GET_WORD_IN;
120
 
121
      default:              next_state <= GET_WORD_IN;
122
 
123
    endcase
124
 
125
 
126
  // --------------------------------------------------------------------
127
  //
128
  reg [(8*N)-1:0] tdata_r;
129
  reg [I-1:0]     tid_r;
130
  reg [D-1:0]     tdest_r;
131
  reg             tlast_r;
132
  reg [U-1:0]     tuser_r;
133
 
134
  always_ff @(posedge aclk)
135
    if(axis_in.tvalid & axis_in.tready)
136
    begin
137
      tdata_r <= axis_in.tdata;
138
      tid_r   <= axis_in.tid;
139
      tdest_r <= axis_in.tdest;
140
      tlast_r <= axis_in.tlast;   // packet width % S == 0 else tlast becomes invalid
141
      tuser_r <= axis_in.tuser;
142
    end
143
 
144
 
145
  // --------------------------------------------------------------------
146
  //
147
  reg [M_A-1:0] select;
148
  assign almost_last_word = (select == S - 2);
149
 
150
  always_ff @(posedge aclk)
151
    if(~aresetn | (state == GET_WORD_IN))
152
      select <= 0;
153
    else if(axis_downsizer_bus.tvalid & axis_downsizer_bus.tready)
154
      select <= select + 1;
155
 
156
 
157
  // --------------------------------------------------------------------
158
  //
159
  wire [M_NW-1:0] mux_in_tdata [M_D-1:0];
160
  wire [M_NW-1:0] mux_out_tdata;
161
 
162
  recursive_mux #(.A(M_A), .W(M_NW))
163
    tdata_mux_i(.data_in(mux_in_tdata), .data_out(mux_out_tdata), .*);
164
 
165
 
166
  // --------------------------------------------------------------------
167
  //
168 35 qaztronic
  genvar j;
169
 
170 31 qaztronic
  generate
171 35 qaztronic
    for(j = 0; j < M_D; j++)
172
      begin : tdata_gen
173 31 qaztronic
        assign mux_in_tdata[j] = tdata_r[j*M_NW +: M_NW];
174 35 qaztronic
      end
175 31 qaztronic
  endgenerate
176
 
177
 
178
  // --------------------------------------------------------------------
179
  //
180
  generate
181 35 qaztronic
    begin : tuser_gen
182 31 qaztronic
      if(BYTES_PER_TUSER != 0)
183 35 qaztronic
      begin : tuser_tuser_0_gen
184 31 qaztronic
        wire [M_UW-1:0] mux_in_tuser [M_D-1:0];
185
 
186
        recursive_mux #(.A(M_A), .W(M_UW))
187
          tuser_mux_i(.data_in(mux_in_tuser), .data_out(axis_downsizer_bus.tuser), .*);
188
 
189 35 qaztronic
        for(j = 0; j < M_D; j++)
190
        begin : tuser_j_gen
191 31 qaztronic
          assign mux_in_tuser[j] = tuser_r[j*M_UW +: M_UW] & {M_UW{axis_downsizer_bus.tvalid}};
192 35 qaztronic
        end
193 31 qaztronic
      end
194
      else
195 35 qaztronic
      begin : tuser_tuser_gen
196 31 qaztronic
        assign axis_downsizer_bus.tuser = tuser_r & {U{axis_downsizer_bus.tvalid}};
197 35 qaztronic
      end
198 31 qaztronic
    end
199
  endgenerate
200
 
201
 
202
  // --------------------------------------------------------------------
203
  //
204
  assign axis_in.tready   = (state == GET_WORD_IN) |
205
                            ((state == LAST_WORD_OUT) & (next_state == MUX_WORD_OUT));
206
  assign axis_downsizer_bus.tvalid  = (state != GET_WORD_IN);
207
 
208
  assign axis_downsizer_bus.tdata  = mux_out_tdata;
209
  assign axis_downsizer_bus.tid    = tid_r;
210
  assign axis_downsizer_bus.tdest  = tdest_r;
211
  assign axis_downsizer_bus.tlast  = (select == S - 1) ? tlast_r : 1'b0;
212
 
213
 
214
  // --------------------------------------------------------------------
215
  //
216
  axis_register_slice #(.N(N), .U(U))
217
    axis_register_slice_i(.axis_in(axis_downsizer_bus), .*);
218
 
219
 
220
// --------------------------------------------------------------------
221
//
222
endmodule
223
 
224
 

powered by: WebSVN 2.1.0

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