logger_arbiter393.v 7.11 KB
Newer Older
1 2 3
/*******************************************************************************
 * Module: logger_arbiter393
 * Date:2015-07-06  
4
 * Author: Andrey Filippov     
5 6
 * Description: arbiter for the event_logger
 *
7
 * Copyright (c) 2015 Elphel, Inc.
8 9 10 11 12 13 14 15 16 17 18 19
 * logger_arbiter393.v is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 *  logger_arbiter393.v 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/> .
20 21 22 23 24 25
 *
 * Additional permission under GNU GPL version 3 section 7:
 * If you modify this Program, or any covered work, by linking or combining it
 * with independent modules provided by the FPGA vendor only (this permission
 * does not extend to any 3-rd party modules, "soft cores" or macros) under
 * different license terms solely for the purpose of generating binary "bitstream"
26
 * files and/or simulating the code, the copyright holders of this Program give
27 28
 * you the right to distribute the covered work without those independent modules
 * as long as the source code for them is available from the FPGA vendor free of
Andrey Filippov's avatar
Andrey Filippov committed
29
 * charge, and there is no dependence on any encrypted modules for simulating of
30 31 32
 * the combined code. This permission applies to you if the distributed code
 * contains all the components and scripts required to completely simulate it
 * with at least one of the Free Software programs.
33 34 35 36
 *******************************************************************************/
`timescale 1ns/1ps

module  logger_arbiter393(
37 38 39 40 41 42 43 44 45 46 47 48 49
    input                         xclk,     // half frequency (80 MHz nominal)
    input                         rst,      // module reset (sync)
    input                   [3:0] ts_rq_in, // in requests for timestamp (single-cycle - just leading edge )
    output                  [3:0] ts_rq,        // out request for timestamp, to timestmp module
    input                   [3:0] ts_grant,     // granted ts requests from timestamping module
    input                   [3:0] rdy,          // channels ready (leading edge - became ready, trailing - no more data, use zero)
    output reg              [3:0] nxt,          // pulses to modules to output next word
    output                  [1:0] channel,      // decoded channel number (2 bits)
    output                  [1:0] ts_sel,       // select timestamp word to be output (0..3)
    output                        ts_en,        // 1 - use timestamp, 0 - channel data (or 16'h0 if !ready)
    output reg                    dv,           // output data valid (from registered mux - 2 stage - first selects data and ready, second ts/data/zero)
    output                 [23:0] sample_counter);// number of 64-byte samples logged
/*
50 51 52 53 54 55 56 57 58 59 60 61 62
  input         xclk;  // half frequency (80 MHz nominal)
  input         rst;   // reset module
  input  [ 3:0] ts_rq_in; // in requests for timestamp (sinlgle-cycle)
  output [ 3:0] ts_rq;        // out request for timestamp, to timestmp module
  input  [ 3:0] ts_grant;     // granted ts requests from timestamping module
  input  [ 3:0] rdy;          // channels ready (leading edge - became ready, trailing - no more data, use zero)
  output [ 3:0] nxt;          // pulses to modules to output next word
  output [ 1:0] channel;      // decoded channel number (2 bits)
  output [ 1:0] ts_sel;       // select timestamp word to be output (0..3)
  output        ts_en;        // 1 - use timestamp, 0 - channel data (or 16'h0 if !ready)
  output        dv;           // output data valid (from registered mux - 2 stage - first selects data and ready, second ts/data/zero)
  output [23:0] sample_counter;// number of 64-byte samples logged
*/
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
    reg     [3:0] ts_rq_in_d;
    reg     [3:0] ts_rq_r;
    reg     [3:0] ts_valid;
//  reg     [3:0] ts_rq_reset;
    reg     [3:0] channels_ready;// channels granted and ready
    reg     [3:1] chn1hot;       // channels 1-hot - granted and ready, priority applied
    reg           rq_not_zero;   // at least one channel is ready for processing (same time as chn1hot[3:0])
    reg     [1:0] channel_r;
//  reg           start; Not used!
    reg           busy;
    wire          wstart;
    reg           ts_en_r;
    reg     [4:0] seq_cntr;
    reg           seq_cntr_last;
    reg     [1:0] ts_sel_r;
//  reg           dv;
    reg           inc_sample_counter;
    reg    [23:0] sample_counter_r;// number of 64-byte samples logged
//  reg    [ 3:0] nxt;
    reg           pre_nxt;
    reg    [ 3:0] chn_servicing; //1-hot channel being service
    wire    [3:0] wts_rq;
    
    assign wstart =         !busy && rq_not_zero;
    assign wts_rq[3:0] =    ts_rq_in[3:0] & ~ts_rq_in_d[3:0] & (~rdy[3:0] | chn_servicing[3:0]);
    assign sample_counter = sample_counter_r;
    assign ts_rq =          ts_rq_r;
    assign channel =        channel_r;
    assign ts_en =          ts_en_r;
    assign ts_sel =         ts_sel_r;
    
    always @ (posedge xclk) begin
        ts_rq_in_d[3:0] <= ts_rq_in[3:0];
      
        if (wstart) channel_r[1:0] <= {chn1hot[3] | chn1hot[2],chn1hot[3] | chn1hot[1]};
        
        if     (wstart) chn_servicing[3:0]  <= {chn1hot[3:1], ~|chn1hot[3:1]};
        else if (!busy) chn_servicing[3:0]  <= 4'h0;
    
    
        if (rst) ts_rq_r[3:0] <= 4'h0;
        else     ts_rq_r[3:0] <= ~ts_grant & ( wts_rq[3:0] | ts_rq_r[3:0]);
    
        if (rst) ts_valid[3:0] <= 4'h0;
        else ts_valid[3:0] <= (ts_grant[3:0] | (ts_valid & ~wts_rq[3:0]));
    
        channels_ready[3:0] <= ts_valid[3:0] & rdy[3:0] & ~chn_servicing[3:0]; // ready should go down during servicing
    
        rq_not_zero <= channels_ready[3:0] != 4'h0;
    
        chn1hot[3:1] <= {channels_ready[3] & ~|channels_ready[2:0],
                         channels_ready[2] & ~|channels_ready[1:0],
                         channels_ready[1] &  ~channels_ready[0]};
    
    //    start <= wstart; Not used !
    
        if  ((seq_cntr[4:0]=='h1e) || rst) busy <= 1'b0;
        else if (rq_not_zero)              busy <= 1'b1;
    
        if (!busy) seq_cntr[4:0] <= 5'h0;
        else       seq_cntr[4:0] <= seq_cntr[4:0] + 1;
    
        seq_cntr_last <= (seq_cntr[4:0]=='h1e);
    
    
        if      (wstart)              ts_en_r <=1'b1;
        else if (seq_cntr[1:0]==2'h3) ts_en_r <=1'b0;
        
        if (!ts_en_r) ts_sel_r[1:0] <= 2'h0;
        else        ts_sel_r[1:0] <=  ts_sel_r[1:0] + 1;
    
        if (!busy || (seq_cntr[4:0]=='h1d)) pre_nxt <= 1'b0;
        else if (seq_cntr[4:0]=='h01)       pre_nxt <= 1'b1;
        
        nxt [3:0]  <= pre_nxt? chn_servicing[3:0]:4'h0;
        
        dv <= busy || seq_cntr_last;
    
        inc_sample_counter <= seq_cntr_last;
    
        if (rst)                     sample_counter_r[23:0] <= 24'h0;
        else if (inc_sample_counter) sample_counter_r[23:0] <= sample_counter_r[23:0] +1;
    end
146
endmodule