x393  1.0
FPGAcodeforElphelNC393camera
sens_hispi_lane.v
Go to the documentation of this file.
1 
39 `timescale 1ns/1ps
40 
42  parameter HISPI_MSB_FIRST = 0
43 )(
44  input ipclk, // half HiSPi recovered clock (165 MHz for 660 bps of MT9F002)
45  input irst, // reset sync to ipclk
46  input [3:0] din, // @posedge ipclk, din[3] came first
47  output reg [11:0] dout, // 12-bit data output
48  output reg dv, // data valid - continuous marks line
49  output reg embed, // valid @sol and up through all dv
50  output reg sof, // always before first sol - not instead of
51  output reg eof, // always after last eol (not instead of)
52  output reg sol, // start of line - 1 cycle before dv
53  output reg eol // end of line - last dv
54 );
55  localparam [3:0] SYNC_SOF = HISPI_MSB_FIRST ? 4'h3 : 4'hc;
56  localparam [3:0] SYNC_SOL = HISPI_MSB_FIRST ? 4'h1 : 4'h8;
57  localparam [3:0] SYNC_EOF = HISPI_MSB_FIRST ? 4'h7 : 4'he;
58 // localparam [3:0] SYNC_EOL = 6;
59 
60  localparam [3:0] SYNC_EMBED = HISPI_MSB_FIRST ? 4'h1 : 4'h8; // other nibble (bit 4)
61 
62  localparam LSB_INDEX = HISPI_MSB_FIRST ? 2 : 0; // nibble number in 12-bit word
63  localparam MSB_INDEX = HISPI_MSB_FIRST ? 0 : 2; // nibble number in 12-bit word
64 
65 
66  reg [3:0] d_r; // rehistered input data
67  wire [2:0] num_trail_0_w; // number of trailing 0-s in the last nibble
68  wire [2:0] num_lead_0_w; // number of leading 0-s in the last nibble
69  wire [2:0] num_trail_1_w; // number of trailing 1-s in the last nibble
70  wire [2:0] num_lead_1_w; // number of leading 1-s in the last nibble
72  reg [3:0] num_running_ones;
73  reg [4:0] num_running_zeros; // after sufficient ones
74  reg prev4ones; // previous data nibble was 4'hf
75  reg [1:0] num_first_zeros; // number of zeros in a first nibble after all ones
76  reg [1:0] shift_val; // barrel shifter select (0 is 4!)
78  reg got_sync; // Got 24 zeros after >=16 1-s
79  reg [3:0] barrel;
80  reg [3:0] sync_decode; // 1-hot decoding of the last sync word
81 
82  reg got_sof;
83  reg got_eof;
84  reg got_sol;
85 // reg got_eol;
86  reg got_embed;
87 
88  reg [2:0] pre_dv;
89  wire [3:0] dout_w;
92  wire start_line_d; // delayed just to turn on pre_dv;
93 
94 
95  assign num_trail_0_w = (|din) ? ((|din[2:0]) ? ((|din[1:0]) ? (din[0] ? 3'h0 : 3'h1) : 3'h2) : 3'h3) : 3'h4;
96  assign num_lead_0_w = (|din) ? ((|din[3:1]) ? ((|din[3:2]) ? (din[3] ? 3'h0 : 3'h1) : 3'h2) : 3'h3) : 3'h4;
97 
98  assign num_trail_1_w = (&din) ? 3'h4 : ((&din[2:0]) ? 3'h3 : ((&din[1:0]) ? 3'h2 :((&din[0]) ? 3'h1 : 3'h0)));
99  assign num_lead_1_w = (&din) ? 3'h4 : ((&din[3:1]) ? 3'h3 : ((&din[3:2]) ? 3'h2 :((&din[3]) ? 3'h1 : 3'h0)));
100 // assign zero_after_ones_w = !((din[0] && !din[1]) || (din[1] && !din[2]) || (din[2] && !din[3]) || (d_r[3] && !din[0]));
101  assign zero_after_ones_w = !((din[0] && !din[1]) || (din[1] && !din[2]) || (din[2] && !din[3]) || (din[3] && !d_r[0]));
102 
103  always @(posedge ipclk) begin
104  d_r <= din;
105  prev4ones <= num_trail_1_w[2];
106 
107  if (prev4ones && !num_trail_1_w[2]) num_first_zeros <= num_trail_0_w[1:0]; // 4 will be 0
108  // first stage - get at least 12 consecutive 1-s, expecting many consecutive 0-s after, so any
109  // 1 after zero should restart counting.
110  if (irst) num_running_ones <= 0;
111  else if ((num_running_ones == 0) || !zero_after_ones_w) num_running_ones <= {1'b0,num_trail_1_w};
112  // keep number of running 1-s saturated to 12 (to prevent roll over). Temporary there could be 13..15
113  // When running 1-s turn to running zeros, the count will not reset and stay on through counting
114  // of 0-s (will only reset by 1 after 0)
115  else num_running_ones <= (&num_running_ones[3:2]) ? 4'hc :
116  (num_running_ones + {1'b0, num_lead_1_w});
117  // Now count consecutive 0-s after (>=12) 1-s. Not using zero_after_ones in the middle of the run - will
118  // rely on the number of running ones being reset in that case
119  // Saturate number with 24 (5'h18), but only first transition from <24 to >=24 is used for sync
120  // detection.
121  if (irst || !num_running_ones[3]) num_running_zeros <= 0;
122 // else if (!num_running_ones[2]) num_running_zeros <= {2'b0,num_trail_0_w};
123  else if (prev4ones) num_running_zeros <= {2'b0,num_trail_0_w};
125 
126  if (irst) got_sync <= 0;
127  else got_sync <= got_sync_w;
128 
129  // got_sync should also abort data run - delayed by 10 clocks
130 
131  if (irst) shift_val <= 0;
132 // else if (got_sync) shift_val <= num_first_zeros;
133  else if (got_sync_w) shift_val <= num_first_zeros;
134 
135  case (shift_val)
136  2'h0: barrel <= din;
137 // 2'h1: barrel <= {d_r[2:0], din[3]};
138  2'h1: barrel <= {d_r[0], din[3:1]};
139  2'h2: barrel <= {d_r[1:0], din[3:2]};
140 // 2'h3: barrel <= {d_r[0], din[3:1]};
141  2'h3: barrel <= {d_r[2:0], din[3]};
142  endcase
143 
144  if (irst) sync_decode <= 0;
145  else if (got_sync) sync_decode <= 4'h1;
146  else sync_decode <= sync_decode << 1;
147 
148  if (got_sync) got_sof <= 0;
149  else if (sync_decode[LSB_INDEX] && (barrel == SYNC_SOF)) got_sof <= 1;
150 
151  if (got_sync) got_eof <= 0;
152  else if (sync_decode[LSB_INDEX] && (barrel == SYNC_EOF)) got_eof <= 1;
153 
154  if (got_sync) got_sol <= 0;
155  else if (sync_decode[LSB_INDEX] && (barrel == SYNC_SOL)) got_sol <= 1;
156 
157 // if (got_sync) got_eol <= 0;
158 // else if (sync_decode[LSB_INDEX] && (barrel == SYNC_EOL)) got_eol <= 1;
159 
160  if (got_sync) got_embed <= 0;
161  else if (sync_decode[1] && (barrel == SYNC_EMBED)) got_embed <= 1;
162 
163  if (irst) dout[ 3:0] <= 0;
164  else if (pre_dv[LSB_INDEX]) dout[ 3:0] <= dout_w;
165 
166  if (irst) dout[ 7:4] <= 0;
167  else if (pre_dv[1]) dout[ 7:4] <= dout_w;
168 
169  if (irst) dout[11:8] <= 0;
170  else if (pre_dv[MSB_INDEX]) dout[11:8] <= dout_w;
171 
172  if (irst || got_sync) pre_dv <= 0;
173  else if (start_line_d) pre_dv <= 1;
174  else pre_dv <= {pre_dv[1:0],pre_dv[2]};
175 
176  if (irst) dv <= 0;
177  else dv <= pre_dv[2];
178 
179  if (irst) sol <= 0;
180  else sol <= start_line_d;
181 
182  if (irst) eol <= 0;
183  else eol <= got_sync && (|pre_dv);
184 
185  if (irst) sof <= 0;
186  else sof <= sync_decode[3] && got_sof;
187 
188  if (irst) eof <= 0;
189  else eof <= sync_decode[3] && got_eof;
190 
191  if (irst) embed <= 0;
192  else if (sync_decode[3]) embed <= got_embed && (got_sof || got_sol);
193  end
194 
196  .WIDTH(4)
197  ) dly_16_dout_i (
198  .clk (ipclk), // input
199  .rst (1'b0), // input
200  .dly (4'h8), // input[3:0]
201  .din (HISPI_MSB_FIRST ? barrel :{barrel[0],barrel[1],barrel[2],barrel[3]}), // input[0:0]
202  .dout (dout_w) // output[0:0]
203  );
205  .WIDTH(1)
206  ) dly_16_pre_start_line_i (
207  .clk (ipclk), // input
208  .rst (1'b0), // input
209  .dly (4'h7), // input[3:0]
210  .din (start_line), // input[0:0]
211  .dout (start_line_d) // output[0:0]
212  );
213 
214 
215 endmodule
7272num_lead_0_wwire[2:0]
7274num_lead_1_wwire[2:0]
10332clk
Definition: dly_16.v:44
7291num_running_zeros_wwire[4:0]
reg [11:0] 7257dout
7271num_trail_0_wwire[2:0]
7284sync_decodereg[3:0]
7269MSB_INDEXHISPI_MSB_FIRST ? 0 : 2
[WIDTH-1:0] 10336dout
Definition: dly_16.v:48
[3:0] 7266SYNC_EOFHISPI_MSB_FIRST ? 4'h7 : 4'he
7273num_trail_1_wwire[2:0]
[WIDTH-1:0] 10335din
Definition: dly_16.v:47
[3:0] 7267SYNC_EMBEDHISPI_MSB_FIRST ? 4'h1 : 4'h8
7280shift_valreg[1:0]
[3:0] 7265SYNC_SOLHISPI_MSB_FIRST ? 4'h1 : 4'h8
7276num_running_onesreg[3:0]
7279num_first_zerosreg[1:0]
7290dout_wwire[3:0]
7268LSB_INDEXHISPI_MSB_FIRST ? 2 : 0
dly_16_pre_start_line_i dly_16
7277num_running_zerosreg[4:0]
[3:0] 7264SYNC_SOFHISPI_MSB_FIRST ? 4'h3 : 4'hc
10333rst
Definition: dly_16.v:45
[3:0] 10334dly
Definition: dly_16.v:46