x393  1.0
FPGAcodeforElphelNC393camera
sens_hispi12l4.v
Go to the documentation of this file.
1 
39 `timescale 1ns/1ps
40 
42  parameter IODELAY_GRP = "IODELAY_SENSOR",
43  parameter integer IDELAY_VALUE = 0,
44  parameter real REFCLK_FREQUENCY = 200.0,
45  parameter HIGH_PERFORMANCE_MODE = "FALSE",
46  parameter SENS_PHASE_WIDTH= 8, // number of bits for te phase counter (depends on divisors)
47 // parameter SENS_PCLK_PERIOD = 3.000, // input period in ns, 0..100.000 - MANDATORY, resolution down to 1 ps
48  parameter SENS_BANDWIDTH = "OPTIMIZED", //"OPTIMIZED", "HIGH","LOW"
49 
50  parameter CLKIN_PERIOD_SENSOR = 3.000, // input period in ns, 0..100.000 - MANDATORY, resolution down to 1 ps
51  parameter CLKFBOUT_MULT_SENSOR = 3, // 330 MHz --> 990 MHz
52  parameter CLKFBOUT_PHASE_SENSOR = 0.000, // CLOCK FEEDBACK phase in degrees (3 significant digits, -360.000...+360.000)
53  parameter IPCLK_PHASE = 0.000,
54  parameter IPCLK2X_PHASE = 0.000,
55  parameter BUF_IPCLK = "BUFR",
56  parameter BUF_IPCLK2X = "BUFR",
57 
58  parameter SENS_DIVCLK_DIVIDE = 1, // Integer 1..106. Divides all outputs with respect to CLKIN
59  parameter SENS_REF_JITTER1 = 0.010, // Expected jitter on CLKIN1 (0.000..0.999)
60  parameter SENS_REF_JITTER2 = 0.010,
61  parameter SENS_SS_EN = "FALSE", // Enables Spread Spectrum mode
62  parameter SENS_SS_MODE = "CENTER_HIGH",//"CENTER_HIGH","CENTER_LOW","DOWN_HIGH","DOWN_LOW"
63  parameter SENS_SS_MOD_PERIOD = 10000, // integer 4000-40000 - SS modulation period in ns
64 
65  parameter DEFAULT_LANE_MAP = 8'b11100100, // one-to-one map (or make it 8'b00111001 ?)
66  parameter HISPI_MSB_FIRST = 0,
67  parameter HISPI_NUMLANES = 4,
68  parameter HISPI_DELAY_CLK = "FALSE",
69  parameter HISPI_MMCM = "TRUE",
70  parameter HISPI_KEEP_IRST = 5, // number of cycles to keep irst on after release of prst (small number - use 1 hot)
71  parameter HISPI_WAIT_ALL_LANES = 4'h8, // number of output pixel cycles to wait after the earliest lane
72  parameter HISPI_FIFO_DEPTH = 4,
73  parameter HISPI_FIFO_START = 7,
74  parameter HISPI_CAPACITANCE = "DONT_CARE",
75  parameter HISPI_DIFF_TERM = "TRUE",
76  parameter HISPI_UNTUNED_SPLIT = "FALSE", // Very power-hungry
77  parameter HISPI_DQS_BIAS = "TRUE",
78  parameter HISPI_IBUF_DELAY_VALUE = "0",
79  parameter HISPI_IBUF_LOW_PWR = "TRUE",
80  parameter HISPI_IFD_DELAY_VALUE = "AUTO",
81  parameter HISPI_IOSTANDARD = "DIFF_SSTL18_I" //"DIFF_SSTL18_II" for high current (13.4mA vs 8mA),
82 )(
83  input pclk, // global clock input, pixel rate (220MHz for MT9F002)
84  input prst, // reset @pclk (add sensor reset here)
85  // I/O pads
86  input [HISPI_NUMLANES-1:0] sns_dp,
87  input [HISPI_NUMLANES-1:0] sns_dn,
88  input sns_clkp,
89  input sns_clkn,
90  // output
91 // output reg [11:0] pxd_out,
92  output [11:0] pxd_out,
93 // output reg vact_out,
94  output hact_out,
95  output sof, // @pclk
96  output reg eof, // @pclk
97 
98  // delay control inputs
99  input mclk,
100  input mrst,
101  input [HISPI_NUMLANES * 8-1:0] dly_data, // delay value (3 LSB - fine delay) - @posedge mclk
102  input set_lanes_map, // set number of physical lane for each logical one
104  input [HISPI_NUMLANES-1:0] set_idelay, // mclk synchronous load idelay value
105  input ld_idelay, // mclk synchronous set idealy value
106  input set_clk_phase, // mclk synchronous set idealy value
107  input rst_mmcm,
108  input ignore_embedded, // ignore lines with embedded data
109 // input wait_all_lanes, // when 0 allow some lanes missing sync (for easier phase adjustment)
110  // MMCP output status
111  output ps_rdy, // output
112  output [7:0] ps_out, // output[7:0] reg
114  output clkin_pxd_stopped_mmcm, // output
115  output clkfb_pxd_stopped_mmcm // output
116 
117 );
118  wire ipclk; // re-generated half HiSPi clock (165 MHz)
119  wire ipclk2x;// re-generated HiSPi clock (330 MHz)
120  wire [HISPI_NUMLANES * 4-1:0] sns_d;
121 // localparam WAIT_ALL_LANES = 4'h8; // number of output pixel cycles to wait after the earliest lane
122 // localparam FIFO_DEPTH = 4;
124  wire irst = irst_r[0];
125  reg [HISPI_NUMLANES * 2-1:0] lanes_map;
129  always @ (posedge mclk) begin
130  if (mrst) lanes_map <= DEFAULT_LANE_MAP; //{2'h3,2'h2,2'h1,2'h0}; // 1-to-1 default map
131  else if (set_lanes_map) lanes_map <= dly_data[HISPI_NUMLANES * 2-1:0];
132 
135  end
136 
137 //non-parametrized lane switch (4x4)
138  always @(posedge ipclk) begin
139  logical_lanes4[ 3: 0] <= sns_d[{lanes_map[1:0],2'b0} +:4];
140  logical_lanes4[ 7: 4] <= sns_d[{lanes_map[3:2],2'b0} +:4];
141  logical_lanes4[11: 8] <= sns_d[{lanes_map[5:4],2'b0} +:4];
142  logical_lanes4[15:12] <= sns_d[{lanes_map[7:6],2'b0} +:4];
143  end
144 
145  always @(posedge ipclk) begin
147  end
148 
157  .BUF_IPCLK (BUF_IPCLK),
169 
172 
180  ) sens_hispi_clock_i (
181  .mclk (mclk), // input
182  .mrst (mrst), // input
183  .phase (dly_data[7:0]), // input[7:0]
184  .set_phase (set_clk_phase), // input
185  .load (ld_idelay), // input
186  .rst_mmcm (rst_mmcm), // input
187  .clp_p (sns_clkp), // input
188  .clk_n (sns_clkn), // input
189  .ipclk (ipclk), // output
190  .ipclk2x (ipclk2x), // output
191  .ps_rdy (ps_rdy), // output
192  .ps_out (ps_out), // output[7:0]
193  .locked_pxd_mmcm (locked_pxd_mmcm), // output
196  );
197 
212  ) sens_hispi_din_i (
213  .mclk (mclk), // input
214  .mrst (mrst), // input
215  .dly_data (dly_data), // input[31:0]
216  .set_idelay (set_idelay), // input[3:0]
217  .ld_idelay (ld_idelay), // input
218  .ipclk (ipclk), // input
219  .ipclk2x (ipclk2x), // input
220  .irst (irst), // input
221 //`ifdef REVERSE_LANES
222 // .din_p ({sns_dp[0],sns_dp[1],sns_dp[2],sns_dp[3]}), // input[3:0]
223 // .din_n ({sns_dn[0],sns_dn[1],sns_dn[2],sns_dn[3]}), // input[3:0]
224 //`else
225  .din_p (sns_dp), // input[3:0]
226  .din_n (sns_dn), // input[3:0]
227 //`endif
228  .dout (sns_d) // output[15:0]
229  );
230 
231 
232 
233  wire [HISPI_NUMLANES * 12-1:0] hispi_aligned;
240  // TODO - try to make that something will be recorded even if some lanes are bad (to simplify phase adjust
241  // possibly - extra control bit (wait_all_lanes)
242  // use earliest SOF
244  reg [1:0] vact_pclk_strt;
245  wire [HISPI_NUMLANES-1:0] rd_run;
246  reg rd_line; // combine all lanes
250  reg sof_pclk;
251 // wire [HISPI_NUMLANES-1:0] sol_pclk = rd_run & ~rd_run_d;
252  wire sol_pclk = |(rd_run & ~rd_run_d); // possibly multi-cycle
253  reg start_fifo_re; // start reading FIFO - single-cycle
254  reg [HISPI_NUMLANES-1:0] good_lanes; // lanes that started active line OK
257  reg hact_r;
258  wire [HISPI_NUMLANES * 12-1:0] fifo_out;
259  wire hact_on;
260  wire hact_off;
262  reg [1:0] vact_pclk;
263  wire [11:0] pxd_out_pre = ({12 {fifo_re_r[0] & rd_run[0]}} & fifo_out[0 * 12 +:12]) |
264  ({12 {fifo_re_r[1] & rd_run[1]}} & fifo_out[1 * 12 +:12]) |
265  ({12 {fifo_re_r[2] & rd_run[2]}} & fifo_out[2 * 12 +:12]) |
266  ({12 {fifo_re_r[3] & rd_run[3]}} & fifo_out[3 * 12 +:12]);
267 
268 
269 
270 
271  assign hact_out = hact_r;
272  assign sof = sof_pclk;
273 
274  // async reset
275  always @ (posedge ipclk or posedge prst) begin
276  if (prst) irst_r <= {HISPI_KEEP_IRST{1'b1}}; // HISPI_KEEP_IRST-1
277  else irst_r <= irst_r >> 1;
278  end
279 
280 
281 
282  always @(posedge ipclk) begin
283 // irst_r <= {irst_r[1:0], prst};
284 
285  if (irst || (|hispi_eof)) vact_ipclk <= 0; // extend output if hact active
286  else if (|hispi_sof) vact_ipclk <= 1;
287 
289  end
290 
291  always @(posedge pclk) begin
292  if (prst || !vact_ipclk) vact_pclk_strt <= 0;
293  else vact_pclk_strt <= {vact_pclk_strt[0], 1'b1};
294 
295  rd_run_d <= rd_run;
296 
297  start_fifo_re <= sol_pclk && !rd_line; // sol_pclk may be multi-cycle
298 
299  sof_pclk <= vact_pclk_strt[0] && ! vact_pclk_strt[1];
300 
301  if (prst || sof_pclk) rd_line <= 0;
302  else if (sol_pclk) rd_line <= 1;
303  else rd_line <= rd_line & (&(~good_lanes | rd_run)); // Off when first of the good lanes goes off
304 
305  rd_line_r <= rd_line;
306 
307  if (sol_pclk && !rd_line) good_lanes <= ~rd_run_d; // should be off before start
308  else if (sol_all_dly) good_lanes <= good_lanes & rd_run; // and now they should be on
309 
310  fifo_re_r <= fifo_re & rd_run; // when data out is ready, mask if not running
311 
312  // not using HISPI_NUMLANES here - fix? Will be 0 (not possible in hispi) when no data
313 /* pxd_out <= ({12 {fifo_re_r[0] & rd_run[0]}} & fifo_out[0 * 12 +:12]) |
314  ({12 {fifo_re_r[1] & rd_run[1]}} & fifo_out[1 * 12 +:12]) |
315  ({12 {fifo_re_r[2] & rd_run[2]}} & fifo_out[2 * 12 +:12]) |
316  ({12 {fifo_re_r[3] & rd_run[3]}} & fifo_out[3 * 12 +:12]); **/
317 
318  if (prst) fifo_re <= 0;
319 // else if (sol_pclk || (rd_line && fifo_re[HISPI_NUMLANES - 1])) fifo_re <= 1;
320  else if (start_fifo_re || (rd_line && fifo_re[HISPI_NUMLANES - 1])) fifo_re <= 1;
321  else fifo_re <= fifo_re << 1;
322 
323 // if (prst || (hact_off && (|(good_lanes & ~rd_run)))) hact_r <= 0;
324  if (prst || (hact_off && (!rd_line || (good_lanes[3] & ~rd_run[3])))) hact_r <= 0;
325  else if (hact_on) hact_r <= 1;
326 
327  vact_pclk <= {vact_pclk[0],vact_pclk_strt [0] || hact_r};
328  eof <= vact_pclk[1] && !vact_pclk[0];
329 // vact_out <= vact_pclk_strt [0] || hact_r;
330  end
331 
333  .WIDTH(1)
334  ) dly_16_start_line_i (
335  .clk (pclk), // input
336  .rst (1'b0), // input
337  .dly (HISPI_WAIT_ALL_LANES), // input[3:0]
338  .din (rd_line && !rd_line_r), // input[0:0]
339  .dout (sol_all_dly) // output[0:0]
340  );
341 
343  .WIDTH(1)
344  ) dly_16_hact_on_i (
345  .clk (pclk), // input
346  .rst (1'b0), // input
347 // .dly (4'h2), // input[3:0]
348 // .dly (4'h3), // input[3:0]
349  .dly (4'h1), // input[3:0]
350 // .dly (4'h2), // input[3:0]
351  .din (sol_pclk), // input[0:0]
352  .dout (hact_on) // output[0:0]
353  );
354 
356  .WIDTH(1)
357  ) dly_16_hact_off_i (
358  .clk (pclk), // input
359  .rst (1'b0), // input
360 // .dly (4'h2), // input[3:0]
361 // .dly (4'h0), // input[3:0]
362  .dly (4'h1), // input[3:0]
363 // .dly (4'h2), // input[3:0]
364  .din (fifo_re[HISPI_NUMLANES - 1]), // input[0:0]
365  .dout (hact_off) // output[0:0]
366  );
367 
369  .WIDTH(12)
370  ) dly_16_pxd_out_i (
371  .clk (pclk), // input
372  .rst (1'b0), // input
373 // .dly (4'h2), // input[3:0]
374  .dly (4'h0), // input[3:0]
375 // .dly (4'h1), // input[3:0]
376  .din (pxd_out_pre), // input[0:0]
377  .dout (pxd_out) // output[0:0]
378  );
379 
380  generate
381  genvar i;
382  for (i=0; i < 4; i=i+1) begin: hispi_lane
385  ) sens_hispi_lane_i (
386  .ipclk (ipclk), // input
387  .irst (irst), // input
388  .din (logical_lanes4[4*i +: 4]), // input[3:0]
389  .dout (hispi_aligned[12*i +: 12]), // output[3:0] reg
390  .dv (hispi_dv[i]), // output reg
391  .embed (hispi_embed[i]), // output reg
392  .sof (hispi_sof[i]), // output reg
393  .eof (hispi_eof[i]), // output reg
394  .sol (hispi_sol[i]), // output reg
395  .eol (hispi_eol[i]) // output reg
396  );
398 // .COUNT_START (HISPI_FIFO_START),
399  .DATA_WIDTH (12),
400  .DATA_DEPTH (HISPI_FIFO_DEPTH)
401  ) sens_hispi_fifo_i (
402  .ipclk (ipclk), // input
403  .irst (irst), // input
404  .we (hispi_dv[i]), // input
405  .sol (hispi_sol[i] && !(hispi_embed[i] && ignore_embedded_ipclk)), // input
406  .eol (hispi_eol[i]), // input
407  .din (hispi_aligned[12*i +: 12]), // input[11:0]
408  .out_dly (fifo_out_dly), // input[3:0]
409  .pclk (pclk), // input
410  .prst (prst), // input
411  .re (fifo_re[i]), // input
412  .dout (fifo_out[12*i +: 12]), // output[11:0] reg
413  .run (rd_run[i]) // output
414  );
415 
416  end
417  endgenerate
418 
419 endmodule
420 
7121fifo_out_dlyreg[HISPI_FIFO_DEPTH-1:0]
7083HISPI_DQS_BIAS"TRUE"
7115sns_dwire[HISPI_NUMLANES*4-1:0]
7066SENS_REF_JITTER10.010
10332clk
Definition: dly_16.v:44
7130vact_pclk_strtreg[1:0]
[HISPI_NUMLANES-1:0] 7091sns_dn
sens_hispi_fifo_i sens_hispi_fifo[generate]
sens_hispi_clock_i sens_hispi_clock
7067SENS_REF_JITTER20.010
7123hispi_dvwire[HISPI_NUMLANES-1:0]
reg [11:0] 7257dout
7080HISPI_CAPACITANCE"DONT_CARE"
7060CLKFBOUT_PHASE_SENSOR0.000
7077HISPI_WAIT_ALL_LANES4'h8
[DATA_WIDTH-1:0] 7236din
[HISPI_NUMLANES-1:0] 7225din_n
7074HISPI_DELAY_CLK"FALSE"
7143fifo_outwire[HISPI_NUMLANES*12-1:0]
7075HISPI_MMCM"TRUE"
7131rd_runwire[HISPI_NUMLANES-1:0]
dly_16_pxd_out_i dly_16
7139good_lanesreg[HISPI_NUMLANES-1:0]
reg [DATA_WIDTH-1:0] 7241dout
7140fifo_rereg[HISPI_NUMLANES-1:0]
7120fifo_out_dly_mclkreg[HISPI_FIFO_DEPTH-1:0]
[HISPI_NUMLANES-1:0] 7219set_idelay
7068SENS_SS_EN"FALSE"
[11:0] 7094pxd_out
7141fifo_re_rreg[HISPI_NUMLANES-1:0]
7135rd_run_dreg[HISPI_NUMLANES-1:0]
7148pxd_out_prewire[11:0]
7052IODELAY_GRP"IODELAY_SENSOR"
7116irst_rreg[HISPI_KEEP_IRST-1:0]
7128hispi_eolwire[HISPI_NUMLANES-1:0]
7057SENS_BANDWIDTH"OPTIMIZED"
[WIDTH-1:0] 10336dout
Definition: dly_16.v:48
7087HISPI_IOSTANDARD"DIFF_SSTL18_I"
7127hispi_solwire[HISPI_NUMLANES-1:0]
7070SENS_SS_MOD_PERIOD10000
7126hispi_eofwire[HISPI_NUMLANES-1:0]
7085HISPI_IBUF_LOW_PWR"TRUE"
[WIDTH-1:0] 10335din
Definition: dly_16.v:47
7081HISPI_DIFF_TERM"TRUE"
7146ignore_embedded_ipclkreg
7069SENS_SS_MODE"CENTER_HIGH"
[HISPI_NUMLANES * 8-1:0] 7218dly_data
[HISPI_NUMLANES * 4-1:0] 7226dout
sens_hispi_lane_i sens_hispi_lane[generate]
7084HISPI_IBUF_DELAY_VALUE"0"
[HISPI_NUMLANES-1:0] 7224din_p
7122hispi_alignedwire[HISPI_NUMLANES*12-1:0]
7125hispi_sofwire[HISPI_NUMLANES-1:0]
7118lanes_mapreg[HISPI_NUMLANES*2-1:0]
7058CLKIN_PERIOD_SENSOR3.000
7055HIGH_PERFORMANCE_MODE"FALSE"
sens_hispi_din_i sens_hispi_din
7071DEFAULT_LANE_MAP8'b11100100
integer 7053IDELAY_VALUE0
7062IPCLK2X_PHASE0.000
7064BUF_IPCLK2X"BUFR"
[HISPI_NUMLANES * 8-1:0] 7100dly_data
7147vact_pclkreg[1:0]
[HISPI_NUMLANES-1:0] 7103set_idelay
[DATA_DEPTH-1:0] 7237out_dly
7086HISPI_IFD_DELAY_VALUE"AUTO"
7124hispi_embedwire[HISPI_NUMLANES-1:0]
real 7054REFCLK_FREQUENCY200.0
7119logical_lanes4reg[HISPI_NUMLANES*4-1:0]
10333rst
Definition: dly_16.v:45
[HISPI_NUMLANES-1:0] 7090sns_dp
[3:0] 10334dly
Definition: dly_16.v:46
7082HISPI_UNTUNED_SPLIT"FALSE"