Commit e9862dab authored by Andrey Filippov's avatar Andrey Filippov

Converting event_logger to use serial timestamps and 4 sesnor channels

parent 6a297fff
......@@ -4,7 +4,7 @@
* Author: andrey
* Description: move data from xclk to mclk domain
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* Copyright (c) 2015 Elphel, Inc.
* buf_xclk_mclk16_393.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
......@@ -21,63 +21,46 @@
`timescale 1ns/1ps
module buf_xclk_mclk16_393(
xclk, // posedge
mclk, // posedge
rst, // @posedge xclk
din,
din_stb,
dout,
dout_stb);
input mclk, // system clock, posedge
input xclk, // half frequency (80 MHz nominal)
input rst, // @posedge xclk reset module
input [15:0] din,
input din_stb,
output reg [15:0] dout,
output reg dout_stb);
input xclk; // half frequency (80 MHz nominal)
input mclk; // system clock - frequency (160 MHz nominal)
input rst; // reset module
input [15:0] din;
input din_stb;
output [15:0] dout;
output dout_stb;
reg [1:0] wa;
reg [1:0] wa_mclk;
reg [1:0] wa_mclk_d;
reg rst_mclk;
reg [1:0] ra;
reg [1:0] ra_next;
reg inc_ra;
wire [15:0] pre_dout;
reg [1:0] wa;
reg [1:0] wa_mclk;
reg [1:0] wa_mclk_d;
reg rst_mclk;
reg [1:0] ra;
reg [1:0] ra_next;
reg inc_ra;
wire [15:0] pre_dout;
reg [15:0] dout;
reg dout_stb;
always @ (posedge xclk) begin
if (rst) wa[1:0] <= 2'h0;
else if (din_stb) wa[1:0] <={wa[0],~wa[1]};
end
always @ (posedge mclk) begin
wa_mclk[1:0] <= wa[1:0];
wa_mclk_d[1:0] <= wa_mclk[1:0];
rst_mclk<= rst;
if (rst_mclk) ra[1:0] <= 2'h0;
else ra[1:0] <= inc_ra?{ra[0],~ra[1]}:{ra[1],ra[0]};
if (rst_mclk) ra_next[1:0] <= 2'h1;
else ra_next[1:0] <= inc_ra?{~ra[1],~ra[0]}:{ra[0],~ra[1]};
inc_ra <= !rst && (ra[1:0]!=wa_mclk_d[1:0]) && (!inc_ra || (ra_next[1:0]!=wa_mclk_d[1:0]));
dout_stb <= inc_ra;
if (inc_ra) dout[15:0] <= pre_dout[15:0];
end
myRAM_WxD_D #( .DATA_WIDTH(16),.DATA_DEPTH(2))
i_fifo_4x16 (.D(din[15:0]),
.WE(din_stb),
.clk(xclk),
.AW(wa[1:0]),
.AR(ra[1:0]),
.QW(),
.QR(pre_dout[15:0]));
endmodule
always @ (posedge xclk) begin
if (rst) wa[1:0] <= 2'h0;
else if (din_stb) wa[1:0] <={wa[0],~wa[1]};
end
always @ (posedge mclk) begin
wa_mclk[1:0] <= wa[1:0];
wa_mclk_d[1:0] <= wa_mclk[1:0];
rst_mclk<= rst;
if (rst_mclk) ra[1:0] <= 2'h0;
else ra[1:0] <= inc_ra?{ra[0],~ra[1]}:{ra[1],ra[0]};
if (rst_mclk) ra_next[1:0] <= 2'h1;
else ra_next[1:0] <= inc_ra?{~ra[1],~ra[0]}:{ra[0],~ra[1]};
inc_ra <= !rst && (ra[1:0]!=wa_mclk_d[1:0]) && (!inc_ra || (ra_next[1:0]!=wa_mclk_d[1:0]));
dout_stb <= inc_ra;
if (inc_ra) dout[15:0] <= pre_dout[15:0];
end
reg [15:0] fifo_4x16_ram[0:3];
always @ (posedge xclk) if (din_stb) fifo_4x16_ram[wa[1:0]] <= din[15:0];
assign pre_dout[15:0] = fifo_4x16_ram[ra[1:0]];
endmodule
......@@ -4,7 +4,7 @@
* Author: andrey
* Description: top module of the event logger (ported from imu_logger)
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* 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
......@@ -42,11 +42,11 @@ module event_logger#(
parameter LOGGER_CONF_GPS_BITS = 4,
parameter LOGGER_CONF_MSG = 13,
parameter LOGGER_CONF_MSG_BITS = 5,
parameter LOGGER_CONF_SYN = 15,
parameter LOGGER_CONF_SYN_BITS = 1,
parameter LOGGER_CONF_EN = 17,
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 = 22,
parameter LOGGER_CONF_DBG = 25, // 22,
parameter LOGGER_CONF_DBG_BITS = 4,
parameter GPIO_N = 10 // number of GPIO bits to control
......@@ -68,9 +68,27 @@ module event_logger#(
input [GPIO_N-1:0] ext_di,
output [GPIO_N-1:0] ext_do,
output [GPIO_N-1:0] ext_en,
input [31:0] ts_rcv_sec, // [31:0] timestamp seconds received over the sync line
input [19:0] ts_rcv_usec, // [19:0] timestamp microseconds received over the sync line
input ts_stb, // strobe when received timestamp is valid - single negedge sclk cycle
// input [31:0] ts_rcv_sec, // [31:0] timestamp seconds received over the sync line
// input [19:0] ts_rcv_usec, // [19:0] timestamp microseconds received over the sync line
// input ts_stb, // strobe when received timestamp is valid - single negedge sclk cycle
// byte-parallel timestamps from 4 sesnors 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 (@negedge mclk)
output data_out_stb,// data out valid (@negedge mclk)
......@@ -94,11 +112,14 @@ module event_logger#(
reg we_period;
reg we_bit_duration;
reg we_message;
reg we_config;
// reg we_config;
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 we_config_rst; // bit 16, 17 - enable - reset modules
// reg we_config_debug; // bits 21:18, 22 - enable
......@@ -108,38 +129,50 @@ module event_logger#(
reg [1:0] config_imu;
reg [3:0] config_gps;
reg [4:0] config_msg;
reg config_syn;
// reg [3:0] config_syn;
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_syn_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 config_syn_mclk;
reg [3:0] config_syn_mclk;
reg config_rst_mclk;
reg [3:0] config_debug_mclk;
reg [15:0] bitHalfPeriod_mclk;
reg [1:0] config_imu_pre;
reg [3:0] config_gps_pre;
reg [4:0] config_msg_pre;
reg config_syn_pre;
reg config_rst_pre;
reg [3:0] config_debug_pre;
// reg [1:0] config_imu_pre;
// reg [3:0] config_gps_pre;
// reg [4:0] config_msg_pre;
// reg config_syn_pre;
// reg config_rst_pre;
// reg [3:0] config_debug_pre;
reg [15:0] bitHalfPeriod;// serial gps speed - number of xclk pulses in half bit period
reg we_bitHalfPeriod;
reg [15:0] bitHalfPeriod_mclk;
reg enable_gps;
reg enable_msg;
reg enable_syn;
// reg [3:0] enable_syn;
wire [3:0] enable_syn_mclk;
reg enable_timestamps;
wire message_trig;
// reg ts_stb_rq;
// reg [1:0] ext_ts_stb;
wire ts_stb_xclk; // re-clocked to posedge xclk
// wire ts_stb_xclk; // re-clocked to posedge xclk
wire gps_ts_stb, ser_do,ser_do_stb;
wire [15:0] imu_data;
......@@ -281,76 +314,78 @@ module event_logger#(
end
*/
always @ (posedge mclk) begin // was negedge
if (cmd_we) cmd_data_r <= cmd_data; // valid next after cmd_we;
// if (we) di_d[15:0] <= di[15:0];
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 <= cmd_we && !cmd_a && (ctrl_addr[6:0] == LOGGER_CONFIG);
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];
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 && cmd_data_r[LOGGER_CONF_EN]) config_rst_mclk <= cmd_data_r[LOGGER_CONF_EN -1 -: LOGGER_CONF_EN_BITS]; // bit 16, 17 - enable
if (we_config && cmd_data_r[LOGGER_CONF_DBG]) config_debug_mclk[3:0] <= cmd_data_r[LOGGER_CONF_DBG - 1 -: LOGGER_CONF_DBG_BITS]; // bit 21:18, 22 - enable
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_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,
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];
end
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
always @ (posedge xclk) begin
bitHalfPeriod[15:0] <= bitHalfPeriod_mclk[15:0];
config_imu_pre[1:0] <= config_imu_mclk[1:0];
config_gps_pre[3:0] <= config_gps_mclk[3:0];
config_msg_pre[4:0] <= config_msg_mclk[4:0];
config_syn_pre <= config_syn_mclk;
config_rst_pre <= config_rst_mclk;
config_debug_pre[3:0] <= config_debug_mclk[3:0];
config_imu[1:0] <= config_imu_pre[1:0];
config_gps[3:0] <= config_gps_pre[3:0];
config_msg[4:0] <= config_msg_pre[4:0];
config_syn <= config_syn_pre;
config_rst <= config_rst_pre;
config_debug[3:0] <= config_debug_pre[3:0];
// enable_gps <= (config_gps[1:0] != 2'h0) && !config_rst;
enable_gps <= (^config_gps[1:0]) && !config_rst; // both 00 and 11 - disable
enable_msg <= (config_gps[3:0] != 4'hf) && !config_rst;
enable_syn <= config_syn && !config_rst;
enable_timestamps <= !config_rst;
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_syn_xclk) config_syn <= config_syn_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] != 2'h0) && !config_rst;
enable_gps <= (^config_gps[1:0]) && !config_rst; // both 00 and 11 - disable
enable_msg <= (config_gps[3:0] != 4'hf) && !config_rst;
// enable_syn <= config_rst? 4'b0 : config_syn;
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
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
pulse_cross_clock i_ts_stb_xclk (.rst(1'b0), .src_clk(mclk), .dst_clk(xclk), .in_pulse(ts_stb), .out_pulse(ts_stb_xclk),.busy());
// pulse_cross_clock i_ts_stb_xclk (.rst(1'b0), .src_clk(mclk), .dst_clk(xclk), .in_pulse(ts_stb), .out_pulse(ts_stb_xclk),.busy());
// generate strobes to copy configuration data from mclk to xclk domain
pulse_cross_clock i_we_config_imu_xclk (.rst(1'b0), .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(1'b0), .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(1'b0), .src_clk(mclk), .dst_clk(xclk), .in_pulse(we_config_msg), .out_pulse(we_config_msg_xclk),.busy());
// pulse_cross_clock i_we_config_syn_xclk (.rst(1'b0), .src_clk(mclk), .dst_clk(xclk), .in_pulse(we_config_syn), .out_pulse(we_config_syn_xclk),.busy());
pulse_cross_clock i_we_config_rst_xclk (.rst(1'b0), .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(1'b0), .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(1'b0), .src_clk(mclk), .dst_clk(xclk), .in_pulse(we_bitHalfPeriod), .out_pulse(we_bitHalfPeriod_xclk),.busy());
cmd_deser #(
.ADDR (LOGGER_ADDR),
......@@ -386,131 +421,139 @@ module event_logger#(
.start (status_start) // input
);
imu_spi393 i_imu_spi ( .sclk(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)
.di(cmd_data_r[15: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)
// .sngl_wire(sngl_wire), // single wire clock/data for the 103695 rev A
.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)
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(.sclk(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)
.di(cmd_data_r[15: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)
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(.xclk(xclk), // half frequency (80 MHz nominal)
.en(enable_syn), // enable module operation, if 0 - reset
.trig(ts_stb_xclk), // ext_ts_stb[1]), // external time stamp updated, single pulse @posedge xclk
.usec(ts_rcv_usec[19:0]), // microseconds from external timestamp (should not chnage after trig for 10 xclk)
.sec(ts_rcv_sec[31:0]), // seconds from external timestamp
.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 (
.sclk(mclk), // 160MHz, negedge
.xclk(xclk), // 80 MHz, posedge
.rst(!enable_timestamps), // reset (@posedge xclk)
.sec(sec[31:0]), // running seconds (@negedge sclk)
.usec(usec[19:0]), // running microseconds (@negedge sclk)
.ts_rq(timestamp_request_long[3:0]),// requests to create timestamps (4 channels), @posedge xclk
.ts_ackn(timestamp_ackn[3:0]), // timestamp for this channel is stored
.ra({channel[1:0],timestamp_sel[1: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 data
imu_exttime393 i_imu_exttime(
.rst (rst), // input global reset
.mclk (mclk), // system clock, negedge
.xclk (xclk), // half frequency (80 MHz nominal)
.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 (
.sclk (mclk), // 160MHz, negedge
.xclk (xclk), // 80 MHz, posedge
.rst (!enable_timestamps), // reset (@posedge xclk)
.sec (sec[31:0]), // running seconds (@negedge sclk)
.usec (usec[19:0]), // running microseconds (@negedge sclk)
.ts_rq (timestamp_request_long[3:0]), // requests to create timestamps (4 channels), @posedge xclk
.ts_ackn (timestamp_ackn[3:0]), // timestamp for this channel is stored
.ra ({channel[1:0],timestamp_sel[1: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 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_state[4:0]),
.debug({debug_unused_a, debug_state[15:12]}),
.bit_dur_cntr(debug_state[31:16]),
.bit_cntr(debug_state[11:7])
);
// output [15:0] debug_state;
// reg [7:0] dbg_cntr;
// assign debug_state[15:12]=3'b0;
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 (ser_do_stb) dbg_cntr[7:0] <= dbg_cntr[7:0]+1;
else if (rs232_start) dbg_cntr[7:0] <= dbg_cntr[7:0]+1;
end
nmea_decoder393 i_nmea_decoder (.sclk(mclk), // system clock, @negedge
.we(we_gps), // registers write enable (@negedge sclk)
.wa(ctrl_addr[4:0]), // registers write address
.wd(cmd_data_r[7:0]), // write data
.xclk(xclk), // 80MHz, posedge
.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()
);
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_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(.xclk(xclk), // posedge
.mclk(mclk), // 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));
// 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
......@@ -4,7 +4,7 @@
* Author: andrey
* Description: get external timestamp (for image)
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* Copyright (c) 2015 Elphel, Inc.
* imu_exttime393.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
......@@ -20,77 +20,166 @@
*******************************************************************************/
`timescale 1ns/1ps
/*
logs frame synchronization data from other camera (same as frame sync)
Logs frame synchronization data from other camera (same as frame sync)
When sesnors are running in free running mode, each sensor may provide individual timestamp (sampled at vsync)
*/
module imu_exttime393(
xclk, // half frequency (80 MHz nominal)
en, // enable module operation, if 0 - reset
trig, // external time stamp updated
usec, // microseconds from external timestamp (should not chnage after trig for 10 xclk)
sec, // seconds from external timestamp
ts, // timestamop request
rdy, // data ready
rd_stb, // data read strobe (increment address)
rdata); // data out (16 bits)
input xclk; // half frequency (80 MHz nominal)
input en; // enable
input trig; // external time stamp updated
input [19:0] usec; // microseconds from external timestamp
input [31:0] sec; // seconds from external timestamp
output ts; // timestamp request
output rdy; // encoded nmea data ready
input rd_stb;// encoded nmea data read strobe (increment address)