library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; use work.CamControl; use work.EdgeDet; use work.MemPack; entity Kamera is Port ( -- fpga clock clk : in std_logic; -- serial port rs232RX : in std_logic; rs232TX : out std_logic; -- camera pins XCLK : out std_logic; -- system clock RSTB : out std_logic := '0'; -- reset (active low) PWDN : out std_logic; -- power down (power down = high) SCL : out std_logic; -- I2C clock SDA : inout std_ulogic; -- I2C i/o PCLK : in std_logic; -- pixel clock HREF : in std_logic; VSYNC : in std_logic; D : in std_logic_vector(9 downto 0); -- pic data -- monitor pins r : out std_logic_vector(7 downto 0); g : out std_logic_vector(7 downto 0); b : out std_logic_vector(7 downto 0); m1 : out std_logic; m2 : out std_logic; mclk : out std_logic; syncT : out std_logic; nsync : out std_logic; nblank : out std_logic; mVSYNC : out std_logic; mHSYNC : out std_logic; -- sram sr1ce : out std_logic; sr1ub : out std_logic; sr1lb : out std_logic; sr2ce : out std_logic; sr2ub : out std_logic; sr2lb : out std_logic; sr12we : out std_logic := '1'; sr12oe : out std_logic; sraddr : out std_logic_vector(17 downto 0); srio : inout std_logic_vector(31 downto 0); -- debug led : out std_logic_vector(7 downto 0); sw : in std_logic_vector(7 downto 0); btn : in std_logic_vector(3 downto 0) ); end Kamera; architecture Behavioral of Kamera is --attribute buffer_type : string; --attribute buffer_type of PCLK : signal is "BUFGP"; signal curPixelPosX: std_logic_vector(15 downto 0) := x"0000"; signal curPixelPosY: std_logic_vector(15 downto 0) := x"0000"; signal h_Sync: std_logic; signal v_Sync: std_logic; signal hCounter: integer range 0 to 799:=0; signal vCounter: integer range 0 to 520:=0; signal hBlack: std_logic:='1'; signal vBlack: std_logic:='1'; signal dcmLocked : std_logic; signal clk05x : std_logic; signal clk1x : std_logic; signal clk2x : std_logic; signal bramWrClk : std_logic; signal bramWrAddr : std_logic_vector(8 downto 0); signal bramWrData : std_logic_vector(15 downto 0); signal bramWrEn : std_logic_vector(3 downto 0) := "0001"; signal bramRdSelNext : integer range 0 to 3; signal bramRdNextCmd : std_logic; signal bramRdNextFrame : std_logic; type t_bramRdData is array (0 to 3) of std_logic_vector(7 downto 0); signal bramRdClk : std_logic; signal bramRdAddr : std_logic_vector(9 downto 0); signal bramRdData : t_bramRdData; signal bramRdSel : integer range 0 to 3; signal bramRdNextCmdBuf : EdgeDet.tBuffer := EdgeDet.tBuffer_InitLow; signal bramRdNextFrameBuf : EdgeDet.tBuffer := EdgeDet.tBuffer_InitLow; type tVGAState is (VGA_Output, Capture1, Capture2, Capture3); signal VGAState : tVGAState := VGA_Output; constant SramInpDir : std_logic_vector(31 downto 0) := "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"; signal rPos : std_logic_vector(17 downto 0) := "000000000000000000"; signal wPos : std_logic_vector(17 downto 0) := "000000000000000000"; signal hReadPos : std_logic_vector(9 downto 0) := "0000000000"; signal vReadPos : std_logic_vector(8 downto 0) := "000000000"; signal showFrame : boolean := False; -- camera input signal dinBuf : std_logic_vector(7 downto 0); signal hrefBuf : EdgeDet.tBuffer := EdgeDet.tBuffer_InitLow; signal vsyncBuf : EdgeDet.tBuffer := EdgeDet.tBuffer_InitHigh; signal isFrame : boolean := False; signal sramWE : boolean := False; signal btnBuf : EdgeDet.tBuffer := EdgeDet.tBuffer_InitLow; begin -- fixed outputs led(6 downto 0) <= (others => '0'); sr1ce <= '0'; sr2ce <= '0'; sr1ub <= '0'; sr2ub <= '0'; sr1lb <= '0'; sr2lb <= '0'; sr12oe <= '0'; -- clocks clk2x_dcm_inst : entity clk2x_dcm(BEHAVIORAL) port map ( CLKIN_IN => clk, RST_IN => '0', CLKDV_OUT => clk05x, CLKIN_IBUFG_OUT => open, CLK0_OUT => clk1x, CLK2X_OUT => clk2x, LOCKED_OUT => dcmLocked ); -- ########################################### -- ### monitor output -- ########################################### -- VGA DAC control m1 <= '0'; m2 <= '0'; nblank <= '1'; nsync <= '1'; syncT <= '0'; mVSYNC <= v_Sync; mHSYNC <= h_Sync; mclk <= not clk05x; -- TODO: synchronize process(clk2x) variable newline : boolean; variable tmpR : std_logic_vector(23 downto 0); variable tmpW : std_logic_vector(23 downto 0); variable tmpSraddr : std_logic_vector(17 downto 0); variable Mem3to4_RState : MemPack.tState := MemPack.tState_Init; variable Mem3to4_WState : MemPack.tState := MemPack.tState_Init; begin if clk2x'event and clk2x='1' and dcmLocked='1' then -- ### VGA output ### -- if not showFrame then -- hCounter <= 0; -- vCounter <= 0; -- end if; case VGAState is when VGA_Output => -- horizontal control hCounter<=hCounter +1; curPixelPosX <= curPixelPosX + x"0001"; newline:=False; case hCounter is when 95 => h_Sync<='0'; -- Zeilen-Sync aus when 143 => hBlack<='0'; -- schwarzer Rand aus curPixelPosX <= x"0000"; when 783 => hBlack<='1'; -- schwarzer Rand ein when 799 => hCounter<=0; -- newline newline:=True; h_Sync<='1'; -- Zeilen-Sync ein rPos <= curPixelPosY * conv_std_logic_vector(480, 18); when others => null; end case; -- vertical control if newline then vCounter<=vCounter+1; curPixelPosY <= curPixelPosY + x"0001"; case vCounter is when 0 => v_Sync<='1'; when 2 => v_Sync<='0'; when 33 => vBlack<='0'; -- was: 30 (!!!) curPixelPosY <= x"0000"; when 512 => vBlack<='1'; -- was: 511 (!!!) showFrame <= False; when 520 => vCounter<=0; rPos <= "000000000000000000"; when others => null; end case; end if; -- draw contents r <= x"00"; g <= x"00"; b <= x"00"; if hBlack='0' and vBlack='0' then -- fetch next 32-bit-word from SRAM ? if MemPack.Mem3to4_readFetchRequired( Mem3to4_RState ) then MemPack.Mem3to4_readSetInpData( Mem3to4_RState, srio ); rPos <= rPos + 1; end if; -- retrieve 24-bit colour word MemPack.Mem3to4_readGetOutpData( Mem3to4_RState, tmpR ); -- output pixel colour r <= tmpR(23 downto 16); g <= tmpR(15 downto 8); b <= tmpR(7 downto 0); -- draw a small red rectangle in the upper left corner if curPixelPosX < x"000a" and curPixelPosY < x"000a" then r <= x"ff"; g <= x"00"; b <= x"00"; end if; end if; -- set address to write sraddr <= wPos; -- compute data to write if ((hReadPos(0)='0') and (vReadPos(0)='0')) or ((hReadPos(0)='1') and (vReadPos(0)='1')) then tmpW := x"00" & bramRdData(bramRdSel) & x"00"; -- green bayer pixel elsif (hReadPos(0)='1') and (vReadPos(0)='0') then tmpW := bramRdData(bramRdSel) & x"00" & x"00"; -- red bayer pixel else tmpW := x"00" & x"00" & bramRdData(bramRdSel); -- blue bayer pixel end if; -- submit write data if sramWE then MemPack.Mem3to4_writeSetInpData( Mem3to4_WState, tmpW ); end if; VGAState <= Capture1; when Capture1 => EdgeDet.setNext(bramRdNextCmdBuf, bramRdNextCmd); EdgeDet.setNext(bramRdNextFrameBuf, bramRdNextFrame); EdgeDet.setNext(btnBuf, sw(0)); -- wait for next frame available if vReadPos = conv_std_logic_vector(480, 9) then showFrame <= True; sramWE <= False; led(7) <= '1'; if EdgeDet.anyEdge(bramRdNextFrameBuf) then --if EdgeDet.anyEdge(btnBuf) then hReadPos <= "0000000000"; vReadPos <= "000000000"; wPos <= "000000000000000000"; led(7) <= '0'; Mem3to4_WState := MemPack.tState_Init; end if; else -- wait for next line available if hReadPos = conv_std_logic_vector(640, 10) then sramWE <= False; if EdgeDet.anyEdge(bramRdNextCmdBuf) then hReadPos <= "0000000000"; vReadPos <= vReadPos + 1; bramRdSel <= bramRdSelNext; sramWE <= True; Mem3to4_WState := MemPack.tState_Init; end if; else hReadPos <= hReadPos + 1; end if; end if; -- write to SRAM ? if sramWE and MemPack.Mem3to4_writeCommitRequired( Mem3to4_WState ) then srio <= MemPack.Mem3to4_writeGetOutpData( Mem3to4_WState ); -- set data sr12we <= '0'; -- enable write wPos <= wPos + 1; -- increment write pos for next write end if; VGAState <= Capture2; when Capture2 => -- disable write sr12we <= '1'; -- output address to read for VGA output: -- 10 bit for column, 8 bit for line sraddr <= rPos; -- i/o input direction srio <= SramInpDir; -- output bram address to read next; TODO: correct? bramRdAddr <= hReadPos; -- bram clock; TODO: correct? bramRdClk <= '1'; VGAState <= Capture3; when Capture3 => bramRdClk <= '0'; VGAState <= VGA_Output; end case; end if; end process; -- ########################################### -- ### Camera input -- ########################################### cam_bram_inst1 : entity cam_bram(cam_bram_a) port map ( clka => bramWrClk, dina => bramWrData, addra => bramWrAddr, wea => bramWrEn(0 downto 0), clkb => bramRdClk, doutb => bramRdData(0), addrb => bramRdAddr ); cam_bram_inst2 : entity cam_bram(cam_bram_a) port map ( clka => bramWrClk, dina => bramWrData, addra => bramWrAddr, wea => bramWrEn(1 downto 1), clkb => bramRdClk, doutb => bramRdData(1), addrb => bramRdAddr ); cam_bram_inst3 : entity cam_bram(cam_bram_a) port map ( clka => bramWrClk, dina => bramWrData, addra => bramWrAddr, wea => bramWrEn(2 downto 2), clkb => bramRdClk, doutb => bramRdData(2), addrb => bramRdAddr ); cam_bram_inst4 : entity cam_bram(cam_bram_a) port map ( clka => bramWrClk, dina => bramWrData, addra => bramWrAddr, wea => bramWrEn(3 downto 3), clkb => bramRdClk, doutb => bramRdData(3), addrb => bramRdAddr ); process(PCLK) variable isLine : boolean := False; variable lower : boolean := True; begin if PCLK'event and PCLK='1' then -- frame start/end ? if EdgeDet.risingEdge(vsyncBuf) then isFrame <= False; elsif EdgeDet.fallingEdge(vsyncBuf) then isFrame <= True; bramRdNextFrame <= not bramRdNextFrame; end if; if isFrame then -- line start/end ? if EdgeDet.risingEdge(hrefBuf) then isLine := True; elsif EdgeDet.fallingEdge(hrefBuf) then isLine := False; bramWrAddr <= "111111111"; -- after increment (see below) address will be 0 bramWrEn <= bramWrEn(2 downto 0) & bramWrEn(3); -- select next bram: shift left ("one hot") bramRdNextCmd <= not bramRdNextCmd; -- notify reader case bramWrEn is -- set readers's next bram when "0001" => bramRdSelNext <= 0; when "0010" => bramRdSelNext <= 1; when "0100" => bramRdSelNext <= 2; when "1000" => bramRdSelNext <= 3; when others => null; end case; end if; -- store data if isLine then if lower then bramWrAddr <= bramWrAddr + 1; bramWrData(7 downto 0) <= dinBuf; bramWrClk <= '0'; lower := False; else bramWrData(15 downto 8) <= dinBuf; bramWrClk <= '1'; lower := True; end if; end if; end if; -- buffer signals dinBuf <= D(9 downto 2); EdgeDet.setNext(hrefBuf, HREF); EdgeDet.setNext(vsyncBuf, VSYNC); end if; end process; -- ########################################### -- ### SCCB bus / camera control -- ########################################### CamControl_Inst : entity CamControl(arch) port map ( clk => clk1x, rs232RX => rs232RX, rs232TX => rs232TX, RSTB => RSTB, PWDN => PWDN, SCL => SCL, SDA => SDA ); XCLK <= clk05x; end Behavioral;