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 31

Go to most recent revision | 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
  generate
169
    begin: tdata_gen
170
      for(genvar j = 0; j < M_D; j++)
171
        assign mux_in_tdata[j] = tdata_r[j*M_NW +: M_NW];
172
    end
173
  endgenerate
174
 
175
 
176
  // --------------------------------------------------------------------
177
  //
178
  generate
179
    begin: tuser_gen
180
      if(BYTES_PER_TUSER != 0)
181
      begin
182
        wire [M_UW-1:0] mux_in_tuser [M_D-1:0];
183
 
184
        recursive_mux #(.A(M_A), .W(M_UW))
185
          tuser_mux_i(.data_in(mux_in_tuser), .data_out(axis_downsizer_bus.tuser), .*);
186
 
187
        for(genvar j = 0; j < M_D; j++)
188
          assign mux_in_tuser[j] = tuser_r[j*M_UW +: M_UW] & {M_UW{axis_downsizer_bus.tvalid}};
189
      end
190
      else
191
        assign axis_downsizer_bus.tuser = tuser_r & {U{axis_downsizer_bus.tvalid}};
192
    end
193
  endgenerate
194
 
195
 
196
  // --------------------------------------------------------------------
197
  //
198
  assign axis_in.tready   = (state == GET_WORD_IN) |
199
                            ((state == LAST_WORD_OUT) & (next_state == MUX_WORD_OUT));
200
  assign axis_downsizer_bus.tvalid  = (state != GET_WORD_IN);
201
 
202
  assign axis_downsizer_bus.tdata  = mux_out_tdata;
203
  assign axis_downsizer_bus.tid    = tid_r;
204
  assign axis_downsizer_bus.tdest  = tdest_r;
205
  assign axis_downsizer_bus.tlast  = (select == S - 1) ? tlast_r : 1'b0;
206
 
207
 
208
  // --------------------------------------------------------------------
209
  //
210
  axis_register_slice #(.N(N), .U(U))
211
    axis_register_slice_i(.axis_in(axis_downsizer_bus), .*);
212
 
213
 
214
// --------------------------------------------------------------------
215
//
216
endmodule
217
 
218
 

powered by: WebSVN 2.1.0

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