diff options
-rw-r--r-- | basys3/basys3.srcs/apu_lut_reader.vhd | 69 | ||||
-rw-r--r-- | basys3/basys3.srcs/apu_lut_reader_tb.vhd | 48 | ||||
-rw-r--r-- | basys3/basys3.srcs/apu_note_to_frequency.vhd | 42 | ||||
-rw-r--r-- | basys3/basys3.srcs/ppu_comp.vhd | 67 | ||||
-rw-r--r-- | basys3/basys3.srcs/ppu_comp_tb.vhd | 44 | ||||
-rw-r--r-- | basys3/basys3.srcs/ppu_plut.vhd | 99 | ||||
-rw-r--r-- | basys3/basys3.srcs/ppu_vga_native.vhd | 125 | ||||
-rw-r--r-- | basys3/basys3.srcs/ppu_vga_native_tb.vhd | 116 | ||||
-rw-r--r-- | basys3/basys3.srcs/ppu_vga_tiny.vhd | 103 | ||||
-rw-r--r-- | basys3/basys3.xpr | 31 | ||||
-rw-r--r-- | test/sdl2/.gitignore | 2 | ||||
-rw-r--r-- | test/sdl2/main.c | 48 | ||||
-rw-r--r-- | test/sdl2/makefile | 18 | ||||
-rw-r--r-- | test/sdl2/readme.md | 6 |
14 files changed, 799 insertions, 19 deletions
diff --git a/basys3/basys3.srcs/apu_lut_reader.vhd b/basys3/basys3.srcs/apu_lut_reader.vhd new file mode 100644 index 0000000..2f92eca --- /dev/null +++ b/basys3/basys3.srcs/apu_lut_reader.vhd @@ -0,0 +1,69 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity apu_lut_reader is + port ( + clk : in std_logic; + rst : in std_logic; + freq : in std_logic_vector(11 downto 0); + wave : in std_logic_vector(1 downto 0); + value : out std_logic_vector(7 downto 0) + ); +end entity; + +architecture behavioral of apu_lut_reader is + + constant AMPLITUDE : natural := 0; + constant SAMPLE_SIZE : natural := 256; + + signal idx : unsigned := (others => '0'); + signal buf : unsigned := (others => '0'); + +begin + + process (clk) + begin + if rst = '1' then + idx <= x"00"; + buf <= x"00"; + value <= x"00"; + elsif rising_edge(clk) then + -- main code here + + if wave = "00" then -- Sawtooth + value <= std_logic_vector( idx ); + elsif wave = "01" then -- Square + if idx < (SAMPLE_SIZE/2) then + value <= x"00"; --std_logic_vector( SAMPLE_SIZE-AMPLITUDE ); -- TODO: make so that this work with a changable amplitude (for square wave) + else + value <= x"FF"; + end if; + elsif wave = "10" then -- Triangle + if idx < (SAMPLE_SIZE/2) then + value <= std_logic_vector( idx*2 ); + else + value <= std_logic_vector( (SAMPLE_SIZE-idx)*2 ); + end if; + else-- wave = "11" then -- Noise + -- TODO: implement noise function here: + value <= x"80"; -- remove this + end if; + + + + if buf < unsigned(freq) then -- change frequency + buf <= buf + 1; + else + buf <= x"00"; + if idx < (SAMPLE_SIZE-1) then -- moves to next index value + idx <= idx + 1; + else + idx <= x"00"; + end if; + end if; + + end if; + end process; + +end architecture; diff --git a/basys3/basys3.srcs/apu_lut_reader_tb.vhd b/basys3/basys3.srcs/apu_lut_reader_tb.vhd new file mode 100644 index 0000000..1b425bf --- /dev/null +++ b/basys3/basys3.srcs/apu_lut_reader_tb.vhd @@ -0,0 +1,48 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library unisim; +use unisim.vcomponents.all; + +entity apu_lut_reader_tb is +end entity; + +architecture Behavioral of apu_lut_reader_tb is + component apu_lut_reader is + port ( + clk : in std_logic; + rst : in std_logic; + freq : in std_logic_vector(11 downto 0); + wave : in std_logic_vector(1 downto 0); + value : out std_logic_vector(7 downto 0) + ); + end component; + + signal OK : boolean := false; + + signal clk : std_logic := '0'; + signal rst : std_logic := '0'; + signal freq : std_logic_vector(11 downto 0) := (others => '0'); + signal wave : std_logic_vector(1 downto 0) := (others => '0'); + +begin + + TB: process + begin + wave <= "00"; + for I in 0 to 255 loop + clk <= '1'; + + -- freq <= '1'; + + + wait for 1 ps; + clk <= '0'; + wait for 1 ps; + + + end loop; + end process; + +end architecture; diff --git a/basys3/basys3.srcs/apu_note_to_frequency.vhd b/basys3/basys3.srcs/apu_note_to_frequency.vhd index 1e47b8e..810cef9 100644 --- a/basys3/basys3.srcs/apu_note_to_frequency.vhd +++ b/basys3/basys3.srcs/apu_note_to_frequency.vhd @@ -5,8 +5,8 @@ use ieee.numeric_std.all; entity apu_note_to_frequency is port ( -- clk : in std_logic; -- rst : in std_logic; - data : in std_logic_vector(7 downto 0); - freq : out std_logic_vector(11 downto 0)); --frequency + data : in std_logic_vector(6 downto 0); + freq : out std_logic_vector(11 downto 0)); -- frequency end entity; architecture Behavioral of apu_note_to_frequency is @@ -14,22 +14,26 @@ architecture Behavioral of apu_note_to_frequency is signal buff : std_logic_vector(15 downto 0) := (others => '0'); signal shift : integer; begin - shift <= to_integer(unsigned(data(2 downto 0))); - buff_small <= - x"f0" when data(7 downto 3) = (x"c" & '0') else -- C 496 - x"d0" when data(7 downto 3) = (x"c" & '1') else -- C# 464 - x"b0" when data(7 downto 3) = (x"d" & '0') else -- D 432 - x"a0" when data(7 downto 3) = (x"d" & '1') else -- D# 416 - x"80" when data(7 downto 3) = (x"e" & '0') else -- E 384 - x"70" when data(7 downto 3) = (x"f" & '0') else -- F 368 - x"58" when data(7 downto 3) = (x"f" & '1') else -- F# 344 - x"40" when data(7 downto 3) = (x"8" & '0') else -- G 320 - x"30" when data(7 downto 3) = (x"8" & '1') else -- G# 304 - x"20" when data(7 downto 3) = (x"a" & '0') else -- A 288 - x"10" when data(7 downto 3) = (x"a" & '1') else -- A# 272 - x"00" when data(7 downto 3) = (x"b" & '0') else -- B 256 - x"01"; - buff <= x"1" & buff_small; - freq <= (others => '0') & buff(15 downto shift); -- bitshift values out (or div by powers of 2) + shift <= to_integer(unsigned( data(2 downto 0) )); + + buff <= + x"1F0" when data(6 downto 3) = (x"1") else -- C 496 + x"1D0" when data(6 downto 3) = (x"2") else -- C#/Db 464 + x"1B0" when data(6 downto 3) = (x"3") else -- D 432 + x"1A0" when data(6 downto 3) = (x"4") else -- D#/Eb 416 + x"180" when data(6 downto 3) = (x"5") else -- E 384 + x"170" when data(6 downto 3) = (x"6") else -- F 368 + x"158" when data(6 downto 3) = (x"7") else -- F#/Gb 344 + x"140" when data(6 downto 3) = (x"8") else -- G 320 + x"130" when data(6 downto 3) = (x"9") else -- G#/Ab 304 + x"120" when data(6 downto 3) = (x"A") else -- A 288 + x"110" when data(6 downto 3) = (x"B") else -- A#/Bb 272 + x"100" when data(6 downto 3) = (x"C") else -- B 256 + x"000"; + + -- buff <= x"1" & buff_small; + freq <= std_logic_vector( shift_right(unsigned(buff), shift) ); + -- freq <= (others => '0') & buff(11 downto shift); -- bitshift values out (or div by powers of 2) -- TODO: NO WORKY!!! (concat (others => '0');) + end architecture; diff --git a/basys3/basys3.srcs/ppu_comp.vhd b/basys3/basys3.srcs/ppu_comp.vhd new file mode 100644 index 0000000..1ea315e --- /dev/null +++ b/basys3/basys3.srcs/ppu_comp.vhd @@ -0,0 +1,67 @@ +---------------------------------------------------------------------------------- +-- Company: +-- Engineer: +-- +-- Create Date: 23.02.2023 10:31:25 +-- Design Name: +-- Module Name: ppu_comp - Behavioral +-- Project Name: +-- Target Devices: +-- Tool Versions: +-- Description: +-- +-- Dependencies: +-- +-- Revision: +-- Revision 0.01 - File Created +-- Additional Comments: +-- +---------------------------------------------------------------------------------- + + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use work.ppu_consts.all; +-- Uncomment the following library declaration if using +-- arithmetic functions with Signed or Unsigned values +--use IEEE.NUMERIC_STD.ALL; + +-- Uncomment the following library declaration if instantiating +-- any Xilinx leaf cells in this code. +--library UNISIM; +--use UNISIM.VComponents.all; + +entity ppu_comp is + Port ( + FG_HIT: in std_logic_vector(PPU_FG_SPRITE_COUNT-1 downto 0); + BG_EN: out std_logic; + FG_EN: out std_logic_vector(PPU_FG_SPRITE_COUNT-1 downto 0)); + +end ppu_comp; + +architecture Behavioral of ppu_comp is +signal FG_HIT_Empty : std_logic_vector(PPU_FG_SPRITE_COUNT-1 downto 0) := (others => '0'); +begin + process (FG_HIT) + variable HIT : BOOLEAN := FALSE; + begin + -- check if fg_hit is not empty + if FG_HIT /= FG_HIT_Empty then + BG_EN <= '0'; + FOR I IN 0 TO PPU_FG_SPRITE_COUNT-1 LOOP + -- if fg_hit is the first one then enable it + IF(FG_HIT(I) = '1' AND HIT = FALSE) THEN + FG_EN(I) <= '1'; + HIT := TRUE; + ELSE + -- make rest low + FG_EN(I) <= '0'; + END IF; + END LOOP; + HIT := FALSE; + else + BG_EN <= '1'; + FG_EN <= (others => '0'); + end if; + end process; +end Behavioral; diff --git a/basys3/basys3.srcs/ppu_comp_tb.vhd b/basys3/basys3.srcs/ppu_comp_tb.vhd new file mode 100644 index 0000000..e8f6893 --- /dev/null +++ b/basys3/basys3.srcs/ppu_comp_tb.vhd @@ -0,0 +1,44 @@ +library ieee; +library unisim; +use ieee.std_logic_1164.all; +use work.ppu_consts.all; +use unisim.vcomponents.all; + +entity ppu_comp_tb is +end ppu_comp_tb; + +architecture behavioral of ppu_comp_tb is +COMPONENT ppu_comp + port ( + FG_HIT: in std_logic_vector(PPU_FG_SPRITE_COUNT-1 downto 0); + BG_EN: out std_logic; + FG_EN: out std_logic_vector(PPU_FG_SPRITE_COUNT-1 downto 0)); +end component; + +signal FG_HIT: std_logic_vector(PPU_FG_SPRITE_COUNT-1 downto 0) := (others => '0'); +signal BG_EN: std_logic := '0'; +signal FG_EN: std_logic_vector(PPU_FG_SPRITE_COUNT-1 downto 0) := (others => '0'); +begin +UUT : ppu_comp port map ( +FG_HIT => FG_HIT, +BG_EN => BG_EN, +FG_EN => FG_EN +); + TB : PROCESS + BEGIN + FG_HIT <= (OTHERS => '0'); + wait for 1 ps; + FG_HIT(6) <= '1'; + FG_HIT(5) <= '1'; + FG_HIT(100) <= '1'; + wait for 1 ps; + + FG_HIT(0) <= '1'; + wait for 1 ps; + FG_HIT <= (OTHERS => '0'); + wait for 1 ps; + + + wait; + END PROCESS; +end Behavioral; diff --git a/basys3/basys3.srcs/ppu_plut.vhd b/basys3/basys3.srcs/ppu_plut.vhd new file mode 100644 index 0000000..d03da1f --- /dev/null +++ b/basys3/basys3.srcs/ppu_plut.vhd @@ -0,0 +1,99 @@ +---------------------------------------------------------------------------------- +-- Company: +-- Engineer: +-- +-- Create Date: 23.02.2023 11:03:27 +-- Design Name: +-- Module Name: ppu_plut - Behavioral +-- Project Name: +-- Target Devices: +-- Tool Versions: +-- Description: +-- +-- Dependencies: +-- +-- Revision: +-- Revision 0.01 - File Created +-- Additional Comments: +-- +---------------------------------------------------------------------------------- + + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use work.ppu_consts.all; +-- Uncomment the following library declaration if using +-- arithmetic functions with Signed or Unsigned values +use IEEE.NUMERIC_STD.ALL; +use ieee.std_logic_unsigned.all; +-- Uncomment the following library declaration if instantiating +-- any Xilinx leaf cells in this code. +--library UNISIM; +--use UNISIM.VComponents.all; + +entity ppu_plut is + Port ( + CLK: in std_logic; -- system clock + CIDX: in std_logic_vector(PPU_PALETTE_CIDX_WIDTH-1 downto 0); -- color in + RESET: in std_logic; + + -- internal memory block (AUX) + PAL_WEN: in std_logic; -- VRAM PAL write enable + PAL_ADDR: in std_logic_vector(PPU_PAL_ADDR_WIDTH-1 downto 0); -- VRAM PAL address + PAL_DATA: in std_logic_vector(PPU_PAL_DATA_WIDTH-1 downto 0); -- VRAM PAL data + + R,G,B: out std_logic_vector(PPU_COLOR_OUTPUT_DEPTH-1 downto 0)); -- VGA color out +end ppu_plut; + +architecture Behavioral of ppu_plut is + component er_ram + generic( + ADDR_W : natural := PPU_PAL_ADDR_WIDTH; -- ADDR line width + DATA_W : natural := PPU_PAL_DATA_WIDTH; -- DATA line width + ADDR_LOW : natural := 16#0000#; -- starting address + ADDR_RANGE : natural := 16#0040#); -- amount of valid addresses after ADDR_LOW + port( + CLK : in std_logic; -- clock + RST : in std_logic; -- async memory clear + WEN : in std_logic; -- write enable + ADDR : in std_logic_vector(ADDR_W-1 downto 0); + DATA : in std_logic_vector(DATA_W-1 downto 0); + REG : out std_logic_vector((ADDR_RANGE*DATA_W)-1 downto 0)); -- exposed register output + end component; + + SIGNAL PLUT : std_logic_vector((64 * PPU_PAL_DATA_WIDTH)-1 downto 0) := (others => '0'); + SIGNAL CHECK_ZERO_CIDX : std_logic_vector(PPU_PALETTE_CIDX_WIDTH-1 downto 0) := (others => '0');-- color in +begin + RAM : component er_ram port map( + CLK => CLK, + RST => RESET, + WEN => PAL_WEN, + ADDR => PAL_ADDR, + DATA => PAL_DATA, + REG => PLUT); + + + process(CLK,RESET) + VARIABLE COLOR : std_logic_vector(PPU_PAL_DATA_WIDTH-1 downto 0) := (others => '0');-- COLORS RGB IN + VARIABLE CIDX_INT : INTEGER := 0; + begin + IF(RESET = '1') THEN + PLUT <= (others => '0'); + ELSE + IF rising_edge (CLK) THEN + IF (CIDX /= CHECK_ZERO_CIDX) THEN + CIDX_INT := TO_INTEGER(UNSIGNED(CIDX)); + COLOR := PLUT((12 * CIDX_INT) + 11 DOWNTO (12*CIDX_INT)); + R <= COLOR(11 DOWNTO 8); + G <= COLOR(7 DOWNTO 4); + B <= COLOR(3 DOWNTO 0); + ELSE + R <= X"0"; + G <= X"0"; + B <= X"0"; + END IF; + END IF; + END IF; + end process; + +end Behavioral; diff --git a/basys3/basys3.srcs/ppu_vga_native.vhd b/basys3/basys3.srcs/ppu_vga_native.vhd new file mode 100644 index 0000000..f5d9809 --- /dev/null +++ b/basys3/basys3.srcs/ppu_vga_native.vhd @@ -0,0 +1,125 @@ +---------------------------------------------------------------------------------- +-- Company: +-- Engineer: +-- +-- Create Date: 22.02.2023 13:20:47 +-- Design Name: +-- Module Name: ppu_vga_native - Behavioral +-- Project Name: +-- Target Devices: +-- Tool Versions: +-- Description: +-- +-- Dependencies: +-- +-- Revision: +-- Revision 0.01 - File Created +-- Additional Comments: +-- +---------------------------------------------------------------------------------- + + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use work.ppu_consts.all; + +use IEEE.NUMERIC_STD.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +-- Uncomment the following library declaration if instantiating +-- any Xilinx leaf cells in this code. +--library UNISIM; +--use UNISIM.VComponents.all; + +entity ppu_vga_native is + Port ( CLK: in std_logic; -- system clock + RESET: in std_logic; + + X: in std_logic_vector(PPU_POS_H_WIDTH-1 downto 0); -- current screen pixel x + Y: in std_logic_vector(PPU_POS_V_WIDTH-1 downto 0); -- current screen pixel y + PREADY: in std_logic; -- current pixel ready (pixel color is stable) + RI,GI,BI: in std_logic_vector(PPU_COLOR_OUTPUT_DEPTH-1 downto 0); -- VGA color in + + RO,GO,BO: out std_logic_vector(PPU_COLOR_OUTPUT_DEPTH-1 downto 0); -- VGA color out + VSYNC, HSYNC: out std_logic); -- VGA sync outputs +end ppu_vga_native; + +architecture Behavioral of ppu_vga_native is + type line_buffer is array(319 downto 0) of std_logic_vector(11 downto 0); + signal ram_x0 : line_buffer; -- buffer 0 + signal ram_x1: line_buffer; -- buffer 1 + signal hcount: STD_LOGIC_VECTOR(9 downto 0):= (others => '0'); + signal vcount: STD_LOGIC_VECTOR(9 downto 0):= (others => '0'); + signal clkCounter: STD_LOGIC_VECTOR(1 downto 0):= (others => '0'); + signal rgb_out : STD_LOGIC_VECTOR(11 downto 0):= (others => '0'); -- output colors + signal px : integer; -- conversion for hcount + signal py :integer; -- conversion for vcount + signal bufferFilledOnbuffer0 : integer; + signal bufferFilledOnbuffer1 :integer; +begin + process (clk, x, y) + variable v_x : integer ; -- integer to hold vector X + begin + if rising_edge(clk) then + clkCounter <= clkCounter + 1; + if(clkCounter = "11")then + v_x := TO_INTEGER(unsigned(x) - 72); + if(v_x >= 0 and v_x < 320 and PREADY = '1') then + if(y(0) = '0') then + ram_x0(v_x) <= RI & GI & BI; + if v_x = 319 then + bufferFilledOnbuffer0 <= TO_INTEGER(unsigned(y) - 14); + end if; + else + ram_x1(v_x) <= RI & GI & BI; + if v_x = 319 then + bufferFilledOnbuffer1 <= TO_INTEGER(unsigned(y) - 14); + end if; + end if; + end if; + -- T display(display data) + if (hcount >= 144) and (hcount < 784) and (vcount >= 31) and (vcount < 511) then + px <= TO_INTEGER(unsigned(hcount) - 144); + py <= TO_INTEGER(unsigned(vcount) - 31); + if(bufferFilledonBuffer0 = (py/2)) then + rgb_out <= ram_x0(px/2); + elsif(bufferFilledonbuffer1 = (py/2)) then + rgb_out <= ram_x1(px/2); + + else + rgb_out <= (others => '0'); + + end if; + end if; + -- pulse width + hsync <= '1'; + if hcount < 97 then + hsync <= '0'; + end if; + + vsync <= '1'; + if vcount < 3 then + vsync <= '0'; + end if; + + -- sync pulse time + hcount <= hcount + 1; + + if hcount = 800 then + vcount <= vcount + 1; + hcount <= (others => '0'); + end if; + + if vcount = 521 then + vcount <= (others => '0'); + end if; + end if; + + -- output colors + RO <= rgb_out(11 downto 8); + GO <= rgb_out(7 downto 4); + BO <= rgb_out(3 downto 0); + end if; + end process; + +end Behavioral; diff --git a/basys3/basys3.srcs/ppu_vga_native_tb.vhd b/basys3/basys3.srcs/ppu_vga_native_tb.vhd new file mode 100644 index 0000000..3a225d8 --- /dev/null +++ b/basys3/basys3.srcs/ppu_vga_native_tb.vhd @@ -0,0 +1,116 @@ +---------------------------------------------------------------------------------- +-- Company: +-- Engineer: +-- +-- Create Date: 22.02.2023 13:28:57 +-- Design Name: +-- Module Name: ppu_vga_native_tb - Behavioral +-- Project Name: +-- Target Devices: +-- Tool Versions: +-- Description: +-- +-- Dependencies: +-- +-- Revision: +-- Revision 0.01 - File Created +-- Additional Comments: +-- +---------------------------------------------------------------------------------- + + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use work.ppu_consts.all; + +use IEEE.NUMERIC_STD.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + + +-- Uncomment the following library declaration if instantiating +-- any Xilinx leaf cells in this code. +library UNISIM; +use UNISIM.VComponents.all; + +entity ppu_vga_native_tb is +end ppu_vga_native_tb; + +architecture Behavioral of ppu_vga_native_tb is +component ppu_vga_native + Port ( CLK: in std_logic; -- system clock + RESET: in std_logic; + + X: in std_logic_vector(PPU_POS_H_WIDTH-1 downto 0); -- current screen pixel x + Y: in std_logic_vector(PPU_POS_V_WIDTH-1 downto 0); -- current screen pixel y + PREADY: in std_logic; -- current pixel ready (pixel color is stable) + RI,GI,BI: in std_logic_vector(PPU_COLOR_OUTPUT_DEPTH-1 downto 0); -- VGA color in + + RO,GO,BO: out std_logic_vector(PPU_COLOR_OUTPUT_DEPTH-1 downto 0); -- VGA color out + VSYNC, HSYNC: out std_logic); -- VGA sync outputs +end component; +signal clk : std_logic := '0'; +signal rst : std_logic := '0'; +signal Pready : std_logic := '0'; + +signal X : std_logic_vector(PPU_POS_H_WIDTH-1 downto 0) := (others => '0'); + +signal Xas : integer := 72; +signal Yas : integer := 14; +signal counter : std_logic_vector(1 downto 0) := (others => '0'); +signal Y : std_logic_vector(PPU_POS_V_WIDTH-1 downto 0) := (others => '0'); +signal RI,GI,BI: std_logic_vector(PPU_COLOR_OUTPUT_DEPTH-1 downto 0) := (others => '0'); -- VGA color in +signal RO,GO,BO: std_logic_vector(PPU_COLOR_OUTPUT_DEPTH-1 downto 0) := (others => '0'); -- VGA color out +signal VSYNC, HSYNC: std_logic := '0'; +begin + +UUT : ppu_vga_native port map( + clk => clk, + reset => rst, + x => x, + y => y, + pready => pready, + ri => ri, + gi => gi, + bi => bi, + ro => ro, + go => go, + bo => bo, + vsync => vsync, + hsync => hsync +); + + tb : process + begin + clk <= '1'; + wait for 1 ps; + clk <= '0'; + wait for 1 ps; + end process; + + + process(clk) + begin + if rising_edge(clk) then + counter <= counter + 1; + end if; + + if(counter = "11") then + pready <= '1'; + ri <= x"d"; + gi <= x"a"; + bi <= x"d"; + x <= std_logic_vector(to_unsigned(Xas, x'length)); + if (Xas = 391) then + Xas <= 72; + y <= std_logic_vector(to_unsigned(Yas, y'length)); + if (Yas = 255) then + Yas <= 14; + else + Yas <= Yas + 1; + end if; + else + Xas <= Xas + 1; + end if; + end if; + end process; +end Behavioral; diff --git a/basys3/basys3.srcs/ppu_vga_tiny.vhd b/basys3/basys3.srcs/ppu_vga_tiny.vhd new file mode 100644 index 0000000..f47df48 --- /dev/null +++ b/basys3/basys3.srcs/ppu_vga_tiny.vhd @@ -0,0 +1,103 @@ +---------------------------------------------------------------------------------- +-- Company: +-- Engineer: +-- +-- Create Date: 22.02.2023 13:13:03 +-- Design Name: +-- Module Name: ppu_vga_tiny - Behavioral +-- Project Name: +-- Target Devices: +-- Tool Versions: +-- Description: +-- +-- Dependencies: +-- +-- Revision: +-- Revision 0.01 - File Created +-- Additional Comments: +-- +---------------------------------------------------------------------------------- + + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use work.ppu_consts.all; + +use IEEE.NUMERIC_STD.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; +-- Uncomment the following library declaration if instantiating +-- any Xilinx leaf cells in this code. +--library UNISIM; +--use UNISIM.VComponents.all; + +entity ppu_vga_tiny is + Port ( + CLK: in std_logic; -- system clock + RESET: in std_logic; + + X: out std_logic_vector(PPU_POS_H_WIDTH-1 downto 0); -- current screen pixel x + Y: out std_logic_vector(PPU_POS_V_WIDTH-1 downto 0); -- current screen pixel y + + VSYNC, VBLANK, + HSYNC, HBLANK: out std_logic); -- VGA sync outputs + +end ppu_vga_tiny; + +architecture Behavioral of ppu_vga_tiny is + signal hcount: STD_LOGIC_VECTOR(PPU_POS_H_WIDTH-1 downto 0):= (others => '0'); + signal vcount: STD_LOGIC_VECTOR(PPU_POS_V_WIDTH-1 downto 0):= (others => '0'); + signal CLKcounter: STD_LOGIC_VECTOR(4 downto 0):= (others => '0'); + +begin +process (CLK) +begin + if rising_edge(CLK) then + CLKcounter <= CLKcounter + 1; + if(CLKcounter > 15) then + clkCounter <= (others => '0'); + -- x,y data uit + X <= hcount; + Y <= vcount; + + --pulse width + if hcount < 32 or hcount >= 320-80 then + hsync <= '0'; + else + hsync <= '1'; + end if; + + if vcount < 8 or vcount >= 240-15 then + vsync <= '0'; + else + vsync <= '1'; + end if; + + -- Hblank and Vblank outputs + if hcount >= 320-80 then + hblank <= '1'; + else + hblank <= '0'; + end if; + + if vcount >= 240-15 then + vblank <= '1'; + else + vblank <= '0'; + end if; + + -- sync pulse time + hcount <= hcount + 1; + + if hcount = 400 then + vcount <= vcount + 1; + hcount <= (others => '0'); + end if; + + if vcount = 255 then + vcount <= (others => '0'); + end if; + end if; + end if; +end process; + +end Behavioral; diff --git a/basys3/basys3.xpr b/basys3/basys3.xpr index 0c452cf..4060a21 100644 --- a/basys3/basys3.xpr +++ b/basys3/basys3.xpr @@ -166,6 +166,37 @@ <Attr Name="UsedIn" Val="simulation"/> </FileInfo> </File> + <File Path="$PSRCDIR/ppu_vga_tiny.vhd"> + <FileInfo> + <Attr Name="UsedIn" Val="synthesis"/> + <Attr Name="UsedIn" Val="simulation"/> + </FileInfo> + </File> + <File Path="$PSRCDIR/ppu_comp.vhd"> + <FileInfo> + <Attr Name="UsedIn" Val="synthesis"/> + <Attr Name="UsedIn" Val="simulation"/> + </FileInfo> + </File> + <File Path="$PSRCDIR/ppu_plut.vhd"> + <FileInfo> + <Attr Name="UsedIn" Val="synthesis"/> + <Attr Name="UsedIn" Val="simulation"/> + </FileInfo> + </File> + <File Path="$PSRCDIR/ppu_vga_native.vhd"> + <FileInfo> + <Attr Name="UsedIn" Val="synthesis"/> + <Attr Name="UsedIn" Val="simulation"/> + </FileInfo> + </File> + <File Path="$PSRCDIR/apu_lut_reader.vhd"> + <FileInfo> + <Attr Name="UserDisabled" Val="1"/> + <Attr Name="UsedIn" Val="synthesis"/> + <Attr Name="UsedIn" Val="simulation"/> + </FileInfo> + </File> <Config> <Option Name="DesignMode" Val="RTL"/> <Option Name="TopModule" Val="ppu"/> diff --git a/test/sdl2/.gitignore b/test/sdl2/.gitignore new file mode 100644 index 0000000..f0c9b81 --- /dev/null +++ b/test/sdl2/.gitignore @@ -0,0 +1,2 @@ +*.o +main diff --git a/test/sdl2/main.c b/test/sdl2/main.c new file mode 100644 index 0000000..beddc3f --- /dev/null +++ b/test/sdl2/main.c @@ -0,0 +1,48 @@ +#include <stdlib.h> +#include <stdbool.h> +#include <math.h> +#include <SDL2/SDL.h> + +#define UPSCALE_FACTOR 3 +#define WIN_HEIGHT 240 +#define WIN_WIDTH 320 +#define FPS 60 + +static void pixel(SDL_Renderer* r, unsigned px, unsigned py, unsigned cr, unsigned cg, unsigned cb) { + SDL_SetRenderDrawColor(r, cr, cg, cb, 255); + SDL_RenderFillRect(r, &(SDL_Rect) {.x = px * UPSCALE_FACTOR, .y = py * UPSCALE_FACTOR, .w = UPSCALE_FACTOR, .h = UPSCALE_FACTOR}); +} + +int main() { + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS); + SDL_Window *window = SDL_CreateWindow("sdl2 test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIN_WIDTH * UPSCALE_FACTOR, WIN_HEIGHT * UPSCALE_FACTOR, SDL_WINDOW_SHOWN); + SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); + + SDL_Event e; + unsigned long frame = 0; + while (true) { + uint32_t start = SDL_GetTicks(); + frame++; + while (SDL_PollEvent(&e)) if (e.type == SDL_QUIT) exit(0); + + SDL_RenderClear(renderer); + + for (unsigned i = 0; i < WIN_WIDTH; i++) { + for (unsigned j = 0; j < WIN_HEIGHT; j++) { + pixel(renderer, i, j, (unsigned)(sqrt(i * 20) + frame) % 255, (i * j + frame) % 255, (j * 20) % 255); + } + } + + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + SDL_RenderPresent(renderer); + + uint32_t end = SDL_GetTicks(); + int wait_for = 1000 / FPS - (end - start); + if (wait_for > 0) SDL_Delay(wait_for); + } + + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); + return 0; +} diff --git a/test/sdl2/makefile b/test/sdl2/makefile new file mode 100644 index 0000000..4c26dc3 --- /dev/null +++ b/test/sdl2/makefile @@ -0,0 +1,18 @@ +CC = gcc +LD = gcc +RM = rm -f +TARGET = main +LFLAGS += -lSDL2 -lm +OBJS += main.o + +all: $(TARGET) + +%.o: %.c + $(CC) -c $(CFLAGS) $< -o $@ + +$(TARGET): $(OBJS) + $(LD) $^ $(LFLAGS) -o $@ + +clean: + $(RM) $(TARGET) $(OBJS) + diff --git a/test/sdl2/readme.md b/test/sdl2/readme.md new file mode 100644 index 0000000..940e315 --- /dev/null +++ b/test/sdl2/readme.md @@ -0,0 +1,6 @@ +# sdl2 test + +this is a simple POC that makes a window to draw PPU graphics to using SDL2. +this code will be moved to the stm32/ppu directory, and the stm32's makefile +will be edited to include a sim target for building the game for desktop +debugging. |