OpenCores
URL https://opencores.org/ocsvn/an-fpga-implementation-of-low-latency-noc-based-mpsoc/an-fpga-implementation-of-low-latency-noc-based-mpsoc/trunk

Subversion Repositories an-fpga-implementation-of-low-latency-noc-based-mpsoc

[/] [an-fpga-implementation-of-low-latency-noc-based-mpsoc/] [trunk/] [mpsoc/] [rtl/] [src_peripheral/] [ni/] [ni_vc_dma.v] - Rev 48

Compare with Previous | Blame | View Log

 
/**********************************************************************
**	File:  ni_vc_dma.v
**	Date:2017-06-11    
**    
**	Copyright (C) 2014-2017  Alireza Monemi
**    
**	This file is part of ProNoC 
**
**	ProNoC ( stands for Prototype Network-on-chip)  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 of the License, or (at your option) any later version.
**
** 	ProNoC 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 ProNoC. If not, see <http:**www.gnu.org/licenses/>.
**
**
**	Description: 
**	NI send-/receive-DMA
**	
**
*******************************************************************/
 
 
// synthesis translate_off
`timescale 1ns / 1ps
// synthesis translate_on
 
 
 
module ni_vc_dma #(   
    parameter MAX_TRANSACTION_WIDTH = 10, // MAximum transaction size will be 2 power of MAX_DMA_TRANSACTION_WIDTH words 
    parameter CRC_EN = "NO",// "YES","NO" if CRC is enable then the CRC32 of all packet data is calculated and sent via tail flit. 
    parameter Fpay=32,
    parameter BYTE_EN = 0,
    //wishbone port parameters
    parameter Dw            =   32,
    parameter M_Aw          =   32,
    parameter TAGw          =   3,
    parameter SELw          =   4
)
(
    // 
    reset,
    clk,
 
    //ctrl signals
    send_enable,    
    send_is_busy,
    send_is_active,
    send_hdr,
    send_tail,
    send_done,
    send_fsm_is_ideal,
    send_pointer_addr, 
    send_data_size,
    send_start, 
 
 
    receive_enable,
    receive_is_busy,
    receive_is_active,   
    receive_done,
    receive_fsm_is_ideal,
    received_flit_is_tail,
    receive_pointer_addr,
    receive_start_index,
    receive_start_index_offset,
    receive_start,
    receive_dat_size_in_byte,
    receive_be,
    receive_max_buff_siz,
 
 
    last_burst,   
    status,
    save_hdr_info,    
 
 
 
    //fifo signals
 
    send_fifo_wr, 
    send_fifo_full,
    send_fifo_nearly_full,
    send_fifo_rd,    
    receive_fifo_rd,  
    receive_fifo_empty,
 
    //busrdt counter control signals
    burst_counter_ld,
    burst_counter_dec,
    burst_size_is_set,
 
    //errors
    burst_size_err,
    send_data_size_err,
    rcive_buff_ovrflw_err, 
    invalid_send_req_err,
 
    //wishbone master rd interface signals
    m_send_sel_o,
    m_send_addr_o,
    m_send_cti_o,
    m_send_stb_o,
    m_send_cyc_o,
    m_send_we_o,
  //  m_send_dat_i,
    m_send_ack_i,    
 
 
     //wishbone master wr interface signals
 
    m_receive_sel_o,
   // m_receive_dat_o,
    m_receive_addr_o,
    m_receive_cti_o,
    m_receive_stb_o,
    m_receive_cyc_o,
    m_receive_we_o,
    m_receive_ack_i  
 
 
 
 
);
 
 
    function integer log2;
      input integer number; begin   
         log2=(number <=1) ? 1: 0;    
         while(2**log2<number) begin    
            log2=log2+1;    
         end       
      end   
    endfunction // log2  
 
 
    //state machine registers/parameters
    localparam
        SEND_ST_NUM=5,
        RECEIVE_ST_NUM=4;
 
    localparam [SEND_ST_NUM-1 :   0]
        SEND_IDEAL = 1,
        SEND_HDR=2,
        SEND_BODY =4,
        SEND_CRC=8,
        SEND_WAIT=16;    
 
 
    localparam [RECEIVE_ST_NUM-1:0]
        RECEIVE_IDEAL = 1,
        RECEIVE_READ_FIFO=2,
        RECEIVE_ACTIVE =4,
        RECEIVE_RELEASE_WB=8;  
 
    localparam [2 : 0]
        CLASSIC = 3'b000,
        CONST_ADDR_BURST = 3'b010,
        INCREMENT_BURST = 3'b011,
        END_OF_BURST = 3'b111;
 
 
 
      //control Registers/ parameters 
 
 
 
    localparam 
        STATUSw=SEND_ST_NUM+RECEIVE_ST_NUM,
        MAX_PCK_SIZE_IN_BYTE = MAX_TRANSACTION_WIDTH + log2(Fpay/8),
        OFFSETw= log2(Fpay/8),
        BEw = (BYTE_EN)? log2(Fpay/8) : 1; 
 
    output  [STATUSw-1  :0] status;  
 
 
    input reset,clk,send_enable,receive_enable;
    output  send_is_busy, receive_is_busy;
    output reg burst_counter_ld,    burst_counter_dec;
    input burst_size_is_set;
    input last_burst;
    output reg  send_hdr;
    output reg  send_done,receive_done;    
 
    output send_tail;
    output reg send_is_active, receive_is_active;
    input received_flit_is_tail;
 
 
    output reg save_hdr_info;
 
    output send_fsm_is_ideal,receive_fsm_is_ideal;
    input  [Dw-1   :   0] send_pointer_addr; 
    input  [Dw-1   :   0] receive_pointer_addr;
    input [MAX_TRANSACTION_WIDTH-1    :   0] receive_start_index;
    input [OFFSETw-1 : 0] receive_start_index_offset;
 
    input  [MAX_TRANSACTION_WIDTH-1    :   0] send_data_size;
    input  [MAX_TRANSACTION_WIDTH-1    :   0] receive_max_buff_siz;
    output [MAX_PCK_SIZE_IN_BYTE-1     :   0] receive_dat_size_in_byte;  
 
    input  send_start, receive_start;    
    input [BEw-1 : 0] receive_be;
 
    //fifo
    output reg  send_fifo_wr, receive_fifo_rd;
    input       send_fifo_full, send_fifo_nearly_full,send_fifo_rd, receive_fifo_empty;
 
   //errors 
 
    output reg burst_size_err;
    output reg send_data_size_err;
    output reg rcive_buff_ovrflw_err; 
    output reg invalid_send_req_err;
 
 
    //wishbone read master interface signals
    output  [SELw-1          :   0] m_send_sel_o;
    output  [M_Aw-1          :   0] m_send_addr_o;
    output reg [TAGw-1       :   0] m_send_cti_o;
    output                          m_send_stb_o;
    output   reg                    m_send_cyc_o;
    output                          m_send_we_o;
   // input   [Dw-1           :  0]   m_send_dat_i;
    input                           m_send_ack_i;    
 
     //wishbone write master interface signals
    output  [SELw-1          :   0] m_receive_sel_o;
  //  output  [Dw-1            :   0] m_receive_dat_o;
    output  [M_Aw-1          :   0] m_receive_addr_o;
    output  reg [TAGw-1      :   0] m_receive_cti_o;
    output                          m_receive_stb_o;
    output  reg                     m_receive_cyc_o;
    output                          m_receive_we_o;
    input                           m_receive_ack_i;   
 
 
    reg [MAX_TRANSACTION_WIDTH-1    :   0] send_counter, send_counter_next;
    reg [MAX_TRANSACTION_WIDTH-1    :   0] receive_counter_next;    
    reg [MAX_TRANSACTION_WIDTH-1    :   0] receive_index,receive_index_next ;      
    reg [MAX_TRANSACTION_WIDTH-1    :   0] receive_counter;   
    reg hdr_flit_is_received,hdr_flit_is_received_next;   
 
    wire last_data = (send_counter == send_data_size-1'b1);
 
    wire receive_overflow= (receive_counter == receive_max_buff_siz);    
 
    reg [SEND_ST_NUM-1    :0] send_ps,send_ns; // read  peresent state, read next sate 
    reg [RECEIVE_ST_NUM-1    :0] receive_ps,receive_ns; // read  peresent state, read next sate
 
    //reg receive_is_busy_next, send_is_busy_next;
 
 
    assign status= {receive_ps,send_ps};
   // assign s_dat_o={{(Dw-STATUSw){1'b0}}, status};
 
    reg  send_crc; 
 
    /* verilator lint_off WIDTH */ 
    assign send_tail =  ( CRC_EN == "NO") ?  last_data : send_crc; 
    /* verilator lint_on WIDTH */  
 
 
    assign send_fsm_is_ideal = (send_ps== SEND_IDEAL);
    assign receive_fsm_is_ideal = (receive_ps== RECEIVE_IDEAL);
    /* verilator lint_off WIDTH */ 
    assign m_send_addr_o =  send_pointer_addr  + send_counter;
    //assign m_receive_addr_o =  receive_pointer_addr  + receive_counter;
    assign m_receive_addr_o =  receive_pointer_addr  + receive_index;
 
 
     /* verilator lint_on WIDTH */  
    assign m_send_stb_o =  m_send_cyc_o;
    assign m_receive_stb_o =  m_receive_cyc_o;
    assign m_receive_we_o = 1'b1;
    assign m_send_we_o = 1'b0;
 
    assign m_send_sel_o = {SELw{1'b1}};
 
 
 
 generate   
 if(BYTE_EN)begin:be 
    wire [OFFSETw:0] byte2 = (receive_be==0)? (1<<OFFSETw) : {1'b0,receive_be}; 
    wire [OFFSETw:0] byte1 = byte2 - {1'b0,receive_start_index_offset}; 
 
    reg  [MAX_PCK_SIZE_IN_BYTE-1     :   0] receive_size_cal;
    always @(*)begin 
        receive_size_cal={MAX_PCK_SIZE_IN_BYTE{1'b0}};
        if (receive_counter==1)begin 
            receive_size_cal [OFFSETw:0]= byte1;
        end else begin 
            /* verilator lint_off WIDTH */ 
            receive_size_cal = (((receive_counter-1'b1)<<OFFSETw)+byte2)-receive_start_index_offset;        
            /* verilator lint_on WIDTH */ 
        end
    end
    assign receive_dat_size_in_byte= receive_size_cal;
 
   /*************
    *  sel generator  
    * ***********/
      wire [SELw-1 : 0]  first_flit_sel,last_flit_sel,first_flit_sel_not;  
 
     little_endian_sel_gen #(
     	.SELw(SELw),
     	.BEw(BEw)
     )
     last_sel_gen
     (
     	.byte_location(receive_be),
     	.sel(last_flit_sel)
 
     );
 
 
    little_endian_sel_gen #(
        .SELw(SELw),
        .BEw(BEw)
     )
     first_sel_gen
     (
        .byte_location(receive_start_index_offset),
        .sel(first_flit_sel_not)
 
     );
 
     assign first_flit_sel =(receive_start_index_offset==0)?{SELw{1'b1}}:   ~first_flit_sel_not;
 
    reg  [SELw-1 : 0] receive_sel;
    wire recive_first_word= (receive_counter == 0);  
 
    always @(*) begin 
        receive_sel = {SELw{1'b1}}; // default all byte enable bits are set. It may changed only for tail flit
 
        if(recive_first_word & received_flit_is_tail) begin 
             receive_sel=  first_flit_sel & last_flit_sel;
        end else  if(recive_first_word )begin 
            receive_sel=  first_flit_sel;
        end else  if (received_flit_is_tail) begin
            receive_sel=  last_flit_sel;
        end
    end
 
 
      assign m_receive_sel_o  = (hdr_flit_is_received)? receive_sel: {SELw{1'b0}};
 
 
 end else begin: nbe
     assign receive_dat_size_in_byte= (receive_counter<< OFFSETw );  
     assign m_receive_sel_o = {SELw{1'b1}};   
 end     
 endgenerate 
 
 
 
 
 
 
 
 
    reg [1:0] active_st,active_st_next;
     //send state machine
    always @ (*) begin 
        // default values 
        send_ns = send_ps;
        send_counter_next=send_counter;
        burst_counter_ld=1'b0;
        burst_counter_dec=1'b0;
        m_send_cti_o =  CONST_ADDR_BURST;
        m_send_cyc_o=1'b0;
        send_fifo_wr=1'b0;
        send_done = 1'b0;
        send_is_active =1'b0;
        send_hdr = 1'b0;
        send_crc = 1'b0; 
        active_st_next = active_st;
 
        burst_size_err=1'b0;
        send_data_size_err=1'b0;
        invalid_send_req_err = 1'b0;
 
        // the send req must be asserted only when the Ni_send_DMA(v) is in ideal status  
        if( (send_ps != SEND_IDEAL && send_ps != SEND_HDR) & send_start) invalid_send_req_err=1'b1; 
 
        case(send_ps)
            SEND_IDEAL: begin 
                if(send_start) begin 
                    if (burst_size_is_set && (send_data_size>0)) begin 
                        send_counter_next= {MAX_TRANSACTION_WIDTH{1'b0}};
                        burst_counter_ld=1'b1;
                        send_ns = SEND_HDR;
                    end else begin // set error reg
                        if(!burst_size_is_set) burst_size_err=1'b1;
                        else send_data_size_err=1'b1; 
                    end
                end
            end // SEND_IDEAL
            SEND_HDR: begin 
                    active_st_next =2'd1;
                    send_is_active =1'b1; // this signal sends request to the send_arbiter, the granted signal is send_enable
                    if(send_enable) begin 
                        send_hdr = 1'b1;                                             
                        if(send_fifo_nearly_full & !send_fifo_rd)  begin
                            send_ns =  SEND_WAIT; 
                        end else begin 
                            send_fifo_wr=1'b1;
                            send_ns =  SEND_BODY;                                                     
                        end
                    end
 
            end // SEND_ACTIVE
 
 
            SEND_BODY: begin 
                    active_st_next =2'd2;
                    send_is_active =1'b1; // this signal sends request to the send_arbiter, the granted signal is send_enable
                    if(send_enable) begin 
                        m_send_cyc_o=1'b1; 
 
                        if(last_data |  last_burst | (send_fifo_nearly_full & !send_fifo_rd))  m_send_cti_o= END_OF_BURST;  
                        if(send_fifo_nearly_full & !send_fifo_rd)  send_ns =  SEND_WAIT;
 
 
                        if (m_send_ack_i) begin 
                                send_fifo_wr=1'b1;
                                send_counter_next=send_counter +1'b1;
                                burst_counter_dec=1'b1;
 
                                if(last_data) begin 
                                    send_ns = ( CRC_EN == "NO") ? SEND_IDEAL : SEND_CRC;
                                  send_done = 1'b1;
 
                                end else if (last_burst | (send_fifo_nearly_full & !send_fifo_rd)) begin 
                                  send_ns = SEND_WAIT;
 
                                end 
                        end 
                    end
 
            end // SEND_BODY
 
          SEND_CRC: begin 
                    active_st_next =2'd3;
                    send_is_active =1'b1; // this signal sends request to the send_arbiter, the granted signal is send_enable
                    if(send_enable) begin 
                        send_crc = 1'b1;                                             
                        if(send_fifo_nearly_full & !send_fifo_rd)  begin
                                send_ns =  SEND_WAIT;  
                        end else begin 
                                send_fifo_wr=1'b1;
                                send_ns =  SEND_IDEAL;
 
                        end
                    end
 
            end // SEND_ACTIVE
 
 
 
 
 
             SEND_WAIT: begin 
                    //burst_counter_next = burst_size;
 
                burst_counter_ld=1'b1;
                if(!send_fifo_full) begin 
                        send_ns = ( active_st ==2'd1) ? SEND_HDR :
                                  ( active_st ==2'd2) ? SEND_BODY : SEND_CRC;
                end
 
            end //SEND_RELEASE_WB
            default: begin
 
 
            end
       endcase      
    end//alays
 
   reg header_ack,header_ack_next; 
   always @(posedge clk) header_ack<= header_ack_next;
 
 
 //receive state machine    
    always @ (*) begin 
        // default values 
        receive_ns = receive_ps;
        receive_counter_next=receive_counter;
        receive_index_next = receive_index;
        m_receive_cyc_o=1'b0;
        m_receive_cti_o= CONST_ADDR_BURST;
        receive_fifo_rd=1'b0;
        receive_done=1'b0;
        receive_is_active =1'b0;
        hdr_flit_is_received_next=hdr_flit_is_received;
        save_hdr_info=1'b0;
        rcive_buff_ovrflw_err=1'b0;
        header_ack_next=1'b0;
            case(receive_ps)
                RECEIVE_IDEAL: begin 
 
                    hdr_flit_is_received_next =1'b0;                
                    if(receive_start )begin 
                        receive_counter_next = {MAX_TRANSACTION_WIDTH{1'b0}};  
                        receive_index_next = receive_start_index;    
                        receive_ns = RECEIVE_READ_FIFO;                         
                    end 
 
                end // RECEIVE_IDEAL
                RECEIVE_READ_FIFO: begin 
                     receive_is_active =1'b1; // this signal sends request to the receive_arbiter, the granted signal is receive_enable
                     if(receive_enable) begin 
                          receive_ns = RECEIVE_ACTIVE; 
                          receive_fifo_rd=1'b1;
                    end
                end
 
 
 
 
 
                RECEIVE_ACTIVE: begin 
                     receive_is_active =1'b1; // this signal sends request to the receive_arbiter, the granted signal is receive_enable
                     if(receive_enable) begin                      
                     /* verilator lint_off WIDTH */ 
  //                          if(CRC_EN == "YES")begin 
                    /* verilator lint_on WIDTH */                             
  //                              if(received_flit_is_tail)begin 
  //                                  m_receive_cyc_o = 1'b0;// make sure do not save crc on data memory
  //                                  receive_ns = RECEIVE_IDEAL;
  //                                  m_receive_cti_o= END_OF_BURST;
  //                                  receive_done=1'b1;  
  //                              end else begin 
  //                                  m_receive_cyc_o=1'b1; 
   //                             end
  //                          end else  
                            m_receive_cyc_o =  hdr_flit_is_received;
                            header_ack_next = !hdr_flit_is_received & (header_ack == 1'b0) ;
 
 
 
                            if (receive_fifo_empty | received_flit_is_tail) begin 
                                m_receive_cti_o= END_OF_BURST;                             
                            end
 
 
                            if (m_receive_ack_i | header_ack) begin 
                                hdr_flit_is_received_next=1'b1;
                                if(! hdr_flit_is_received) save_hdr_info=1'b1;
                                if(! receive_overflow && hdr_flit_is_received) begin 
                                    receive_counter_next=receive_counter +1'b1; //Donot save hedaer flit in memory
                                    receive_index_next = (receive_index==receive_max_buff_siz-1'b1)? {MAX_TRANSACTION_WIDTH{1'b0}}:receive_index+1'b1;
                                end
                                if( receive_overflow)  rcive_buff_ovrflw_err = 1'b1;//set error  
                                if (received_flit_is_tail) begin 
                                    receive_ns = RECEIVE_IDEAL;
                                    m_receive_cti_o= END_OF_BURST; 
                                    receive_done=1'b1; 
                                end
                                else if (receive_fifo_empty) begin 
                                    receive_ns = RECEIVE_RELEASE_WB; 
 
                                end else begin 
                                    receive_fifo_rd=1'b1;
                                end                 
                            end 
                     end               
                end // RECEIVE_ACTIVE
               RECEIVE_RELEASE_WB: begin 
                    if (! receive_fifo_empty) begin 
                                    receive_ns = RECEIVE_READ_FIFO;                                    
                    end                
                end //RELEASE_WB                
                default: begin
 
 
                    end
            endcase
 
    end//alays
 
 /*         
    always @(*)begin 
        send_is_busy_next= send_is_busy;
        if(send_start) send_is_busy_next =1'b1;
        else if(send_done) send_is_busy_next=1'b0;
    end
 */   
    assign send_is_busy = (send_ps != SEND_IDEAL);
    assign receive_is_busy =  (receive_ps != RECEIVE_IDEAL);
 
   /*
     always @(*)begin 
        receive_is_busy_next= receive_is_busy;
        if(receive_done) receive_is_busy_next =1'b0;
        else if(receive_start) receive_is_busy_next=1'b1;
    end
   */
 
 
 
    //registers assigmnet
 
`ifdef SYNC_RESET_MODE 
    always @ (posedge clk )begin 
`else 
    always @ (posedge clk or posedge reset)begin 
`endif   
        if(reset) begin 
            send_ps <= SEND_IDEAL;
            receive_ps <= RECEIVE_IDEAL;
            send_counter <=  {MAX_TRANSACTION_WIDTH{1'b0}};
            receive_counter <=   {MAX_TRANSACTION_WIDTH{1'b0}}; 
            receive_index<= {MAX_TRANSACTION_WIDTH{1'b0}}; 
            hdr_flit_is_received<=1'b0;
            active_st <= 2'd0;
 
        end else begin 
 
            send_ps <= send_ns;
            receive_ps <= receive_ns;
            send_counter <=  send_counter_next;
            receive_counter <=  receive_counter_next; 
            receive_index<=receive_index_next;
            hdr_flit_is_received<=hdr_flit_is_received_next;
            active_st <= active_st_next;          
        end 
    end 
 
 
 
/*
    dma_fifo  #(
         .Dw(Dw),//data_width
         .B(B) // buffer num
    ) 
    the_fifo
    (
         .din(m_send_dat_i),   
         .receive_en(send_fifo_wr), 
         .send_en(fifo_rd), 
         .dout(m_receive_dat_o),  
         .full(send_fifo_full),
         .nearly_full(send_fifo_nearly_full),
         .empty(receive_fifo_empty),
         .reset(reset),
         .clk(clk)
    );
*/
 
 
 
endmodule
 
 
module  little_endian_sel_gen #(
    parameter SELw=4,
    parameter BEw=2
)(
    byte_location,
    sel
);
 
     localparam BE_ONEHOTw= 2**BEw;
 
     output [SELw-1 : 0]  sel;  
     input  [BEw-1 :  0]  byte_location;
 
     wire [SELw-1 : 0]  sel_gen;  
     wire [BE_ONEHOTw-1 : 0] one_hot_code,sel_reversed;
 
      bin_to_one_hot #(
        .BIN_WIDTH(BEw),
        .ONE_HOT_WIDTH(BE_ONEHOTw)
      )
      be_cnv
      (
        .bin_code(byte_location),
        .one_hot_code(one_hot_code)
      );
 
    assign sel_reversed = one_hot_code-1'b1;
 
   genvar i;
   generate
    for (i=0; i<BE_ONEHOTw; i=i+1)begin :ff
        assign sel_gen[i] = sel_reversed[BE_ONEHOTw-i-1];
     //assign tail_flit_sel[i] = sel_reversed[i];
    end//for  
   endgenerate   
   assign sel= (byte_location == {BEw{1'b0}})? {SELw{1'b1}} : sel_gen;
 
endmodule
 
 

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.