malkauns
Newbie level 4
I'm trying to understand how to set up clocks and read data from a MIPI camera sensor. The sensor (Omnivision 5647) uses the MIPI CSI-2 protocol with D-PHY for the physical layer. The stage I am trying to get to is to be able to observer SoT (Start of Transmission) signals after which I can start parsing the CSI-2 protocol packets. In a small MIPI writeup located at https://archive.eetasia.com/www.eetasia.com/ART_8800715969_499489_TA_a466fca2_3.HTM there are 2 statements that are to be taken into consideration when trying to read data:
"The high speed payload data from the transmitter is transmitted on both the edges of the High speed differential clock (DDR clock)"
"The high speed differential clock and the data transmitted from the transmitter are 90 degrees out of phase and with the data being transmitted first."
Using VHDL and Vivado, how do I create logic to successfully read data from this sensor? I have the following code written (with notes/questions) but I'm pretty sure its wrong. It was put together based on my limited understanding and reading various other source code that perform similarly:
I was told that in order to derive the correct delay value I would have to sample the output clock at the rising edge. If it is not 1, decrement the delay value. If it is 1, increment the delay value. This way the delay should always be within +/- 1 of the ideal value.
I have experimented with this code and tried to see how many SoT's I can detect but its very low (<10 per minute). This is probably due to random chance.
Really need help on this one!
"The high speed payload data from the transmitter is transmitted on both the edges of the High speed differential clock (DDR clock)"
"The high speed differential clock and the data transmitted from the transmitter are 90 degrees out of phase and with the data being transmitted first."
Using VHDL and Vivado, how do I create logic to successfully read data from this sensor? I have the following code written (with notes/questions) but I'm pretty sure its wrong. It was put together based on my limited understanding and reading various other source code that perform similarly:
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 library IEEE; use IEEE.std_logic_1164.ALL; use IEEE.numeric_std.all; library unisim; use unisim.vcomponents.all; entity diffclock2 is Port ( pad_p : in std_logic; -- differential pin p from sensor pad_n : in std_logic; -- differential pin n from sensor DLY_CLK : in std_logic; -- not sure what kind of clock to supply here dly_cnt : in std_logic_vector(4 downto 0); -- delay value from 0 to 31 dly_ld_clk : in std_logic; -- tells IDELAYE2 to load value in dly_cnt as the new delay value dly_reset : in std_logic; dly_refclk : in std_logic; -- 200mhz clock CLK_OUT : out std_logic -- output delayed clock ); end diffclock2; architecture behavioral of diffclock2 is signal CLK_IBUFG : std_logic; signal CLK_DLY : std_logic; signal CLK_BUFR : std_logic; begin clk_ibufg_I: IBUFGDS -- ** converts differential pin pair into single clock pin ** generic map ( IOSTANDARD => "LVDS_25", DIFF_TERM => true ) port map ( I => pad_p, IB => pad_n, O => CLK_IBUFG ); clk_idelay_I: IDELAYE2 generic map ( CINVCTRL_SEL => "FALSE", DELAY_SRC => "IDATAIN", HIGH_PERFORMANCE_MODE => "FALSE", IDELAY_TYPE => "VAR_LOAD", IDELAY_VALUE => 0, PIPE_SEL => "FALSE", REFCLK_FREQUENCY => 200.0, SIGNAL_PATTERN => "CLOCK" ) port map ( CNTVALUEOUT => open, DATAOUT => CLK_DLY, -- delayed clock C => DLY_CLK, CE => '0', CINVCTRL => '0', CNTVALUEIN => dly_cnt, DATAIN => '0', IDATAIN => CLK_IBUFG, -- input clock from differential pins on sensor INC => '0', LD => dly_ld_clk, LDPIPEEN => '0', REGRST => dly_reset ); csi_CLK_BUFR: BUFR -- not sure why i need this generic map ( BUFR_DIVIDE => "BYPASS", SIM_DEVICE => "7SERIES" ) port map ( O => CLK_BUFR, CE => '1', CLR => '0', I => CLK_DLY ); -- ** i think i need DDR in here somewhere too?? ** CLK_OUT <= CLK_BUFR; idelayctrl_I: IDELAYCTRL port map ( RDY => open, REFCLK => dly_refclk, --200mhz input clock RST => dly_reset ); end behavioral;
I was told that in order to derive the correct delay value I would have to sample the output clock at the rising edge. If it is not 1, decrement the delay value. If it is 1, increment the delay value. This way the delay should always be within +/- 1 of the ideal value.
I have experimented with this code and tried to see how many SoT's I can detect but its very low (<10 per minute). This is probably due to random chance.
Really need help on this one!
Last edited by a moderator: