/******************************************************************************* * Module: event_logger * Date:2015-07-06 * Author: Andrey Filippov * Description: top module of the event logger (ported from imu_logger) * * Copyright (c) 2015 Elphel, Inc. * event_logger.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. * * event_logger.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/> . *******************************************************************************/ `timescale 1ns/1ps module event_logger#( parameter LOGGER_ADDR = 'h720, //..'h721 parameter LOGGER_STATUS = 'h722, // .. 'h722 parameter LOGGER_STATUS_REG_ADDR = 'h39, // just 1 location) parameter LOGGER_MASK = 'h7fe, parameter LOGGER_STATUS_MASK = 'h7ff, parameter LOGGER_PAGE_IMU = 0, // 'h00..'h1f - overlaps with period/duration/halfperiod/config? parameter LOGGER_PAGE_GPS = 1, // 'h20..'h3f parameter LOGGER_PAGE_MSG = 2, // 'h40..'h5f parameter LOGGER_PERIOD = 0, parameter LOGGER_BIT_DURATION = 1, parameter LOGGER_BIT_HALF_PERIOD = 2, //rs232 half bit period parameter LOGGER_CONFIG = 3, parameter LOGGER_CONF_IMU = 2, parameter LOGGER_CONF_IMU_BITS = 2, parameter LOGGER_CONF_GPS = 7, parameter LOGGER_CONF_GPS_BITS = 4, parameter LOGGER_CONF_MSG = 13, parameter LOGGER_CONF_MSG_BITS = 5, parameter LOGGER_CONF_SYN = 18, // 15, parameter LOGGER_CONF_SYN_BITS = 4, // 1, parameter LOGGER_CONF_EN = 20, // 17, parameter LOGGER_CONF_EN_BITS = 1, parameter LOGGER_CONF_DBG = 25, // 22, parameter LOGGER_CONF_DBG_BITS = 4, parameter GPIO_N = 10 // number of GPIO bits to control )( // input rst, input mclk, // system clock input xclk, // was in 353: half frequency (80 MHz nominal) input mrst, // @ posedge mclk - sync reset input xrst, // @ posedge xclk - sync reset // programming interface input [7:0] cmd_ad, // byte-serial command address/data (up to 6 bytes: AL-AH-D0-D1-D2-D3 input cmd_stb, // strobe (with first byte) for the command a/d output [7:0] status_ad, // status address/data - up to 5 bytes: A - {seq,status[1:0]} - status[2:9] - status[10:17] - status[18:25] output status_rq, // input request to send status downstream input status_start, // Acknowledge of the first status packet byte (address) output ts_local_snap, // @posedge xclk request to take a local time snapshot input ts_local_stb, // @posedge xclk one clock pulse before receiving a local TS data input [7:0] ts_local_data, // @posedge xclk local timestamp data (s0,s1,s2,s3,u0,u1,u2,u3==0) input [GPIO_N-1:0] ext_di, output [GPIO_N-1:0] ext_do, output [GPIO_N-1:0] ext_en, // byte-parallel timestamps from 4 sensors channels (in triggered mode all are the same, different only in free running mode) // each may generate logger event, channel number encoded in bits 25:24 of the external microseconds input ts_stb_chn0, // @mclk 1 clock before ts_rcv_data is valid input [7:0] ts_data_chn0, // @mclk byte-wide serialized timestamp message received or local input ts_stb_chn1, // @mclk 1 clock before ts_rcv_data is valid input [7:0] ts_data_chn1, // @mclk byte-wide serialized timestamp message received or local input ts_stb_chn2, // @mclk 1 clock before ts_rcv_data is valid input [7:0] ts_data_chn2, // @mclk byte-wide serialized timestamp message received or local input ts_stb_chn3, // @mclk 1 clock before ts_rcv_data is valid input [7:0] ts_data_chn3, // @mclk byte-wide serialized timestamp message received or local // TODO: Convert to 32-bit? output [15:0] data_out, // 16-bit data out to DMA1 (@posdge mclk) output data_out_stb,// data out valid (@posedge mclk) // sample_counter, // could be DMA latency, safe to use sample_counter-1 output [31:0] debug_state); wire [23:0] sample_counter; // TODO: read with status! could be DMA latency, safe to use sample_counter-1 wire ser_di; // gps serial data in wire gps_pulse1sec; wire mosi; // to IMU, bit 2 in J9 wire miso; // from IMU, bit 3 on J9 wire sda, sda_en, scl, scl_en; reg [6:0] ctrl_addr=7'h0; // 0 - period, 1 - reserved, 2..31 - registers to log, >32 - gps parameters, >64 - odometer message reg we_d; // only if wa was 0 reg we_imu; reg we_gps; reg we_period; reg we_bit_duration; reg we_message; reg we_config_imu; // bits 1:0, 2 - enable slot[1:0] reg we_config_gps; // bits 6:3, 7 - enable - {ext,invert, slot[1:0]} slot==0 - disable reg we_config_msg; // bits 12:8,13 - enable - {invert,extinp[3:0]} extinp[3:0]=='hf' - disable reg we_config_syn; // bit 14, 15 - enable - enable logging external timestamps reg we_config_rst; // bit 14, 15 - enable - enable logging external timestamps reg we_config_debug; // bit 14, 15 - enable - enable logging external timestamps reg we_bitHalfPeriod; reg [1:0] config_imu; reg [3:0] config_gps; reg [4:0] config_msg; reg config_rst; reg [3:0] config_debug; reg [15:0] bitHalfPeriod;// serial gps speed - number of xclk pulses in half bit period wire we_config_imu_xclk; // copy config_imu_mclk (@mclk) to config_imu (@xclk) wire we_config_gps_xclk; wire we_config_msg_xclk; wire we_config_rst_xclk; wire we_config_debug_xclk; wire we_bitHalfPeriod_xclk; reg [1:0] config_imu_mclk; reg [3:0] config_gps_mclk; reg [4:0] config_msg_mclk; reg [3:0] config_syn_mclk; reg config_rst_mclk; reg [3:0] config_debug_mclk; reg [15:0] bitHalfPeriod_mclk; reg enable_gps; reg enable_msg; wire [3:0] enable_syn_mclk; reg enable_timestamps; wire message_trig; wire gps_ts_stb, ser_do,ser_do_stb; wire [15:0] imu_data; wire [15:0] nmea_data; wire [15:0] extts_data; wire [15:0] msg_data; wire [15:0] timestamps_rdata; // multiplexed timestamp data reg [2:0] gps_pulse1sec_d; reg [1:0] gps_pulse1sec_denoise; reg [7:0] gps_pulse1sec_denoise_count; reg gps_pulse1sec_single; wire [3:0] timestamp_request; // 0 - imu, 1 - gps, 2 - ext, 3 - msg wire [3:0] timestamp_ackn; wire [3:0] timestamp_request_long; //from sub-module ts request until reset by arbiter, to allow timestamp_ackn wire [3:0] channel_ready; // 0 - imu, 1 - gps, 2 - ext, 3 - msg wire [3:0] channel_next; // 0 - imu, 1 - gps, 2 - ext, 3 - msg wire [1:0] channel; // currently logged channel number wire [1:0] timestamp_sel; // selected word in timestamp (0..3) wire ts_en; // log timestamp (when false - data) wire mux_data_valid; // data valid from multiplexer (to xclk->mclk converter fifo) reg [15:0] mux_data_source;// data multiplexed from 1 of the 4 channels reg mux_rdy_source; // data ready multiplexed from 1of the 4 channels (to fill rest with zeros) reg [15:0] mux_data_final; // data multiplexed between timestamps and channel data (or 0 if ~ready) wire rs232_wait_pause;// may be used as reset for decoder wire rs232_start; // serial character start (single pulse) wire nmea_sent_start; // serial character start (single pulse) // reg [1:0] debug_reg; reg [7:0] dbg_cntr; wire pre_message_trig; wire [15:0] ext_di16 ={{(16-GPIO_N){1'b0}},ext_di}; wire cmd_a; // single bit wire [31:0] cmd_data; reg [31:0] cmd_data_r; // valid next after cmd_we; wire cmd_we; wire cmd_status; assign ext_en = {{(GPIO_N-5){1'b0}}, (config_imu[1:0]==2'h2)?1'b1:1'b0, 1'b0, (config_imu[1:0]==2'h1)?1'b1:1'b0, (config_imu[1:0]!=2'h0)?{sda_en,scl_en}:2'h0}; assign ext_do= {{(GPIO_N-5){1'b0}}, (config_imu[1:0]==2'h2)?mosi:1'b0, 1'b0, (config_imu[1:0]==2'h1)?mosi:1'b0, (config_imu[1:0]!=2'h0)?{sda,scl}:2'h0}; assign miso= config_imu[1]? (config_imu[0]?1'b0 :ext_di[5]): (config_imu[0]?ext_di[3]:1'b0); assign ser_di= config_gps[1]? (config_gps[0]?1'b0 :ext_di[4]): (config_gps[0]?ext_di[2]:1'b0); assign gps_pulse1sec=config_gps[2]^(config_gps[1]? (config_gps[0]?1'b0 :ext_di[5]): (config_gps[0]?ext_di[3]:1'b0)); assign pre_message_trig = ext_di16[config_msg[3:0]]; assign message_trig= config_msg[4]^pre_message_trig; assign timestamp_request[1]=config_gps[3]? (config_gps[2]?nmea_sent_start:gps_ts_stb):gps_pulse1sec_single; // filter gps_pulse1sec always @ (posedge xclk) begin if (config_rst) gps_pulse1sec_d[2:0] <= 3'h0; else gps_pulse1sec_d[2:0] <= {gps_pulse1sec_d[1:0], gps_pulse1sec}; if (config_rst) gps_pulse1sec_denoise[0] <= 1'b0; else if (gps_pulse1sec_denoise_count[7:0]==8'h0) gps_pulse1sec_denoise[0] <= gps_pulse1sec_d[2]; if (gps_pulse1sec_d[2]==gps_pulse1sec_denoise[0]) gps_pulse1sec_denoise_count[7:0] <= 8'hff; else gps_pulse1sec_denoise_count[7:0] <= gps_pulse1sec_denoise_count[7:0] - 1; gps_pulse1sec_denoise[1] <= gps_pulse1sec_denoise[0]; gps_pulse1sec_single <= !gps_pulse1sec_denoise[1] && gps_pulse1sec_denoise[0]; end always @ (posedge mclk) begin // was negedge if (cmd_we) cmd_data_r <= cmd_data; // valid next after cmd_we; we_d <= cmd_we && !cmd_a; we_imu <= cmd_we && !cmd_a && (ctrl_addr[6:5] == LOGGER_PAGE_IMU); we_gps <= cmd_we && !cmd_a && (ctrl_addr[6:5] == LOGGER_PAGE_GPS); we_message <= cmd_we && !cmd_a && (ctrl_addr[6:5] == LOGGER_PAGE_MSG); we_period <= cmd_we && !cmd_a && (ctrl_addr[6:0] == LOGGER_PERIOD); we_bit_duration <= cmd_we && !cmd_a && (ctrl_addr[6:0] == LOGGER_BIT_DURATION); we_bitHalfPeriod<= cmd_we && !cmd_a && (ctrl_addr[6:0] == LOGGER_BIT_HALF_PERIOD); we_config_imu <= cmd_we && !cmd_a && (ctrl_addr[6:0] == LOGGER_CONFIG) && cmd_data[LOGGER_CONF_IMU]; we_config_gps <= cmd_we && !cmd_a && (ctrl_addr[6:0] == LOGGER_CONFIG) && cmd_data[LOGGER_CONF_GPS]; we_config_msg <= cmd_we && !cmd_a && (ctrl_addr[6:0] == LOGGER_CONFIG) && cmd_data[LOGGER_CONF_MSG]; we_config_syn <= cmd_we && !cmd_a && (ctrl_addr[6:0] == LOGGER_CONFIG) && cmd_data[LOGGER_CONF_SYN]; we_config_rst <= cmd_we && !cmd_a && (ctrl_addr[6:0] == LOGGER_CONFIG) && cmd_data[LOGGER_CONF_EN]; we_config_debug <= cmd_we && !cmd_a && (ctrl_addr[6:0] == LOGGER_CONFIG) && cmd_data[LOGGER_CONF_DBG]; if (we_config_imu) config_imu_mclk[1:0] <= cmd_data_r[LOGGER_CONF_IMU - 1 -: LOGGER_CONF_IMU_BITS]; // bits 1:0, 2 - enable slot[1:0] if (we_config_gps) config_gps_mclk[3:0] <= cmd_data_r[LOGGER_CONF_GPS - 1 -: LOGGER_CONF_GPS_BITS]; // bits 6:3, 7 - enable - {ext,inver, slot[1:0]} slot==0 - disable if (we_config_msg) config_msg_mclk[4:0] <= cmd_data_r[LOGGER_CONF_MSG - 1 -: LOGGER_CONF_MSG_BITS]; // bits 12:8,13 - enable - {invert,extinp[3:0]} extinp[3:0]=='hf' - disable if (we_config_syn) config_syn_mclk <= cmd_data_r[LOGGER_CONF_SYN - 1 -: LOGGER_CONF_SYN_BITS]; // bit 14, 15 - enable if (we_config_rst) config_rst_mclk <= cmd_data_r[LOGGER_CONF_EN -1 -: LOGGER_CONF_EN_BITS]; // bit 16, 17 - enable if (we_config_debug) config_debug_mclk[3:0] <= cmd_data_r[LOGGER_CONF_DBG - 1 -: LOGGER_CONF_DBG_BITS]; // bit 21:18, 22 - enable if (we_bitHalfPeriod) bitHalfPeriod_mclk[15:0] <= cmd_data_r[15:0]; if (cmd_we && cmd_a) ctrl_addr[6:5] <= cmd_data[6:5]; if (cmd_we && cmd_a) ctrl_addr[4:0] <= cmd_data[4:0]; else if (we_d && (ctrl_addr[4:0]!=5'h1f)) ctrl_addr[4:0] <=ctrl_addr[4:0]+1; // no roll over, end assign enable_syn_mclk= config_rst_mclk? 4'b0 : config_syn_mclk; always @ (posedge xclk) begin if (we_bitHalfPeriod_xclk) bitHalfPeriod[15:0] <= bitHalfPeriod_mclk[15:0]; if (we_config_imu_xclk) config_imu <= config_imu_mclk; if (we_config_gps_xclk) config_gps <= config_gps_mclk; if (we_config_msg_xclk) config_msg <= config_msg_mclk; if (we_config_rst_xclk) config_rst <= config_rst_mclk; if (we_config_debug_xclk) config_debug <= config_debug_mclk; enable_gps <= (^config_gps[1:0]) && !config_rst; // both 00 and 11 - disable enable_msg <= (config_gps[3:0] != 4'hf) && !config_rst; enable_timestamps <= !config_rst; end always @ (posedge xclk) begin mux_data_source[15:0] <= channel[1]? (channel[0]?msg_data[15:0]:extts_data[15:0]): (channel[0]?nmea_data[15:0]:imu_data[15:0]); mux_rdy_source <= channel[1]? (channel[0]?channel_ready[3]:channel_ready[2]): (channel[0]?channel_ready[1]:channel_ready[0]); mux_data_final[15:0] <= ts_en? timestamps_rdata[15:0]: (mux_rdy_source? mux_data_source[15:0]: 16'h0); // replace 16'h0 with some pattern to debug output end // generate strobes to copy configuration data from mclk to xclk domain pulse_cross_clock i_we_config_imu_xclk (.rst(mrst), .src_clk(mclk), .dst_clk(xclk), .in_pulse(we_config_imu), .out_pulse(we_config_imu_xclk),.busy()); pulse_cross_clock i_we_config_gps_xclk (.rst(mrst), .src_clk(mclk), .dst_clk(xclk), .in_pulse(we_config_gps), .out_pulse(we_config_gps_xclk),.busy()); pulse_cross_clock i_we_config_msg_xclk (.rst(mrst), .src_clk(mclk), .dst_clk(xclk), .in_pulse(we_config_msg), .out_pulse(we_config_msg_xclk),.busy()); pulse_cross_clock i_we_config_rst_xclk (.rst(mrst), .src_clk(mclk), .dst_clk(xclk), .in_pulse(we_config_rst), .out_pulse(we_config_rst_xclk),.busy()); pulse_cross_clock i_we_config_debug_xclk (.rst(mrst), .src_clk(mclk), .dst_clk(xclk), .in_pulse(we_config_debug), .out_pulse(we_config_debug_xclk),.busy()); pulse_cross_clock i_we_bitHalfPeriod_xclk (.rst(mrst), .src_clk(mclk), .dst_clk(xclk), .in_pulse(we_bitHalfPeriod), .out_pulse(we_bitHalfPeriod_xclk),.busy()); cmd_deser #( .ADDR (LOGGER_ADDR), .ADDR_MASK (LOGGER_MASK), .NUM_CYCLES (6), .ADDR_WIDTH (1), .DATA_WIDTH (32), .ADDR1 (LOGGER_STATUS), .ADDR_MASK1 (LOGGER_STATUS_MASK) ) cmd_deser_32bit_i ( .rst (1'b0), //rst), // input .clk (mclk), // input .srst (mrst), // input .ad (cmd_ad), // input[7:0] .stb (cmd_stb), // input .addr (cmd_a), // output[3:0] .data (cmd_data), // output[31:0] .we ({cmd_status,cmd_we}) // output ); status_generate #( .STATUS_REG_ADDR (LOGGER_STATUS_REG_ADDR), .PAYLOAD_BITS (26), .REGISTER_STATUS (1) ) status_generate_i ( .rst (1'b0), // rst), // input .clk (mclk), // input .srst (mrst), // input .we (cmd_status), // input .wd (cmd_data[7:0]), // input[7:0] .status ({sample_counter,2'b0}), // input[25:0] // 2 LSBs - may add "real" status .ad (status_ad), // output[7:0] .rq (status_rq), // output .start (status_start) // input ); imu_spi393 i_imu_spi ( // .rst(rst), .mclk (mclk), // system clock, negedge .xclk (xclk), // half frequency (80 MHz nominal) .we_ra (we_imu), // write enable for registers to log (@negedge mclk) .we_div (we_bit_duration), // write enable for clock dividing(@negedge mclk) .we_period (we_period), // write enable for IMU cycle period(@negedge mclk) 0 - disable, 1 - single, >1 - half bit periods .wa (ctrl_addr[4:0]), // write address for register (5 bits, @negedge mclk) .din (cmd_data_r[31:0]), // 16?-bit data in (di, not di_d) .mosi (mosi), // to IMU, bit 2 in J9 .miso (miso), // from IMU, bit 3 on J9 .config_debug (config_debug[3:0]), .sda (sda), // sda, shared with i2c, bit 1 .sda_en (sda_en), // enable sda output (when sda==0 and 1 cycle after sda 0->1) .scl (scl), // scl, shared with i2c, bit 0 .scl_en (scl_en), // enable scl output (when scl==0 and 1 cycle after sda 0->1) .ts (timestamp_request[0]), // timestamop request .rdy (channel_ready[0]), // data ready .rd_stb (channel_next[0]), // data read strobe (increment address) .rdata (imu_data[15:0])); // data out (16 bits) /* logs events from odometer (can be software triggered), includes 56-byte message written to the buffer So it is possible to assert trig input (will request timestamp), write message by software, then de-assert the trig input - message with the timestamp will be logged fixed-length de-noise circuitry with latency 256*T(xclk) (~3usec) */ imu_message393 i_imu_message( .mclk (mclk), // system clock, negedge .xclk (xclk), // half frequency (80 MHz nominal) .we (we_message), // write enable for registers to log (@negedge sclk), with lower data half .wa (ctrl_addr[3:0]), // write address for register (4 bits, @negedge sclk) .din (cmd_data_r[31:0]), // 16-bit data in multiplexed .en (enable_msg), // enable module operation, if 0 - reset .trig (message_trig), // leading edge - sample time, trailing set rdy .ts (timestamp_request[3]),// timestamop request .rdy (channel_ready[3]), // data ready .rd_stb (channel_next[3]), // data read strobe (increment address) .rdata (msg_data[15:0])); // data out (16 bits) /* logs frame synchronization data from other camera (same as frame sync) */ // ts_stb (mclk) -> trig) imu_exttime393 i_imu_exttime( // .rst (rst), // input global reset .mclk (mclk), // system clock, negedge .xclk (xclk), // half frequency (80 MHz nominal) .mrst (mrst), // @mclk - sync reset .xrst (xrst), // @xclk - sync reset .en_chn_mclk (enable_syn_mclk), // enable module operation, if 0 - reset .ts_stb_chn0 (ts_stb_chn0), // input .ts_data_chn0 (ts_data_chn0), // input[7:0] .ts_stb_chn1 (ts_stb_chn1), // input .ts_data_chn1 (ts_data_chn1), // input[7:0] .ts_stb_chn2 (ts_stb_chn2), // input .ts_data_chn2 (ts_data_chn2), // input[7:0] .ts_stb_chn3 (ts_stb_chn3), // input .ts_data_chn3 (ts_data_chn3), // input[7:0] .ts (timestamp_request[2]), // timestamop request .rdy (channel_ready[2]), // data ready .rd_stb (channel_next[2]), // data read strobe (increment address) .rdata (extts_data[15:0])); // data out (16 bits) imu_timestamps393 i_imu_timestamps ( .xclk (xclk), // 80 MHz, posedge .rst (!enable_timestamps), // reset (@posedge xclk) .ts_snap (ts_local_snap), // output (@posedge xclk) - get local TS snapshot .ts_stb (ts_local_stb), // input (@posedge xclk) - 1 xclk before local ts data .ts_data (ts_local_data), // input[7:0] (@posedge xclk) - local TS data .ts_rq (timestamp_request_long[3:0]), // input[3:0] requests to create timestamps (4 channels), @posedge xclk .ts_ackn (timestamp_ackn[3:0]), // output[3:0] timestamp for this channel is stored .ra ({channel[1:0],timestamp_sel[1:0]}), // input[3:0]read address (2 MSBs - channel number, 2 LSBs - usec_low, (usec_high ORed with channel <<24), sec_low, sec_high .dout (timestamps_rdata[15:0])); // output[15:0] output data wire debug_unused_a; // SuppressThisWarning Veditor (unused) rs232_rcv393 i_rs232_rcv ( .xclk (xclk), // half frequency (80 MHz nominal) .bitHalfPeriod (bitHalfPeriod[15:0]), // half of the serial bit duration, in xclk cycles .ser_di (ser_di), // rs232 (ttl) serial data in .ser_rst (!enable_gps), // reset (force re-sync) .ts_stb (gps_ts_stb), // strobe timestamp (start of message) (reset bit counters in nmea decoder) .wait_just_pause (rs232_wait_pause), // may be used as reset for decoder .start (rs232_start), // serial character start (single pulse) .ser_do (ser_do), // serial data out(@posedge xclk) LSB first! .ser_do_stb (ser_do_stb), // output data strobe (@posedge xclk), first cycle after ser_do becomes valid .debug ({debug_unused_a, debug_state[15:12]}), .bit_dur_cntr (debug_state[31:16]), .bit_cntr (debug_state[11:7]) ); assign debug_state[6:0] = dbg_cntr [6:0]; always @ (posedge xclk) begin if (!enable_gps) dbg_cntr[7:0] <= 8'h0; else if (rs232_start) dbg_cntr[7:0] <= dbg_cntr[7:0]+1; end nmea_decoder393 i_nmea_decoder ( .mclk (mclk), // system clock, @posedge .xclk (xclk), // 80MHz, posedge .we (we_gps), // registers write enable .wa (ctrl_addr[4:0]), // registers write address .wd (cmd_data_r[7:0]), // write data .start (gps_ts_stb), // start of the serial message .rs232_wait_pause (rs232_wait_pause), // may be used as reset for decoder .start_char (rs232_start), // serial character start (single pulse) .nmea_sent_start (nmea_sent_start), // serial character start (single pulse) .ser_di (ser_do), // serial data in (LSB first) .ser_stb (ser_do_stb), // serial data strobe, single-cycle, first cycle after ser_di valid .rdy (channel_ready[1]), // encoded nmea data ready .rd_stb (channel_next[1]), // encoded nmea data read strobe (increment address) .rdata (nmea_data[15:0]), // encoded data (16 bits) .ser_rst (!enable_gps), // reset (now only debug register) .debug() ); // Logger handshakes timestamps through request/grant, so it is OK to make slow serial communication with RTC) logger_arbiter393 i_logger_arbiter( .xclk (xclk), // 80 MHz, posedge .rst (config_rst), // module reset .ts_rq_in (timestamp_request[3:0]), // in requests for timestamp (single-cycle - just leading edge ) .ts_rq (timestamp_request_long[3:0]),// out request for timestamp, to timestmp module .ts_grant (timestamp_ackn[3:0]), // granted ts requests from timestamping module .rdy (channel_ready[3:0]), // channels ready (leading edge - became ready, trailing - no more data, use zero) .nxt (channel_next[3:0]), // pulses to modules to output next word .channel (channel[1:0]), // decoded channel number (2 bits) .ts_sel (timestamp_sel[1:0]), // select timestamp word to be output (0..3) .ts_en (ts_en), // 1 - use timestamp, 0 - channel data (or 16'h0 if !ready) .dv (mux_data_valid), // output data valid (from registered mux - 2 stage - first selects data and ready, second ts/data/zero) .sample_counter (sample_counter)); // number of 64-byte samples logged buf_xclk_mclk16_393 i_buf_xclk_mclk16( .mclk (mclk), // posedge .xclk (xclk), // posedge .rst (config_rst), // @posedge xclk .din (mux_data_final[15:0]), .din_stb (mux_data_valid), .dout (data_out[15:0]), .dout_stb (data_out_stb)); endmodule