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

Subversion Repositories openhmc

[/] [openhmc/] [trunk/] [openHMC/] [rtl/] [hmc_controller/] [tx/] [tx_crc_combine.v] - Rev 15

Compare with Previous | Blame | View Log

/*
 *                              .--------------. .----------------. .------------.
 *                             | .------------. | .--------------. | .----------. |
 *                             | | ____  ____ | | | ____    ____ | | |   ______ | |
 *                             | ||_   ||   _|| | ||_   \  /   _|| | | .' ___  || |
 *       ___  _ __   ___ _ __  | |  | |__| |  | | |  |   \/   |  | | |/ .'   \_|| |
 *      / _ \| '_ \ / _ \ '_ \ | |  |  __  |  | | |  | |\  /| |  | | || |       | |
 *       (_) | |_) |  __/ | | || | _| |  | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
 *      \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
 *           | |               | |            | | |              | | |          | |
 *           |_|               | '------------' | '--------------' | '----------' |
 *                              '--------------' '----------------' '------------'
 *
 *  openHMC - An Open Source Hybrid Memory Cube Controller
 *  (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
 *  www.ziti.uni-heidelberg.de
 *  B6, 26
 *  68159 Mannheim
 *  Germany
 *
 *  Contact: openhmc@ziti.uni-heidelberg.de
 *  http://ra.ziti.uni-heidelberg.de/openhmc
 *
 *   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 3 of the License, or
 *   (at your option) any later version.
 *
 *   This source file 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 file.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 *  Module name: tx_crc_combine
 *
 */
 
 `default_nettype none
 
module tx_crc_combine #(
    parameter LOG_FPW       = 2,
    parameter FPW           = 4,
    parameter DWIDTH        = 512
) (
 
    //----------------------------------
    //----SYSTEM INTERFACE
    //----------------------------------
    input   wire                clk,
    input   wire                res_n,
 
    //----------------------------------
    //----Input data
    //----------------------------------
    input   wire [FPW-1:0]      d_in_hdr,
    input   wire [FPW-1:0]      d_in_tail,
    input   wire [DWIDTH-1:0]   d_in_data,
 
    //----------------------------------
    //----Outputs
    //----------------------------------
    output  wire [DWIDTH-1:0]   d_out_data
 
);
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------WIRING AND SIGNAL STUFF---------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
 
`include "hmc_field_functions.h"
//------------------------------------------------------------------------------------General Assignments
integer i_f;    //counts to FPW
integer i_f2;   //counts to FPW inside another i_f loop
integer i_c;    //depth of the crc data pipeline
 
genvar f, f2;
 
//------------------------------------------------------------------------------------Split input data into FLITs
wire  [128-1:0]       d_in_flit   [FPW-1:0];
generate
    for(f = 0; f < (FPW); f = f + 1) begin
        assign d_in_flit[f] = d_in_data[(f*128)+128-1:f*128];
    end
endgenerate
 
reg  [3:0]              d_in_flit_lng_dly     [FPW-1:0];
reg  [DWIDTH-1:0]       d_in_data_dly;
reg  [FPW-1:0]          d_in_tail_dly;
reg  [FPW-1:0]          d_in_hdr_dly;
reg  [LOG_FPW-1:0]      d_in_flit_target_crc  [FPW-1:0];
 
//------------------------------------------------------------------------------------CRC Target Assignment
reg                     swap_crc;
 
//Retrieve the target crc from the header and assign to corresponding tail
reg  [LOG_FPW-1:0]      target_crc_per_tail         [FPW-1:0];
reg  [LOG_FPW-1:0]      target_crc_per_tail1        [FPW-1:0];
reg  [LOG_FPW-1:0]      target_crc_per_tail_comb    [FPW-1:0];
reg  [LOG_FPW-1:0]      target_crc_comb;
reg  [LOG_FPW-1:0]      target_crc_temp;
 
//------------------------------------------------------------------------------------CRC Modules Input stage
wire [31:0]    crc_init_out      [FPW-1:0];
reg  [31:0]    crc_accu_in       [FPW-1:0];
reg  [FPW-1:0] crc_accu_in_valid [FPW-1:0];
reg  [FPW-1:0] crc_accu_in_tail  [FPW-1:0];
wire [31:0]    crc_per_flit      [FPW-1:0];
 
 
//------------------------------------------------------------------------------------Inter CRC stage
reg  [3:0]                  payload_remain [FPW-1:0];
 
wire [(FPW*32)-1:0] crc_accu_in_combined [FPW-1:0];
generate
    for(f=0;f<FPW;f=f+1) begin
        for(f2=0;f2<FPW;f2=f2+1) begin
            assign crc_accu_in_combined[f][(f2*32)+31:(f2*32)] = crc_accu_in_valid[f][f2] ? crc_accu_in[f2] : 32'h0;
        end
    end
endgenerate
 
//------------------------------------------------------------------------------------Data Pipeline signals
reg  [DWIDTH-1:0]       crc_data_pipe_in_data                               [1:0];
reg  [FPW-1:0]          crc_data_pipe_in_tail                               [1:0];
wire [128-1:0]          crc_data_pipe_out_data_flit                         [FPW-1:0];
 
generate
    for(f = 0; f < (FPW); f = f + 1) begin : assign_data_pipe_output
        assign crc_data_pipe_out_data_flit[f]                        = crc_data_pipe_in_data[1][(f*128)+127:f*128];
    end
endgenerate
 
 
reg  [128-1:0]       data_rdy_flit   [FPW-1:0];
generate
        for(f = 0; f < (FPW); f = f + 1) begin : reorder_flits_to_word
            assign d_out_data[(f*128)+128-1:(f*128)] = data_rdy_flit[f];
        end
endgenerate
 
//==================================================================================
//---------------------------------Retrieve the lengths to invalide FLITs
//==================================================================================
always @(*)  begin
//Retrieve the length from the header and assign it to the tail. This information will be used in the
//invalidation stage to the correct number of FLITs
 
    target_crc_comb = target_crc_temp;
 
    for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
 
        if(d_in_hdr_dly[i_f]) begin
            target_crc_comb = d_in_flit_target_crc[i_f];
        end
 
        if(d_in_tail_dly[i_f]) begin
            target_crc_per_tail_comb[i_f] = target_crc_comb;
        end else begin
            target_crc_per_tail_comb[i_f] = {4{1'b0}};
        end
 
    end
end
 
//Register combinational values
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n)  begin `else
always @(posedge clk)  begin `endif
if(!res_n) begin
    for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
        target_crc_per_tail[i_f] <= 0;
    end
    target_crc_temp    <= {4{1'b0}};
end else begin
    for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
        target_crc_per_tail[i_f] <= target_crc_per_tail_comb[i_f];
    end
    target_crc_temp    <= target_crc_comb;
end
end
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------LOGIC STARTS HERE---------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
//====================================================================
//---------------------------------Assign input data stream to target CRCs
//====================================================================
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n)  begin `else
always @(posedge clk)  begin `endif
if(!res_n) begin
    for(i_f=0;i_f<FPW;i_f=i_f+1)begin
        d_in_flit_target_crc[i_f] <= {LOG_FPW{1'b0}};
    end
    swap_crc            <= 1'b0;
end else begin
 
    for(i_f=0;i_f<FPW;i_f=i_f+1)begin
        d_in_flit_target_crc[i_f] <= {LOG_FPW{1'b0}};
    end
 
    //Reset if seen a tail
    if(|d_in_tail) begin
        swap_crc        <= 1'b0;
    end
 
    for(i_f=0;i_f<FPW;i_f=i_f+1)begin
        if(d_in_hdr[i_f])begin
 
            if(i_f+lng(d_in_flit[i_f])>FPW) begin
            //If the current packet spreads over multiple cycles
 
                if(swap_crc) begin
                    //If the last packet was swapped and the current packet also spreads over the more than 1 cycle use crc 0 now
                    d_in_flit_target_crc[i_f]   <= 3'h0;
                end else begin
                    d_in_flit_target_crc[i_f]   <= FPW-1'b1;
                    swap_crc                    <= 1'b1;
                end
 
            end else begin
 
                d_in_flit_target_crc[i_f] <= i_f;
 
                //If the highest order CRC contains a data packet that ends in this cycle, dont use this crc
                //It's ok always to decrement by 1 since we know the lowest order CRC would not be used (at least FLIT0 goes to highest order CRC)
                if(swap_crc && !(d_in_hdr > d_in_tail)) begin
                    d_in_flit_target_crc[i_f] <= i_f-1;
                end
 
            end
        end
    end
 
end
end
 
//Register input values to be used in CRC assignment logic after crc init stage
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n)  begin `else
always @(posedge clk)  begin `endif
 
    //------------Data Propagation
    `ifdef RESET_ALL
        if(!res_n) d_in_data_dly <= {DWIDTH{1'b0}};
        else
    `endif
    d_in_data_dly <= d_in_data;
    //----------------------------
 
    `ifdef RESET_ALL
    if(!res_n) begin
        for(i_f=0;i_f<FPW;i_f=i_f+1)begin
            d_in_flit_lng_dly[i_f]  <= 4'h0;
        end
        d_in_tail_dly <= {FPW{1'b0}};
        d_in_hdr_dly  <= {FPW{1'b0}};
    end else 
    `endif
    begin
        for(i_f=0;i_f<FPW;i_f=i_f+1)begin
            d_in_flit_lng_dly[i_f]  <= lng(d_in_flit[i_f]);
        end
        d_in_tail_dly <= d_in_tail;
        d_in_hdr_dly  <= d_in_hdr;
    end
end
 
//====================================================================
//---------------------------------Inter CRC stage, CRC assignment Logic
//====================================================================
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n)  begin `else
always @(posedge clk)  begin `endif
 
    //------------Data Propagation
    for(i_f=0;i_f<FPW;i_f=i_f+1)begin
    `ifdef RESET_ALL
        if(!res_n) crc_accu_in[i_f] <= {32{1'b0}};
        else
    `endif
        crc_accu_in[i_f] <= crc_init_out[i_f];
    end
    //----------------------------
 
if(!res_n) begin
    for(i_f=0;i_f<FPW;i_f=i_f+1)begin
        crc_accu_in_valid[i_f]  <= {FPW{1'b0}};
        crc_accu_in_tail[i_f]  <= {FPW{1'b0}};
        payload_remain[i_f]     <= 4'h0;
    end
end else begin
 
    for(i_f=0;i_f<FPW;i_f=i_f+1)begin
 
        crc_accu_in_valid[i_f]  <= 4'h0;
        crc_accu_in_tail[i_f]  <= 4'h0;
    end
 
    for(i_f=0;i_f<FPW;i_f=i_f+1)begin
    //First go through accu crcs
 
        if(|payload_remain[i_f]) begin
 
            if(payload_remain[i_f] > FPW) begin
                crc_accu_in_valid[i_f]  <= {FPW{1'b1}};
                payload_remain[i_f]     <= payload_remain[i_f]-FPW;
            end else begin
                crc_accu_in_valid[i_f]  <= {FPW{1'b1}} >> (FPW-payload_remain[i_f]);
                crc_accu_in_tail[i_f]   <= 1'b1 << (payload_remain[i_f]-1);
                payload_remain[i_f]     <= 4'h0;
            end
        end
 
        for(i_f2=0;i_f2<FPW;i_f2=i_f2+1)begin
            if(i_f==d_in_flit_target_crc[i_f2] && d_in_hdr_dly[i_f2]) begin
            //Then go through all input crcs from the init crc and find the crc's that must be assigned to the currently selected crc
 
                if( (i_f2+d_in_flit_lng_dly[i_f2]) >FPW ) begin
                    payload_remain[i_f] <= (d_in_flit_lng_dly[i_f2]-FPW+i_f2);
                    crc_accu_in_valid[i_f]   <=  {FPW{1'b1}} >> i_f2 << i_f2;
                end else begin
                    crc_accu_in_tail[i_f] <= 1'b1 << d_in_flit_lng_dly[i_f2]+i_f2-1;
                    crc_accu_in_valid[i_f]   <=  ({FPW{1'b1}} >> (FPW-i_f2-d_in_flit_lng_dly[i_f2])) >> i_f2 << i_f2;
                end
            end
 
        end
    end
end
end
 
//====================================================================
//---------------------------------Constant propagation of the data pipeline
//====================================================================
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n)  begin `else
always @(posedge clk)  begin `endif
 
    //------------Data Propagation
    `ifdef RESET_ALL
        if (!res_n) begin
            for(i_c=0;i_c<2;i_c=i_c+1)begin
                crc_data_pipe_in_data[i_c]       <= {DWIDTH{1'b0}};
            end
        end else 
    `endif
    begin
        crc_data_pipe_in_data[0]   <= d_in_data_dly;
        crc_data_pipe_in_data[1]   <= crc_data_pipe_in_data[0];
    end
    //----------------------------
 
    `ifdef RESET_ALL
    if(!res_n) begin
        for(i_c=0;i_c<2;i_c=i_c+1)begin
            crc_data_pipe_in_tail[i_c]       <= {FPW{1'b0}};
        end
 
        for(i_f=0;i_f<(FPW);i_f=i_f+ 1) begin
            target_crc_per_tail1[i_f] <= {LOG_FPW{1'b0}};
        end
    end else
    `endif
    begin
 
    //We keep the tails per FLIT so they are not part of the data pipe
    for(i_f=0;i_f<(FPW);i_f=i_f+ 1) begin
        target_crc_per_tail1[i_f] <= target_crc_per_tail[i_f];
    end
 
    //Set the first stage of the data pipeline
    crc_data_pipe_in_tail[0]       <= d_in_tail_dly;
 
    //Data Pipeline propagation
    crc_data_pipe_in_tail[1]       <= crc_data_pipe_in_tail[0];
    end
end
 
//====================================================================
//---------------------------------At the end of the data pipeline get and add CRCs
//====================================================================
//Data Pipeline output stage to final FLIT reg
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n)  begin `else
always @(posedge clk)  begin `endif
 
    for(i_f=0;i_f<FPW;i_f=i_f+1)begin
    `ifdef RESET_ALL
    if(!res_n) begin
        data_rdy_flit[i_f]  <= {128{1'b0}};    
    end else 
    `endif
    begin
        data_rdy_flit[i_f]  <= crc_data_pipe_out_data_flit[i_f];
 
        if(crc_data_pipe_in_tail[1][i_f])begin    //Finally add the crc
            data_rdy_flit[i_f][128-1:128-32] <= crc_per_flit[target_crc_per_tail1[i_f]];
        end
    end
    end
end
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------INSTANTIATIONS HERE-------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
//Init CRC: Calculate the remainders of each input FLIT individually
generate
    for(f=0;f<FPW;f=f+1) begin : crc_init_gen
        crc_128_init crc_init_I
        (
            .clk(clk),
            `ifdef RESET_ALL
                .res_n(res_n),
            `endif
            .inData(d_in_flit[f]),
            .crc(crc_init_out[f])
        );
    end
endgenerate
 
//Calculate the actual CRC over all valid remainders
generate
    for(f=0;f<FPW;f=f+1) begin : crc_accu_gen
        crc_accu #(
        .FPW(FPW)
        )
        crc_accu_I
        (
            .clk(clk),
            .res_n(res_n),
            .tail(crc_accu_in_tail[f]),
            .d_in(crc_accu_in_combined[f]),
            .crc_out(crc_per_flit[f])
        );
    end
endgenerate
 
endmodule
`default_nettype wire

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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