diff --git a/lib/VGA_ctrl/src/vga_frontend64.vhd b/lib/VGA_ctrl/src/vga_frontend64.vhd index 0a78718..cd33c3f 100644 --- a/lib/VGA_ctrl/src/vga_frontend64.vhd +++ b/lib/VGA_ctrl/src/vga_frontend64.vhd @@ -123,7 +123,7 @@ architecture Behavioral of vga_frontend64 is -- Bus master signals constant MAX_REQUEST_CNT : natural := tsvga.ts_h.ncyc_scan*tsvga.ts_v.ncyc_scan; - + signal bufchg : std_logic; signal bufchg_irq_en : std_logic; signal bufchg_flag : std_logic; @@ -158,12 +158,46 @@ architecture Behavioral of vga_frontend64 is signal read_cnt : unsigned(28 downto 0); signal bus_read_fin : std_logic; + signal CYC_O_scan : std_logic; signal STB_O_scan : std_logic; signal ADDR_O_scan : unsigned(31 downto 0); signal pixel_cnt : natural range 0 to MAX_REQUEST_CNT/2-1; signal front : unsigned(31 downto 0); signal back : unsigned(31 downto 0); + -- Blitter vars + constant BLIT_CHUNK_SIZE : natural := 32; + signal blit_chunk_cnt : natural range 0 to BLIT_CHUNK_SIZE-1; + + -- Blitter FIFO signals + signal blitfifo_full : std_logic; + signal blitfifo_empty : std_logic; + signal blitfifo_almost_empty : std_logic; + signal blitfifo_almost_full : std_logic; + signal blitfifo_color_re : std_logic; + signal blitfifo_color_we : std_logic; + signal blitfifo_color_out : unsigned(63 downto 0); + signal blitfifo_color_in : unsigned(63 downto 0); + + signal blit_reset : std_logic; + signal blit_src_cnt_x : unsigned(31 downto 0); + signal blit_src_cnt_y : unsigned(31 downto 0); + signal blit_src_off_y : unsigned(31 downto 0); + signal blit_src_offset : unsigned(31 downto 0); + signal blit_src_finish : std_logic; + signal CYC_O_blit_src : std_logic; + signal STB_O_blit_src : std_logic; + signal ADDR_O_blit_src : unsigned(31 downto 0); + + signal blit_dst_cnt_x : unsigned(31 downto 0); + signal blit_dst_cnt_y : unsigned(31 downto 0); + signal blit_dst_off_y : unsigned(31 downto 0); + signal blit_dst_offset : unsigned(31 downto 0); + signal blit_dst_finish : std_logic; + signal CYC_O_blit_dst : std_logic; + signal STB_O_blit_dst : std_logic; + signal ADDR_O_blit_dst : unsigned(31 downto 0); + signal odd_pixel : unsigned(NextExpBaseTwo(tsvga.ts_h.ncyc_scan)-1 downto 0); -- Bus FIFO @@ -185,7 +219,7 @@ architecture Behavioral of vga_frontend64 is alias bus_fifo_sel_out is bus_fifo_dout(103 downto 96); alias bus_fifo_we_out is bus_fifo_dout(104); - type vm_state_t is (init, idle, rdy, bus_request, bus_data); + type vm_state_t is (init, idle, rdy, scan_bus_request, scan_bus_read, blit_src_bus_request, blit_src_bus_read, blit_dst_bus_request, blit_dst_bus_fin); signal s, sn : vm_state_t; begin @@ -204,12 +238,34 @@ proc_bufchg_irq: end if; end process; -proc_blit_flags: +proc_blit_request_flags: + process(CLK_I) + begin + if rising_edge(CLK_I) then + blit_reset <= '0'; + if pixel_cnt_rst = '1' then + blit_request <= '0'; + blit_reset <= '1'; + elsif blit_request = '0' then + if blit_request_set = '1' then + blit_request <= '1'; + blit_reset <= '1'; + end if; + elsif blit_dst_finish = '1' and blitfifo_empty = '1' then + blit_request <= '0'; + end if; + end if; + end process; + +proc_blit_complete_flag: process(CLK_I) begin if rising_edge(CLK_I) then if RST_I = '1' then - blit_request <= '0'; + blit_complete <= '0'; + elsif blit_dst_finish = '1' and blitfifo_empty = '1' then + blit_complete <= '1'; + elsif blit_complete_ack = '1' then blit_complete <= '0'; end if; end if; @@ -301,7 +357,34 @@ inst_linefifo: entity work.fifo_async fifo_color_in <= MDAT_I; fifo_color_re <= stat_scan and odd_pixel(0); - fifo_color_we <= ACK_I and read_bus_en; -- TODO: + fifo_color_we <= ACK_I and read_bus_en and CYC_O_scan; -- TODO: + +inst_blitfifo: entity work.fifo_sync + GENERIC MAP + ( + addr_width => NextExpBaseTwo(32), + data_width => 64, + almost_full_thresh => 24, + almost_empty_thresh => 8 + ) + PORT MAP + ( + rst => RST_I, + clk => CLK_I, + we => blitfifo_color_we, + re => blitfifo_color_re, + data_w => blitfifo_color_in, + data_r => blitfifo_color_out, + fifo_full => blitfifo_full, + fifo_empty => blitfifo_empty, + fifo_afull => blitfifo_almost_full, + fifo_aempty => blitfifo_almost_empty + + ); + + blitfifo_color_in <= MDAT_I; + blitfifo_color_re <= CYC_O_blit_dst and bus_rdy; + blitfifo_color_we <= ACK_I and read_bus_en and CYC_O_blit_src; -- TODO: -- Instantiate synchronous FIFO inst_bus_fifo: entity work.fifo_sync @@ -326,12 +409,16 @@ inst_bus_fifo: entity work.fifo_sync bus_rdy <= not bus_fifo_full; bus_fifo_re <= not bus_fifo_empty and SRDY_I; bus_fifo_we <= request_en; - bus_fifo_data_in <= (others => '-'); - bus_fifo_addr_in <= ADDR_O_scan; + bus_fifo_data_in <= blitfifo_color_out; + bus_fifo_addr_in <= ADDR_O_blit_src when CYC_O_blit_src = '1' else + ADDR_O_blit_dst when CYC_O_blit_dst = '1' else + ADDR_O_scan; bus_fifo_sel_in <= (others => '1'); - bus_fifo_we_in <= '0'; + bus_fifo_we_in <= CYC_O_blit_dst; ADDR_O_scan <= front + (to_unsigned(pixel_cnt, 29) & "000"); + CYC_O <= CYC_O_scan or CYC_O_blit_src or CYC_O_blit_dst; + vga_master_next: process(CLK_I) begin @@ -345,11 +432,15 @@ vga_master_next: end process; vga_master: - process(s, stat_vga_rdy, vga_master_en, vga_scan_rdy, fifo_almost_empty, fifo_almost_full, SRDY_I, ACK_I, bus_read_fin) + process(s, stat_vga_rdy, vga_master_en, vga_scan_rdy, fifo_almost_empty, fifo_almost_full, SRDY_I, ACK_I, bus_read_fin, bus_fifo_empty, blit_chunk_cnt) begin - CYC_O <= '0'; + CYC_O_scan <= '0'; STB_O_scan <= '0'; + CYC_O_blit_src <= '0'; + STB_O_blit_src <= '0'; + CYC_O_blit_dst <= '0'; + STB_O_blit_dst <= '0'; pixel_cnt_rst <= '0'; request_cnt_rst <= '0'; request_en <= '0'; @@ -371,19 +462,26 @@ vga_master: when rdy => request_cnt_rst <= '1'; if fifo_almost_empty = '1' then - sn <= bus_request; + sn <= scan_bus_request; + elsif blit_request = '1' then + if blitfifo_empty = '1' then + sn <= blit_src_bus_request; + else + sn <= blit_dst_bus_request; + end if; end if; - when bus_request => - CYC_O <= '1'; + when scan_bus_request => + CYC_O_scan <= '1'; STB_O_scan <= '1'; request_en <= '1'; read_bus_en <= '1'; if fifo_almost_full = '1' then - sn <= bus_data; + sn <= scan_bus_read; end if; - when bus_data => - CYC_O <= '1'; + + when scan_bus_read => + CYC_O_scan <= '1'; read_bus_en <= '1'; if bus_read_fin = '1' then sn <= rdy; @@ -391,6 +489,37 @@ vga_master: sn <= idle; end if; end if; + + when blit_src_bus_request => + CYC_O_blit_src <= '1'; + STB_O_blit_src <= '1'; + request_en <= '1'; + read_bus_en <= '1'; + if blit_chunk_cnt = 0 then + sn <= blit_src_bus_read; + end if; + + when blit_src_bus_read => + CYC_O_blit_src <= '1'; + read_bus_en <= '1'; + if bus_read_fin = '1' then + sn <= rdy; + end if; + + when blit_dst_bus_request => + CYC_O_blit_dst <= '1'; + STB_O_blit_dst <= '1'; + request_en <= '1'; + if blit_chunk_cnt = 0 then + sn <= blit_dst_bus_fin; + end if; + + when blit_dst_bus_fin => + CYC_O_blit_dst <= '1'; + if bus_fifo_empty = '1' then + sn <= rdy; + end if; + when others => sn <= idle; @@ -440,7 +569,7 @@ proc_scan_addr: if pixel_cnt_rst = '1' then pixel_cnt <= 0; front <= host_fb_front; - elsif request_en = '1' and bus_rdy = '1' then + elsif STB_O_scan = '1' and bus_rdy = '1' then if pixel_cnt /= MAX_REQUEST_CNT/2-1 then pixel_cnt <= pixel_cnt + 1; else @@ -454,6 +583,78 @@ proc_scan_addr: end if; end process; + ADDR_O_blit_src <= blit_addr_src_0 + blit_src_offset; + +proc_blit_chunk_counter: + process(CLK_I) + begin + if rising_edge(CLK_I) then + if request_en = '0' then + blit_chunk_cnt <= BLIT_CHUNK_SIZE-1; + elsif blit_chunk_cnt /= 0 and bus_rdy = '1' and (STB_O_blit_src = '1' or STB_O_blit_dst = '1') then + blit_chunk_cnt <= blit_chunk_cnt - 1; + end if; + end if; + end process; + +proc_blit_addr_src: + process(CLK_I) + begin + if rising_edge(CLK_I) then + if blit_reset = '1' then + blit_src_cnt_x <= (others => '0'); + blit_src_cnt_y <= (others => '0'); + blit_src_offset <= (others => '0'); + blit_src_off_y <= blit_dimx_src_0; + blit_src_finish <= '0'; + elsif STB_O_blit_src = '1' and bus_rdy = '1' then + if blit_src_cnt_x /= blit_nx then + blit_src_cnt_x <= blit_src_cnt_x + 1; + blit_src_offset <= blit_src_offset + 8; + else + if blit_src_cnt_y /= blit_ny then + blit_src_cnt_x <= (others => '0'); + blit_src_offset <= blit_src_off_y; + blit_src_cnt_y <= blit_src_cnt_y + 1; + blit_src_off_y <= blit_src_off_y + blit_dimx_src_0; + else + blit_src_finish <= '1'; + end if; + end if; + end if; + end if; + end process; + + ADDR_O_blit_dst <= blit_addr_dst + blit_dst_offset; + +proc_blit_addr_dst: + process(CLK_I) + begin + if rising_edge(CLK_I) then + if blit_reset = '1' then + blit_dst_cnt_x <= (others => '0'); + blit_dst_cnt_y <= (others => '0'); + blit_dst_offset <= (others => '0'); + blit_dst_off_y <= blit_dimx_dst; + blit_dst_finish <= '0'; + elsif STB_O_blit_dst = '1' and bus_rdy = '1' then + if blit_dst_cnt_x /= blit_nx then + blit_dst_cnt_x <= blit_dst_cnt_x + 1; + blit_dst_offset <= blit_dst_offset + 8; + else + if blit_dst_cnt_y /= blit_ny then + blit_dst_cnt_x <= (others => '0'); + blit_dst_offset <= blit_dst_off_y; + blit_dst_cnt_y <= blit_dst_cnt_y + 1; + blit_dst_off_y <= blit_dst_off_y + blit_dimx_dst; + else + blit_dst_finish <= '1'; + end if; + end if; + end if; + end if; + end process; + inst_char_gen : entity work.char_gen GENERIC MAP (