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; 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 curPosX: std_logic_vector(15 downto 0) := x"00A0"; signal curPosY: std_logic_vector(15 downto 0) := x"00A0"; 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(9 downto 0); signal bramWrData : std_logic_vector(15 downto 0); signal bramWrEn : std_logic_vector(3 downto 0) := "0001"; signal bramWrEnInt : integer range 0 to 3; signal bramWrEnIntNext : integer range 0 to 3; type t_bramRdData is array (0 to 3) of std_logic_vector(7 downto 0); signal bramRdClk : std_logic; signal bramRdAddr : std_logic_vector(10 downto 0); signal bramRdData : t_bramRdData; signal bramRdSel : integer range 0 to 3; signal bramRdSelNext : integer range 0 to 3; type tVGAState is (VGA_Output, Capture1, Capture2, Capture3); signal VGAState : tVGAState := VGA_Output; constant SramInpDir : std_logic_vector(31 downto 0) := "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"; signal hWritePos : std_logic_vector(9 downto 0) := "0000000000"; signal vWritePos : std_logic_vector(7 downto 0) := "00000000"; -- 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; begin -- fixed outputs led(7 downto 1) <= (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 vsl_hCt, vsl_vCt: std_logic_vector(15 downto 0); variable newline : boolean; variable tmp: std_logic_vector(31 downto 0); variable cnt : std_logic_vector(0 downto 0); -- used for /2 clock (25MHz) begin if clk2x'event and clk2x='1' and dcmLocked='1' then -- ### VGA output ### vsl_vCt := CONV_STD_LOGIC_VECTOR(vCounter, 16); vsl_hCt := CONV_STD_LOGIC_VECTOR(hCounter, 16); 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 when others => null; end case; -- vertical control if newline then vCounter<=vCounter+1; curPixelPosY <= curPixelPosY + x"0001"; case vCounter is when 1 => v_Sync<='0'; when 31 => vBlack<='0'; -- was: 30 (!!!) curPixelPosY <= x"0000"; when 511 => vBlack<='1'; -- was: 511 (!!!) when 520 => vCounter<=0; v_Sync<='1'; when others => null; end case; end if; -- draw contents r <= x"00"; g <= x"00"; b <= x"00"; if hBlack='1' then -- elsif vBlack='1' then -- else -- if btn(0)='1' then -- r <= sw; -- elsif btn(1)='1' then -- g <= sw; -- elsif btn(2)='1' then -- b <= sw; -- elsif btn(3)='1' then -- r <= vsl_vCt(7 downto 0); -- g <= vsl_hCt(7 downto 0); -- b <= vsl_vCt(7 downto 0) - vsl_hCt(7 downto 0); -- end if; -- pixel output tmp := srio; r <= tmp(23 downto 16); g <= tmp(15 downto 8); b <= tmp(7 downto 0); 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 <= vWritePos & hWritePos; -- compute data to write tmp := x"00" & (sw + vWritePos) & hWritePos(7 downto 0) & (vWritePos - hWritePos(7 downto 0)); -- (4), test pattern VGAState <= Capture1; when Capture1 => -- TODO: -- (1) read write data from block ram, -- (2) enable write only if data available, -- (3) increment/change write addresses -- (4) TEST PATTERN -- (5) synchronization --if vCounter = 0 and hCounter = 0 then -- (5), sync --if btn(0)='1' then if not isFrame then hWritePos <= "0000000000"; vWritePos <= "00000000"; bramRdSel <= bramWrEnInt; -- get bram where first line will be written end if; if not (vWritePos = "11111111" and hWritePos = "1111111111") then -- set write data srio <= tmp; -- enable write sr12we <= '0'; led(0) <= '0'; else led(0) <= '1'; end if; if hWritePos = "1111111111" and not (vWritePos = "11111111") then -- (3), inc address hWritePos <= "0000000000"; vWritePos <= vWritePos + 1; end if; if not (hWritePos = "1111111111") then hWritePos <= hWritePos + 1; 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 <= curPixelPosY(7 downto 0) & curPixelPosX(9 downto 0); -- i/o input direction srio <= SramInpDir; VGAState <= Capture3; when Capture3 => 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; end if; if isFrame then -- line start/end ? if EdgeDet.risingEdge(hrefBuf) then isLine := True; elsif EdgeDet.fallingEdge(hrefBuf) then isLine := False; bramWrAddr <= "1111111111"; -- after increment (see below) address will be 0 bramWrEn <= bramWrEn(2 downto 0) & bramWrEn(3); -- select next bram: shift left ("one hot") 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; with bramWrEn select bramWrEnInt <= 0 when "0001", 1 when "0010", 2 when "0100", 3 when others; with bramWrEn select bramWrEnIntNext <= 1 when "0001", 2 when "0010", 3 when "0100", 0 when others; -- ########################################### -- ### 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;