Loading sensor/sens_hispi12l4.v +144 −1 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ module sens_hispi12l4#( parameter SENS_SS_MODE = "CENTER_HIGH",//"CENTER_HIGH","CENTER_LOW","DOWN_HIGH","DOWN_LOW" parameter SENS_SS_MOD_PERIOD = 10000, // integer 4000-40000 - SS modulation period in ns parameter HISPI_MSB_FIRST = 0, parameter HISPI_NUMLANES = 4, parameter HISPI_CAPACITANCE = "DONT_CARE", parameter HISPI_DIFF_TERM = "TRUE", Loading Loading @@ -76,6 +77,7 @@ module sens_hispi12l4#( input ld_idelay, // mclk synchronous set idealy value input set_clk_phase, // mclk synchronous set idealy value input rst_mmcm, // input wait_all_lanes, // when 0 allow some lanes missing sync (for easier phase adjustment) // MMCP output status output ps_rdy, // output output [7:0] ps_out, // output[7:0] reg Loading Loading @@ -154,7 +156,148 @@ module sens_hispi12l4#( .dout (sns_d) // output[15:0] ); localparam WAIT_ALL_LANES = 8; // number of output pixel cycles to wait after the earliest lane localparam FIFO_DEPTH = 4; wire [HISPI_NUMLANES * 12-1:0] hispi_aligned; wire [HISPI_NUMLANES-1:0] hispi_dv; wire [HISPI_NUMLANES-1:0] hispi_embed; wire [HISPI_NUMLANES-1:0] hispi_sof; wire [HISPI_NUMLANES-1:0] hispi_eof; wire [HISPI_NUMLANES-1:0] hispi_sol; wire [HISPI_NUMLANES-1:0] hispi_eol; // TODO - try to make that something will be recorded even if some lanes are bad (to simplify phase adjust // possibly - extra control bit (wait_all_lanes) // use earliest SOF reg vact_ipclk; reg [1:0] vact_pclk_strt; wire [HISPI_NUMLANES-1:0] rd_run; reg rd_line; // combine all lanes reg rd_line_r; wire sol_all_dly; reg [HISPI_NUMLANES-1:0] rd_run_d; reg sof_pclk; // wire [HISPI_NUMLANES-1:0] sol_pclk = rd_run & ~rd_run_d; wire sol_pclk = |(rd_run & ~rd_run_d); // possibly multi-cycle reg [HISPI_NUMLANES-1:0] good_lanes; // lanes that started active line OK reg [HISPI_NUMLANES-1:0] fifo_re; reg [HISPI_NUMLANES-1:0] fifo_re_r; reg hact_r; wire [HISPI_NUMLANES * 12-1:0] fifo_out; wire hact_on; wire hact_off; assign hact_out = hact_r; always @(posedge ipclk) begin if (irst || (|hispi_eof[i])) vact_ipclk <= 0; // extend output if hact active else if (|hispi_sof) vact_ipclk <= 1; end always @(posedge pclk) begin vact_pclk_strt <= {vact_pclk_strt[0],vact_ipclk}; rd_run_d <= rd_run; sof_pclk <= vact_pclk_strt[0] && ! vact_pclk_strt[1]; if (prst || sof_pclk) rd_line <= 0; else if (sol_pclk) rd_line <= 1; else rd_line <= rd_line & (&(~good_lanes | rd_run)); // Off when first of the good lanes goes off rd_line_r <= rd_line; if (sol_pclk && !rd_line) good_lanes <= ~rd_run; // should be off before start else if (sol_all_dly) good_lanes <= good_lanes & rd_run; // and now they should be on fifo_re_r <= fifo_re & rd_run; // when data out is ready, mask if not running // not using HISPI_NUMLANES here - fix? Will be 0 (not possible in hispi) when no data pxd_out <= ({12 {fifo_re_r[0]}} & fifo_out[0 * 12 +:12]) | ({12 {fifo_re_r[1]}} & fifo_out[1 * 12 +:12]) | ({12 {fifo_re_r[2]}} & fifo_out[2 * 12 +:12]) | ({12 {fifo_re_r[3]}} & fifo_out[3 * 12 +:12]); if (prst) fifo_re <= 0; else if (sol_pclk || (rd_line && fifo_re[HISPI_NUMLANES - 1])) fifo_re <= 1; else fifo_re <= fifo_re << 1; if (prst || hact_off) hact_r <= 0; else if (hact_on) hact_r <= 1; vact_out <= vact_pclk_strt [0] || hact_r; end dly_16 #( .WIDTH(1) ) dly_16_start_line_i ( .clk (pclk), // input .rst (1'b0), // input .dly (WAIT_ALL_LANES), // input[3:0] .din (rd_line && !rd_line_r), // input[0:0] .dout (sol_all_dly) // output[0:0] ); dly_16 #( .WIDTH(1) ) dly_16_hact_on_i ( .clk (pclk), // input .rst (1'b0), // input .dly (2), // input[3:0] .din (sol_pclk), // input[0:0] .dout (hact_on) // output[0:0] ); dly_16 #( .WIDTH(1) ) dly_16_hact_off_i ( .clk (pclk), // input .rst (1'b0), // input .dly (2), // input[3:0] .din (fifo_re[HISPI_NUMLANES - 1]), // input[0:0] .dout (hact_off) // output[0:0] ); generate genvar i; for (i=0; i < 4; i=i+1) begin: hispi_lane sens_hispi_lane #( .HISPI_MSB_FIRST(HISPI_MSB_FIRST) ) sens_hispi_lane_i ( .ipclk (ipclk), // input .irst (irst), // input .din (sns_d[4*i +: 4]), // input[3:0] .dout (hispi_aligned[12*i +: 12]), // output[3:0] reg .dv (hispi_dv[i]), // output reg .embed (hispi_embed[i]), // output reg .sof (hispi_sof[i]), // output reg .eof (hispi_eof[i]), // output reg .sol (hispi_sol[i]), // output reg .eol (hispi_eol[i]) // output reg ); sens_hispi_fifo #( .COUNT_START (7), .DATA_WIDTH (12), .DATA_DEPTH (FIFO_DEPTH) ) sens_hispi_fifo_i ( .ipclk (ipclk), // input .irst (irst), // input .we (hispi_dv[i]), // input .sol (hispi_sol[i]), // input .eol (hispi_eol[i]), // input .din (hispi_aligned[12*i +: 12]), // input[11:0] .pclk (pclk), // input .prst (prst), // input .re (fifo_re[i]), // input .dout (fifo_out[12*i +: 12]), // output[11:0] reg .run (rd_run[i]) // output ); end endgenerate endmodule sensor/sens_hispi_lane.v +36 −27 Original line number Diff line number Diff line Loading @@ -26,7 +26,7 @@ module sens_hispi_lane#( input ipclk, // half HiSPi recovered clock (165 MHz for 660 bps of MT9F002) input irst, // reset sync to ipclk input [3:0] din, // @posedge ipclk, din[3] came first output reg [3:0] dout, // data output, aligned (decide about bit order) output reg [11:0] dout, // 12-bit data output output reg dv, // data valid - continuous marks line output reg embed, // valid @sol and up through all dv output reg sof, // always before first sol - not instead of Loading @@ -40,7 +40,10 @@ module sens_hispi_lane#( // localparam [3:0] SYNC_EOL = 6; localparam [3:0] SYNC_EMBED = HISPI_MSB_FIRST ? 4'h1 : 4'h8; // other nibble (bit 4) localparam SYNC_NIBBLE = HISPI_MSB_FIRST ? 2 : 0; // decode which nibble of the last sync word localparam LSB_INDEX = HISPI_MSB_FIRST ? 2 : 0; // nibble number in 12-bit word localparam MSB_INDEX = HISPI_MSB_FIRST ? 0 : 2; // nibble number in 12-bit word reg [3:0] d_r; // rehistered input data wire [2:0] num_trail_0_w; // number of trailing 0-s in the last nibble Loading @@ -64,7 +67,7 @@ module sens_hispi_lane#( // reg got_eol; reg got_embed; reg pre_dv; reg [2:0] pre_dv; wire [3:0] dout_w; wire [4:0] num_running_zeros_w = num_running_zeros + {1'b0, num_lead_0_w}; wire start_line = sync_decode[3] && (got_sol || got_sof); Loading Loading @@ -120,34 +123,41 @@ module sens_hispi_lane#( else sync_decode <= sync_decode << 1; if (got_sync) got_sof <= 0; else if (sync_decode[SYNC_NIBBLE] && (barrel == SYNC_SOF)) got_sof <= 1; else if (sync_decode[LSB_INDEX] && (barrel == SYNC_SOF)) got_sof <= 1; if (got_sync) got_eof <= 0; else if (sync_decode[SYNC_NIBBLE] && (barrel == SYNC_EOF)) got_eof <= 1; else if (sync_decode[LSB_INDEX] && (barrel == SYNC_EOF)) got_eof <= 1; if (got_sync) got_sol <= 0; else if (sync_decode[SYNC_NIBBLE] && (barrel == SYNC_SOL)) got_sol <= 1; else if (sync_decode[LSB_INDEX] && (barrel == SYNC_SOL)) got_sol <= 1; // if (got_sync) got_eol <= 0; // else if (sync_decode[SYNC_NIBBLE] && (barrel == SYNC_EOL)) got_eol <= 1; // else if (sync_decode[LSB_INDEX] && (barrel == SYNC_EOL)) got_eol <= 1; if (got_sync) got_embed <= 0; else if (sync_decode[1] && (barrel == SYNC_EMBED)) got_embed <= 1; if (irst) dout <= 0; else dout <= dout_w; if (irst) dout[ 3:0] <= 0; else if (pre_dv[LSB_INDEX]) dout[ 3:0] <= dout_w; if (irst) dout[ 7:4] <= 0; else if (pre_dv[1]) dout[ 7:4] <= dout_w; if (irst) dout[11:8] <= 0; else if (pre_dv[MSB_INDEX]) dout[11:8] <= dout_w; if (irst || got_sync) pre_dv <= 0; else if (start_line_d) pre_dv <= 1; else pre_dv <= {pre_dv[1:0],pre_dv[2]}; if (irst) dv <= 0; else dv <= pre_dv; else dv <= pre_dv[2]; if (irst) sol <= 0; else sol <= start_line_d; if (irst) eol <= 0; else eol <= got_sync && pre_dv; else eol <= got_sync && (|pre_dv); if (irst) sof <= 0; else sof <= sync_decode[3] && got_sof; Loading Loading @@ -180,4 +190,3 @@ module sens_hispi_lane#( endmodule util_modules/fifo_cross_clocks.v +6 −5 Original line number Diff line number Diff line Loading @@ -82,12 +82,13 @@ module fifo_cross_clocks end always @ (posedge rclk or posedge rst) begin if (rst) raddr <= 0; else if (rrst) raddr <= 0; // making rrst set FIFO to empty regardless of current waddr (write should be stopped) if (rst) raddr <= waddr; // 0; else if (rrst) raddr <= waddr; // 0; else if (re) raddr <= raddr_plus1; if (rst) raddr_gray_top3 <= 0; else if (rrst) raddr_gray_top3 <= 0; if (rst) raddr_gray_top3 <= waddr[DATA_DEPTH-1 -: 3] ^ {1'b0,waddr[DATA_DEPTH-1 -: 2]}; // 0; else if (rrst) raddr_gray_top3 <= waddr[DATA_DEPTH-1 -: 3] ^ {1'b0,waddr[DATA_DEPTH-1 -: 2]}; // 0; else if (re) raddr_gray_top3 <= raddr_plus1_gray_top3; end Loading Loading
sensor/sens_hispi12l4.v +144 −1 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ module sens_hispi12l4#( parameter SENS_SS_MODE = "CENTER_HIGH",//"CENTER_HIGH","CENTER_LOW","DOWN_HIGH","DOWN_LOW" parameter SENS_SS_MOD_PERIOD = 10000, // integer 4000-40000 - SS modulation period in ns parameter HISPI_MSB_FIRST = 0, parameter HISPI_NUMLANES = 4, parameter HISPI_CAPACITANCE = "DONT_CARE", parameter HISPI_DIFF_TERM = "TRUE", Loading Loading @@ -76,6 +77,7 @@ module sens_hispi12l4#( input ld_idelay, // mclk synchronous set idealy value input set_clk_phase, // mclk synchronous set idealy value input rst_mmcm, // input wait_all_lanes, // when 0 allow some lanes missing sync (for easier phase adjustment) // MMCP output status output ps_rdy, // output output [7:0] ps_out, // output[7:0] reg Loading Loading @@ -154,7 +156,148 @@ module sens_hispi12l4#( .dout (sns_d) // output[15:0] ); localparam WAIT_ALL_LANES = 8; // number of output pixel cycles to wait after the earliest lane localparam FIFO_DEPTH = 4; wire [HISPI_NUMLANES * 12-1:0] hispi_aligned; wire [HISPI_NUMLANES-1:0] hispi_dv; wire [HISPI_NUMLANES-1:0] hispi_embed; wire [HISPI_NUMLANES-1:0] hispi_sof; wire [HISPI_NUMLANES-1:0] hispi_eof; wire [HISPI_NUMLANES-1:0] hispi_sol; wire [HISPI_NUMLANES-1:0] hispi_eol; // TODO - try to make that something will be recorded even if some lanes are bad (to simplify phase adjust // possibly - extra control bit (wait_all_lanes) // use earliest SOF reg vact_ipclk; reg [1:0] vact_pclk_strt; wire [HISPI_NUMLANES-1:0] rd_run; reg rd_line; // combine all lanes reg rd_line_r; wire sol_all_dly; reg [HISPI_NUMLANES-1:0] rd_run_d; reg sof_pclk; // wire [HISPI_NUMLANES-1:0] sol_pclk = rd_run & ~rd_run_d; wire sol_pclk = |(rd_run & ~rd_run_d); // possibly multi-cycle reg [HISPI_NUMLANES-1:0] good_lanes; // lanes that started active line OK reg [HISPI_NUMLANES-1:0] fifo_re; reg [HISPI_NUMLANES-1:0] fifo_re_r; reg hact_r; wire [HISPI_NUMLANES * 12-1:0] fifo_out; wire hact_on; wire hact_off; assign hact_out = hact_r; always @(posedge ipclk) begin if (irst || (|hispi_eof[i])) vact_ipclk <= 0; // extend output if hact active else if (|hispi_sof) vact_ipclk <= 1; end always @(posedge pclk) begin vact_pclk_strt <= {vact_pclk_strt[0],vact_ipclk}; rd_run_d <= rd_run; sof_pclk <= vact_pclk_strt[0] && ! vact_pclk_strt[1]; if (prst || sof_pclk) rd_line <= 0; else if (sol_pclk) rd_line <= 1; else rd_line <= rd_line & (&(~good_lanes | rd_run)); // Off when first of the good lanes goes off rd_line_r <= rd_line; if (sol_pclk && !rd_line) good_lanes <= ~rd_run; // should be off before start else if (sol_all_dly) good_lanes <= good_lanes & rd_run; // and now they should be on fifo_re_r <= fifo_re & rd_run; // when data out is ready, mask if not running // not using HISPI_NUMLANES here - fix? Will be 0 (not possible in hispi) when no data pxd_out <= ({12 {fifo_re_r[0]}} & fifo_out[0 * 12 +:12]) | ({12 {fifo_re_r[1]}} & fifo_out[1 * 12 +:12]) | ({12 {fifo_re_r[2]}} & fifo_out[2 * 12 +:12]) | ({12 {fifo_re_r[3]}} & fifo_out[3 * 12 +:12]); if (prst) fifo_re <= 0; else if (sol_pclk || (rd_line && fifo_re[HISPI_NUMLANES - 1])) fifo_re <= 1; else fifo_re <= fifo_re << 1; if (prst || hact_off) hact_r <= 0; else if (hact_on) hact_r <= 1; vact_out <= vact_pclk_strt [0] || hact_r; end dly_16 #( .WIDTH(1) ) dly_16_start_line_i ( .clk (pclk), // input .rst (1'b0), // input .dly (WAIT_ALL_LANES), // input[3:0] .din (rd_line && !rd_line_r), // input[0:0] .dout (sol_all_dly) // output[0:0] ); dly_16 #( .WIDTH(1) ) dly_16_hact_on_i ( .clk (pclk), // input .rst (1'b0), // input .dly (2), // input[3:0] .din (sol_pclk), // input[0:0] .dout (hact_on) // output[0:0] ); dly_16 #( .WIDTH(1) ) dly_16_hact_off_i ( .clk (pclk), // input .rst (1'b0), // input .dly (2), // input[3:0] .din (fifo_re[HISPI_NUMLANES - 1]), // input[0:0] .dout (hact_off) // output[0:0] ); generate genvar i; for (i=0; i < 4; i=i+1) begin: hispi_lane sens_hispi_lane #( .HISPI_MSB_FIRST(HISPI_MSB_FIRST) ) sens_hispi_lane_i ( .ipclk (ipclk), // input .irst (irst), // input .din (sns_d[4*i +: 4]), // input[3:0] .dout (hispi_aligned[12*i +: 12]), // output[3:0] reg .dv (hispi_dv[i]), // output reg .embed (hispi_embed[i]), // output reg .sof (hispi_sof[i]), // output reg .eof (hispi_eof[i]), // output reg .sol (hispi_sol[i]), // output reg .eol (hispi_eol[i]) // output reg ); sens_hispi_fifo #( .COUNT_START (7), .DATA_WIDTH (12), .DATA_DEPTH (FIFO_DEPTH) ) sens_hispi_fifo_i ( .ipclk (ipclk), // input .irst (irst), // input .we (hispi_dv[i]), // input .sol (hispi_sol[i]), // input .eol (hispi_eol[i]), // input .din (hispi_aligned[12*i +: 12]), // input[11:0] .pclk (pclk), // input .prst (prst), // input .re (fifo_re[i]), // input .dout (fifo_out[12*i +: 12]), // output[11:0] reg .run (rd_run[i]) // output ); end endgenerate endmodule
sensor/sens_hispi_lane.v +36 −27 Original line number Diff line number Diff line Loading @@ -26,7 +26,7 @@ module sens_hispi_lane#( input ipclk, // half HiSPi recovered clock (165 MHz for 660 bps of MT9F002) input irst, // reset sync to ipclk input [3:0] din, // @posedge ipclk, din[3] came first output reg [3:0] dout, // data output, aligned (decide about bit order) output reg [11:0] dout, // 12-bit data output output reg dv, // data valid - continuous marks line output reg embed, // valid @sol and up through all dv output reg sof, // always before first sol - not instead of Loading @@ -40,7 +40,10 @@ module sens_hispi_lane#( // localparam [3:0] SYNC_EOL = 6; localparam [3:0] SYNC_EMBED = HISPI_MSB_FIRST ? 4'h1 : 4'h8; // other nibble (bit 4) localparam SYNC_NIBBLE = HISPI_MSB_FIRST ? 2 : 0; // decode which nibble of the last sync word localparam LSB_INDEX = HISPI_MSB_FIRST ? 2 : 0; // nibble number in 12-bit word localparam MSB_INDEX = HISPI_MSB_FIRST ? 0 : 2; // nibble number in 12-bit word reg [3:0] d_r; // rehistered input data wire [2:0] num_trail_0_w; // number of trailing 0-s in the last nibble Loading @@ -64,7 +67,7 @@ module sens_hispi_lane#( // reg got_eol; reg got_embed; reg pre_dv; reg [2:0] pre_dv; wire [3:0] dout_w; wire [4:0] num_running_zeros_w = num_running_zeros + {1'b0, num_lead_0_w}; wire start_line = sync_decode[3] && (got_sol || got_sof); Loading Loading @@ -120,34 +123,41 @@ module sens_hispi_lane#( else sync_decode <= sync_decode << 1; if (got_sync) got_sof <= 0; else if (sync_decode[SYNC_NIBBLE] && (barrel == SYNC_SOF)) got_sof <= 1; else if (sync_decode[LSB_INDEX] && (barrel == SYNC_SOF)) got_sof <= 1; if (got_sync) got_eof <= 0; else if (sync_decode[SYNC_NIBBLE] && (barrel == SYNC_EOF)) got_eof <= 1; else if (sync_decode[LSB_INDEX] && (barrel == SYNC_EOF)) got_eof <= 1; if (got_sync) got_sol <= 0; else if (sync_decode[SYNC_NIBBLE] && (barrel == SYNC_SOL)) got_sol <= 1; else if (sync_decode[LSB_INDEX] && (barrel == SYNC_SOL)) got_sol <= 1; // if (got_sync) got_eol <= 0; // else if (sync_decode[SYNC_NIBBLE] && (barrel == SYNC_EOL)) got_eol <= 1; // else if (sync_decode[LSB_INDEX] && (barrel == SYNC_EOL)) got_eol <= 1; if (got_sync) got_embed <= 0; else if (sync_decode[1] && (barrel == SYNC_EMBED)) got_embed <= 1; if (irst) dout <= 0; else dout <= dout_w; if (irst) dout[ 3:0] <= 0; else if (pre_dv[LSB_INDEX]) dout[ 3:0] <= dout_w; if (irst) dout[ 7:4] <= 0; else if (pre_dv[1]) dout[ 7:4] <= dout_w; if (irst) dout[11:8] <= 0; else if (pre_dv[MSB_INDEX]) dout[11:8] <= dout_w; if (irst || got_sync) pre_dv <= 0; else if (start_line_d) pre_dv <= 1; else pre_dv <= {pre_dv[1:0],pre_dv[2]}; if (irst) dv <= 0; else dv <= pre_dv; else dv <= pre_dv[2]; if (irst) sol <= 0; else sol <= start_line_d; if (irst) eol <= 0; else eol <= got_sync && pre_dv; else eol <= got_sync && (|pre_dv); if (irst) sof <= 0; else sof <= sync_decode[3] && got_sof; Loading Loading @@ -180,4 +190,3 @@ module sens_hispi_lane#( endmodule
util_modules/fifo_cross_clocks.v +6 −5 Original line number Diff line number Diff line Loading @@ -82,12 +82,13 @@ module fifo_cross_clocks end always @ (posedge rclk or posedge rst) begin if (rst) raddr <= 0; else if (rrst) raddr <= 0; // making rrst set FIFO to empty regardless of current waddr (write should be stopped) if (rst) raddr <= waddr; // 0; else if (rrst) raddr <= waddr; // 0; else if (re) raddr <= raddr_plus1; if (rst) raddr_gray_top3 <= 0; else if (rrst) raddr_gray_top3 <= 0; if (rst) raddr_gray_top3 <= waddr[DATA_DEPTH-1 -: 3] ^ {1'b0,waddr[DATA_DEPTH-1 -: 2]}; // 0; else if (rrst) raddr_gray_top3 <= waddr[DATA_DEPTH-1 -: 3] ^ {1'b0,waddr[DATA_DEPTH-1 -: 2]}; // 0; else if (re) raddr_gray_top3 <= raddr_plus1_gray_top3; end Loading