x393  1.0
FPGAcodeforElphelNC393camera
imu_spi393.v
Go to the documentation of this file.
1 
39 `timescale 1ns/1ps
40 
41 module imu_spi393(
42 // input rst,
43  input mclk, // system clock, negedge TODO:COnvert to posedge!
44  input xclk, // half frequency (80 MHz nominal)
45 
46  input we_ra, // write enable for registers to log (@negedge clk)
47  input we_div,// write enable for clock dividing(@negedge clk)
48  input we_period,// write enable for IMU cycle period(@negedge clk) 0 - disable, 1 - single, >1 - half bit periods
49  input [ 4:0] wa, // write address for register (5 bits, @negedge clk)
50  input [31:0] din, //
51  output mosi, // to IMU, bit 2 in J9
52  input miso, // from IMU, bit 3 on J9
53  input [ 3:0] config_debug, // bit 0 - long sda_en
54  output sda, // sda, shared with i2c, bit 1
55  output sda_en, // enable sda output (when sda==0 and 1 cycle after sda 0->1)
56  output scl, // scl, shared with i2c, bit 0
57  output scl_en, // enable scl output (when scl==0 and 1 cycle after sda 0->1)
58  output ts, // timestamop request
59  output rdy, // data ready
60  input rd_stb, // data read strobe (increment address)
61  output [15:0] rdata); // data out (16 bits)
62  /*
63  input mclk; // system clock, negedge
64  input xclk; // half frequency (80 MHz nominal)
65  input we_ra; // write enable for registers to log (@negedge mclk)
66  input we_div;// write enable for clock dividing(@negedge mclk)
67  input we_period;// write enable for IMU cycle period(@negedge clk)
68  input [4:0] wa; // write address for register (5 bits, @negedge mclk)
69  input [15:0] di; // 16-bit data in
70  output mosi; // to IMU, bit 2 in J9
71  input miso; // from IMU, bit 3 on J9
72  input [3:0] config_debug;
73  output sda; // sda, shared with i2c, bit 1
74  output sda_en; // enable sda output (when sda==0 and 1 cycle after sda 0->1)
75  output scl; // scl, shared with i2c, bit 0
76  output scl_en; // enable scl output (when scl==0 and 1 cycle after sda 0->1)
77  output ts; // timestamp request
78 
79  output rdy; // encoded nmea data ready
80  input rd_stb; // encoded nmea data read strobe (increment address)
81  output [15:0] rdata; // encoded data (16 bits)
82 // output sngl_wire; // combined clock/data
83  */
84  reg [ 7:0] bit_duration_mclk=8'h0;
85  reg [ 7:0] bit_duration;
86  reg [ 7:0] bit_duration_cntr=8'h0;
87  reg bit_duration_zero; // just for simulation
88 
89  reg [ 3:0] clk_en=4'h0;
90  reg [ 1:0] clk_div;
91  reg [ 4:0] imu_in_word= 5'b0; // number of IMU output word in a sample (0..31), 0..3 - timestamp
93  wire [15:0] imu_in_buf;
94 
95  reg [4:0] reg_seq_number; // number of register in a sequence
96  wire [6:1] imu_reg_number; // register numer to read
97 
98  reg [1:0] seq_state; // 0 - idle, 1 - prepare spi(4?), 2 - spi-comm(32*29), 3 - finish (2)
99  reg [9:0] seq_counter;
103  reg [15:0] mosi_reg;
104 // wire mosi;
105  reg [1:0] sda_r;
106  reg [1:0] scl_r;
107 // wire scl_en;
109  reg [15:0] miso_reg;
110  reg last_bit; // last clk _/~ in spi word (but first one)
111  reg last_bit_ext=1'b0; // from last bit till buffer write
113  reg [ 4:0] raddr;
114  reg rdy_r=1'b0;
116  reg ts_r; // delay imu_start by one cycle, so it will be after rdy is reset
117 
118  reg [31:0] period; // 0 - disable, 1 - single, >1 - period in 50 ns steps
119 // reg [15:0] di_d;
120 
122  reg [1:0] imu_enabled=2'h0;
124  reg [1:0] imu_run;
126  reg [1:0] imu_when_ready;
127 
130  reg [1:0] imu_start_grant;
133  reg [31:0] period_counter;
134  wire en;
135  reg [4:01] we_timer;
137  reg [1:0] first_prepare_d;
140  reg [7:0] stall_dur_mclk;
141  reg [7:0] stall_dur;
142  reg stall; // stall between words to satisfy SPI stall time
143  reg [7:0] stall_cntr; // stall counter (in half mclk periods)
145  reg skip_stall; // first word after CS -\_
147 
150  reg [2:0] imu_data_ready_d;
151  reg [5:0] imu_data_ready;
152  reg [1:0] seq_state_zero;
153 
154  reg pre_scl;
155  reg [2:0] sngl_wire_stb;
156  reg [1:0] sngl_wire_r;
157  wire sngl_wire;
158  wire config_single_wire; // used in 103695 rev A
159 
160  assign sngl_wire = ~|sngl_wire_r[1:0];
161 
162  assign shift_mosi = (clk_en[3] && seq_counter[0] && !stall);
164 
165  assign config_long_sda_en = config_debug[0];
166  assign config_late_clk = config_debug[1];
167  assign config_single_wire = config_debug[2];
168 
169  assign en= imu_enabled[1];
170  assign sda_en= !config_single_wire && (!sda_r[0] || !sda_r[1] || (config_long_sda_en && (seq_state[1:0]!=2'b0)));
171  assign scl_en= !config_single_wire && (!scl_r[0] || !scl_r[1]);
172 
173  assign sda = sda_r[0];
174  assign scl = scl_r[0];
175  assign rdy = rdy_r;
176  assign ts = ts_r;
177 
178 
179  always @ (posedge mclk) begin
180  // di_d[15:0] <= di[15:0];
181  if (we_div) bit_duration_mclk[7:0] <= din[7:0];
182  if (we_div) stall_dur_mclk[7:0] <= din[15:8];
183  we_timer[4:1] <= {we_timer[3:1], we_period};
184 
185  if (we_period) period[31:0] <= din[31:0];
186  if (we_timer[2]) imu_run_mclk <= (period[31:1]!=31'b0); // double-cycle
188 
189  if (we_timer[2]) imu_when_ready_mclk <= &period[31:16]; // double-cycle
190 
191  if (!imu_enabled_mclk || imu_start_grant[1]) imu_start_mclk <= 1'b0;
193  end
194 
195 // debounce imu_data_ready
196  always @ (posedge xclk) begin
197  seq_state_zero[1:0] <= {seq_state_zero[0], ~|seq_state[1:0]};
198  imu_ready_reset <= !imu_enabled[1] || (seq_state[1:0]!=2'b0) || !imu_when_ready[1];
199  if (imu_ready_reset) imu_data_ready_d[2:0] <=3'b0;
200  else imu_data_ready_d[2:0] <= {imu_data_ready_d[1:0], miso};
201 
202  if (imu_ready_reset) imu_data_ready[0] <= 1'b0;
203  else if (imu_ready_denoise_count[6:0]==7'h0) imu_data_ready[0] <= imu_data_ready_d[2];
204 
205  if (imu_data_ready_d[2]==imu_data_ready[0]) imu_ready_denoise_count[6:0] <= 7'h7f; // use period LSBs?
206  else imu_ready_denoise_count[6:0] <= imu_ready_denoise_count[6:0] - 1;
207 
208  if (imu_ready_reset) imu_data_ready[1] <= 1'b0;
209  else if (imu_data_ready[0]) imu_data_ready[1] <= 1'b1;
210 
211  if (imu_ready_reset) imu_data_ready[2] <= 1'b0;
212  else if (imu_data_ready[1] && !imu_data_ready[0]) imu_data_ready[2] <= 1'b1;
213 
214  if (imu_ready_reset) imu_data_ready[3] <= 1'b0;
215  else if (imu_data_ready[2] && imu_data_ready[0]) imu_data_ready[3] <= 1'b1;
216 
217  if (clk_en[1]) imu_data_ready[4] <= imu_data_ready[3] ;
218 
219  imu_data_ready[5] <=clk_en[1] && imu_data_ready[3] && !imu_data_ready[4]; // single pulse @clk_en[2]
220  end
221 
222  always @ (posedge xclk) begin
224  imu_run[1:0] <= {imu_run[0],imu_run_mclk};
225 
227 
228  if (~imu_run[1:0]) imu_run_confirmed <= 1'b0;
229  else if (imu_start_first) imu_run_confirmed <= imu_run[1];
232 
233  imu_start_first<=clk_en[1] && imu_start_grant[1] && !imu_start_first_was; // single xclk at clk_en[2] time slot
235  (!imu_when_ready[1] && imu_run_confirmed && (period_counter[31:0]==32'h1) && clk_en[2]) ||
236  imu_data_ready[5]; // single pulses at clk_en[3]
237 
238  if (imu_start || imu_when_ready[1]) period_counter[31:0] <= period[31:0];
239  else if (clk_en[3]) period_counter[31:0] <= period_counter[31:0] - 1;
240  end
241 
242 
243  always @ (posedge xclk) begin
244  bit_duration[7:0] <= bit_duration_mclk[7:0];
245  stall_dur[7:0] <= stall_dur_mclk[7:0];
246 
247  bit_duration_zero <= (bit_duration[7:0] == 8'h0);
248  clk_div[1:0] <= en ? (clk_div[1:0] + 1) : 2'b0;
249  clk_en[3:0] <= {clk_en[2:0], clk_div[1:0] == 2'h3};
250  if (bit_duration_zero || (bit_duration_cntr[7:0]==8'h0)) bit_duration_cntr[7:0]<=bit_duration[7:0];
251  else bit_duration_cntr[7:0] <= bit_duration_cntr[7:0]-1;
252  clk_en[3:0] <= {clk_en[2:0], bit_duration_cntr[7:0] == 8'h3 }; // change 9'h3 to enforce frequency limit
253  end
254 
255  always @ (posedge xclk) begin
256  pre_seq_counter_zero <= clk_en[1] && (seq_counter[9:0]==10'h0) && (seq_state[1:0]!=2'h0); // active at clk_en[2]
257  seq_counter_zero <= pre_seq_counter_zero; // active at clk_en[3]
258  if (!en) seq_state[1:0] <= 2'h0;
259  else if (imu_start) seq_state[1:0] <= 2'h1;
260  else if (seq_counter_zero ) seq_state[1:0] <= seq_state[1:0] + 1; // will not count from 0 as seq_counter_zero will be disabled
261 
262  if (!en) first_prepare <=1'b0;
263  else if (imu_start) first_prepare <=1'b1;
264  else if (clk_en[3]) first_prepare <=1'b0;
265 
266  if (!en) first_prepare_d[1:0] <= 2'b0;
267  else if (clk_en[3]) first_prepare_d[1:0] <= {first_prepare_d[0],first_prepare};
268 
269  end_prepare <= pre_seq_counter_zero && (seq_state[1:0]==2'h1);
270  end_spi <= pre_seq_counter_zero && (seq_state[1:0]==2'h2);
271 
272  if (!en) seq_counter[9:0] <= 10'h000;
273  else if (imu_start) seq_counter[9:0] <= config_late_clk?10'h005:10'h003; // should be odd
274  else if (end_prepare) seq_counter[9:0] <= 10'h39f;
275  else if (end_spi) seq_counter[9:0] <= 10'h001;
276  else if (clk_en[3] && (seq_state[1:0]!=2'h0) && !stall) seq_counter[9:0] <= seq_counter[9:0] - 1;
278 // set_mosi_spi <= clk_en[2] && (seq_state[1:0]==2'h2) && (seq_counter[4:0]==5'h1f) && (seq_counter[9:5]!=6'h0) && !stall; // last word use zero
279  set_mosi_spi <= clk_en[2] && (seq_state[1:0]==2'h2) && (seq_counter[4:0]==5'h1f) && (seq_counter[9:5] != 0) && !stall; // last word use zero
280 
281  // no stall before the first word
282  if (!en) skip_stall <= 1'b0;
283  else if (end_prepare) skip_stall <= 1'b1;
284  else if (clk_en[3]) skip_stall <= 1'b0;
285 
286  set_stall <= clk_en[0] && (seq_state[1:0]==2'h2) && (seq_counter[4:0]==5'h1f) && !skip_stall && !stall; // @ clk_en[1]
287 
288  if (!en) mosi_reg[15:0] <= 16'h0;
289  else if (set_mosi_prepare) mosi_reg[15:0] <= 16'h7fff;
290  else if (set_mosi_spi) mosi_reg[15:0] <= {1'b0,imu_reg_number[6:1],9'b0};
291  else if (shift_mosi) mosi_reg[15:0] <= {mosi_reg[14:0],1'b0};
292 
293  // stall switches at clk_en[2]
294  // stall switches at clk_en[1]
295  if (!en) stall_cntr[7:0] <= 8'h0;
296  else if (set_stall) stall_cntr[7:0] <= stall_dur[7:0];
297  else if (clk_en[1]) stall_cntr[7:0] <= stall?(stall_cntr[7:0]-1):8'h0;
298 
299 
300  if (!en) stall <= 1'b0;
301  else if (set_stall) stall <= (stall_dur[7:0]!=0);
302  else if (clk_en[1] && (stall_cntr[7:1]==0)) stall <= 1'b0;
303 
304 
305 
306  if (!en) sda_r <=2'b11;
307  else if (clk_en[3]) sda_r <= {sda_r[0], !(first_prepare_d[1] || (seq_counter[0] && (seq_state[1:0]==2'h3)))} ;
308 
309 
310  if (!en) pre_scl <=1'b1;
311  else if (clk_en[2]) pre_scl <= (seq_state[1:0]!=2'h2) || !seq_counter[0] || stall;
312 
313  scl_r[0] <= pre_scl;
314  if (!en) scl_r[1] <=1'b1;
315  else if (clk_en[3]) scl_r[1] <= scl_r[0];
316 
317 
318  sngl_wire_stb[2:0] <={sngl_wire_stb[1:0], en & ((scl_r[0] ^ pre_scl) | end_prepare)};
319 
320  if (!en) sngl_wire_r[0]<=1'b0;
321  else if ((pre_scl ^scl_r[0]) | end_prepare) sngl_wire_r[0]<=1'b1;
322  else if (!mosi_reg[15] || sngl_wire_stb[2] || scl_r[0]) sngl_wire_r[0]<=1'b0;
323 
324 
325 
326  if (imu_start) reg_seq_number[4:0] <= 5'h04;
327  else if (set_mosi_spi) reg_seq_number[4:0] <= reg_seq_number[4:0] + 1;
328 
329  shift_miso <= !scl_r[1] && clk_en[2]; // active at clk_en[3]
330 
331  if (shift_miso) miso_reg[15:0] <= {miso_reg[14:0], miso};
332 
333  last_bit <= clk_en[2] && (seq_state[1:0]==2'h2) && (seq_counter[4:0]==5'h0) && (seq_counter[9:5]!=5'h1c);
334  last_bit_ext <= en && (last_bit || (last_bit_ext && !(clk_en[2] && !seq_counter[0])));
335 
338  if (imu_start) imu_in_word[4:0] <= 5'h0;
339  else if (imu_wr_buf) imu_in_word[4:0] <= imu_in_word[4:0] + 1;
340 
341  last_buf_wr <= (pre_imu_wr_buf && (seq_state[1:0]==2'h3));
342 
343  end
344 
345  always @ (negedge xclk) begin
346  sngl_wire_r[1] <= sngl_wire_stb[0];
347  end
348 
349  always @ (posedge xclk) begin
350 
351  if (!en || imu_start) raddr[4:0] <= 5'h0;
352  else if (rd_stb) raddr[4:0] <= raddr[4:0] + 1;
353 
354  if (imu_start || (rd_stb && (raddr[4:0]==5'h1b)) || !en) rdy_r <= 1'b0; // only 28 words, not 32
355  else if (last_buf_wr) rdy_r <= 1'b1;
356 
357  ts_r <=imu_start;
358 
359  end
360 
361  assign imu_in_buf[15:0]= miso_reg[15:0];
362 
363 /*
364  myRAM_WxD_D #( .DATA_WIDTH(6),.DATA_DEPTH(5))
365  i_registers2log (.D(di_d[6:1]),
366  .WE(we_ra),
367  .clk(!mclk),
368  .AW(wa[4:0]),
369  .AR(reg_seq_number[4:0]),
370  .QW(),
371  .QR(imu_reg_number[6:1]));
372 */
373  reg [5:0] registers2log_ram[0:31];
374  always @ (posedge mclk) if (we_ra) begin
375  registers2log_ram[wa[4:0]] <= din[6:1];
376  end
377  assign imu_reg_number[6:1] = registers2log_ram[reg_seq_number[4:0]];
378 /*
379  myRAM_WxD_D #( .DATA_WIDTH(16),.DATA_DEPTH(5))
380  i_odbuf0 (.D(imu_in_buf[15:0]),
381  .WE(imu_wr_buf),
382  .clk(xclk),
383  .AW(imu_in_word[4:0]),
384  .AR(raddr[4:0]),
385  .QW(),
386  .QR(rdata[15:0]));
387 */
388  reg [15:0] odbuf0_ram[0:31];
389  always @ (posedge xclk) if (imu_wr_buf) begin
390  odbuf0_ram[imu_in_word[4:0]] <= imu_in_buf[15:0];
391  end
392  assign rdata[15:0] = odbuf0_ram[raddr[4:0]];
393 
394 
395 endmodule
396 
3673period_counterreg[31:0]
Definition: imu_spi393.v:133
3692pre_sclreg
Definition: imu_spi393.v:154
3646set_mosi_spireg
Definition: imu_spi393.v:101
3635imu_in_wordreg[4:0]
Definition: imu_spi393.v:91
3684set_stallreg
Definition: imu_spi393.v:144
3634clk_divreg[1:0]
Definition: imu_spi393.v:90
3677first_prepare_dreg[1:0]
Definition: imu_spi393.v:137
3676first_preparereg
Definition: imu_spi393.v:136
3695sngl_wirewire
Definition: imu_spi393.v:157
3685skip_stallreg
Definition: imu_spi393.v:145
3669imu_start_mclkreg
Definition: imu_spi393.v:129
3667imu_when_readyreg[1:0]
Definition: imu_spi393.v:126
3640imu_reg_numberwire[6:1]
Definition: imu_spi393.v:96
3681stall_durreg[7:0]
Definition: imu_spi393.v:141
3643end_spireg
Definition: imu_spi393.v:100
3650sda_rreg[1:0]
Definition: imu_spi393.v:105
3694sngl_wire_rreg[1:0]
Definition: imu_spi393.v:156
3671imu_start_firstreg
Definition: imu_spi393.v:131
3688imu_ready_denoise_countreg[6:0]
Definition: imu_spi393.v:149
3670imu_start_grantreg[1:0]
Definition: imu_spi393.v:130
3645set_mosi_preparereg
Definition: imu_spi393.v:101
3683stall_cntrreg[7:0]
Definition: imu_spi393.v:143
3658rdy_rreg
Definition: imu_spi393.v:114
[31:0] 3617din
Definition: imu_spi393.v:50
[ 4:0] 3616wa
Definition: imu_spi393.v:49
3672imu_start_first_wasreg
Definition: imu_spi393.v:132
3630bit_durationreg[7:0]
Definition: imu_spi393.v:85
3629bit_duration_mclkreg[7:0]
Definition: imu_spi393.v:84
3666imu_when_ready_mclkreg
Definition: imu_spi393.v:125
3662imu_enabled_mclkreg
Definition: imu_spi393.v:121
3687imu_ready_resetreg
Definition: imu_spi393.v:148
3642seq_counterreg[9:0]
Definition: imu_spi393.v:99
3636pre_imu_wr_bufreg
Definition: imu_spi393.v:92
3631bit_duration_cntrreg[7:0]
Definition: imu_spi393.v:86
3639reg_seq_numberreg[4:0]
Definition: imu_spi393.v:95
3661periodreg[31:0]
Definition: imu_spi393.v:118
3668imu_run_confirmedreg
Definition: imu_spi393.v:128
3649mosi_regreg[15:0]
Definition: imu_spi393.v:103
3656last_buf_wrreg
Definition: imu_spi393.v:112
3637imu_wr_bufreg
Definition: imu_spi393.v:92
3655last_bit_extreg
Definition: imu_spi393.v:111
3696config_single_wirewire
Definition: imu_spi393.v:158
3691seq_state_zeroreg[1:0]
Definition: imu_spi393.v:152
[0:31] 3698odbuf0_ramreg[15:0]
Definition: imu_spi393.v:388
3682stallreg
Definition: imu_spi393.v:142
3651scl_rreg[1:0]
Definition: imu_spi393.v:106
3657raddrreg[4:0]
Definition: imu_spi393.v:113
3675we_timerreg[4:01]
Definition: imu_spi393.v:135
3638imu_in_bufwire[15:0]
Definition: imu_spi393.v:93
3664imu_run_mclkreg
Definition: imu_spi393.v:123
3648pre_seq_counter_zeroreg
Definition: imu_spi393.v:102
3679config_late_clkwire
Definition: imu_spi393.v:139
3647seq_counter_zeroreg
Definition: imu_spi393.v:102
3680stall_dur_mclkreg[7:0]
Definition: imu_spi393.v:140
3690imu_data_readyreg[5:0]
Definition: imu_spi393.v:151
3689imu_data_ready_dreg[2:0]
Definition: imu_spi393.v:150
3665imu_runreg[1:0]
Definition: imu_spi393.v:124
3652shift_misoreg
Definition: imu_spi393.v:108
3678config_long_sda_enwire
Definition: imu_spi393.v:138
3674enwire
Definition: imu_spi393.v:134
3641seq_statereg[1:0]
Definition: imu_spi393.v:98
3693sngl_wire_stbreg[2:0]
Definition: imu_spi393.v:155
[15:0] 3628rdata
Definition: imu_spi393.v:61
[ 3:0] 3620config_debug
Definition: imu_spi393.v:53
3644end_preparereg
Definition: imu_spi393.v:100
3686shift_mosiwire
Definition: imu_spi393.v:146
3654last_bitreg
Definition: imu_spi393.v:110
3653miso_regreg[15:0]
Definition: imu_spi393.v:109
3632bit_duration_zeroreg
Definition: imu_spi393.v:87
3659imu_startreg
Definition: imu_spi393.v:115
3633clk_enreg[3:0]
Definition: imu_spi393.v:89
[0:31] 3697registers2log_ramreg[5:0]
Definition: imu_spi393.v:373
3663imu_enabledreg[1:0]
Definition: imu_spi393.v:122