Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Reading data from MIPI CSI-2 camera sensor

Status
Not open for further replies.

malkauns

Newbie level 4
Joined
Jul 29, 2016
Messages
5
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
67
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:


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:

Did you look at the libraries guide for the 7 Series?

The description for the C pin of the IDELAYE2 is quite descriptive of what clock should be on the pin. Here is an excerpt of the first line from the libraries guide for that primitive All control inputs to IDELAYE2 primitive (RST, CE, and INC) are synchronous to the clock input (C).

Why do you think you need the DDR registers in this file. This file looks to have been taken from some other design and the rest of the design has the DDR registers for the data and some other control and clocking logic.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top