aboutsummaryrefslogtreecommitdiff
path: root/basys3/basys3.srcs/ppu_dispctl.vhd
diff options
context:
space:
mode:
Diffstat (limited to 'basys3/basys3.srcs/ppu_dispctl.vhd')
-rw-r--r--basys3/basys3.srcs/ppu_dispctl.vhd76
1 files changed, 70 insertions, 6 deletions
diff --git a/basys3/basys3.srcs/ppu_dispctl.vhd b/basys3/basys3.srcs/ppu_dispctl.vhd
index e1086b2..8f07f93 100644
--- a/basys3/basys3.srcs/ppu_dispctl.vhd
+++ b/basys3/basys3.srcs/ppu_dispctl.vhd
@@ -1,5 +1,6 @@
library ieee;
use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
use work.ppu_consts.all;
@@ -30,19 +31,82 @@ architecture Behavioral of ppu_dispctl is
rsta_busy : out std_logic;
rstb_busy : out std_logic);
end component;
- signal RGB_COLOR : std_logic_vector(PPU_RGB_COLOR_OUTPUT_DEPTH-1 downto 0);
+ signal CLK25 : unsigned(1 downto 0) := (others => '0'); -- clock divider (100_000_000/4)
+ signal PCOUNT, HCOUNT, VCOUNT : unsigned(PPU_VGA_SIGNAL_PIXEL_WIDTH-1 downto 0) := (others => '0');
+ signal ADDR_I, ADDR_O : std_logic_vector(PPU_DISPCTL_SLBUF_ADDR_WIDTH-1 downto 0);
+ signal DATA_I, DATA_O : std_logic_vector(PPU_RGB_COLOR_OUTPUT_DEPTH-1 downto 0);
+ signal T_POS_X : unsigned(PPU_SCREEN_T_POS_X_WIDTH-1 downto 0) := (others => '0');
+ signal T_POS_Y : unsigned(PPU_SCREEN_T_POS_Y_WIDTH-1 downto 0) := (others => '0');
+ signal N_POS_X : unsigned(PPU_SCREEN_N_POS_X_WIDTH-1 downto 0) := (others => '0');
+ signal N_POS_Y : unsigned(PPU_SCREEN_N_POS_Y_WIDTH-1 downto 0) := (others => '0');
+ signal ACTIVE, HACTIVE, VACTIVE : std_logic := '0';
begin
- RGB_COLOR <= RI & GI & BI;
+ DATA_I <= RI & GI & BI;
+ ADDR_I <= std_logic_vector(resize(T_POS_X, ADDR_I'length)) when T_POS_Y(0) = '0' else std_logic_vector(resize(T_POS_X, ADDR_I'length) + PPU_SCREEN_WIDTH);
+
+ X <= std_logic_vector(T_POS_X);
+ Y <= std_logic_vector(T_POS_Y);
+
+ RO <= DATA_O(11 downto 8);
+ GO <= DATA_O(7 downto 4);
+ BO <= DATA_O(3 downto 0);
+
+ HCOUNT <= PCOUNT mod PPU_VGA_H_TOTAL;
+ VCOUNT <= PCOUNT / PPU_VGA_H_TOTAL mod PPU_VGA_V_TOTAL;
+
+ HACTIVE <= '1' when
+ (HCOUNT > (PPU_VGA_H_PORCH_BACK)) and
+ (HCOUNT <= (PPU_VGA_H_PORCH_BACK + PPU_VGA_H_ACTIVE)) else '0';
+ VACTIVE <= '1' when
+ (VCOUNT > (PPU_VGA_V_PORCH_BACK)) and
+ (VCOUNT <= (PPU_VGA_V_PORCH_BACK + PPU_VGA_V_ACTIVE)) else '0';
+ ACTIVE <= HACTIVE and VACTIVE;
+
+ NVSYNC <= '1' when
+ (VCOUNT > (PPU_VGA_V_PORCH_BACK + PPU_VGA_V_ACTIVE)) and
+ (VCOUNT <= (PPU_VGA_V_PORCH_BACK + PPU_VGA_V_ACTIVE + PPU_VGA_V_SYNC)) else '0';
+ NHSYNC <= '1' when VACTIVE = '1' and
+ (HCOUNT > (PPU_VGA_H_PORCH_BACK + PPU_VGA_H_ACTIVE)) and
+ (HCOUNT <= (PPU_VGA_H_PORCH_BACK + PPU_VGA_H_ACTIVE + PPU_VGA_H_SYNC)) else '0';
+
+ N_POS_X <= resize(HCOUNT - PPU_VGA_H_PORCH_BACK, N_POS_X'length);
+ N_POS_Y <= resize(VCOUNT - PPU_VGA_V_PORCH_BACK, N_POS_Y'length);
+
+ T_POS_X <= resize(N_POS_X / 2, T_POS_X'length);
+ T_POS_Y <= resize(N_POS_Y / 2, T_POS_Y'length);
scanline_buffer : component ppu_dispctl_slbuf port map(
clka => CLK,
wea => (others => PREADY),
- addra => (others => '0'),
- dina => RGB_COLOR,
+ addra => ADDR_I,
+ dina => DATA_I,
clkb => CLK,
rstb => RESET,
- addrb => (others => '0'),
- doutb => open,
+ addrb => ADDR_O,
+ doutb => DATA_O,
rsta_busy => open,
rstb_busy => open);
+
+ process(CLK, RESET)
+ begin
+ if RESET = '1' then
+ CLK25 <= (others => '0');
+ elsif rising_edge(CLK) then
+ CLK25 <= CLK25 + 1;
+ end if;
+ end process;
+
+ process(CLK25(1), RESET)
+ variable V_PCOUNT : unsigned(PPU_VGA_SIGNAL_PIXEL_WIDTH-1 downto 0) := (others => '0');
+ begin
+ PCOUNT <= V_PCOUNT;
+ if RESET = '1' then
+ V_PCOUNT := (others => '0');
+ elsif rising_edge(CLK25(1)) then
+ V_PCOUNT := V_PCOUNT + 1;
+ if V_PCOUNT = PPU_VGA_SIGNAL_PIXEL_IDX_MAX then
+ V_PCOUNT := (others => '0');
+ end if;
+ end if;
+ end process;
end Behavioral;