diff options
author | James McKenzie <root@ka-ata-killa.panaceas.james.local> | 2025-04-27 01:50:05 +0100 |
---|---|---|
committer | James McKenzie <root@ka-ata-killa.panaceas.james.local> | 2025-04-27 01:50:05 +0100 |
commit | 1b2a1318c6e00dacdb70682332558abf3263a5d2 (patch) | |
tree | 2d6a704c3f0f4e6eae26f26acc5d482cac6a386d | |
parent | 9b0c9c5c83a75c6190687a07177dfedcc2077fda (diff) | |
download | hp_instrument_lcds-1b2a1318c6e00dacdb70682332558abf3263a5d2.tar.gz hp_instrument_lcds-1b2a1318c6e00dacdb70682332558abf3263a5d2.tar.bz2 hp_instrument_lcds-1b2a1318c6e00dacdb70682332558abf3263a5d2.zip |
note quite working
-rw-r--r-- | spartan6/hp_lcd_driver/Makefile | 4 | ||||
-rw-r--r-- | spartan6/hp_lcd_driver/hp_lcd_driver.ucf | 15 | ||||
-rw-r--r-- | spartan6/hp_lcd_driver/hp_lcd_driver.vhdl | 87 | ||||
-rw-r--r-- | spartan6/hp_lcd_driver/output_analog.vhdl | 42 | ||||
-rw-r--r-- | spartan6/hp_lcd_driver/output_stage.vhdl | 78 | ||||
-rw-r--r-- | spartan6/hp_lcd_driver/pll_50_p10_p2_p.xco (renamed from spartan6/hp_lcd_driver/pll_50_91_18.xco) | 30 | ||||
-rw-r--r-- | spartan6/hp_lcd_driver/serdes_n_to_1.vhdl | 118 | ||||
-rw-r--r-- | spartan6/hp_lcd_driver/tmds_encoder.vhdl | 117 | ||||
-rw-r--r-- | spartan6/hp_lcd_driver/tmds_output.vhdl | 167 | ||||
-rw-r--r-- | spartan6/hp_lcd_driver/tmds_phy.vhdl | 66 |
10 files changed, 628 insertions, 96 deletions
diff --git a/spartan6/hp_lcd_driver/Makefile b/spartan6/hp_lcd_driver/Makefile index bd2180e..39963a2 100644 --- a/spartan6/hp_lcd_driver/Makefile +++ b/spartan6/hp_lcd_driver/Makefile @@ -3,10 +3,10 @@ include relpath.mk PART=xc6slx9-2-tqg144 TOP=hp_lcd_driver BUILD=build -VSRCS=synchronizer.vhdl debounce.vhdl edge_det.vhdl input_formatter.vhdl input_stage.vhdl output_formatter.vhdl output_analog.vhdl output_stage.vhdl hp_lcd_driver.vhdl +VSRCS=synchronizer.vhdl debounce.vhdl edge_det.vhdl input_formatter.vhdl input_stage.vhdl output_formatter.vhdl output_analog.vhdl serdes_n_to_1.vhdl tmds_encoder.vhdl tmds_phy.vhdl tmds_output.vhdl output_stage.vhdl hp_lcd_driver.vhdl UCF=hp_lcd_driver.ucf UT=hp_lcd_driver.ut -IPSRCS= pll_50_80.xco pll_50_91_18.xco vram.xco +IPSRCS= pll_50_80.xco pll_50_p10_p2_p.xco vram.xco DESIGN_NAME=${TOP} ISE_HOME=/software/apps/xilinx/ISE/14.7/ISE_DS/ISE ISE_BINDIR_32=${ISE_HOME}/bin/lin diff --git a/spartan6/hp_lcd_driver/hp_lcd_driver.ucf b/spartan6/hp_lcd_driver/hp_lcd_driver.ucf index 8e67eae..e4a5fc2 100644 --- a/spartan6/hp_lcd_driver/hp_lcd_driver.ucf +++ b/spartan6/hp_lcd_driver/hp_lcd_driver.ucf @@ -1,3 +1,14 @@ -NET "hdmi_r" IOSTANDARD = LVCMOS33; -NET "hdmi_b" LOC = P67; +#NET "hdmi_r" IOSTANDARD = LVCMOS33; +#NET "hdmi_b" LOC = P67; +NET "clk_50m_in" IOSTANDARD = LVCMOS33; +NET "sys_rst_n" IOSTANDARD = LVCMOS33; +NET "video(0)" IOSTANDARD = LVCMOS33; +NET "video(1)" IOSTANDARD = LVCMOS33; +NET "hsync_in" IOSTANDARD = LVCMOS33; +NET "vsync_in" IOSTANDARD = LVCMOS33; +NET "r_out" IOSTANDARD = LVCMOS33; +NET "b_out" IOSTANDARD = LVCMOS33; +NET "g_out" IOSTANDARD = LVCMOS33; +NET "hsync_out" IOSTANDARD = LVCMOS33; +NET "vsync_out" IOSTANDARD = LVCMOS33; diff --git a/spartan6/hp_lcd_driver/hp_lcd_driver.vhdl b/spartan6/hp_lcd_driver/hp_lcd_driver.vhdl index 7f52ca1..a5fc8d7 100644 --- a/spartan6/hp_lcd_driver/hp_lcd_driver.vhdl +++ b/spartan6/hp_lcd_driver/hp_lcd_driver.vhdl @@ -41,15 +41,20 @@ entity hp_lcd_driver is video : in std_logic_vector(video_width-1 downto 0); hsync_in : in std_logic; vsync_in : in std_logic; - red_out : out std_logic; - blue_out : out std_logic; - green_out : out std_logic; + r_out : out std_logic; + b_out : out std_logic; + g_out : out std_logic; hsync_out : out std_logic; vsync_out : out std_logic; - hdmi_c : out std_logic; - hdmi_r : out std_logic; - hdmi_g : out std_logic; - hdmi_b : out std_logic); + hdmi_c_p : out std_logic; + hdmi_c_n : out std_logic; + hdmi_r_p : out std_logic; + hdmi_r_n : out std_logic; + hdmi_g_p : out std_logic; + hdmi_g_n : out std_logic; + hdmi_b_p : out std_logic; + hdmi_b_n : out std_logic); + end hp_lcd_driver; architecture Behavioral of hp_lcd_driver is @@ -61,15 +66,19 @@ architecture Behavioral of hp_lcd_driver is signal rd_addr : std_logic_vector(addr_width-1 downto 0); signal rd_data : std_logic_vector(video_width-1 downto 0); - signal red : std_logic_vector(7 downto 0); - signal green : std_logic_vector(7 downto 0); - signal blue : std_logic_vector(7 downto 0); + signal r : std_logic_vector(7 downto 0); + signal g : std_logic_vector(7 downto 0); + signal b : std_logic_vector(7 downto 0); signal i_clk : std_logic; - signal o_clk_5 : std_logic; + + signal o_clk_locked : std_logic; +-- signal o_clk_ub : std_logic; signal o_clk : std_logic; - signal o_clk_n : std_logic; +-- signal o_clk_x2_ub : std_logic; + signal o_clk_x2 : std_logic; + signal o_clk_x10 : std_logic; signal clk_50m : std_logic; @@ -86,7 +95,6 @@ begin ); - ipll : entity work.pll_50_80 port map ( reset => sys_rst, @@ -94,14 +102,25 @@ begin clk_80_out => i_clk ); - opll : entity work.pll_50_91_18 + opll : entity work.pll_50_p10_p2_p port map ( reset => sys_rst, clk_50_in => clk_50m, - clk_91_666_out => o_clk_5, - clk_18_333_out => o_clk + pclk_x10_out => o_clk_x10, + pclk_x2_out => o_clk_x2, + pclk_out => o_clk, + LOCKED => o_clk_locked ); +-- o_clk_x2_buf: BUFG port map ( +-- I=>o_clk_x2_ub, +-- O=>o_clk_x2 +-- ); +-- o_clk_buf: BUFG port map ( +-- I=>o_clk_ub, +-- O=>o_clk +-- ); + input0 : entity work.input_stage generic map( video_width => video_width, @@ -137,6 +156,15 @@ begin ); + r<= x"ff" when rd_data(1)='1' else + x"00"; + g<= x"ff" when rd_data(0)='1' else + x"ff" when rd_data(1)='1' else + x"00"; + b<=x"00"; + + + output0 : entity work.output_stage -- works at 60Hz xrandr --newmode "$M" 18.24 384 400 440 600 592 593 596 613 -HSync +Vsync @@ -154,22 +182,29 @@ begin v_stride => 384 ) port map( + clk_locked => o_clk_locked, clk => o_clk, + clk_x2 => o_clk_x2, + clk_x10 => o_clk_x10, sys_rst_n => sys_rst_n, vsync_in => vsync_in, - red_in => red, - green_in => green, - blue_in => blue, + r_in => r, + g_in => g, + b_in => b, addr_out => rd_addr, - red_out => red_out, - green_out => green_out, - blue_out => blue_out, + r_out => r_out, + g_out => g_out, + b_out => b_out, hsync_out => hsync_out, vsync_out => vsync_out, - hdmi_r => hdmi_r, - hdmi_g => hdmi_g, - hdmi_b => hdmi_b, - hdmi_c => hdmi_c +hdmi_c_p=> hdmi_c_p, +hdmi_c_n=> hdmi_c_n, +hdmi_r_p=> hdmi_r_p, +hdmi_r_n=> hdmi_r_n, +hdmi_g_p=> hdmi_g_p, +hdmi_g_n=> hdmi_g_n, +hdmi_b_p=> hdmi_b_p, +hdmi_b_n=> hdmi_b_n ); diff --git a/spartan6/hp_lcd_driver/output_analog.vhdl b/spartan6/hp_lcd_driver/output_analog.vhdl index 35b509f..29870cf 100644 --- a/spartan6/hp_lcd_driver/output_analog.vhdl +++ b/spartan6/hp_lcd_driver/output_analog.vhdl @@ -9,16 +9,16 @@ entity output_analog is clk : in std_logic; sys_rst_n : in std_logic; - red_in : in std_logic; - green_in : in std_logic; - blue_in : in std_logic; + r_in : in std_logic; + g_in : in std_logic; + b_in : in std_logic; hsync_in : in std_logic; vsync_in : in std_logic; blank_in : in std_logic; - red_out : out std_logic; - green_out : out std_logic; - blue_out : out std_logic; + r_out : out std_logic; + g_out : out std_logic; + b_out : out std_logic; hsync_out : out std_logic; vsync_out : out std_logic ); @@ -28,9 +28,9 @@ end output_analog; architecture beh of output_analog is - signal red_r : std_logic; - signal green_r : std_logic; - signal blue_r : std_logic; + signal r_r : std_logic; + signal g_r : std_logic; + signal b_r : std_logic; signal hsync_r : std_logic; signal vsync_r : std_logic; @@ -43,16 +43,16 @@ begin process (sys_rst_n, clk) begin if sys_rst_n = '0' then - red_r <= '0'; - green_r <= '0'; - blue_r <= '0'; + r_r <= '0'; + g_r <= '0'; + b_r <= '0'; hsync_r <= '0'; vsync_r <= '0'; blank_r <= '0'; elsif rising_edge(clk) then - red_r <= red_in; - green_r <= green_in; - blue_r <= blue_in; + r_r <= r_in; + g_r <= g_in; + b_r <= b_in; hsync_r <= hsync_in; vsync_r <= vsync_in; blank_r <= blank_in; @@ -64,15 +64,15 @@ begin process (sys_rst_n, clk) begin if sys_rst_n = '0' then - red_out <= '0'; - green_out <= '0'; - blue_out <= '0'; + r_out <= '0'; + g_out <= '0'; + b_out <= '0'; hsync_out <= '0'; vsync_out <= '0'; elsif rising_edge(clk) then - red_out <= red_r and not blank_r; - green_out <= green_r and not blank_r; - blue_out <= blue_r and not blank_r; + r_out <= r_r and not blank_r; + g_out <= g_r and not blank_r; + b_out <= b_r and not blank_r; hsync_out <= hsync_r; vsync_out <= vsync_r; end if; diff --git a/spartan6/hp_lcd_driver/output_stage.vhdl b/spartan6/hp_lcd_driver/output_stage.vhdl index d5cf87a..8c33685 100644 --- a/spartan6/hp_lcd_driver/output_stage.vhdl +++ b/spartan6/hp_lcd_driver/output_stage.vhdl @@ -24,35 +24,41 @@ entity output_stage is ); port ( + clk_locked : in std_logic; clk : in std_logic; + clk_x2 : in std_logic; + clk_x10 : in std_logic; sys_rst_n : in std_logic; vsync_in : in std_logic; addr_out : out std_logic_vector(addr_width - 1 downto 0); - red_in : in std_logic_vector(7 downto 0); - green_in : in std_logic_vector(7 downto 0); - blue_in : in std_logic_vector(7 downto 0); + r_in : in std_logic_vector(7 downto 0); + g_in : in std_logic_vector(7 downto 0); + b_in : in std_logic_vector(7 downto 0); - red_out : out std_logic; - green_out : out std_logic; - blue_out : out std_logic; + r_out : out std_logic; + g_out : out std_logic; + b_out : out std_logic; hsync_out : out std_logic; vsync_out : out std_logic; - hdmi_c : out std_logic; - hdmi_r : out std_logic; - hdmi_g : out std_logic; - hdmi_b : out std_logic + hdmi_c_p : out std_logic; + hdmi_c_n : out std_logic; + hdmi_r_p : out std_logic; + hdmi_r_n : out std_logic; + hdmi_g_p : out std_logic; + hdmi_g_n : out std_logic; + hdmi_b_p : out std_logic; + hdmi_b_n : out std_logic ); end output_stage; architecture beh of output_stage is - signal n_clk : std_logic; signal s_vsync_in : std_logic; signal d_vsync_in : std_logic; @@ -113,41 +119,53 @@ begin output_analog : entity work.output_analog port map( sys_rst_n => sys_rst_n, + clk => clk, hsync_in => hsync, vsync_in => vsync, blank_in => blank, - red_in => green_in(7), - green_in => green_in(6), - blue_in => blue_in(7), + r_in => g_in(7), + g_in => g_in(6), + b_in => b_in(7), - red_out => red_out, - green_out => green_out, - blue_out => blue_out, + r_out => r_out, + g_out => g_out, + b_out => b_out, hsync_out => hsync_out, vsync_out => vsync_out ); +output_tmds: entity work.tmds_output + port map ( + sys_rst_n => sys_rst_n, + pclk_locked => clk_locked, + pclk => clk, + pclk_x2 => clk_x2, + pclk_x10 => clk_x10, + + r_in => r_in, + g_in => g_in, + b_in => b_in, + hsync => hsync, + vsync => vsync, + blank => blank, + + tmds_c_out_p => hdmi_c_p, + tmds_c_out_n => hdmi_c_n, + tmds_r_out_p => hdmi_r_p, + tmds_r_out_n => hdmi_r_n, + tmds_g_out_p => hdmi_g_p, + tmds_g_out_n => hdmi_g_n, + tmds_b_out_p => hdmi_b_p, + tmds_b_out_n => hdmi_b_n +); - n_clk <= not clk; - hdmi_r <= hsync; - hdmi_g <= vsync; - hdmi_b <= green_in(7); - o_clk_buf : ODDR2 - port map ( - D0 => '1', - D1 => '0', - C0 => clk, - C1 => n_clk, - CE => '1', - Q => hdmi_c - ); end beh; diff --git a/spartan6/hp_lcd_driver/pll_50_91_18.xco b/spartan6/hp_lcd_driver/pll_50_p10_p2_p.xco index 1d02dba..9d75f11 100644 --- a/spartan6/hp_lcd_driver/pll_50_91_18.xco +++ b/spartan6/hp_lcd_driver/pll_50_p10_p2_p.xco @@ -1,7 +1,7 @@ ############################################################## # # Xilinx Core Generator version 14.7 -# Date: Sat Apr 26 17:51:02 2025 +# Date: Sat Apr 26 23:17:11 2025 # ############################################################## # @@ -41,11 +41,11 @@ SELECT Clocking_Wizard xilinx.com:ip:clk_wiz:3.6 # BEGIN Parameters CSET calc_done=DONE CSET clk_in_sel_port=CLK_IN_SEL -CSET clk_out1_port=clk_91_666_out +CSET clk_out1_port=pclk_x10_out CSET clk_out1_use_fine_ps_gui=false -CSET clk_out2_port=clk_18_333_out +CSET clk_out2_port=pclk_x2_out CSET clk_out2_use_fine_ps_gui=false -CSET clk_out3_port=CLK_OUT3 +CSET clk_out3_port=pclk_out CSET clk_out3_use_fine_ps_gui=false CSET clk_out4_port=CLK_OUT4 CSET clk_out4_use_fine_ps_gui=false @@ -74,14 +74,14 @@ CSET clkout1_requested_out_freq=91.667 CSET clkout1_requested_phase=0.000 CSET clkout2_drives=BUFG CSET clkout2_requested_duty_cycle=50.000 -CSET clkout2_requested_out_freq=18.333 +CSET clkout2_requested_out_freq=36.667 CSET clkout2_requested_phase=0.000 CSET clkout2_used=true CSET clkout3_drives=BUFG CSET clkout3_requested_duty_cycle=50.000 -CSET clkout3_requested_out_freq=100.000 +CSET clkout3_requested_out_freq=18.333 CSET clkout3_requested_phase=0.000 -CSET clkout3_used=false +CSET clkout3_used=true CSET clkout4_drives=BUFG CSET clkout4_requested_duty_cycle=50.000 CSET clkout4_requested_out_freq=100.000 @@ -103,17 +103,17 @@ CSET clkout7_requested_out_freq=100.000 CSET clkout7_requested_phase=0.000 CSET clkout7_used=false CSET clock_mgr_type=AUTO -CSET component_name=pll_50_91_18 +CSET component_name=pll_50_p10_p2_p CSET daddr_port=DADDR CSET dclk_port=DCLK CSET dcm_clk_feedback=2X CSET dcm_clk_out1_port=CLKFX -CSET dcm_clk_out2_port=CLK2X -CSET dcm_clk_out3_port=CLK0 +CSET dcm_clk_out2_port=CLKDV +CSET dcm_clk_out3_port=CLK2X CSET dcm_clk_out4_port=CLK0 CSET dcm_clk_out5_port=CLK0 CSET dcm_clk_out6_port=CLK0 -CSET dcm_clkdv_divide=2.0 +CSET dcm_clkdv_divide=15.0 CSET dcm_clkfx_divide=6 CSET dcm_clkfx_multiply=11 CSET dcm_clkgen_clk_out1_port=CLKFX @@ -189,7 +189,7 @@ CSET mmcm_notes=None CSET mmcm_ref_jitter1=0.010 CSET mmcm_ref_jitter2=0.010 CSET mmcm_startup_wait=false -CSET num_out_clks=2 +CSET num_out_clks=3 CSET override_dcm=false CSET override_dcm_clkgen=false CSET override_mmcm=false @@ -203,10 +203,10 @@ CSET pll_clkin_period=20.000 CSET pll_clkout0_divide=6 CSET pll_clkout0_duty_cycle=0.500 CSET pll_clkout0_phase=0.000 -CSET pll_clkout1_divide=30 +CSET pll_clkout1_divide=15 CSET pll_clkout1_duty_cycle=0.500 CSET pll_clkout1_phase=0.000 -CSET pll_clkout2_divide=1 +CSET pll_clkout2_divide=30 CSET pll_clkout2_duty_cycle=0.500 CSET pll_clkout2_phase=0.000 CSET pll_clkout3_divide=1 @@ -266,4 +266,4 @@ CSET use_status=false MISC pkg_timestamp=2012-05-10T12:44:55Z # END Extra information GENERATE -# CRC: 95fa1f8c +# CRC: d987c511 diff --git a/spartan6/hp_lcd_driver/serdes_n_to_1.vhdl b/spartan6/hp_lcd_driver/serdes_n_to_1.vhdl new file mode 100644 index 0000000..dccf6af --- /dev/null +++ b/spartan6/hp_lcd_driver/serdes_n_to_1.vhdl @@ -0,0 +1,118 @@ +library ieee; +use ieee.std_logic_1164.all; +use IEEE.NUMERIC_STD.all; + +library UNISIM; +use UNISIM.vcomponents.all; + + +entity serdes_n_to_1 is + generic ( + SF : natural :=8 + ); + port ( + +ioclk: in std_logic; +serdesstrobe: in std_logic; +reset : in std_logic; +gclk : in std_logic; +datain : in std_logic_vector(SF-1 downto 0); +iob_data_out : out std_logic +); +end serdes_n_to_1; + + +architecture beh of serdes_n_to_1 is + +signal cascade_di:std_logic; +signal cascade_do:std_logic; +signal cascade_ti:std_logic; +signal cascade_to:std_logic; +signal mdatain:std_logic_vector(8 downto 0); + +begin + +datain_for_1 : for b in 0 to SF -1 generate + mdatain(b)<=datain(b); +end generate; + +datain_for_2 : for b in SF to 8 generate + mdatain(b)<='0'; +end generate; + +-- mdatain <= ( SF-1 downto 0 => datain, others =>'0'); + + oserdes_m : OSERDES2 + generic map ( + DATA_WIDTH => SF, + DATA_RATE_OQ => "SDR", + DATA_RATE_OT => "SDR", + SERDES_MODE => "MASTER", + OUTPUT_MODE => "DIFFERENTIAL" + ) + port map ( + OQ => iob_data_out, + OCE => '1', + CLK0 => ioclk, + CLK1 => '0', + IOCE => serdesstrobe, + RST => reset, + CLKDIV => gclk, + D4 => mdatain(7), + D3 => mdatain(6), + D2 => mdatain(5), + D1 => mdatain(4), +-- TQ => , + T1 => '0', + T2 => '0', + T3 => '0', + T4 => '0', + TRAIN => '0', + TCE => '1', + SHIFTIN1 => '1', -- Dummy input in Master + SHIFTIN2 => '1', -- Dummy input in Master + SHIFTIN3 => cascade_do, -- Cascade output D data from slave + SHIFTIN4 => cascade_to, -- Cascade output T data from slave + SHIFTOUT1 => cascade_di, -- Cascade input D data to slave + SHIFTOUT2 => cascade_ti -- Cascade input T data to slave +-- SHIFTOUT3 => , -- Dummy output in Master +-- SHIFTOUT4 => -- Dummy output in Master + ); + + oserdes_s : OSERDES2 + generic map ( + DATA_WIDTH=>SF, -- SERDES word width. This should match the setting is BUFPLL + DATA_RATE_OQ=>"SDR", -- <SDR>, DDR + DATA_RATE_OT =>"SDR", -- <SDR>, DDR + SERDES_MODE =>"SLAVE", -- <DEFAULT>, MASTER, SLAVE + OUTPUT_MODE =>"DIFFERENTIAL" + ) + port map ( +-- OQ => , + OCE => '1', + CLK0 => ioclk, + CLK1 => '0', + IOCE => serdesstrobe, + RST => reset, + CLKDIV => gclk, + D4 => mdatain(3), + D3 => mdatain(2), + D2 => mdatain(1), + D1 => mdatain(0), +-- TQ => , + T1 => '0', + T2 => '0', + T3 => '0', + T4 => '0', + TRAIN => '0', + TCE => '1', + SHIFTIN1 => cascade_di, -- Cascade input D from Master + SHIFTIN2 => cascade_ti, -- Cascade input T from Master + SHIFTIN3 => '1', -- Dummy input in Slave + SHIFTIN4 => '1', -- Dummy input in Slave +-- SHIFTOUT1 => , -- Dummy output in Slave +-- SHIFTOUT2 => , -- Dummy output in Slave + SHIFTOUT3 => cascade_do, -- Cascade output D data to Master + SHIFTOUT4 => cascade_to) ; -- Cascade output T data to Master + +end beh; diff --git a/spartan6/hp_lcd_driver/tmds_encoder.vhdl b/spartan6/hp_lcd_driver/tmds_encoder.vhdl new file mode 100644 index 0000000..0a83498 --- /dev/null +++ b/spartan6/hp_lcd_driver/tmds_encoder.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/spartan6/hp_lcd_driver/tmds_output.vhdl b/spartan6/hp_lcd_driver/tmds_output.vhdl new file mode 100644 index 0000000..3d169ee --- /dev/null +++ b/spartan6/hp_lcd_driver/tmds_output.vhdl @@ -0,0 +1,167 @@ +library ieee; +use ieee.std_logic_1164.all; +use IEEE.NUMERIC_STD.all; + +library UNISIM; +use UNISIM.vcomponents.all; + + +entity tmds_output is + port ( + sys_rst_n : in std_logic; + pclk_locked: in std_logic; + pclk: in std_logic; + pclk_x2: in std_logic; + pclk_x10: in std_logic; + r_in: in std_logic_vector(7 downto 0); + g_in: in std_logic_vector(7 downto 0); + b_in: in std_logic_vector(7 downto 0); + hsync: in std_logic; + vsync: in std_logic; + blank: in std_logic; + tmds_c_out_p: out std_logic; + tmds_c_out_n: out std_logic; + tmds_r_out_p: out std_logic; + tmds_r_out_n: out std_logic; + tmds_g_out_p: out std_logic; + tmds_g_out_n: out std_logic; + tmds_b_out_p: out std_logic; + tmds_b_out_n: out std_logic +); +end tmds_output; + + +architecture beh of tmds_output is + +signal ctrl: std_logic_vector(1 downto 0); +signal r_p10:std_logic_vector(9 downto 0); +signal g_p10:std_logic_vector(9 downto 0); +signal b_p10:std_logic_vector(9 downto 0); + +signal phy_reset: std_logic; +signal bufpll_lock:std_logic; +signal upper:std_logic; +signal ioclk: std_logic; +signal serdesstrobe:std_logic; + +begin + + + ctrl <= vsync & hsync; + + + + + enc_r: entity work.tmds_encoder + port map ( + sys_rst_n => sys_rst_n, + clk => pclk, + ctrl => ctrl, + blank => blank, + din => r_in, + dout => r_p10 + ); + + + enc_g: entity work.tmds_encoder + port map ( + sys_rst_n => sys_rst_n, + clk => pclk, + ctrl => "11", + blank => blank, + din => g_in, + dout => g_p10 + ); + + + + enc_b: entity work.tmds_encoder + port map ( + sys_rst_n => sys_rst_n, + clk => pclk, + ctrl => "11", + blank => blank, + din => b_in, + dout => b_p10 + ); + + +ioclk_buf: BUFPLL + generic map ( DIVIDE => 5) + port map ( + PLLIN => pclk_x10, + GCLK => pclk_x2, + LOCKED => pclk_locked, + IOCLK => ioclk, + SERDESSTROBE => serdesstrobe + ); + + + phy_reset <= not sys_rst_n or not bufpll_lock; + + process (pclk_x2) begin + if phy_reset='1' then + upper<='1'; + elsif rising_edge(pclk_x2) then + upper<= not upper; + end if ; + end process; + + +--phy_c : entity work.tmds_phy +-- port map ( +-- reset => phy_reset, +-- pclk_x2 => pclk_x2, +-- serdesstrobe => serdesstrobe, +-- ioclk => ioclk, +-- upper => upper, +-- din => "1111100000", +-- tmds_out_p => tmds_c_out_p, +-- tmds_out_n => tmds_c_out_n +--); +tmds_c_out_p <= '0'; +tmds_c_out_n <= '1'; + +phy_r : entity work.tmds_phy + port map ( + reset => phy_reset, + pclk_x2 => pclk_x2, + serdesstrobe => serdesstrobe, + ioclk=>ioclk, + upper=>upper, + din => r_p10, + tmds_out_p => tmds_r_out_p, + tmds_out_n => tmds_r_out_n +); + + +phy_g : entity work.tmds_phy + port map ( + reset => phy_reset, + pclk_x2 => pclk_x2, + serdesstrobe => serdesstrobe, + ioclk=>ioclk, + upper=>upper, + din => g_p10, + tmds_out_p => tmds_g_out_p, + tmds_out_n => tmds_g_out_n +); + + +phy_b : entity work.tmds_phy + port map ( + reset => phy_reset, + pclk_x2 => pclk_x2, + serdesstrobe => serdesstrobe, + ioclk=>ioclk, + upper=>upper, + din => b_p10, + tmds_out_p => tmds_b_out_p, + tmds_out_n => tmds_b_out_n +); + + + + + +end beh; diff --git a/spartan6/hp_lcd_driver/tmds_phy.vhdl b/spartan6/hp_lcd_driver/tmds_phy.vhdl new file mode 100644 index 0000000..84c37f9 --- /dev/null +++ b/spartan6/hp_lcd_driver/tmds_phy.vhdl @@ -0,0 +1,66 @@ +library ieee; +use ieee.std_logic_1164.all; +use IEEE.NUMERIC_STD.all; + +library UNISIM; +use UNISIM.vcomponents.all; + +entity tmds_phy is + port ( + reset : in std_logic; + pclk_x2: in std_logic; + ioclk: in std_logic; + serdesstrobe: in std_logic; + din: in std_logic_vector(9 downto 0); + upper: in std_logic; + tmds_out_p: out std_logic; + tmds_out_n: out std_logic +); +end tmds_phy; + + +architecture beh of tmds_phy is + +signal din_s:std_logic_vector(9 downto 0); +signal p5_n:std_logic_vector(4 downto 0); +signal p5:std_logic_vector(4 downto 0); +signal s:std_logic; + + + +begin + + process (pclk_x2) begin + if rising_edge(pclk_x2) then + if upper='1' then + din_s <= din; + p5 <= din_s(9 downto 5); + p5_n <= din_s(4 downto 0); + else + p5<=p5_n; + end if; + end if; + end process; + + + serdes : entity work.serdes_n_to_1 + generic map(SF=>5) + port map ( + ioclk => ioclk, + serdesstrobe => serdesstrobe, + reset => reset, + gclk => pclk_x2, + datain => p5, + iob_data_out =>s + ); + + obuf : OBUFDS + generic map ( IOSTANDARD => "TMDS_33") + port map ( + I=>s, + O=>tmds_out_p, + OB=>tmds_out_n + ); + + +end beh; |