Added support for Sample generator camera controller frame detector

master
gaurav 2022-07-11 20:41:28 +02:00
parent 2efe376768
commit aa5b83fb73
2 changed files with 115 additions and 46 deletions

View File

@ -43,7 +43,7 @@ begin
if (state_time_counter == 0)
begin
camera_state <= camera_state + (camera_state != state_idle); //go to next state if state is not equal to state_active
camera_state <= camera_state + (camera_state != state_idle); //go to next state if state is not equal to state_idle
case(camera_state)
state_reset:

View File

@ -17,7 +17,7 @@ Takes MIPI Clock and 4 Data lane as input convert into Parallel YUV output
Ouputs 32bit YUV data with Frame sync, lsync and pixel clock
*/
module mipi_csi_16_nx( //reset_in,
module mipi_csi_16_nx( reset_in,
mipi_clk_p_in,
mipi_clk_n_in,
mipi_data_p_in,
@ -32,15 +32,27 @@ module mipi_csi_16_nx( //reset_in,
pclk_o, //data output on pos edge , should be latching into receiver on negedge
data_o,
fsync_o, //active high
lsync_o //active high
lsync_o, //active high
//these pins may or many not be needed depeding on hardware config
cam_ctrl_in, //control camera control input from host
cam_pwr_en_o, //enable camera power
cam_reset_o, //camera reset to camera
cam_xmaster_o //camera master or slave
);
parameter MIPI_LANES = 2; //number of mipi lanes with camera. Only 2 or 4
parameter MIPI_GEAR = 8; //deserializer gearing ratio. Only 8 or 16
parameter MIPI_PIXEL_PER_CLOCK = 2; // number of pixels pipeline process in one clock cycle. With 2 Lanes and Gear 8 only 2 or 4, With 4 Lanes only 4 or 8
parameter MIPI_PIXEL_PER_CLOCK = 2; // number of pixels pipeline process in one clock cycle. With 2 Lanes and Gear 8 only 2 or 4 with gear 16 only 4 , With 4 Lanes only 4 or 8
parameter MAX_PIXEL_WIDTH = 12; //max pixel width , 14bit (RAW14) , IMX219 has 10bit while IMX477 has 12bit and IMX294 has 14bit
//input reset_in;
parameter FRAME_DETECT = 1; //if 1 MIPI start frame packet will be detected and used as frame sync rather than mipi_clk_lp , used for sensor whoes clock does not go into lp while frame sync is inactive
//this should never be active unless testing
parameter SAMPLE_GENERATOR = 0; //if 1 a ROM based sample generator will be activated for testing, Sample generator uses 2 ROM lines as that is what mipimum needed to an image with correct enough colors, ROM file are first.rom and second.rom
input reset_in;
input cam_ctrl_in;
input mipi_clk_p_in;
input mipi_clk_n_in;
input [MIPI_LANES-1:0]mipi_data_p_in;
@ -50,6 +62,10 @@ input mipi_clk_n_in1;
input [MIPI_LANES-1:0]mipi_data_p_in1;
input [MIPI_LANES-1:0]mipi_data_n_in1;
output cam_pwr_en_o;
output cam_reset_o;
output cam_xmaster_o;
output pclk_o;
output [31:0]data_o;
output fsync_o;
@ -70,14 +86,15 @@ wire is_decoded_valid;
wire is_raw_line_valid;
wire is_unpacked_valid;
wire is_rgb_valid;
wire is_rgb_corrected_valid;
wire is_yuv_valid;
wire is_yuv_line_valid;
wire mipi_out_clk;
wire [31 :0]mipi_data_raw_hw;
wire [31 :0]mipi_data_raw;
//wire [((MIPI_LANES * MIPI_GEAR) - 1) :0]mipi_data_raw_hw;
//wire [((MIPI_LANES * MIPI_GEAR) - 1) :0]mipi_data_raw;
wire [((MIPI_LANES * MIPI_GEAR) - 1) :0]byte_aligned;
wire [((MIPI_LANES * MIPI_GEAR) - 1) :0]lane_aligned;
wire [((MIPI_LANES * MIPI_GEAR) - 1) :0]decoded_data;
@ -85,35 +102,23 @@ wire [2:0]packet_type;
wire [15:0]packet_length;
wire [((MAX_PIXEL_WIDTH * MIPI_PIXEL_PER_CLOCK ) - 1 ):0]unpacked_data;
wire [((MAX_PIXEL_WIDTH * MIPI_PIXEL_PER_CLOCK * 3) - 1 ):0]rgb_data;
wire [((MAX_PIXEL_WIDTH * MIPI_PIXEL_PER_CLOCK * 3) - 1 ):0]rgb_corrected;
wire [((MIPI_PIXEL_PER_CLOCK * 8 * 2 ) - 1 ):0]yuv_data;
//wire frame_sync_in;
wire line_reset;
wire frame_sync;
wire [1:0] sync_pulse;
wire hf_clk;
int_osc int_osc_ins1(.hf_out_en_i(1'b1),
.hf_clk_out_o(mipi_out_clk),
.lf_clk_out_o(osc_clk));
wire ready;
wire [15:0]debug_16;
wire [7:0]debug_aligner;
//&& (byte_aligned[23:16] == 8'hb8 ) && (byte_aligned[39:32] == 8'hb8 ) && (byte_aligned[55:48] == 8'hb8 )
wire line_reset;
wire [1:0] sync_pulse;
//assign data_o = mipi_data_raw_hw;
//assign mipi_out_clk = ; //yellow
//assign lsync_o = !frame_sync; //green
//assign fsync_o = mipi_out_clk & out_lsync ; //orange
//assign data_o[1] = is_yuv_valid; //blue
//assign data_o[3] = out_lsync;
//assign data_o = {3'b111,1'b1, yuv_line_valid , is_yuv_valid, lsync_o & mipi_out_clk, is_yuv_valid & mipi_byte_clock , 3'b0, lane_aligned[7:0] == 8'hB8, is_lane_aligned_valid, is_decoded_valid & mipi_byte_clock, is_decoded_valid, mipi_byte_clock, 3'b0, debug_16[10:6], 2'b0, debug_16[5:0]};
//wirere [15:0]debug_word;
//assign debug_16 = {packet_length[15:2]};
//Lattice FPGA Engineering sample chip does not allow manual PHY pin assignment* for PHY and our hardware uses PHY1 rather than PHY0, this instance with go to PHY0 while our actual instance will go to PHY 1
//*Lattice Does allow manual pin assignment but when you assign manually PHY will not work at all. Appears to be ES chip bug.
//As i am using Lattice ES chips i need to use Radiant 2.0 , DPHY IP has been changed a little with Radiant 3.1
dphy_dummy mipi_csi_phy_inst0(.sync_clk_i(osc_clk),
.sync_rst_i(1'b0),
.lmmi_clk_i(1'b0),
@ -126,9 +131,9 @@ dphy_dummy mipi_csi_phy_inst0(.sync_clk_i(osc_clk),
.lmmi_rdata_o(),
.lmmi_rdata_valid_o(),
.hs_rx_en_i(1'b1),
//.hs_rx_clk_en_i(1'b1), //new
//.hs_rx_data_en_i(1'b1), //new
//.hs_data_des_en_i(1'b1), //new
//.hs_rx_clk_en_i(1'b1),
//.hs_rx_data_en_i(1'b1),
//.hs_data_des_en_i(1'b1),
.hs_rx_data_o(dummy_out),
//.hs_rx_data_sy nc_o(),
.lp_rx_en_i(1'b1),
@ -178,7 +183,7 @@ csi_dphy mipi_csi_phy_inst1(.sync_clk_i(osc_clk),
.ready_o()) ;
/*
generate
generate //if hardware mipi lane n does not match to FPGA PHY lane n then adjust here because Lattice ES chip does not allow manual pin assigment
if ( (MIPI_GEAR == 16) && (MIPI_LANES == 4))
begin
assign mipi_data_raw = {mipi_data_raw_hw[15:0], mipi_data_raw_hw[31:16], mipi_data_raw_hw[63:48] ,mipi_data_raw_hw[47:32]}; //If schematic lane 0 may not connected PHY lane 0 , May need to swap here because its not possible to do before PHY IP, because Radiant auto assign PHY ports
@ -200,32 +205,81 @@ endgenerate */
assign mipi_data_raw = mipi_data_raw_hw;
camera_controller camera_controller_ins0( .sclk_i(osc_clk),
.reset_i(reset_in),
.cam_ctrl_in(cam_ctrl_in),
.cam_pwr_en_o(cam_pwr_en_o),
.cam_reset_o(cam_reset_o),
.cam_xmaster_o(cam_xmaster_o)
);
line_reset_generator line_reset_generator_ins1(.clk_i(mipi_byte_clock),
line_reset_generator line_reset_generator_ins0(.clk_i(mipi_byte_clock),
.lp_data_i(lp_rx_data_p[0]),
.line_reset_o(line_reset));
assign frame_sync = lp_rx_clk_p;
genvar i;
generate
for (i = 0;i < MIPI_LANES; i = i +1) begin
genvar i;
if (SAMPLE_GENERATOR)
begin
wire dummy_byte_valid; //sample generator should neve be active unless debugging
assign is_byte_valid = {dummy_byte_valid,dummy_byte_valid};
sample_generator sample_generator_ins( .framesync_i(frame_sync),
.clk_i(mipi_byte_clock),
.reset_i(line_reset),
.byte_o(byte_aligned),
.byte_valid_o(dummy_byte_valid));
mipi_csi_rx_byte_aligner #(.MIPI_GEAR(MIPI_GEAR))mipi_rx_byte_aligner_0( .clk_i(mipi_byte_clock),
end
else
begin
for (i = 0;i < MIPI_LANES; i = i +1)
begin
mipi_csi_rx_byte_aligner #(.MIPI_GEAR(MIPI_GEAR))mipi_rx_byte_aligner_0(.clk_i(mipi_byte_clock),
.reset_i(line_reset),
.byte_i(mipi_data_raw[(MIPI_GEAR * i) +: MIPI_GEAR]),
.byte_o( byte_aligned[(MIPI_GEAR * i) +: MIPI_GEAR]),
.byte_valid_o(is_byte_valid[i]));
end
end
endgenerate
generate
if (FRAME_DETECT)
begin
frame_detector #(.MIPI_GEAR(MIPI_GEAR)) frame_detector_ins0( .reset_i(reset_in),
.clk_i(mipi_byte_clock),
.data_valid_i(is_byte_valid[0]),
.data_lane0_i(byte_aligned[0 +: MIPI_GEAR]),
.detected_frame_sync_o(frame_sync));
end
else
begin
assign frame_sync = lp_rx_clk_p;
end
endgenerate
mipi_csi_rx_lane_aligner #(.MIPI_GEAR(MIPI_GEAR), .MIPI_LANES(MIPI_LANES))mipi_rx_lane_aligner( .clk_i(mipi_byte_clock),
.reset_i(line_reset),
.bytes_valid_i(is_byte_valid),
.byte_i(byte_aligned),
.lane_valid_o(is_lane_aligned_valid),
.lane_byte_o(lane_aligned));
generate
if ( (MIPI_GEAR == 16) && (MIPI_LANES == 4))
@ -236,8 +290,7 @@ generate
.output_valid_o(is_decoded_valid),
.data_o(decoded_data),
.packet_length_o(),
.packet_type_o(packet_type),
.debug_o());
.packet_type_o(packet_type));
mipi_csi_rx_raw_depacker_16b4lane #(.PIXEL_WIDTH(MAX_PIXEL_WIDTH)) mipi_csi_rx_raw_depacker_0( .clk_i(mipi_byte_clock),
.data_valid_i(is_decoded_valid),
@ -256,8 +309,7 @@ generate
.output_valid_o(is_decoded_valid),
.data_o(decoded_data),
.packet_length_o(),
.packet_type_o(packet_type),
.debug_o());
.packet_type_o(packet_type));
@ -278,8 +330,7 @@ generate
.output_valid_o(is_decoded_valid),
.data_o(decoded_data),
.packet_length_o(),
.packet_type_o(packet_type),
.debug_o());
.packet_type_o(packet_type));
mipi_csi_rx_raw_depacker_8b4lane #(.PIXEL_WIDTH(MAX_PIXEL_WIDTH)) mipi_csi_rx_raw_depacker_0( .clk_i(mipi_byte_clock),
.data_valid_i(is_decoded_valid),
@ -300,8 +351,7 @@ generate
.output_valid_o(is_decoded_valid),
.data_o(decoded_data),
.packet_length_o(),
.packet_type_o(packet_type),
.debug_o());
.packet_type_o(packet_type));
if (( MIPI_PIXEL_PER_CLOCK == 4) )
@ -340,6 +390,25 @@ debayer_filter #(.PIXEL_WIDTH(MAX_PIXEL_WIDTH), .PIXEL_PER_CLK(MIPI_PIXEL_PER_CL
.data_valid_i(is_unpacked_valid),
.output_o(rgb_data),
.output_valid_o(is_rgb_valid));
/*
color_correction_matrix #(.PIXEL_WIDTH(MAX_PIXEL_WIDTH), .PIXEL_PER_CLK(MIPI_PIXEL_PER_CLOCK))color_correction_matrix_0(
.clk_i(mipi_byte_clock),
.reset_i(frame_sync),
.line_valid_i(is_raw_line_valid),
.data_i(rgb_data),
.data_valid_i(is_rgb_valid),
.output_o(rgb_corrected),
.output_valid_o(is_rgb_corrected_valid));
rgb_to_yuv #(.PIXEL_WIDTH(MAX_PIXEL_WIDTH), .PIXEL_PER_CLK(MIPI_PIXEL_PER_CLOCK))rgb_to_yuv_0( .clk_i(mipi_byte_clock),
.rgb_i(rgb_corrected),
.rgb_valid_i(is_rgb_corrected_valid),
.line_valid_i(is_raw_line_valid),
.yuv_o(yuv_data),
.yuv_valid_o(is_yuv_valid),
.yuv_line_o(yuv_line_valid));
*/
rgb_to_yuv #(.PIXEL_WIDTH(MAX_PIXEL_WIDTH), .PIXEL_PER_CLK(MIPI_PIXEL_PER_CLOCK))rgb_to_yuv_0( .clk_i(mipi_byte_clock),
.rgb_i(rgb_data),
@ -348,7 +417,7 @@ rgb_to_yuv #(.PIXEL_WIDTH(MAX_PIXEL_WIDTH), .PIXEL_PER_CLK(MIPI_PIXEL_PER_CLOCK)
.yuv_o(yuv_data),
.yuv_valid_o(is_yuv_valid),
.yuv_line_o(yuv_line_valid));
//wire line_wire;
output_reformatter #(.PIXEL_PER_CLK(MIPI_PIXEL_PER_CLOCK))out_reformatter_0( .clk_i(mipi_byte_clock),
.line_sync_i(yuv_line_valid),
@ -362,5 +431,5 @@ output_reformatter #(.PIXEL_PER_CLK(MIPI_PIXEL_PER_CLOCK))out_reformatter_0( .cl
assign pclk_o = mipi_out_clk; //output clock always available
assign fsync_o = !frame_sync; //activate fsync Active high
//assign lsync_o = line_wire & mipi_out_clk;
//assign lsync_o = is_yuv_valid;
endmodule