kopia lustrzana https://github.com/hoglet67/RGBtoHDMI
152 wiersze
4.6 KiB
VHDL
152 wiersze
4.6 KiB
VHDL
----------------------------------------------------------------------------------
|
|
-- Engineer: David Banks
|
|
--
|
|
-- Create Date: 14/4/2017
|
|
-- Module Name: RGBtoHDMI CPLD
|
|
-- Project Name: RGBtoHDMI
|
|
-- Target Devices: XC9572XL
|
|
--
|
|
-- Version: 0.50
|
|
--
|
|
----------------------------------------------------------------------------------
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.numeric_std.all;
|
|
|
|
entity RGBtoHDMI is
|
|
Port (
|
|
-- From Beeb RGB Connector
|
|
R: in std_logic;
|
|
G: in std_logic;
|
|
B: in std_logic;
|
|
nCSYNC: in std_logic;
|
|
|
|
-- From Pi
|
|
clk: in std_logic;
|
|
|
|
-- To PI GPIO
|
|
quad: out std_logic_vector(11 downto 0);
|
|
psync: out std_logic;
|
|
hsync: out std_logic;
|
|
vsync: out std_logic;
|
|
field: out std_logic;
|
|
|
|
-- Test
|
|
SW: in std_logic;
|
|
LED1: out std_logic;
|
|
LED2: out std_logic
|
|
);
|
|
end RGBtoHDMI;
|
|
|
|
architecture Behavorial of RGBtoHDMI is
|
|
|
|
-- For Mode 7
|
|
-- constant sample_point : unsigned(10 downto 0) := to_unsigned(2048 - 48 * 2 + 3, 11);
|
|
|
|
-- For Modes 6..0
|
|
constant sample_point : unsigned(10 downto 0) := to_unsigned(2048 - 32 * 23 + 3, 11);
|
|
|
|
signal shift : std_logic_vector(11 downto 0);
|
|
|
|
signal nCSYNC1 : std_logic;
|
|
signal nCSYNC2 : std_logic;
|
|
|
|
-- The counter runs at 4x pixel clock
|
|
--
|
|
-- It serves several purposes:
|
|
-- 1. Counts the 12us between the rising edge of nCSYNC and the first pixel
|
|
-- 2. Counts within each pixel (bits 0 and 1)
|
|
-- 3. Counts counts pixels within a quad pixel (bits 2 and 3)
|
|
-- 4. Handles double buffering of alternative quad pixels (bit 4)
|
|
--
|
|
-- At the moment we don't count pixels with the line, the Pi does that
|
|
--
|
|
-- The sequence is basically:
|
|
-- 1280, 1280, ..., 1280, 1281, 1282, ... , 2047
|
|
-- 0, 1, 2, ..., 14, 15 - first quad pixel
|
|
-- 16, 17, 18, ..., 30, 31, -- second quad pixel
|
|
-- ...
|
|
-- 1280, 1280, ..., 1280, 1281, 1282, ... , 2047
|
|
|
|
signal counter : unsigned(10 downto 0);
|
|
|
|
-- Hsync is every 64us
|
|
signal led_counter : unsigned(11 downto 0);
|
|
|
|
begin
|
|
|
|
process(nCSYNC)
|
|
begin
|
|
if rising_edge(nCSYNC) then
|
|
led_counter <= led_counter + 1;
|
|
end if;
|
|
end process;
|
|
|
|
process(clk)
|
|
begin
|
|
if rising_edge(clk) then
|
|
-- synchronize nCSYNC to the sampling clock
|
|
nCSYNC1 <= nCSYNC;
|
|
nCSYNC2 <= nCSYNC1;
|
|
|
|
if nCSYNC1 = '0' and nCSYNC2 = '1' then
|
|
-- start of horizontal line sync pulse
|
|
hsync <= '1';
|
|
psync <= '0';
|
|
-- counter is used to measure how long the pulse is
|
|
counter <= to_unsigned(0, counter'length);
|
|
|
|
elsif nCSYNC1 = '1' and nCSYNC2 = '0' then
|
|
-- end of horizontal line sync pulse
|
|
hsync <= '0';
|
|
|
|
-- test for vertical sync
|
|
-- a normal line sync pulse is 4us
|
|
-- a saturated counter (512 == 8us) value can only happen during vsync
|
|
if counter = 512 then
|
|
vsync <= '1';
|
|
else
|
|
vsync <= '0';
|
|
end if;
|
|
|
|
-- counter is used to find sampling point for first pixel
|
|
counter <= sample_point;
|
|
|
|
elsif nCSYNC1 = '0' then
|
|
-- within the line sync pulse
|
|
-- saturate counter at 8us.
|
|
if counter < 512 then
|
|
counter <= counter + 1;
|
|
end if;
|
|
|
|
else
|
|
-- within the line
|
|
if counter = 31 then
|
|
counter <= to_unsigned(0, counter'length);
|
|
else
|
|
counter <= counter + 1;
|
|
end if;
|
|
if counter(10) = '0' then
|
|
if counter(1 downto 0) = "10" then
|
|
shift <= B & G & R & shift(11 downto 3);
|
|
if counter(3 downto 2) = "00" then
|
|
quad <= shift;
|
|
psync <= counter(4);
|
|
end if;
|
|
end if;
|
|
else
|
|
quad <= (others => '0');
|
|
psync <= '0';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
field <= '1';
|
|
|
|
LED1 <= not SW;
|
|
|
|
LED2 <= led_counter(led_counter'left);
|
|
|
|
end Behavorial;
|