diff --git a/.gitignore b/.gitignore index 8fb3e498..f517e72e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ *~ vhdl/iseconfig/ vhdl/working/ +vhdl_alt/iseconfig/ +vhdl_alt/working/ src/scripts/CMakeCache.txt src/scripts/CMakeFiles/ diff --git a/src/rpi-gpio.c b/src/rpi-gpio.c index 22a26ffa..5025f017 100644 --- a/src/rpi-gpio.c +++ b/src/rpi-gpio.c @@ -25,8 +25,8 @@ void RPI_SetGpioInput(rpi_gpio_pin_t gpio) rpi_gpio_value_t RPI_GetGpioValue(rpi_gpio_pin_t gpio) { - rpi_gpio_value_t result = RPI_IO_UNKNOWN; - + uint32_t result; + switch (gpio / 32) { case 0: @@ -38,16 +38,15 @@ rpi_gpio_value_t RPI_GetGpioValue(rpi_gpio_pin_t gpio) break; default: + return RPI_IO_UNKNOWN; break; } - if (result != RPI_IO_UNKNOWN) - { - if (result) - result = RPI_IO_HI; + if (result) { + return RPI_IO_HI; + } else { + return RPI_IO_LO; } - - return result; } void RPI_ToggleGpio(rpi_gpio_pin_t gpio) diff --git a/vhdl_alt/RGBtoHDMI.ucf b/vhdl_alt/RGBtoHDMI.ucf new file mode 100644 index 00000000..db1b7d31 --- /dev/null +++ b/vhdl_alt/RGBtoHDMI.ucf @@ -0,0 +1,71 @@ +# Global Clock Nets +NET "clk" BUFG=CLK; + +# Global Clock Nets +NET "sp_clk" BUFG=CLK; + +# 96MHz clock domain +NET "clk" TNM_NET = clk_period_grp_1; +TIMESPEC TS_clk_period_1 = PERIOD "clk_period_grp_1" 10.4ns HIGH; + +# 10MHz clock domain +#NET "sp_clk" TNM_NET = clk_period_grp_2; +#TIMESPEC TS_clk_period_2 = PERIOD "clk_period_grp_2" 100ns HIGH; + +NET "clk" LOC = "P43"; # input gpio21 + +NET "R0" LOC = "P33"; # input +NET "G0" LOC = "P32"; # input +NET "B0" LOC = "P31"; # input +NET "R1" LOC = "P34"; # input +NET "G1" LOC = "P36"; # input +NET "B1" LOC = "P37"; # input +NET "S" LOC = "P30"; # input + +NET "SW1" LOC = "P39"; # input gpio16 +NET "SW2" LOC = "P40"; # input gpio26 +NET "SW3" LOC = "P41"; # input gpio19 +NET "link" LOC = "P42"; # input gpio25 (connects to link / test point) +NET "spare" LOC = "P3"; # input gpio12 + +NET "mode7" LOC = "P19"; # input gpio22 +NET "elk" LOC = "P18"; # input gpio24 +NET "sp_clk" LOC = "P44"; # input gpio20 +NET "sp_data" LOC = "P20"; # input gpio23 +NET "sp_clken" LOC = "P1"; # input gpio13 + +NET "quad(0)" LOC = "P7"; # output gpio0 +NET "quad(1)" LOC = "P6"; # output gpio1 +NET "quad(2)" LOC = "P29"; # output gpio2 +NET "quad(3)" LOC = "P28"; # output gpio3 +NET "quad(4)" LOC = "P27"; # output gpio4 +NET "quad(5)" LOC = "P5"; # output gpio5 +NET "quad(6)" LOC = "P2"; # output gpio6 +NET "quad(7)" LOC = "P8"; # output gpio7 +NET "quad(8)" LOC = "P12"; # output gpio8 +NET "quad(9)" LOC = "P14"; # output gpio9 +NET "quad(10)" LOC = "P16"; # output gpio10 +NET "quad(11)" LOC = "P13"; # output gpio11 + +NET "psync" LOC = "P22"; # output gpio17 +NET "csync" LOC = "P23"; # output gpio18 + +NET "LED1" LOC = "P21"; # output gpio27 (bidirectional, driven from Pi) +NET "LED2" LOC = "P38"; # output to LED2 (used as mode 7 indicator) + +NET "quad(0)" SLOW; +NET "quad(1)" SLOW; +NET "quad(2)" SLOW; +NET "quad(3)" SLOW; +NET "quad(4)" SLOW; +NET "quad(5)" SLOW; +NET "quad(6)" SLOW; +NET "quad(7)" SLOW; +NET "quad(8)" SLOW; +NET "quad(9)" SLOW; +NET "quad(10)" SLOW; +NET "quad(11)" SLOW; +NET "psync" SLOW; +NET "csync" SLOW; +NET "LED1" SLOW; +NET "LED2" SLOW; diff --git a/vhdl_alt/RGBtoHDMI.vhdl b/vhdl_alt/RGBtoHDMI.vhdl new file mode 100644 index 00000000..d6c16da6 --- /dev/null +++ b/vhdl_alt/RGBtoHDMI.vhdl @@ -0,0 +1,280 @@ +---------------------------------------------------------------------------------- +-- 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 + R0: in std_logic; + G0: in std_logic; + B0: in std_logic; + R1: in std_logic; + G1: in std_logic; + B1: in std_logic; + S: in std_logic; + + -- From Pi + clk: in std_logic; + mode7: in std_logic; + elk: in std_logic; + sp_clk: in std_logic; + sp_clken: in std_logic; + sp_data: in std_logic; + + -- To PI GPIO + quad: out std_logic_vector(11 downto 0); + psync: out std_logic; + csync: out std_logic; + + -- User interface + SW1: in std_logic; + SW2: in std_logic; -- currently unused + SW3: in std_logic; -- currently unused + spare: in std_logic; -- currently unused + link: in std_logic; -- currently unused + LED1: out std_logic; + LED2: out std_logic + ); +end RGBtoHDMI; + +architecture Behavorial of RGBtoHDMI is + + -- For Modes 0..6 + 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); + + -- Sampling points + constant INIT_SAMPLING_POINTS : std_logic_vector(20 downto 0) := "000000000000011011011"; + + 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; + + -- The sampling counter runs at 96MHz + -- - In modes 0..6 it is 6x the pixel clock + -- - In mode 7 it is 8x the 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, 1, 2) + -- 3. Counts counts pixels within a quad pixel (bits 3 and 4) + -- 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); + + -- 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; + + -- Break out of sp + signal delay_R : std_logic_vector(2 downto 0); + signal delay_G : std_logic_vector(2 downto 0); + signal delay_B : std_logic_vector(2 downto 0); + + signal offset_A : std_logic_vector(1 downto 0); + signal offset_B : std_logic_vector(1 downto 0); + signal offset_C : std_logic_vector(1 downto 0); + signal offset_D : std_logic_vector(1 downto 0); + signal offset_E : std_logic_vector(1 downto 0); + signal offset_F : std_logic_vector(1 downto 0); + signal offset : std_logic_vector(1 downto 0); + + signal adjusted_counter : unsigned(2 downto 0); + + -- Index to allow cycling between A, B and C in Mode 7 + signal sp_index : std_logic_vector(2 downto 0); + + -- Sample pixel on next clock; pipelined to reduce the number of product terms + signal sample_R : std_logic; + signal sample_G : std_logic; + signal sample_B : std_logic; + + signal R : std_logic; + signal G : std_logic; + signal B : std_logic; + +begin + + R <= R1 when elk = '1' else R0; + G <= G1 when elk = '1' else G0; + B <= B1 when elk = '1' else B0; + + delay_R <= sp_reg(2 downto 0); + delay_G <= sp_reg(5 downto 3); + delay_B <= sp_reg(8 downto 6); + offset_A <= sp_reg(10 downto 9); + offset_B <= sp_reg(12 downto 11); + offset_C <= sp_reg(14 downto 13); + offset_D <= sp_reg(16 downto 15); + offset_E <= sp_reg(18 downto 17); + offset_F <= sp_reg(20 downto 19); + + -- Shift the bits in LSB first + process(sp_clk, SW1) + begin + 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); + end if; + end if; + end process; + + process(clk) + begin + if rising_edge(clk) then + + -- synchronize CSYNC to the sampling clock + CSYNC1 <= S; + + -- Counter is used to find sampling point for first pixel + if CSYNC1 = '0' then + if mode7 = '1' then + counter <= mode7_offset; + else + counter <= default_offset; + end if; + elsif counter(11) = '1' then + counter <= counter + 1; + elsif mode7 = '1' or counter(2 downto 0) /= 5 then + counter(5 downto 0) <= counter(5 downto 0) + 1; + else + counter(5 downto 0) <= counter(5 downto 0) + 3; + end if; + + -- Sample point offset index + if CSYNC1 = '0' then + sp_index <= "000"; + else + -- so index offset changes at the same time counter wraps 7->0 + if counter(2 downto 0) = 6 then + case sp_index is + when "000" => + sp_index <= "001"; + when "001" => + sp_index <= "010"; + when "010" => + sp_index <= "011"; + when "011" => + sp_index <= "100"; + when "100" => + sp_index <= "101"; + when others => + sp_index <= "000"; + end case; + end if; + end if; + + -- Sample point offset + case sp_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; + + -- Adjusted counter is the counter value with the offset added in + -- + -- The offset is sign extended offset to 3 bits so values are: + -- 00 -> 000 (0) + -- 01 -> 001 (1) + -- 10 -> 110 (-2) + -- 11 -> 111 (-1) + adjusted_counter <= counter(2 downto 0) + unsigned(offset(1) & offset(1 downto 0)); + + -- R sample/shift control + if counter(11) = '0' and adjusted_counter(2 downto 0) = unsigned(delay_R) then + sample_R <= '1'; + else + sample_R <= '0'; + end if; + + -- G sample/shift control + if counter(11) = '0' and adjusted_counter(2 downto 0) = unsigned(delay_G) then + sample_G <= '1'; + else + sample_G <= '0'; + end if; + + -- B sample/shift control + if counter(11) = '0' and adjusted_counter(2 downto 0) = unsigned(delay_B) then + sample_B <= '1'; + else + sample_B <= '0'; + end if; + + -- R Sample/shift register + if sample_R = '1' then + shift_R <= R & shift_R(3 downto 1); + end if; + + -- G Sample/shift register + if sample_G = '1' then + shift_G <= G & shift_G(3 downto 1); + end if; + + -- B Sample/shift register + if sample_B = '1' then + shift_B <= B & shift_B(3 downto 1); + end if; + + -- Output quad register + if counter(11) = '0' then + if counter(4 downto 0) = "00001" 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'); + psync <= '0'; + end if; + + end if; + end process; + + csync <= S; -- pass through, as clock might not be running + --LED1 <= 'Z'; -- allow this to be driven from the Pi + --LED2 <= not(mode7); + +end Behavorial; diff --git a/vhdl_alt/RGBtoHDMI.xise b/vhdl_alt/RGBtoHDMI.xise new file mode 100644 index 00000000..e55c603e --- /dev/null +++ b/vhdl_alt/RGBtoHDMI.xise @@ -0,0 +1,237 @@ + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/vhdl_alt/fitting.notes b/vhdl_alt/fitting.notes new file mode 100644 index 00000000..fb99398b --- /dev/null +++ b/vhdl_alt/fitting.notes @@ -0,0 +1,248 @@ +1. Original design: + +Function Mcells FB Inps Pterms IO +Block Used/Tot Used/Tot Used/Tot Used/Tot +FB1 18/18* 27/54 69/90 6/ 9 +FB2 18/18* 34/54 60/90 8/ 9 +FB3 18/18* 19/54 32/90 5/ 9 +FB4 18/18* 37/54 56/90 7/ 7* + ----- ----- ----- ----- + 72/72 117/216 217/360 26/34 + + +2. New design, with RGB mux, switch pass throughs, etc commented out +(failed to map sp_reg<9>, hence one less macrocell) + +Function Mcells FB Inps Pterms IO +Block Used/Tot Used/Tot Used/Tot Used/Tot +FB1 18/18* 26/54 51/90 7/ 9 +FB2 18/18* 25/54 33/90 6/ 9 +FB3 18/18* 35/54 61/90 8/ 9 +FB4 17/18 53/54 70/90 4/ 7 + ----- ----- ----- ----- + 71/72 139/216 215/360 25/34 + + +3. Change from csync=>S to csync=>CSYNC1 (as passthroughs still use up a macro cell). +(now fits) + +Function Mcells FB Inps Pterms IO +Block Used/Tot Used/Tot Used/Tot Used/Tot +FB1 17/18 33/54 64/90 7/ 9 +FB2 18/18* 25/54 33/90 6/ 9 +FB3 18/18* 35/54 61/90 8/ 9 +FB4 18/18* 37/54 58/90 4/ 7 + ----- ----- ----- ----- + 71/72 130/216 216/360 25/34 + + +4. Add in RGB mux: +(still fits) + +Function Mcells FB Inps Pterms IO +Block Used/Tot Used/Tot Used/Tot Used/Tot +FB1 17/18 33/54 64/90 7/ 9 +FB2 18/18* 25/54 33/90 9/ 9* +FB3 18/18* 37/54 61/90 8/ 9 +FB4 18/18* 41/54 61/90 5/ 7 + ----- ----- ----- ----- + 71/72 136/216 219/360 29/34 + +5. Add in SW2out <= SW2: +(still fits) + +Function Mcells FB Inps Pterms IO +Block Used/Tot Used/Tot Used/Tot Used/Tot +FB1 18/18* 28/54 62/90 8/ 9 +FB2 18/18* 25/54 33/90 9/ 9* +FB3 18/18* 37/54 61/90 8/ 9 +FB4 18/18* 48/54 64/90 6/ 7 + ----- ----- ----- ----- + 72/72 138/216 220/360 31/34 + +6. Change to optimization effort normal->high: +(no difference) + +Function Mcells FB Inps Pterms IO +Block Used/Tot Used/Tot Used/Tot Used/Tot +FB1 18/18* 28/54 62/90 8/ 9 +FB2 18/18* 25/54 33/90 9/ 9* +FB3 18/18* 37/54 61/90 8/ 9 +FB4 18/18* 48/54 64/90 6/ 7 + ----- ----- ----- ----- + 72/72 138/216 220/360 31/34 + +7. Change to optimization effort speed->area: +(no difference) + +Function Mcells FB Inps Pterms IO +Block Used/Tot Used/Tot Used/Tot Used/Tot +FB1 18/18* 28/54 62/90 8/ 9 +FB2 18/18* 25/54 33/90 9/ 9* +FB3 18/18* 37/54 61/90 8/ 9 +FB4 18/18* 48/54 64/90 6/ 7 + ----- ----- ----- ----- + 72/72 138/216 220/360 31/34 + +8. Fitter Implmenetation Template: Optimize Balance-> Optimize Speed: +(no difference) + +Function Mcells FB Inps Pterms IO +Block Used/Tot Used/Tot Used/Tot Used/Tot +FB1 18/18* 28/54 62/90 8/ 9 +FB2 18/18* 25/54 33/90 9/ 9* +FB3 18/18* 37/54 61/90 8/ 9 +FB4 18/18* 48/54 64/90 6/ 7 + ----- ----- ----- ----- + 72/72 138/216 220/360 31/34 + + +9. Fitter Implmenetation Template: Optimize Speed -> Optimize Density: +(no difference) + +Function Mcells FB Inps Pterms IO +Block Used/Tot Used/Tot Used/Tot Used/Tot +FB1 18/18* 28/54 62/90 8/ 9 +FB2 18/18* 25/54 33/90 9/ 9* +FB3 18/18* 37/54 61/90 8/ 9 +FB4 18/18* 48/54 64/90 6/ 7 + ----- ----- ----- ----- + 72/72 138/216 220/360 31/34 + +10. Reverted to original .xise file +Cleaned up design to remove SW2/3 pass throughs +Used gpio22/23 for mode7 / sp_data +Used gpio19/26 for sw2/3 (not via cpld) +(same result as 4 above) + +Function Mcells FB Inps Pterms IO +Block Used/Tot Used/Tot Used/Tot Used/Tot +FB1 17/18 33/54 64/90 5/ 9 +FB2 18/18* 25/54 33/90 9/ 9* +FB3 18/18* 37/54 61/90 8/ 9 +FB4 18/18* 41/54 61/90 7/ 7* + ----- ----- ----- ----- + 71/72 136/216 219/360 29/34 + +11. Final design on 5/6/2018 + +(Added SW2, SW3, Link as unused inputs) +(Added LED1 as output, driven to Z, still uses one macro cell) + +Function Mcells FB Inps Pterms IO +Block Used/Tot Used/Tot Used/Tot Used/Tot +FB1 18/18* 27/54 61/90 5/ 9 +FB2 18/18* 25/54 33/90 9/ 9* +FB3 18/18* 37/54 61/90 9/ 9* +FB4 18/18* 48/54 64/90 7/ 7* + ----- ----- ----- ----- + 72/72 137/216 219/360 30/34 + +12. Minor changes 1.15pm on 5/5/2018 + +(Removed SW1Out passthrough) +(csync output is back to being passthrough) + +Function Mcells FB Inps Pterms IO +Block Used/Tot Used/Tot Used/Tot Used/Tot +FB1 18/18* 25/54 35/90 4/ 9 +FB2 18/18* 34/54 65/90 9/ 9* +FB3 18/18* 37/54 61/90 9/ 9* +FB4 18/18* 39/54 58/90 7/ 7* + ----- ----- ----- ----- + 72/72 135/216 219/360 29/34 + +13. Removed SW1 from sp_reg assignment block + +(the is prone to noise on the prototype, as it clamped at 2V by an LED) + +Function Mcells FB Inps Pterms IO +Block Used/Tot Used/Tot Used/Tot Used/Tot +FB1 18/18* 25/54 35/90 3/ 9 +FB2 18/18* 34/54 65/90 9/ 9* +FB3 18/18* 37/54 61/90 9/ 9* +FB4 18/18* 39/54 58/90 7/ 7* + ----- ----- ----- ----- + 72/72 135/216 219/360 28/34 + +14. Added sp_clken and spare + +Function Mcells FB Inps Pterms IO +Block Used/Tot Used/Tot Used/Tot Used/Tot +FB1 18/18* 30/54 63/90 5/ 9 +FB2 18/18* 26/54 46/90 9/ 9* +FB3 18/18* 35/54 60/90 8/ 9 +FB4 18/18* 47/54 71/90 7/ 7* + ----- ----- ----- ----- + 72/72 138/216 240/360 29/34 + +15. Replaced counter2(5..3) with load saving two registers + +Function Mcells FB Inps Pterms IO +Block Used/Tot Used/Tot Used/Tot Used/Tot +FB1 18/18* 40/54 72/90 5/ 9 +FB2 17/18 24/54 49/90 9/ 9* +FB3 18/18* 34/54 60/90 8/ 9 +FB4 17/18 35/54 63/90 7/ 7* + ----- ----- ----- ----- + 70/72 133/216 244/360 29/34 + +16. Alternative design +(after lots of messing to get it to route) +(timing rubbush, 18ns) +(68 registers) + +Function Mcells FB Inps Pterms IO +Block Used/Tot Used/Tot Used/Tot Used/Tot +FB1 18/18* 34/54 53/90 4/ 9 +FB2 18/18* 26/54 36/90 8/ 9 +FB3 18/18* 30/54 50/90 9/ 9* +FB4 16/18 38/54 86/90 6/ 7 + ----- ----- ----- ----- + 70/72 128/216 225/360 27/34 + +17. Repipelined offset and alternative_counter to improve timing + +(note big reduction in product term usage) +(70 registers) +(11.0ns) + +Function Mcells FB Inps Pterms IO +Block Used/Tot Used/Tot Used/Tot Used/Tot +FB1 18/18* 35/54 45/90 4/ 9 +FB2 17/18 25/54 35/90 8/ 9 +FB3 18/18* 30/54 50/90 9/ 9* +FB4 18/18* 42/54 66/90 6/ 7 + ----- ----- ----- ----- + 71/72 132/216 196/360 27/34 + +18. Sign extended offset to 3-bits + +(surprisingly no change in resource usage) +(70 registers) +(11.0ns) + +Function Mcells FB Inps Pterms IO +Block Used/Tot Used/Tot Used/Tot Used/Tot +FB1 18/18* 35/54 45/90 4/ 9 +FB2 17/18 25/54 35/90 8/ 9 +FB3 18/18* 30/54 50/90 9/ 9* +FB4 18/18* 42/54 66/90 6/ 7 + ----- ----- ----- ----- + 71/72 132/216 196/360 27/34 + +19. Adjust pipelining timing + +(sp_index when counter = 6 rather than 7) +(load when counter = 1 rather than 1) +(70 registers) +(11.0ns) + +Function Mcells FB Inps Pterms IO +Block Used/Tot Used/Tot Used/Tot Used/Tot +FB1 18/18* 35/54 45/90 4/ 9 +FB2 17/18 25/54 35/90 8/ 9 +FB3 18/18* 30/54 50/90 9/ 9* +FB4 18/18* 42/54 66/90 6/ 7 + ----- ----- ----- ----- + 71/72 132/216 196/360 27/34