Commit 9ce986ab authored by Andrey Filippov's avatar Andrey Filippov

adding code for top of the hispi decoder

parent 1b4f3f2c
...@@ -43,6 +43,7 @@ module sens_hispi12l4#( ...@@ -43,6 +43,7 @@ module sens_hispi12l4#(
parameter SENS_SS_MODE = "CENTER_HIGH",//"CENTER_HIGH","CENTER_LOW","DOWN_HIGH","DOWN_LOW" 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 SENS_SS_MOD_PERIOD = 10000, // integer 4000-40000 - SS modulation period in ns
parameter HISPI_MSB_FIRST = 0,
parameter HISPI_NUMLANES = 4, parameter HISPI_NUMLANES = 4,
parameter HISPI_CAPACITANCE = "DONT_CARE", parameter HISPI_CAPACITANCE = "DONT_CARE",
parameter HISPI_DIFF_TERM = "TRUE", parameter HISPI_DIFF_TERM = "TRUE",
...@@ -76,6 +77,7 @@ module sens_hispi12l4#( ...@@ -76,6 +77,7 @@ module sens_hispi12l4#(
input ld_idelay, // mclk synchronous set idealy value input ld_idelay, // mclk synchronous set idealy value
input set_clk_phase, // mclk synchronous set idealy value input set_clk_phase, // mclk synchronous set idealy value
input rst_mmcm, input rst_mmcm,
// input wait_all_lanes, // when 0 allow some lanes missing sync (for easier phase adjustment)
// MMCP output status // MMCP output status
output ps_rdy, // output output ps_rdy, // output
output [7:0] ps_out, // output[7:0] reg output [7:0] ps_out, // output[7:0] reg
...@@ -154,7 +156,148 @@ module sens_hispi12l4#( ...@@ -154,7 +156,148 @@ module sens_hispi12l4#(
.dout (sns_d) // output[15:0] .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 endmodule
...@@ -26,7 +26,7 @@ module sens_hispi_lane#( ...@@ -26,7 +26,7 @@ module sens_hispi_lane#(
input ipclk, // half HiSPi recovered clock (165 MHz for 660 bps of MT9F002) input ipclk, // half HiSPi recovered clock (165 MHz for 660 bps of MT9F002)
input irst, // reset sync to ipclk input irst, // reset sync to ipclk
input [3:0] din, // @posedge ipclk, din[3] came first 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 dv, // data valid - continuous marks line
output reg embed, // valid @sol and up through all dv output reg embed, // valid @sol and up through all dv
output reg sof, // always before first sol - not instead of output reg sof, // always before first sol - not instead of
...@@ -40,7 +40,10 @@ module sens_hispi_lane#( ...@@ -40,7 +40,10 @@ module sens_hispi_lane#(
// localparam [3:0] SYNC_EOL = 6; // localparam [3:0] SYNC_EOL = 6;
localparam [3:0] SYNC_EMBED = HISPI_MSB_FIRST ? 4'h1 : 4'h8; // other nibble (bit 4) 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 reg [3:0] d_r; // rehistered input data
wire [2:0] num_trail_0_w; // number of trailing 0-s in the last nibble wire [2:0] num_trail_0_w; // number of trailing 0-s in the last nibble
...@@ -64,7 +67,7 @@ module sens_hispi_lane#( ...@@ -64,7 +67,7 @@ module sens_hispi_lane#(
// reg got_eol; // reg got_eol;
reg got_embed; reg got_embed;
reg pre_dv; reg [2:0] pre_dv;
wire [3:0] dout_w; wire [3:0] dout_w;
wire [4:0] num_running_zeros_w = num_running_zeros + {1'b0, num_lead_0_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); wire start_line = sync_decode[3] && (got_sol || got_sof);
...@@ -120,34 +123,41 @@ module sens_hispi_lane#( ...@@ -120,34 +123,41 @@ module sens_hispi_lane#(
else sync_decode <= sync_decode << 1; else sync_decode <= sync_decode << 1;
if (got_sync) got_sof <= 0; 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; 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; 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; // 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; if (got_sync) got_embed <= 0;
else if (sync_decode[1] && (barrel == SYNC_EMBED)) got_embed <= 1; else if (sync_decode[1] && (barrel == SYNC_EMBED)) got_embed <= 1;
if (irst) dout <= 0; if (irst) dout[ 3:0] <= 0;
else dout <= dout_w; 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; if (irst || got_sync) pre_dv <= 0;
else if (start_line_d) pre_dv <= 1; else if (start_line_d) pre_dv <= 1;
else pre_dv <= {pre_dv[1:0],pre_dv[2]};
if (irst) dv <= 0; if (irst) dv <= 0;
else dv <= pre_dv; else dv <= pre_dv[2];
if (irst) sol <= 0; if (irst) sol <= 0;
else sol <= start_line_d; else sol <= start_line_d;
if (irst) eol <= 0; if (irst) eol <= 0;
else eol <= got_sync && pre_dv; else eol <= got_sync && (|pre_dv);
if (irst) sof <= 0; if (irst) sof <= 0;
else sof <= sync_decode[3] && got_sof; else sof <= sync_decode[3] && got_sof;
...@@ -180,4 +190,3 @@ module sens_hispi_lane#( ...@@ -180,4 +190,3 @@ module sens_hispi_lane#(
endmodule endmodule
...@@ -82,12 +82,13 @@ module fifo_cross_clocks ...@@ -82,12 +82,13 @@ module fifo_cross_clocks
end end
always @ (posedge rclk or posedge rst) begin always @ (posedge rclk or posedge rst) begin
if (rst) raddr <= 0; // making rrst set FIFO to empty regardless of current waddr (write should be stopped)
else if (rrst) raddr <= 0; if (rst) raddr <= waddr; // 0;
else if (rrst) raddr <= waddr; // 0;
else if (re) raddr <= raddr_plus1; else if (re) raddr <= raddr_plus1;
if (rst) 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 <= 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; else if (re) raddr_gray_top3 <= raddr_plus1_gray_top3;
end end
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment