URL
https://opencores.org/ocsvn/qaz_libs/qaz_libs/trunk
Subversion Repositories qaz_libs
[/] [qaz_libs/] [trunk/] [axi4_stream_lib/] [src/] [axis_downsizer.sv] - Rev 35
Compare with Previous | Blame | View Log
////////////////////////////////////////////////////////////////////////// //////// Copyright (C) 2015 Authors and OPENCORES.ORG //////// //////// This source file may be used and distributed without //////// restriction provided that this copyright statement is not //////// removed from the file and that any derivative work contains //////// the original copyright notice and the associated disclaimer. //////// //////// This source file is free software; you can redistribute it //////// and/or modify it under the terms of the GNU Lesser General //////// Public License as published by the Free Software Foundation; //////// either version 2.1 of the License, or (at your option) any //////// later version. //////// //////// This source is distributed in the hope that it will be //////// useful, but WITHOUT ANY WARRANTY; without even the implied //////// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //////// PURPOSE. See the GNU Lesser General Public License for more //////// details. //////// //////// You should have received a copy of the GNU Lesser General //////// Public License along with this source; if not, download it //////// from http://www.opencores.org/lgpl.shtml //////// //////////////////////////////////////////////////////////////////////////moduleaxis_downsizer#(N, // data bus width in bytesI = 1, // TID widthD = 1, // TDEST widthU, // TUSER widthS, // tdata size divisorUSE_TSTRB = 0, // set to 1 to enable, 0 to disableUSE_TKEEP = 0, // set to 1 to enable, 0 to disableBYTES_PER_TUSER // bytes per tuser bit. Set to 0 for transfer based.)(axis_if axis_in,axis_if axis_out,input aclk,input aresetn);// --------------------------------------------------------------------// synthesis translate_offinitialbegina_divisor: assert(S > 1) else $fatal;a_tdata_mod: assert(N % S == 0) else $fatal;a_tstrb_unsuported: assert(USE_TSTRB == 0) else $fatal;a_tkeep_unsuported: assert(USE_TKEEP == 0) else $fatal;a_bytes_per_tuser: assert((BYTES_PER_TUSER == 0) | (N % BYTES_PER_TUSER == 0)) else $fatal;a_tuser: assert((BYTES_PER_TUSER == 0) | (U % S == 0)) else $fatal;end// synthesis translate_on// --------------------------------------------------------------------// --------------------------------------------------------------------//localparam M_A = $clog2(S);localparam M_D = 2 ** M_A;localparam M_NW = (N*8)/ S;localparam M_UW = U / S;// --------------------------------------------------------------------//localparam U_OUT = (BYTES_PER_TUSER == 0) ? U : U / (N / BYTES_PER_TUSER);axis_if #(.N(N/S), .U(U_OUT)) axis_downsizer_bus(.*);// --------------------------------------------------------------------//wire almost_last_word;//---------------------------------------------------// state machine binary definitionsenum reg [2:0]{GET_WORD_IN = 3'b001,MUX_WORD_OUT = 3'b010,LAST_WORD_OUT = 3'b100} state, next_state;//---------------------------------------------------// state machine flopalways_ff @(posedge aclk)if(~aresetn)state <= GET_WORD_IN;elsestate <= next_state;//---------------------------------------------------// state machinealways_combcase(state)GET_WORD_IN: if(axis_in.tvalid)next_state <= MUX_WORD_OUT;elsenext_state <= GET_WORD_IN;MUX_WORD_OUT: if(almost_last_word & axis_downsizer_bus.tready)next_state <= LAST_WORD_OUT;elsenext_state <= MUX_WORD_OUT;LAST_WORD_OUT: if(~axis_downsizer_bus.tready)next_state <= LAST_WORD_OUT;else if(axis_in.tvalid)next_state <= MUX_WORD_OUT;elsenext_state <= GET_WORD_IN;default: next_state <= GET_WORD_IN;endcase// --------------------------------------------------------------------//reg [(8*N)-1:0] tdata_r;reg [I-1:0] tid_r;reg [D-1:0] tdest_r;reg tlast_r;reg [U-1:0] tuser_r;always_ff @(posedge aclk)if(axis_in.tvalid & axis_in.tready)begintdata_r <= axis_in.tdata;tid_r <= axis_in.tid;tdest_r <= axis_in.tdest;tlast_r <= axis_in.tlast; // packet width % S == 0 else tlast becomes invalidtuser_r <= axis_in.tuser;end// --------------------------------------------------------------------//reg [M_A-1:0] select;assign almost_last_word = (select == S - 2);always_ff @(posedge aclk)if(~aresetn | (state == GET_WORD_IN))select <= 0;else if(axis_downsizer_bus.tvalid & axis_downsizer_bus.tready)select <= select + 1;// --------------------------------------------------------------------//wire [M_NW-1:0] mux_in_tdata [M_D-1:0];wire [M_NW-1:0] mux_out_tdata;recursive_mux #(.A(M_A), .W(M_NW))tdata_mux_i(.data_in(mux_in_tdata), .data_out(mux_out_tdata), .*);// --------------------------------------------------------------------//genvar j;generatefor(j = 0; j < M_D; j++)begin : tdata_genassign mux_in_tdata[j] = tdata_r[j*M_NW +: M_NW];endendgenerate// --------------------------------------------------------------------//generatebegin : tuser_genif(BYTES_PER_TUSER != 0)begin : tuser_tuser_0_genwire [M_UW-1:0] mux_in_tuser [M_D-1:0];recursive_mux #(.A(M_A), .W(M_UW))tuser_mux_i(.data_in(mux_in_tuser), .data_out(axis_downsizer_bus.tuser), .*);for(j = 0; j < M_D; j++)begin : tuser_j_genassign mux_in_tuser[j] = tuser_r[j*M_UW +: M_UW] & {M_UW{axis_downsizer_bus.tvalid}};endendelsebegin : tuser_tuser_genassign axis_downsizer_bus.tuser = tuser_r & {U{axis_downsizer_bus.tvalid}};endendendgenerate// --------------------------------------------------------------------//assign axis_in.tready = (state == GET_WORD_IN) |((state == LAST_WORD_OUT) & (next_state == MUX_WORD_OUT));assign axis_downsizer_bus.tvalid = (state != GET_WORD_IN);assign axis_downsizer_bus.tdata = mux_out_tdata;assign axis_downsizer_bus.tid = tid_r;assign axis_downsizer_bus.tdest = tdest_r;assign axis_downsizer_bus.tlast = (select == S - 1) ? tlast_r : 1'b0;// --------------------------------------------------------------------//axis_register_slice #(.N(N), .U(U))axis_register_slice_i(.axis_in(axis_downsizer_bus), .*);// --------------------------------------------------------------------//endmodule
