Documente Academic
Documente Profesional
Documente Cultură
FromHamsterworksWiki!
ThisFPGAProjectwasfinishedinSeptember2013.
SeeZedboard_VGA_HDMIforanupdatedprojectthatincludescolourspaceconversionfromRGB
I'vefinallycometogripswiththeZedboard'sADV7511HDMItransmitter.ThepinsconnectedontheZynq
thatwerelabeledD0throughD15intheschematicsareactuallyD8throughD23(verifiedonschematic).The
forcestheuseoftheYCrCbcolourspace,whichIknewverylittleabout.
ThecodebelowincludestheregistersettingstoruninYCbCr422mode,andoutputRGBtotheHDMIport,
workinginDVIDmode.Thecodeissetuptodisplayred,black,green,whiteandbluecolourbars.
ThemissingingredientwastheregistersettingforxD0withoutitsetto3CtheCbCrcomponentsarenot
captured.
Contents
1Sourcefiles
1.1zedboard_hdmi.vhd
1.2i2c_sender.vhd
1.3zedboard.ucf
2Testprograms
2.1csc.c
Sourcefiles
Thisisasmallprojectwithonlythreefiles.
zedboard_hdmi.vhd
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
--
-- Create Date: 06:01:06 10/02/2013
--
-- Description:
-- Drive the ADV7511 HDMI encoder directly from the PL fabric
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
Library UNISIM;
use UNISIM.vcomponents.all;
entity zedboard_hdmi is
Port ( clk_100 : in STD_LOGIC;
hdmi_clk : out STD_LOGIC;
hdmi_hsync : out STD_LOGIC;
hdmi_vsync : out STD_LOGIC;
hdmi_d : out STD_LOGIC_VECTOR (15 downto 0);
hdmi_de : out STD_LOGIC;
hdmi_int : in STD_LOGIC;
hdmi_scl : out STD_LOGIC;
hdmi_sda : inout STD_LOGIC);
end zedboard_hdmi;
-- Colours converted using The RGB -> YCbCr converter app found on Google Gadgets
-- Y Cb Cr
constant C_BLACK : std_logic_vector(23 downto 0) := x"108080"; -- 16 128 128
constant C_RED : std_logic_vector(23 downto 0) := x"515AF0"; -- 81 90 240
constant C_GREEN : std_logic_vector(23 downto 0) := x"AC2A1B"; -- 172 42 27
constant C_BLUE : std_logic_vector(23 downto 0) := x"20F076"; -- 32 240 118
constant C_WHITE : std_logic_vector(23 downto 0) := x"EA8080"; -- 234 128 128
begin
-- Set the video mode to 1280x720x60Hz (75MHz pixel clock needed)
hVisible <= ZERO + 1280;
hStartSync <= ZERO + 1280+72;
hEndSync <= ZERO + 1280+72+80;
hMax <= ZERO + 1280+72+80+216-1;
vSyncActive <= '1';
colour_proc: process(hcounter,vcounter)
begin
if hcounter < 256 then
colour <= C_RED;
elsif hcounter < 512 then
colour <= C_BLACK;
elsif hcounter < 768 then
colour <= C_GREEN;
elsif hcounter < 1024 then
colour <= C_WHITE;
else
colour <= C_BLUE;
end if;
end process;
-- there is a 16 bit interface into the HDMI transmitter, although I only use 8 bits
Y <= colour(23 downto 16) & x"00";
Cb <= colour(15 downto 8) & x"00";
Cr <= colour( 7 downto 0) & x"00";
------------------------------------------------------------------------
-- VGA Signal Generation
-- We only update when the second clock edge has been sent
--- to the HDMI encoder
------------------------------------------------------------------------
if edge = '1' then
if vcounter >= vVisible then
blanking <= '1';
elsif hcounter >= hVisible then
blanking <= '1';
else
blanking <= '0';
end if;
ODDR_inst : ODDR
generic map(
DDR_CLK_EDGE => "OPPOSITE_EDGE", INIT => '0',SRTYPE => "SYNC")
port map (
Q => hdmi_clk,
C => clk_VGAx2,
D1 => hdmi_clk_bits(0),
D2 => hdmi_clk_bits(1),
CE => '1', R => '0', S => '0'
);
i2c_sender.vhd
----------------------------------------------------------------------------------
-- Engineer: <mfield@concepts.co.nz
--
-- Description: Send register writes over an I2C-like interface
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity i2c_sender is
Port ( clk : in STD_LOGIC;
resend : in STD_LOGIC;
sioc : out STD_LOGIC;
siod : inout STD_LOGIC
);
end i2c_sender;
---------------
-- Input mode
---------------
x"1506", -- YCbCr 422, DDR, External sync
x"4810", -- Left justified data (D23 downto 8)
x"1637", -- 8 bit style 2, 1st half on rising edge - YCrCb clipping
x"1700", -- output aspect ratio 16:9, external DE
x"D03C", -- auto sync data - must be set for DDR modes.
---------------
-- Output mode
---------------
x"AF04", -- DVI mode
x"4c04", -- Deep colour off (HDMI only?) - not needed
x"4000", -- Turn off additional data packets - not needed
-----------------------------------------------------------------
-- As a start, here's the identity Matrix a <= A, b <= B, c <= C
-----------------------------------------------------------------
-- -- ([R or Cr]* A1 + [G or Y] * A2 + [B or Cb] * A3)/4096 + A4 = Red or Cr
-- x"18A8", x"1900", x"1A00", x"1B00", x"1C00", x"1D00", x"1E00", x"1F00",
--
-- -- ([R or Cr]* B1 + [G or Y] * B2 + [B or Cb] * B3)/4096 + B4 = Green or Y
-- x"2000", x"2100", x"2208", x"2300", x"2400", x"2500", x"2604", x"2700",
--
-- -- ([R or Cr]* C1 + [G or Y] * C2 + [B or Cb] * C3)/4096 + C4 = Blue or Cb
-- x"2808", x"2900", x"2A00", x"2B00", x"2C08", x"2D00", x"2E04", x"2F00",
--------------------------------------------------------------
-- Here is the YCrCb => RGB conversion, as per programming guide
-- This is table 57 - HDTV YCbCr (16 to 255) to RGB (0 to 255)
--------------------------------------------------------------
-- (Cr * A1 + Y * A2 + Cb * A3)/4096 + A4 = Red
x"18E7", x"1934", x"1A04", x"1BAD", x"1C00", x"1D00", x"1E1C", x"1F1B",
registers: process(clk)
begin
if rising_edge(clk) then
reg_value <= reg_value_pairs(to_integer(unsigned(address)));
end if;
end process;
i2c_send: process(clk)
begin
if rising_edge(clk) then
if resend = '1' then
address <= (others => '0');
clk_first_quarter <= (others => '1');
clk_last_quarter <= (others => '1');
busy_sr <= (others => '0');
divider <= (others => '0');
initial_pause <= (others => '0');
finished <= '0';
end if;
zedboard.ucf
Testprograms
csc.c
I'vealsowrittenasmalltestprogramtoverifytheColourSpaceConversionregistersettings.Hereisthe
program'soutput:
hamster@LogiPi-Dev:~/csc$ ./csc
Constants in hex
0734 04ad 0000 1c1b
1ddc 04ad 1f24 0135
0000 04ad 087c 1b77
Constants as floats
1.8008 1.1689 0.0000 -0.9736
-0.5352 1.1689 -0.2148 0.3018
0.0000 1.1689 2.1211 -1.1338
Cr Y Cb => R G B
Black 0.502 0.063 0.502 => 0.004 0.000 0.004
Red 0.941 0.318 0.353 => 1.000 0.094 0.000
Green 0.106 0.675 0.165 => 0.006 0.998 0.004
Blue 0.463 0.125 0.941 => 0.006 0.000 1.000
White 0.502 0.918 0.502 => 1.000 0.998 1.000
hamster@LogiPi-Dev:~/csc$
Andhereisthesource:
/****************************************************************
* csc.c : testing Colour space conversion settings on the ADV7511
*
* Author : Mike Field [hamster@snap.net.nz]
****************************************************************/
#include <stdio.h>
// These are the register values from the ADV7511 for Colour Space
// Conversion. I have not paid any attention to the constant's scale
// bits in Register 18[6:5]
int reg_values[] = {
0x18E7, 0x1934, 0x1A04, 0x1BAD, 0x1C00, 0x1D00, 0x1E1C, 0x1F1B,
0x201D, 0x21DC, 0x2204, 0x23AD, 0x241F, 0x2524, 0x2601, 0x2735,
0x2800, 0x2900, 0x2A04, 0x2BAD, 0x2C08, 0x2D7C, 0x2E1B, 0x2F77
};
struct test_vector {
char *name;
int value;
} test_values[] = {
{"Black", 0x108080}, // 16 128 128
{"Red", 0x515AF0}, // 81 90 240 RED
{"Green", 0xAC2A1B}, // 172 42 27 GREEN
{"Blue", 0x20F076}, // 32 240 118 BLUE
{"White", 0xEA8080} // 234 128 128 WHITE
};
printf("Constants in hex\n");
for(i=0;i<12;i+=4)
printf("%04x %04x %04x %04x\n",csc_int[i],csc_int[i+1],csc_int[i+2], csc_int[i+3] );
printf("\n");
for(i=0;i<12;i+=1) {
csc_float[i] = csc_int[i]/4096.0;
if(csc_int[i] & 0x1000)
csc_float[i] -= 2.0;
csc_float[i] *= 4.0;
}
printf("Constants as floats\n");
for(i=0;i<12;i+=4)
printf("%8.4f %8.4f %8.4f %8.4f\n",csc_float[i],csc_float[i+1],csc_float[i+2], csc_float[i+3] );
printf("\n");
Retrievedfrom"http://hamsterworks.co.nz/mediawiki/index.php/Zedboard_HDMI_v2"
Thispagewaslastmodifiedon8September2013,at09:25.