From 9dd59b9990c94cf858ee4a0fdaded44435dd8876 Mon Sep 17 00:00:00 2001 From: David Banks Date: Sat, 9 Jun 2018 11:33:01 +0100 Subject: [PATCH] CPLD Normal: Dropped sp_default and made more similar to alternative Change-Id: Idd72c5478b49bd2977b49b8a3640ed243c259ac9 --- vhdl/RGBtoHDMI.vhdl | 211 ++++++++++++++++++++++++-------------------- vhdl/fitting.notes | 27 ++++-- 2 files changed, 134 insertions(+), 104 deletions(-) diff --git a/vhdl/RGBtoHDMI.vhdl b/vhdl/RGBtoHDMI.vhdl index a4c85abc..14df6891 100644 --- a/vhdl/RGBtoHDMI.vhdl +++ b/vhdl/RGBtoHDMI.vhdl @@ -1,12 +1,12 @@ ---------------------------------------------------------------------------------- -- Engineer: David Banks -- --- Create Date: 14/4/2017 +-- Create Date: 9/6/2018 -- Module Name: RGBtoHDMI CPLD -- Project Name: RGBtoHDMI -- Target Devices: XC9572XL -- --- Version: 0.50 +-- Version: 0.9 -- ---------------------------------------------------------------------------------- library ieee; @@ -54,14 +54,16 @@ architecture Behavorial of RGBtoHDMI is constant default_offset : unsigned(11 downto 0) := to_unsigned(4096 - 64 * 17 + 6, 12); -- For Mode 7 - constant mode7_offset : unsigned(11 downto 0) := to_unsigned(4096 - 96 * 12 + 4, 12); + constant mode7_offset : unsigned(11 downto 0) := to_unsigned(4096 - 96 * 12 + 4, 12); -- Sampling points - constant INIT_SAMPLING_POINTS : std_logic_vector(20 downto 0) := "011011011011011011011"; + constant INIT_SAMPLING_POINTS : std_logic_vector(17 downto 0) := "011011011011011011"; - signal shift : std_logic_vector(11 downto 0); + signal shift_R : std_logic_vector(3 downto 0); + signal shift_G : std_logic_vector(3 downto 0); + signal shift_B : std_logic_vector(3 downto 0); - signal CSYNC1 : std_logic; + signal CSYNC1 : std_logic; -- The sampling counter runs at 96MHz -- - In modes 0..6 it is 6x the pixel clock @@ -74,45 +76,43 @@ architecture Behavorial of RGBtoHDMI is -- 4. Handles double buffering of alternative quad pixels (bit 5) -- -- At the moment we don't count pixels with the line, the Pi does that - signal counter : unsigned(11 downto 0); + signal counter : unsigned(11 downto 0); -- Sample point register; -- - -- In Modes 0..6 each pixel lasts 6 clocks (96MHz / 16MHz). The original - -- pixel clock is a clean 16Mhz clock, so only one sample point is needed. - -- -- In Mode 7 each pixel lasts 8 clocks (96MHz / 12MHz). The original -- pixel clock is a regenerated 6Mhz clock, and both edges are used. -- Due to the way it is generated, there are three distinct phases, - -- hence three sampling points are used. - signal sp_reg : std_logic_vector(20 downto 0) := INIT_SAMPLING_POINTS; + -- each with different rising/falling edge speeds, hence six sampling + -- points are used. + -- + -- In Modes 0..6 each pixel lasts 6 clocks (96MHz / 16MHz). The original + -- pixel clock is a clean 16Mhz clock, so only one sample point is needed. + -- To achieve this, all six values are set to be the same. This minimises + -- the logic in the CPLD. + signal sp_reg : std_logic_vector(17 downto 0) := INIT_SAMPLING_POINTS; - -- Break out of sp - signal sp : std_logic_vector(2 downto 0); - signal mode7_sp_A : std_logic_vector(2 downto 0); - signal mode7_sp_B : std_logic_vector(2 downto 0); - signal mode7_sp_C : std_logic_vector(2 downto 0); - signal mode7_sp_D : std_logic_vector(2 downto 0); - signal mode7_sp_E : std_logic_vector(2 downto 0); - signal mode7_sp_F : std_logic_vector(2 downto 0); - signal default_sp : std_logic_vector(2 downto 0); + -- Break out of sp_reg + signal offset_A : std_logic_vector(2 downto 0); + signal offset_B : std_logic_vector(2 downto 0); + signal offset_C : std_logic_vector(2 downto 0); + signal offset_D : std_logic_vector(2 downto 0); + signal offset_E : std_logic_vector(2 downto 0); + signal offset_F : std_logic_vector(2 downto 0); - -- Index to allow cycling between A, B and C in Mode 7 - signal sp_index : std_logic_vector(2 downto 0); + -- Pipelined offset mux output + signal offset : std_logic_vector(2 downto 0); + + -- Index to cycle through offsets A..F + signal index : std_logic_vector(2 downto 0); -- Sample pixel on next clock; pipelined to reduce the number of product terms - signal sample : std_logic; + signal sample : std_logic; - -- Load quad on next clock; pipelined to reduce the number of product terms - signal load : std_logic; - - -- Toggle on each quad loading - signal toggle : std_logic; - - - signal R : std_logic; - signal G : std_logic; - signal B : std_logic; + -- RGB Input Mux + signal R : std_logic; + signal G : std_logic; + signal B : std_logic; begin @@ -120,19 +120,16 @@ begin G <= G1 when elk = '1' else G0; B <= B1 when elk = '1' else B0; - mode7_sp_A <= sp_reg(2 downto 0); - mode7_sp_B <= sp_reg(5 downto 3); - mode7_sp_C <= sp_reg(8 downto 6); - mode7_sp_D <= sp_reg(11 downto 9); - mode7_sp_E <= sp_reg(14 downto 12); - mode7_sp_F <= sp_reg(17 downto 15); - default_sp <= sp_reg(20 downto 18); + offset_A <= sp_reg(2 downto 0); + offset_B <= sp_reg(5 downto 3); + offset_C <= sp_reg(8 downto 6); + offset_D <= sp_reg(11 downto 9); + offset_E <= sp_reg(14 downto 12); + offset_F <= sp_reg(17 downto 15); -- Shift the bits in LSB first process(sp_clk, SW1) begin - --if SW1 = '0' then - -- sp_reg <= INIT_SAMPLING_POINTS; if rising_edge(sp_clk) then if sp_clken = '1' then sp_reg <= sp_data & sp_reg(sp_reg'left downto sp_reg'right + 1); @@ -143,23 +140,10 @@ begin process(clk) begin if rising_edge(clk) then + -- synchronize CSYNC to the sampling clock CSYNC1 <= S; - -- quad load - if counter(4 downto 0) = "00000" then - load <= '1'; - else - load <= '0'; - end if; - - -- sample shift - if counter(2 downto 0) = unsigned(sp) then - sample <= '1'; - else - sample <= '0'; - end if; - -- Counter is used to find sampling point for first pixel if CSYNC1 = '0' then if mode7 = '1' then @@ -170,63 +154,98 @@ begin elsif counter(11) = '1' then counter <= counter + 1; elsif mode7 = '1' or counter(2 downto 0) /= 5 then - counter(4 downto 0) <= counter(4 downto 0) + 1; + counter(5 downto 0) <= counter(5 downto 0) + 1; else - counter(4 downto 0) <= counter(4 downto 0) + 3; + counter(5 downto 0) <= counter(5 downto 0) + 3; end if; - -- Sample point offsets + + -- Sample point offset index if CSYNC1 = '0' then - sp_index <= "000"; - if mode7 = '1' then - sp <= mode7_sp_A; - else - sp <= default_sp; + index <= "000"; + else + -- so index offset changes at the same time counter wraps 7->0 + if counter(2 downto 0) = 6 then + case index is + when "000" => + index <= "001"; + when "001" => + index <= "010"; + when "010" => + index <= "011"; + when "011" => + index <= "100"; + when "100" => + index <= "101"; + when others => + index <= "000"; + end case; end if; - elsif mode7 = '1' and counter(2 downto 0) = 7 then - -- within the line - case sp_index is - when "000" => - sp_index <= "001"; - sp <= mode7_sp_B; - when "001" => - sp_index <= "010"; - sp <= mode7_sp_C; - when "010" => - sp_index <= "011"; - sp <= mode7_sp_D; - when "011" => - sp_index <= "100"; - sp <= mode7_sp_E; - when "100" => - sp_index <= "101"; - sp <= mode7_sp_F; - when others => - sp_index <= "000"; - sp <= mode7_sp_A; - end case; end if; - -- Sample/shift registers - if counter(11) = '0' and sample = '1' then - shift <= B & G & R & shift(11 downto 3); + -- Sample point offset + case index is + when "000" => + offset <= offset_B; + when "001" => + offset <= offset_C; + when "010" => + offset <= offset_D; + when "011" => + offset <= offset_E; + when "100" => + offset <= offset_F; + when others => + offset <= offset_A; + end case; + + -- sample/shift control + if counter(11) = '0' and counter(2 downto 0) = unsigned(offset) then + sample <= '1'; + else + sample <= '0'; + end if; + + -- R Sample/shift register + if sample = '1' then + shift_R <= R & shift_R(3 downto 1); + end if; + + -- G Sample/shift register + if sample = '1' then + shift_G <= G & shift_G(3 downto 1); + end if; + + -- B Sample/shift register + if sample = '1' then + shift_B <= B & shift_B(3 downto 1); end if; -- Output quad register if counter(11) = '0' then - if load = '1' then - quad <= shift; - toggle <= not toggle; + if counter(4 downto 0) = "00000" then + quad(11) <= shift_B(3); + quad(10) <= shift_G(3); + quad(9) <= shift_R(3); + quad(8) <= shift_B(2); + quad(7) <= shift_G(2); + quad(6) <= shift_R(2); + quad(5) <= shift_B(1); + quad(4) <= shift_G(1); + quad(3) <= shift_R(1); + quad(2) <= shift_B(0); + quad(1) <= shift_G(0); + quad(0) <= shift_R(0); + psync <= counter(5); end if; else - quad <= (others => '0'); - toggle <= '0'; + quad <= (others => '0'); + psync <= '0'; end if; end if; end process; - psync <= toggle; csync <= S; -- pass through, as clock might not be running LED1 <= 'Z'; -- allow this to be driven from the Pi LED2 <= not(mode7); diff --git a/vhdl/fitting.notes b/vhdl/fitting.notes index 7baf1090..ecd9bb63 100644 --- a/vhdl/fitting.notes +++ b/vhdl/fitting.notes @@ -200,22 +200,33 @@ FB4 18/18* 37/54 70/90 7/ 7* 17. Update counter to hopefully implement more efficiently -Function Mcells FB Inps Pterms IO -Block Used/Tot Used/Tot Used/Tot Used/Tot +Function Mcells FB Inps Pterms IO +Block Used/Tot Used/Tot Used/Tot Used/Tot FB1 18/18* 38/54 54/90 5/ 9 FB2 16/18 21/54 45/90 9/ 9* FB3 18/18* 30/54 49/90 8/ 9 FB4 18/18* 35/54 65/90 7/ 7* - ----- ----- ----- ----- - 70/72 124/216 213/360 29/34 + ----- ----- ----- ----- + 70/72 124/216 213/360 29/34 18. Load always in cycle 0 -Function Mcells FB Inps Pterms IO -Block Used/Tot Used/Tot Used/Tot Used/Tot +Function Mcells FB Inps Pterms IO +Block Used/Tot Used/Tot Used/Tot Used/Tot FB1 18/18* 38/54 53/90 5/ 9 FB2 16/18 21/54 45/90 9/ 9* FB3 18/18* 30/54 45/90 8/ 9 FB4 18/18* 37/54 63/90 7/ 7* - ----- ----- ----- ----- - 70/72 126/216 206/360 29/34 + ----- ----- ----- ----- + 70/72 126/216 206/360 29/34 + +19. Dropped seperate sp_default stage + +Function Mcells FB Inps Pterms IO +Block Used/Tot Used/Tot Used/Tot Used/Tot +FB1 18/18* 30/54 42/90 5/ 9 +FB2 17/18 25/54 34/90 9/ 9* +FB3 18/18* 29/54 55/90 8/ 9 +FB4 13/18 35/54 44/90 7/ 7* + ----- ----- ----- ----- + 66/72 119/216 175/360 29/34