x393  1.0
FPGAcodeforElphelNC393camera
imu_exttime393.v
Go to the documentation of this file.
1 
39 `timescale 1ns/1ps
40 /*
41 Logs frame synchronization data from other camera (same as frame sync)
42 When sensors are running in free running mode, each sensor may provide individual timestamp (sampled at vsync)
43 */
44 
46 // input rst,
47  input mclk, // system clock, negedge TODO:COnvert to posedge!
48  input xclk, // half frequency (80 MHz nominal)
49  input mrst, // @ posedge mclk - sync reset
50  input xrst, // @ posedge xclk - sync reset
51  input [3:0] en_chn_mclk, // enable per-channel module operation, if all 0 - reset
52  // byte-parallel timestamps from 4 sensors channels (in triggered mode all are the same, different only in free running mode)
53  // each may generate logger event, channel number encoded in bits 25:24 of the external microseconds
54 
55  input ts_stb_chn0, // @mclk 1 clock before ts_rcv_data is valid
56  input [7:0] ts_data_chn0, // @mclk byte-wide serialized timestamp message received or local
57 
58  input ts_stb_chn1, // @mclk 1 clock before ts_rcv_data is valid
59  input [7:0] ts_data_chn1, // @mclk byte-wide serialized timestamp message received or local
60 
61  input ts_stb_chn2, // @mclk 1 clock before ts_rcv_data is valid
62  input [7:0] ts_data_chn2, // @mclk byte-wide serialized timestamp message received or local
63 
64  input ts_stb_chn3, // @mclk 1 clock before ts_rcv_data is valid
65  input [7:0] ts_data_chn3, // @mclk byte-wide serialized timestamp message received or local
66 
67  output ts, // timestamop request
68  output reg rdy, // data ready will go up with timestamp request (ahead of actual time), but it will
69  // anyway be ready sooner, than the local timestamp retrieved ant sent
70  input rd_stb, // data read strobe (increment address) - continuous 1'b1 until allthe packet is read out
71  output [15:0] rdata); // data out (16 bits)
72 
73  reg [ 4:0] raddr;
76  reg en;
77 
78  reg rd_stb_r;
79  reg rd_start; // 1 xclk pulse at the readout start
81  reg ts_full; // internal 4 x 16 fifo is full (or getting full)
82  reg [3:0] in_full; // input fifo has (or is acquiring) timestamp
83  wire pre_copy_w;
84  reg [1:0] copy_selected; // copying from the winner of 4 input fifos to the x16 output fifo
86  reg [2:0] copy_cntr; // byte counter for copying
87  reg [1:0] sel_chn; // selected channel
88  wire [3:0] chn1hot={(sel_chn == 2'h3), (sel_chn == 2'h2), (sel_chn == 2'h1), (sel_chn == 2'h0)};
90  wire [3:0] chn_pri_w;
91  wire [1:0] chn_enc_w;
92 
93  reg [15:0] ts_ram [0:3]; // inner timestamp x16 memory that receives timestamp from one of the 4 input channel fifos
94  wire [31:0] dout_chn;
95  wire [7:0] copy_data; // data from the selected input fifos
96  reg [7:0] copy_data_r; // low byte of the timestamp data being copied from one of the input fifos to the ts_ram
97 
98  assign chn_pri_w = {in_full[3] & ~(|in_full[2:0]),
99  in_full[2] & ~(|in_full[1:0]),
100  in_full[1] & ~in_full[0],
101  in_full[0]};
102  assign chn_enc_w = {chn_pri_w[3] | chn_pri_w[2],
103  chn_pri_w[3] | chn_pri_w[1]};
104 
105  assign pre_copy_w = (|in_full) && !copy_selected[0] && !ts_full;
106  assign copy_data = dout_chn[sel_chn * 8 +: 8]; // 4:1 mux
107 
108 // acquire external timestamps @ mclk
109 
110  always @ (posedge mclk) begin
111 
113  if (!en_mclk) ts_full <= 0;
114  else if (pre_copy_started) ts_full <= 1; // turns on before in_full[*] - || will have no glitches
115  else if (rd_start_mclk) ts_full <= 0;
116 
117  if (!en_mclk) in_full <= 0;
118  else in_full <= en_chn_mclk & (ts_stb | (in_full & ~(chn1hot & {4{copy_started}})));
119 
120  copy_selected <= {copy_selected[0], pre_copy_w | (copy_selected[0] & ~(&copy_cntr[2:1]))}; // off at count 6
121 
122  if (pre_copy_w) sel_chn <= chn_enc_w;
123 
124  if (!copy_selected[1]) copy_cntr <= 4; // reverse order - timestamp message start with seconds, here usec first
125  else copy_cntr <= copy_cntr + 1;
126 
127  copy_data_r <= copy_data; // previous data is low byte
128  // write x16 timestamp data to RAM, insert channel number into unused microseconds byte
130 
131  end
132 
133  assign rdata[15:0] = ts_ram[raddr[1:0]];
134 
135 
136  always @ (posedge xclk) begin
137  en <= en_mclk;
138  rd_stb_r <= rd_stb;
139  rd_start <= en && rd_stb && ! rd_stb_r;
140  if (!en || ts) raddr[4:0] <= 5'h0;
141  else if (rd_stb) raddr[4:0] <= raddr[4:0] + 1;
142 
143  if (!en) rdy <= 1'b0;
144  else if (ts) rdy <= 1'b1; // too early, but it will become ready in time, before the local timestamp
145  else if (rd_stb && (raddr[1:0]==2'h3)) rdy <= 1'b0;
146  end
147 
148 
149 
150  timestamp_fifo timestamp_fifo_chn0_i (
151 // .rst (rst), // input
152  .sclk (mclk), // input
153  .srst (mrst), // input
154  .pre_stb (ts_stb[0]), // input
155  .din (ts_data_chn0), // input[7:0]
156  .aclk (mclk), // input
157  .arst (mrst), // input
158  .advance (ts_stb[0]), // enough time
159  .rclk (mclk), // input
160  .rrst (mrst), // input
161  .rstb (pre_copy_started && (sel_chn == 2'h0)),// input
162  .dout (dout_chn[0 * 8 +: 8]) // output[7:0] reg valid with copy_selected[1]
163  );
164 
165  timestamp_fifo timestamp_fifo_chn1_i (
166 // .rst (rst), // input
167  .sclk (mclk), // input
168  .srst (mrst), // input
169  .pre_stb (ts_stb[1]), // input
170  .din (ts_data_chn1), // input[7:0]
171  .aclk (mclk), // input
172  .arst (mrst), // input
173  .advance (ts_stb[1]), // enough time
174  .rclk (mclk), // input
175  .rrst (mrst), // input
176  .rstb (pre_copy_started && (sel_chn == 2'h1)),// input
177  .dout (dout_chn[1 * 8 +: 8]) // output[7:0] reg valid with copy_selected[1]
178  );
179 
180  timestamp_fifo timestamp_fifo_chn2_i (
181 // .rst (rst), // input
182  .sclk (mclk), // input
183  .srst (mrst), // input
184  .pre_stb (ts_stb[2]), // input
185  .din (ts_data_chn2), // input[7:0]
186  .aclk (mclk), // input
187  .arst (mrst), // input
188  .advance (ts_stb[2]), // enough time
189  .rclk (mclk), // input
190  .rrst (mrst), // input
191  .rstb (pre_copy_started && (sel_chn == 2'h2)),// input
192  .dout (dout_chn[2 * 8 +: 8]) // output[7:0] reg valid with copy_selected[1]
193  );
194 
195  timestamp_fifo timestamp_fifo_chn3_i (
196 // .rst (rst), // input
197  .sclk (mclk), // input
198  .srst (mrst), // input
199  .pre_stb (ts_stb[3]), // input
200  .din (ts_data_chn3), // input[7:0]
201  .aclk (mclk), // input
202  .arst (mrst), // input
203  .advance (ts_stb[3]), // enough time
204  .rclk (mclk), // input
205  .rrst (mrst), // input
206  .rstb (pre_copy_started && (sel_chn == 2'h3)),// input
207  .dout (dout_chn[3 * 8 +: 8]) // output[7:0] reg valid with copy_selected[1]
208  );
209 
210 
212 
213 // generate timestamp request as soon as one of the sub-channels starts copying. That time stamp will be stored for this (ext) channel
215 
216 endmodule
217 
3584chn1hotwire[3:0]
3578in_fullreg[3:0]
[0:3] 3588ts_ramreg[15:0]
3589dout_chnwire[31:0]
3585pre_copy_startedwire
[15:0] 3569rdata
3587chn_enc_wwire[1:0]
[7:0] 3563ts_data_chn2
3590copy_datawire[7:0]
[7:0] 3565ts_data_chn3
3583sel_chnreg[1:0]
3572ts_stbwire[3:0]
3570raddrreg[4:0]
[7:0] 3561ts_data_chn1
[7:0] 3559ts_data_chn0
3580copy_selectedreg[1:0]
reg [ 7:0] 9614dout
3582copy_cntrreg[2:0]
timestamp_fifo_chn3_i timestamp_fifo
[3:0] 3557en_chn_mclk
3591copy_data_rreg[7:0]
3586chn_pri_wwire[3:0]