summaryrefslogtreecommitdiffstats
path: root/fpga
diff options
context:
space:
mode:
authorroot <root@new-fish.medaka.james.internal>2025-10-05 17:30:19 +0100
committerroot <root@new-fish.medaka.james.internal>2025-10-05 17:30:19 +0100
commit7f512741992ea4fb7d210a4b915b128b75f91675 (patch)
tree94100deb09e9010b6c9b2d5375cf037033d2f778 /fpga
parent5444ea0d10af34230d37bedde683c1ec3a2ef83e (diff)
downloadhp_instrument_lcds-7f512741992ea4fb7d210a4b915b128b75f91675.tar.gz
hp_instrument_lcds-7f512741992ea4fb7d210a4b915b128b75f91675.tar.bz2
hp_instrument_lcds-7f512741992ea4fb7d210a4b915b128b75f91675.zip
sync, and alternate tmds_encoders
Diffstat (limited to 'fpga')
-rw-r--r--fpga/ebaz4205/doc/DOC/EM6GD16EWKG.pdfbin0 -> 836310 bytes
-rw-r--r--fpga/ebaz4205/ebaz4205_fpga/.gitignore2
-rw-r--r--fpga/ebaz4205/ebaz4205_fpga/README.md45
-rw-r--r--fpga/ebaz4205/src/uboot-debug.patch21
-rw-r--r--fpga/hp_lcd_driver/Makefile9
-rw-r--r--fpga/hp_lcd_driver/clkgen_artix7.vhdl15
-rw-r--r--fpga/hp_lcd_driver/ebaz4205.xdc34
-rw-r--r--fpga/hp_lcd_driver/output_stage.vhdl2
-rw-r--r--fpga/hp_lcd_driver/tmds_encode.vhdl6
-rw-r--r--fpga/hp_lcd_driver/tmds_encoder_a.vhdl117
-rw-r--r--fpga/hp_lcd_driver/tmds_encoder_b.vhdl143
-rw-r--r--fpga/hp_lcd_driver/tmds_encoder_c.vhdl162
-rw-r--r--fpga/hp_lcd_driver/tmds_phy_artix7.vhdl2
-rw-r--r--fpga/hp_lcd_driver/zynq7_ip/mmcm_0.tcl39
-rw-r--r--fpga/hp_lcd_driver/zynq7_wrapper.vhdl5
15 files changed, 547 insertions, 55 deletions
diff --git a/fpga/ebaz4205/doc/DOC/EM6GD16EWKG.pdf b/fpga/ebaz4205/doc/DOC/EM6GD16EWKG.pdf
new file mode 100644
index 0000000..232d4ce
--- /dev/null
+++ b/fpga/ebaz4205/doc/DOC/EM6GD16EWKG.pdf
Binary files differ
diff --git a/fpga/ebaz4205/ebaz4205_fpga/.gitignore b/fpga/ebaz4205/ebaz4205_fpga/.gitignore
index 336fdb9..237b1b4 100644
--- a/fpga/ebaz4205/ebaz4205_fpga/.gitignore
+++ b/fpga/ebaz4205/ebaz4205_fpga/.gitignore
@@ -1,2 +1,4 @@
build/
hdlmake/
+LICENSE
+NOT/
diff --git a/fpga/ebaz4205/ebaz4205_fpga/README.md b/fpga/ebaz4205/ebaz4205_fpga/README.md
new file mode 100644
index 0000000..892164f
--- /dev/null
+++ b/fpga/ebaz4205/ebaz4205_fpga/README.md
@@ -0,0 +1,45 @@
+# ebaz4205_fpga
+
+The EBAZ4205 was originally developed as cryptomining control board.
+Due to it's low price on the marked it is also perfect to learn
+the Zynq platform. This repo provides a minimal FPGA Design.
+
+## Maintainer
+
+ Lukas Lichtl (admin@embed-me.com)
+
+## Hardware Support
+
+There seem to be two hardware versions currently sold, one with a
+PHY oscillator mounted and one where it is missing.
+This design current supports both versions.
+
+## Dependencies
+
+The configuration/makefile generation depends on:
+
+* [hdlmake](https://hdlmake.readthedocs.io/en/master/)
+
+The build depends on:
+
+* [Xilinx Vivado](https://www.xilinx.com/products/design-tools/vivado.html)
+
+## Configure
+
+In order to generate the Makefile for the build, make sure that hdlmake
+is in the path and run the following commands:
+
+ cd build
+ hdlmake
+
+## Build
+
+The build process requires Xilinx Vivado. To generate a bitstream run:
+
+ make
+
+## Vivado GUI
+
+To open the design in the Vivado GUI once the build is done:
+
+ vivado ebaz4205_top.xpr \ No newline at end of file
diff --git a/fpga/ebaz4205/src/uboot-debug.patch b/fpga/ebaz4205/src/uboot-debug.patch
new file mode 100644
index 0000000..b645fba
--- /dev/null
+++ b/fpga/ebaz4205/src/uboot-debug.patch
@@ -0,0 +1,21 @@
+diff --git a/arch/arm/mach-zynq/cpu.c b/arch/arm/mach-zynq/cpu.c
+index e5f55771..489f71f5 100644
+--- a/arch/arm/mach-zynq/cpu.c
++++ b/arch/arm/mach-zynq/cpu.c
+@@ -137,8 +137,16 @@ int print_cpuinfo(void)
+ if (version > (PCW_SILICON_VERSION_3 << 1))
+ version += 1;
+
++
++
+ printf("CPU: Zynq %s\n", zynq_fpga_descs[cpu_id].devicename);
+ printf("Silicon: v%d.%d\n", version >> 1, version & 1);
++
++ zynq_slcr_unlock();
++ version=readl(&slcr_base->ocm_cfg);
++ zynq_slcr_lock();
++
++ printf("SCLR_BASE=%p, &OCM_CFG=%p, OCM_CFG=0x%08x\n",slcr_base,&slcr_base->ocm_cfg,version);
+ return 0;
+ }
+ #endif
diff --git a/fpga/hp_lcd_driver/Makefile b/fpga/hp_lcd_driver/Makefile
index 6b72967..f61517d 100644
--- a/fpga/hp_lcd_driver/Makefile
+++ b/fpga/hp_lcd_driver/Makefile
@@ -1,14 +1,17 @@
DIP=10.16.66.113
-TARGETS= ebaz4205 #rando_a7 #smh-ac415b #spartan6 #ep4ce6 smh-ac415
+#TARGETS=rando_a7
+TARGETS=ebaz4205
+#TARGETS= ebaz4205 #rando_a7 #smh-ac415b #spartan6 #ep4ce6 smh-ac415
#fish:smh-ac415
-#better_default: build_rando_a7/hp_lcd_driver.svf
-# ./prog_a7
better_default: ${TARGETS:%=build_%/hp_lcd_driver.svf}
scp build_ebaz4205/out/hp_lcd_driver.bin ${DIP}:/boot/uboot/hp_lcd_driver.bin
ssh -n ${DIP} reboot < /dev/null &
+qbetter_default: build_rando_a7/hp_lcd_driver.svf
+ ./prog_a7
+
default: ${TARGETS:%=build_%/hp_lcd_driver.svf}
diff --git a/fpga/hp_lcd_driver/clkgen_artix7.vhdl b/fpga/hp_lcd_driver/clkgen_artix7.vhdl
index 643b91f..046437f 100644
--- a/fpga/hp_lcd_driver/clkgen_artix7.vhdl
+++ b/fpga/hp_lcd_driver/clkgen_artix7.vhdl
@@ -21,9 +21,8 @@ architecture Behavioural of clkgen is
signal clk_260m : std_logic;
signal clk_78_571m : std_logic;
- signal clk_80m : std_logic;
- signal clk_24m : std_logic;
- signal clk_48m : std_logic;
+ signal clk_26m : std_logic;
+ signal clk_52m : std_logic;
signal clk_50m : std_logic;
signal reset : std_logic;
@@ -39,9 +38,9 @@ begin
mmcm_0_i : mmcm_0 port map (
clk_in1 => clk_50m,
clk_out1 => clk_260m,
- clk_out2 => clk_80m,
- clk_out3 => clk_48m,
- clk_out4 => clk_24m,
+ clk_out2 => open,
+ clk_out3 => clk_52m,
+ clk_out4 => clk_26m,
reset => reset,
locked => locked
);
@@ -53,8 +52,8 @@ begin
);
o_clk_phy <= clk_260m;
- o_clk <= clk_24m;
- o_clk_x2 <= clk_48m;
+ o_clk <= clk_26m;
+ o_clk_x2 <= clk_52m;
i_clk <= clk_78_571m;
diff --git a/fpga/hp_lcd_driver/ebaz4205.xdc b/fpga/hp_lcd_driver/ebaz4205.xdc
index 64660eb..30b073a 100644
--- a/fpga/hp_lcd_driver/ebaz4205.xdc
+++ b/fpga/hp_lcd_driver/ebaz4205.xdc
@@ -27,8 +27,8 @@ set_property PACKAGE_PIN W14 [get_ports {red_led}]
set_property IOSTANDARD LVCMOS33 [get_ports *_led]
-#set_property IOSTANDARD LVCMOS33 [get_ports clk_50m]
-#set_property PACKAGE_PIN R4 [get_ports clk_50m]
+set_property IOSTANDARD LVCMOS33 [get_ports clk_50m]
+set_property PACKAGE_PIN N18 [get_ports clk_50m]
#set_property PACKAGE_PIN T1 [get_ports {led_1}]
#set_property IOSTANDARD LVCMOS33 [get_ports {led_1}]
@@ -37,14 +37,10 @@ set_property PACKAGE_PIN G19 [get_ports {hdmi_b_p}]; #data2-5
set_property PACKAGE_PIN G20 [get_ports {hdmi_b_n}]; #data2-7
set_property PACKAGE_PIN K19 [get_ports {hdmi_g_p}]; #data2-13
set_property PACKAGE_PIN J19 [get_ports {hdmi_g_n}]; #data2-9
-#set_property PACKAGE_PIN T20 [get_ports {hdmi_g_p}]; #data3-16
-#set_property PACKAGE_PIN U20 [get_ports {hdmi_g_n}]; #data3-17
set_property PACKAGE_PIN L19 [get_ports {hdmi_r_p}]; #data2-16
set_property PACKAGE_PIN L20 [get_ports {hdmi_r_n}]; #data2-18
set_property PACKAGE_PIN L16 [get_ports {hdmi_c_p}]; #data2-15
set_property PACKAGE_PIN L17 [get_ports {hdmi_c_n}]; #data2-20
-#set_property PACKAGE_PIN N17 [get_ports {hdmi_c_p}]; #data3-9
-#set_property PACKAGE_PIN P18 [get_ports {hdmi_c_n}]; #data3-7
set_property IOSTANDARD TMDS_33 [get_ports {hdmi_c_p}]
set_property IOSTANDARD TMDS_33 [get_ports {hdmi_c_n}]
@@ -55,13 +51,13 @@ set_property IOSTANDARD TMDS_33 [get_ports {hdmi_g_n}]
set_property IOSTANDARD TMDS_33 [get_ports {hdmi_b_p}]
set_property IOSTANDARD TMDS_33 [get_ports {hdmi_b_n}]
-##set_property DRIVE 16 [get_ports {hdmi_c_p}]
-##set_property DRIVE 16 [get_ports {hdmi_c_n}]
-##set_property DRIVE 16 [get_ports {hdmi_r_p}]
-##set_property DRIVE 16 [get_ports {hdmi_r_n}]
-##set_property DRIVE 16 [get_ports {hdmi_g_p}]
-##set_property DRIVE 16 [get_ports {hdmi_g_n}]
-##set_property DRIVE 16 [get_ports {hdmi_b_p}]
+set_property DRIVE 16 [get_ports {hdmi_c_p}]
+set_property DRIVE 16 [get_ports {hdmi_c_n}]
+set_property DRIVE 16 [get_ports {hdmi_r_p}]
+set_property DRIVE 16 [get_ports {hdmi_r_n}]
+set_property DRIVE 16 [get_ports {hdmi_g_p}]
+set_property DRIVE 16 [get_ports {hdmi_g_n}]
+set_property DRIVE 16 [get_ports {hdmi_b_p}]
#
set_property PACKAGE_PIN K18 [get_ports {hdmi_vcc}]; #data2-11 (12 is gnd)
set_property IOSTANDARD LVCMOS33 [get_ports {hdmi_vcc}]
@@ -120,7 +116,8 @@ set_property IOSTANDARD LVCMOS33 [get_ports {hsync_in}]
#set_property IOSTANDARD LVCMOS33 [get_ports {sys_rst_n}]
#set_property PULLTYPE PULLUP [get_ports {sys_rst_n}]
#
-#create_clock -period 20.000 -name pcie_clkin [get_ports clk_50m]
+
+create_clock -period 20.000 -name pcie_clkin [get_ports clk_50m]
##set_false_path -from [get_ports pci_exp_rst_n]
#
@@ -147,10 +144,11 @@ set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property CFGBVS VCCO [current_design]
-set_max_delay -from [get_pins {common_i/output0/tmds_o/phy_g/ld2_reg[*]/C}] -to [get_pins {common_i/output0/tmds_o/phy_g/ld_reg[*]/D}] 9
-set_max_delay -from [get_pins {common_i/output0/tmds_o/phy_b/ld2_reg[*]/C}] -to [get_pins {common_i/output0/tmds_o/phy_b/ld_reg[*]/D}] 9
-set_max_delay -from [get_pins {common_i/output0/tmds_o/phy_r/ld2_reg[*]/C}] -to [get_pins {common_i/output0/tmds_o/phy_r/ld_reg[*]/D}] 9
-set_max_delay -from [get_pins {common_i/output0/tmds_o/phy_c/ld2_reg[*]/C}] -to [get_pins {common_i/output0/tmds_o/phy_c/ld_reg[*]/D}] 9
+set_max_delay -from [get_pins {common_i/output0/tmds_o/phy_g/ld2_reg[*]/C}] -to [get_pins {common_i/output0/tmds_o/phy_g/ld_reg[*]/D}] 7
+set_max_delay -from [get_pins {common_i/output0/tmds_o/phy_b/ld2_reg[*]/C}] -to [get_pins {common_i/output0/tmds_o/phy_b/ld_reg[*]/D}] 7
+set_max_delay -from [get_pins {common_i/output0/tmds_o/phy_r/ld2_reg[*]/C}] -to [get_pins {common_i/output0/tmds_o/phy_r/ld_reg[*]/D}] 7
+set_max_delay -from [get_pins {common_i/output0/tmds_o/phy_c/ld2_reg[*]/C}] -to [get_pins {common_i/output0/tmds_o/phy_c/ld_reg[*]/D}] 7
+
diff --git a/fpga/hp_lcd_driver/output_stage.vhdl b/fpga/hp_lcd_driver/output_stage.vhdl
index 37ae297..9808a42 100644
--- a/fpga/hp_lcd_driver/output_stage.vhdl
+++ b/fpga/hp_lcd_driver/output_stage.vhdl
@@ -143,8 +143,6 @@ begin
b <= b_in;
-
-
dh : entity work.delay
generic map(stages => 2)
port map (
diff --git a/fpga/hp_lcd_driver/tmds_encode.vhdl b/fpga/hp_lcd_driver/tmds_encode.vhdl
index fe69a56..ed5e288 100644
--- a/fpga/hp_lcd_driver/tmds_encode.vhdl
+++ b/fpga/hp_lcd_driver/tmds_encode.vhdl
@@ -30,7 +30,11 @@ architecture beh of tmds_encode is
begin
- c_p10 <= "1111100000";
+-- c_p10 <= "1111000001";
+ c_p10 <= "1111100000";
+-- c_p10 <= "0111110000";
+-- c_p10 <= "0011111000";
+-- c_p10 <= "0001111100";
ctrl <= vsync & hsync;
diff --git a/fpga/hp_lcd_driver/tmds_encoder_a.vhdl b/fpga/hp_lcd_driver/tmds_encoder_a.vhdl
new file mode 100644
index 0000000..40f8dd4
--- /dev/null
+++ b/fpga/hp_lcd_driver/tmds_encoder_a.vhdl
@@ -0,0 +1,117 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity tmds_encoder is
+ port (
+ clk : in std_logic;
+ sys_rst_n : in std_logic;
+ blank : in std_logic;
+ ctrl : in std_logic_vector(1 downto 0);
+ din : in std_logic_vector(7 downto 0);
+ dout : out std_logic_vector(9 downto 0)
+ );
+end tmds_encoder;
+
+architecture beh of tmds_encoder is
+ signal n_ones_din : integer range 0 to 8;
+
+ signal xored, xnored : std_logic_vector(8 downto 0);
+ signal q_m : std_logic_vector(8 downto 0);
+
+ -- a positive value represents the excess number of 1's that have been transmitted
+ -- a negative value represents the excess number of 0's that have been transmitted
+ signal disparity : signed(3 downto 0) := to_signed(0, 4);
+ -- difference between 1's and 0's (/2 since the last bit is never used)
+ signal diff : signed(3 downto 0) := to_signed(0, 4);
+
+begin
+
+ -- ones counter for input data
+ process(din) is
+ variable c : integer range 0 to 8;
+ begin
+ c := 0;
+ for i in 0 to 7 loop
+ if din(i) = '1' then
+ c := c + 1;
+ end if;
+ end loop;
+ n_ones_din <= c;
+ end process;
+
+ -- create xor encodings
+ xored(0) <= din(0);
+ encode_xor : for i in 1 to 7 generate
+ begin
+ xored(i) <= din(i) xor xored(i - 1);
+ end generate;
+ xored(8) <= '1';
+
+ -- create xnor encodings
+ xnored(0) <= din(0);
+ encode_xnor : for i in 1 to 7 generate
+ begin
+ xnored(i) <= din(i) xnor xnored(i - 1);
+ end generate;
+ xnored(8) <= '0';
+
+ -- use xnored or xored data based on the ones
+ q_m <= xnored when n_ones_din > 4 or (n_ones_din = 4 and din(0) = '0') else xored;
+
+ -- ones counter for internal data
+ process(q_m) is
+ variable c : integer range 0 to 8;
+ begin
+ c := 0;
+ for i in 0 to 7 loop
+ if q_m(i) = '1' then
+ c := c + 1;
+ end if;
+ end loop;
+ diff <= to_signed(c-4, 4);
+ end process;
+
+ process(clk) is
+ begin
+ if rising_edge(clk) then
+ if blank = '1' then
+ case ctrl is
+ when "00" => dout <= "1101010100";
+ when "01" => dout <= "0010101011";
+ when "10" => dout <= "0101010100";
+ when others => dout <= "1010101011";
+ end case;
+ disparity <= (others => '0');
+ else
+ if disparity = 0 or diff = 0 then
+ -- xnored data
+ if q_m(8) = '0' then
+ dout <= "10" & not q_m(7 downto 0);
+ disparity <= disparity - diff;
+ -- xored data
+ else
+ dout <= "01" & q_m(7 downto 0);
+ disparity <= disparity + diff;
+ end if;
+ elsif (diff(diff'left) = '0' and disparity(disparity'left) = '0') or
+ (diff(diff'left) = '1' and disparity(disparity'left) = '1') then
+ dout <= '1' & q_m(8) & not q_m(7 downto 0);
+ if q_m(8) = '1' then
+ disparity <= disparity + 1 - diff;
+ else
+ disparity <= disparity - diff;
+ end if;
+ else
+ dout <= '0' & q_m;
+ if q_m(8) = '1' then
+ disparity <= disparity + diff;
+ else
+ disparity <= disparity - 1 + diff;
+ end if;
+ end if;
+ end if;
+ end if;
+ end process;
+end beh;
+
diff --git a/fpga/hp_lcd_driver/tmds_encoder_b.vhdl b/fpga/hp_lcd_driver/tmds_encoder_b.vhdl
new file mode 100644
index 0000000..a6e8b54
--- /dev/null
+++ b/fpga/hp_lcd_driver/tmds_encoder_b.vhdl
@@ -0,0 +1,143 @@
+--------------------------------------------------------------------------------
+--
+-- FileName: tmds_encoder.vhd
+-- Dependencies: none
+-- Design Software: Quartus II 64-bit Version 13.1.0 Build 162 SJ Full Version
+--
+-- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY
+-- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
+-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+-- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY
+-- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
+-- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
+-- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
+-- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
+-- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
+--
+-- Version History
+-- Version 1.0 8/7/2014 Scott Larson
+-- Initial Public Release
+-- Version 2.0 2/24/2014 Scott Larson
+-- Corrected bug in the control signals
+--
+--------------------------------------------------------------------------------
+
+LIBRARY ieee;
+USE ieee.std_logic_1164.all;
+
+ENTITY tmds_encoder IS
+ PORT(
+ clk : in std_logic;
+ sys_rst_n : in std_logic;
+ blank : in std_logic;
+ ctrl : in std_logic_vector(1 downto 0);
+ din : in std_logic_vector(7 downto 0);
+ dout : out std_logic_vector(9 downto 0)
+ );
+END tmds_encoder;
+
+ARCHITECTURE logic OF tmds_encoder IS
+ SIGNAL q_m : STD_LOGIC_VECTOR(8 DOWNTO 0); --internal data
+ SIGNAL ones_din : INTEGER RANGE 0 TO 8; --number of ones in the input data
+ SIGNAL ones_q_m : INTEGER RANGE 0 TO 8; --number of ones in the internal data
+ SIGNAL diff_q_m : INTEGER RANGE -8 TO 8; --number of ones minus the number of zeros in the internal data
+ SIGNAL disparity : INTEGER RANGE -16 TO 15; --disparity
+BEGIN
+
+ --count the ones in the input data byte
+ PROCESS(din)
+ VARIABLE ones: INTEGER RANGE 0 TO 8;
+ BEGIN
+ ones := 0;
+ FOR i IN 0 TO 7 LOOP
+ IF(din(i) = '1') THEN
+ ones := ones + 1;
+ END IF;
+ END LOOP;
+ ones_din <= ones;
+ END PROCESS;
+
+ --process interval data to minimize transitions
+ PROCESS(din, q_m, ones_din)
+ BEGIN
+ IF(ones_din > 4 OR (ones_din = 4 AND din(0) = '0')) THEN
+ q_m(0) <= din(0);
+ q_m(1) <= q_m(0) XNOR din(1);
+ q_m(2) <= q_m(1) XNOR din(2);
+ q_m(3) <= q_m(2) XNOR din(3);
+ q_m(4) <= q_m(3) XNOR din(4);
+ q_m(5) <= q_m(4) XNOR din(5);
+ q_m(6) <= q_m(5) XNOR din(6);
+ q_m(7) <= q_m(6) XNOR din(7);
+ q_m(8) <= '0';
+ ELSE
+ q_m(0) <= din(0);
+ q_m(1) <= q_m(0) XOR din(1);
+ q_m(2) <= q_m(1) XOR din(2);
+ q_m(3) <= q_m(2) XOR din(3);
+ q_m(4) <= q_m(3) XOR din(4);
+ q_m(5) <= q_m(4) XOR din(5);
+ q_m(6) <= q_m(5) XOR din(6);
+ q_m(7) <= q_m(6) XOR din(7);
+ q_m(8) <= '1';
+ END IF;
+ END PROCESS;
+
+ --count the ones in the internal data
+ PROCESS(q_m)
+ VARIABLE ones: INTEGER RANGE 0 TO 8;
+ BEGIN
+ ones := 0;
+ FOR i IN 0 TO 7 LOOP
+ IF(q_m(i) = '1') THEN
+ ones := ones + 1;
+ END IF;
+ END LOOP;
+ ones_q_m <= ones;
+ diff_q_m <= ones + ones - 8; --determine the difference between the number of ones and zeros
+ END PROCESS;
+
+ --determine output and new disparity
+ PROCESS(clk)
+ BEGIN
+ IF(clk'EVENT AND clk = '1') THEN
+ IF(blank = '0') THEN
+ IF(disparity = 0 OR ones_q_m = 4) THEN
+ IF(q_m(8) = '0') THEN
+ dout <= NOT q_m(8) & q_m(8) & NOT q_m(7 DOWNTO 0);
+ disparity <= disparity - diff_q_m;
+ ELSE
+ dout <= NOT q_m(8)& q_m(8 DOWNTO 0);
+ disparity <= disparity + diff_q_m;
+ END IF;
+ ELSE
+ IF((disparity > 0 AND ones_q_m > 4) OR (disparity < 0 AND ones_q_m < 4)) THEN
+ dout <= '1' & q_m(8) & NOT q_m(7 DOWNTO 0);
+ IF(q_m(8) = '0') THEN
+ disparity <= disparity - diff_q_m;
+ ELSE
+ disparity <= disparity - diff_q_m + 2;
+ END IF;
+ ELSE
+ dout <= '0' & q_m(8 DOWNTO 0);
+ IF(q_m(8) = '0') THEN
+ disparity <= disparity + diff_q_m - 2;
+ ELSE
+ disparity <= disparity + diff_q_m;
+ END IF;
+ END IF;
+ END IF;
+ ELSE
+ CASE ctrl IS
+ WHEN "00" => dout <= "1101010100";
+ WHEN "01" => dout <= "0010101011";
+ WHEN "10" => dout <= "0101010100";
+ WHEN "11" => dout <= "1010101011";
+ WHEN OTHERS => NULL;
+ END CASE;
+ disparity <= 0;
+ END IF;
+ END IF;
+ END PROCESS;
+
+END logic;
diff --git a/fpga/hp_lcd_driver/tmds_encoder_c.vhdl b/fpga/hp_lcd_driver/tmds_encoder_c.vhdl
new file mode 100644
index 0000000..03415aa
--- /dev/null
+++ b/fpga/hp_lcd_driver/tmds_encoder_c.vhdl
@@ -0,0 +1,162 @@
+--------------------------------------------------------------------------------
+--
+-- FileName: tmds_encoder.vhd
+-- Dependencies: none
+-- Design Software: Quartus II 64-bit Version 13.1.0 Build 162 SJ Full Version
+--
+-- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY
+-- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
+-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+-- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY
+-- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
+-- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
+-- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
+-- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
+-- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
+--
+-- Version History
+-- Version 1.0 8/7/2014 Scott Larson
+-- Initial Public Release
+-- Version 2.0 2/24/2014 Scott Larson
+-- Corrected bug in the control signals
+--
+--------------------------------------------------------------------------------
+
+LIBRARY ieee;
+USE ieee.std_logic_1164.all;
+
+ENTITY tmds_encoder IS
+ PORT(
+ clk : in std_logic;
+ sys_rst_n : in std_logic;
+ blank : in std_logic;
+ ctrl : in std_logic_vector(1 downto 0);
+ din : in std_logic_vector(7 downto 0);
+ dout : out std_logic_vector(9 downto 0)
+ );
+END tmds_encoder;
+
+ARCHITECTURE logic OF tmds_encoder IS
+ SIGNAL dind : std_logic_vector(7 downto 0);
+ SIGNAL q_m : STD_LOGIC_VECTOR(8 DOWNTO 0); --internal data
+ SIGNAL q_md : STD_LOGIC_VECTOR(8 DOWNTO 0); --internal data
+ SIGNAL ones_din : INTEGER RANGE 0 TO 8; --number of ones in the input data
+ SIGNAL ones_dind : INTEGER RANGE 0 TO 8; --number of ones in the input data
+ SIGNAL ones_q_md : INTEGER RANGE 0 TO 8; --number of ones in the internal data
+ SIGNAL diff_q_md : INTEGER RANGE -8 TO 8; --number of ones minus the number of zeros in the internal data
+ SIGNAL disparity : INTEGER RANGE -16 TO 15; --disparity
+BEGIN
+
+ --count the ones in the input data byte
+ PROCESS(din)
+ VARIABLE ones: INTEGER RANGE 0 TO 8;
+ BEGIN
+ ones := 0;
+ FOR i IN 0 TO 7 LOOP
+ IF(din(i) = '1') THEN
+ ones := ones + 1;
+ END IF;
+ END LOOP;
+ ones_din <= ones;
+ END PROCESS;
+
+ process(clk) begin
+ if rising_edge(clk) then
+ dind<=din;
+ ones_dind<=ones_din;
+ end if;
+ end process;
+
+
+ --process interval data to minimize transitions
+ PROCESS(dind, q_m, ones_dind)
+ BEGIN
+ IF(ones_dind > 4 OR (ones_dind = 4 AND dind(0) = '0')) THEN
+ q_m(0) <= dind(0);
+ q_m(1) <= q_m(0) XNOR dind(1);
+ q_m(2) <= q_m(1) XNOR dind(2);
+ q_m(3) <= q_m(2) XNOR dind(3);
+ q_m(4) <= q_m(3) XNOR dind(4);
+ q_m(5) <= q_m(4) XNOR dind(5);
+ q_m(6) <= q_m(5) XNOR dind(6);
+ q_m(7) <= q_m(6) XNOR dind(7);
+ q_m(8) <= '0';
+ ELSE
+ q_m(0) <= dind(0);
+ q_m(1) <= q_m(0) XOR dind(1);
+ q_m(2) <= q_m(1) XOR dind(2);
+ q_m(3) <= q_m(2) XOR dind(3);
+ q_m(4) <= q_m(3) XOR dind(4);
+ q_m(5) <= q_m(4) XOR dind(5);
+ q_m(6) <= q_m(5) XOR dind(6);
+ q_m(7) <= q_m(6) XOR dind(7);
+ q_m(8) <= '1';
+ END IF;
+ END PROCESS;
+
+ process(clk) begin
+ if rising_edge(clk) then
+ q_md<=q_m;
+ end if;
+ end process;
+
+
+
+ --count the ones in the internal data
+ PROCESS(q_md)
+ VARIABLE ones: INTEGER RANGE 0 TO 8;
+ BEGIN
+ ones := 0;
+ FOR i IN 0 TO 7 LOOP
+ IF(q_md(i) = '1') THEN
+ ones := ones + 1;
+ END IF;
+ END LOOP;
+ ones_q_md <= ones;
+ diff_q_md <= ones + ones - 8; --determine the difference between the number of ones and zeros
+ END PROCESS;
+
+ --determine output and new disparity
+ PROCESS(clk)
+ BEGIN
+ IF(clk'EVENT AND clk = '1') THEN
+ IF(blank = '0') THEN
+ IF(disparity = 0 OR ones_q_md = 4) THEN
+ IF(q_md(8) = '0') THEN
+ dout <= NOT q_md(8) & q_md(8) & NOT q_md(7 DOWNTO 0);
+ disparity <= disparity - diff_q_md;
+ ELSE
+ dout <= NOT q_md(8)& q_md(8 DOWNTO 0);
+ disparity <= disparity + diff_q_md;
+ END IF;
+ ELSE
+ IF((disparity > 0 AND ones_q_md > 4) OR (disparity < 0 AND ones_q_md < 4)) THEN
+ dout <= '1' & q_md(8) & NOT q_md(7 DOWNTO 0);
+ IF(q_md(8) = '0') THEN
+ disparity <= disparity - diff_q_md;
+ ELSE
+ disparity <= disparity - diff_q_md + 2;
+ END IF;
+ ELSE
+ dout <= '0' & q_md(8 DOWNTO 0);
+ IF(q_md(8) = '0') THEN
+ disparity <= disparity + diff_q_md - 2;
+ ELSE
+ disparity <= disparity + diff_q_md;
+ END IF;
+ END IF;
+ END IF;
+ ELSE
+ CASE ctrl IS
+ WHEN "00" => dout <= "1101010100";
+ WHEN "01" => dout <= "0010101011";
+ WHEN "10" => dout <= "0101010100";
+ WHEN "11" => dout <= "1010101011";
+ WHEN OTHERS => NULL;
+ END CASE;
+ disparity <= 0;
+ END IF;
+ END IF;
+ END PROCESS;
+
+END logic;
diff --git a/fpga/hp_lcd_driver/tmds_phy_artix7.vhdl b/fpga/hp_lcd_driver/tmds_phy_artix7.vhdl
index 604ec23..81e4b7e 100644
--- a/fpga/hp_lcd_driver/tmds_phy_artix7.vhdl
+++ b/fpga/hp_lcd_driver/tmds_phy_artix7.vhdl
@@ -77,8 +77,8 @@ begin
sr <= ld;
else
sr(8 downto 0) <= sr (9 downto 1);
- s <= sr(0);
end if;
+ s <= sr(0);
end if;
end process;
diff --git a/fpga/hp_lcd_driver/zynq7_ip/mmcm_0.tcl b/fpga/hp_lcd_driver/zynq7_ip/mmcm_0.tcl
index 089476d..f394b48 100644
--- a/fpga/hp_lcd_driver/zynq7_ip/mmcm_0.tcl
+++ b/fpga/hp_lcd_driver/zynq7_ip/mmcm_0.tcl
@@ -5,32 +5,33 @@ source $source_dir/zynq7_config.tcl
create_ip -name clk_wiz -vendor xilinx.com -library ip -version 6.0 -module_name mmcm_0 -dir $ip_dir
set_property -dict [list \
- CONFIG.PRIM_IN_FREQ {50} \
+ CONFIG.PRIM_IN_FREQ {50.0} \
CONFIG.CLKOUT2_USED {true} \
CONFIG.CLKOUT3_USED {true} \
CONFIG.CLKOUT4_USED {true} \
- CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {260} \
- CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {86.667} \
- CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {52} \
- CONFIG.CLKOUT4_REQUESTED_OUT_FREQ {26} \
+ CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {259.89583} \
+ CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {86.63194} \
+ CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {51.97917} \
+ CONFIG.CLKOUT4_REQUESTED_OUT_FREQ {25.98958} \
CONFIG.CLKIN1_JITTER_PS {200.0} \
- CONFIG.MMCM_CLKFBOUT_MULT_F {26.000} \
+ CONFIG.MMCM_DIVCLK_DIVIDE {3} \
+ CONFIG.MMCM_CLKFBOUT_MULT_F {62.375} \
CONFIG.MMCM_CLKIN1_PERIOD {20.000} \
CONFIG.MMCM_CLKIN2_PERIOD {10.0} \
- CONFIG.MMCM_CLKOUT0_DIVIDE_F {5.000} \
- CONFIG.MMCM_CLKOUT1_DIVIDE {15} \
- CONFIG.MMCM_CLKOUT2_DIVIDE {25} \
- CONFIG.MMCM_CLKOUT3_DIVIDE {50} \
+ CONFIG.MMCM_CLKOUT0_DIVIDE_F {4.000} \
+ CONFIG.MMCM_CLKOUT1_DIVIDE {12} \
+ CONFIG.MMCM_CLKOUT2_DIVIDE {20} \
+ CONFIG.MMCM_CLKOUT3_DIVIDE {40} \
CONFIG.NUM_OUT_CLKS {4} \
- CONFIG.CLKOUT1_JITTER {120.627} \
- CONFIG.CLKOUT1_PHASE_ERROR {154.678} \
- CONFIG.CLKOUT2_JITTER {146.190} \
- CONFIG.CLKOUT2_PHASE_ERROR {154.678} \
- CONFIG.CLKOUT3_JITTER {165.425} \
- CONFIG.CLKOUT3_PHASE_ERROR {154.678} \
- CONFIG.CLKOUT4_JITTER {202.151} \
- CONFIG.CLKOUT4_PHASE_ERROR {154.678} \
- ] [get_ips mmcm_0]
+ CONFIG.CLKOUT1_JITTER {233.255} \
+ CONFIG.CLKOUT1_PHASE_ERROR {408.086} \
+ CONFIG.CLKOUT2_JITTER {268.940} \
+ CONFIG.CLKOUT2_PHASE_ERROR {408.086} \
+ CONFIG.CLKOUT3_JITTER {287.637} \
+ CONFIG.CLKOUT3_PHASE_ERROR {408.086} \
+ CONFIG.CLKOUT4_JITTER {316.603} \
+ CONFIG.CLKOUT4_PHASE_ERROR {408.086} \
+ ] [get_ips mmcm_0]
generate_target all [get_ips]
diff --git a/fpga/hp_lcd_driver/zynq7_wrapper.vhdl b/fpga/hp_lcd_driver/zynq7_wrapper.vhdl
index 529a1b1..2c732a0 100644
--- a/fpga/hp_lcd_driver/zynq7_wrapper.vhdl
+++ b/fpga/hp_lcd_driver/zynq7_wrapper.vhdl
@@ -75,6 +75,7 @@ entity zynq7_wrapper is
red_led : out std_logic;
--in
+ clk_50m : in std_logic;
video : in std_logic_vector(input_video_width -1 downto 0);
hsync_in : in std_logic;
vsync_in : in std_logic;
@@ -142,7 +143,6 @@ architecture arch of zynq7_wrapper is
signal eth0_mdio_mdio_o : std_logic;
signal eth0_mdio_mdio_t : std_logic;
- signal clk_50m : std_logic;
signal sys_rst_n : std_logic;
signal vnc_clk : std_logic;
@@ -154,7 +154,6 @@ architecture arch of zynq7_wrapper is
begin
- clk_50m <= hp0_aclk;
common_i : entity work.common
generic map (
@@ -213,7 +212,7 @@ begin
FCLK_CLK0 => eth0_clk_o,
FCLK_CLK1 => gp0_aclk,
FCLK_CLK2 => hp0_aclk,
- FCLK_CLK2 => clk_50m,
+ FCLK_CLK2 => open,
FCLK_RESET1_N => gp0_nrst,
FCLK_RESET2_N => hp0_nrst,
FCLK_RESET3_N => sys_rst_n,