From dff1254bd960dd86d64d8bb7feb8c154a7df865c Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Sat, 15 May 2010 15:05:35 +0000 Subject: [PATCH] fixed unaligned src blitter bug Committed on the Free edition of March Hare Software CVSNT Server. Upgrade to CVS Suite for more features and support: http://march-hare.com/cvsnt/ git-svn-id: http://moon:8086/svn/vhdl/trunk@913 cc03376c-175c-47c8-b038-4cd826a8556b --- lib/VGA_ctrl/src/vga_frontend64.vhd | 149 ++++++++++++++++------------ 1 file changed, 88 insertions(+), 61 deletions(-) diff --git a/lib/VGA_ctrl/src/vga_frontend64.vhd b/lib/VGA_ctrl/src/vga_frontend64.vhd index 66e6f13..9142e54 100644 --- a/lib/VGA_ctrl/src/vga_frontend64.vhd +++ b/lib/VGA_ctrl/src/vga_frontend64.vhd @@ -195,7 +195,8 @@ architecture Behavioral of vga_frontend64 is signal blit_src_do_extra2 : std_logic; signal blit_src_row_cnt : unsigned(31 downto 0); - signal blit_src_last_in_row : std_logic; + signal blit_src_first : std_logic; + signal blit_src_last : 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); @@ -210,12 +211,14 @@ architecture Behavioral of vga_frontend64 is signal blit_dst_reg_vld : std_logic; signal blit_dst_unaligned : std_logic; signal blit_dst_row_cnt : unsigned(31 downto 0); - signal blit_dst_last_in_row : std_logic; + signal blit_dst_first : std_logic; + signal blit_dst_last : std_logic; signal blit_dst_do_extra : std_logic; signal blit_dst_reg_be : unsigned(7 downto 0); signal blit_dst_rdy : std_logic; signal blit_dst_we : std_logic; signal blit_dst_re : std_logic; + signal blit_dst_vld : std_logic; 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); @@ -255,6 +258,39 @@ architecture Behavioral of vga_frontend64 is type vm_state_t is (init, rdy, scan_bus_request, scan_bus_read, blit_src_bus_request, blit_src_bus_read, blit_dst_prime_pipe, blit_dst_bus_request, bus_fin); signal s, sn : vm_state_t; + type byte_en_rom_t is array (0 to 2*8-1) of unsigned (8-1 downto 0); + + function gen_byte_en_rom(N : natural) return byte_en_rom_t is + variable k : integer; + variable result : byte_en_rom_t; + begin + + k:=0; + + result(k) := (others => '1'); + k := k + 1; + + for i in 1 to N-1 loop + result(k) := (N-1 downto i => '1') & (i-1 downto 0 => '0'); + k := k + 1; + end loop; + + result(k) := (others => '1'); + k := k + 1; + + for i in 1 to N-1 loop + result(k) := (N-1 downto i => '0') & (i-1 downto 0 => '1'); + k := k + 1; + end loop; + + return result; + end gen_byte_en_rom; + + signal byte_en_rom : byte_en_rom_t := gen_byte_en_rom(8); + signal byte_en : unsigned (8-1 downto 0); + signal eb : std_logic; + +-------------------------------------------------------------------------- begin proc_synced_vga_scan_en: @@ -442,7 +478,7 @@ vga_master_next: end process; vga_master: - process(s, stat_vga_rdy, vga_scan_dma_en2, fifo_almost_empty, fifo_almost_full, SRDY_I, ACK_I, bus_read_fin, bus_fifo_rdy, bus_fifo_empty, blit_chunk_cnt, blitfifo_src_empty, blit_dst_reg_vld, blit_src_finish, blit_dst_finish, blit_const_color_en, blitfifo_src_full) + process(s, stat_vga_rdy, vga_scan_dma_en2, fifo_almost_empty, fifo_almost_full, SRDY_I, ACK_I, bus_read_fin, bus_fifo_rdy, bus_fifo_empty, blit_chunk_cnt, blitfifo_src_empty, blit_dst_vld, blit_src_finish, blit_dst_finish, blit_const_color_en, blitfifo_src_full) begin CYC_O_scan <= '0'; @@ -472,7 +508,7 @@ vga_master: if fifo_almost_empty = '1' and vga_scan_dma_en2 = '1' then sn <= scan_bus_request; elsif blit_request = '1' then -- ToDo: richtig prüfen anhand eines states wer dran ist. Nicht auf FIFO state prüfen - if blitfifo_src_empty = '0' or blit_dst_reg_vld = '1' then + if blitfifo_src_empty = '0' or blit_dst_vld = '1' then sn <= blit_dst_prime_pipe; elsif blit_const_color_en = '0' then sn <= blit_src_bus_request; @@ -519,18 +555,18 @@ vga_master: when blit_dst_prime_pipe => bus_cycle_en <= '1'; CYC_O_blit_dst <= '1'; - STB_O_blit_dst <= blit_dst_reg_vld; - blit_chunk_cnt_en <= blit_dst_reg_vld; - if blit_dst_reg_vld = '1' then + STB_O_blit_dst <= blit_dst_vld; + blit_chunk_cnt_en <= blit_dst_vld; + if blit_dst_vld = '1' then sn <= blit_dst_bus_request; end if; when blit_dst_bus_request => bus_cycle_en <= '1'; CYC_O_blit_dst <= '1'; - STB_O_blit_dst <= blit_dst_reg_vld; - blit_chunk_cnt_en <= blit_dst_reg_vld; - if blit_chunk_cnt = 0 or blit_dst_reg_vld = '0' then + STB_O_blit_dst <= blit_dst_vld; + blit_chunk_cnt_en <= blit_dst_vld; + if blit_chunk_cnt = 0 or blit_dst_vld = '0' then sn <= bus_fin; end if; @@ -656,27 +692,27 @@ proc_blit_src_counter: if blit_reset = '1' then blit_src_row_cnt <= (others => '0'); blit_src_unaligned <= '0'; - blit_src_last_in_row <= '0'; - if blit_src_addr (2 downto 0) /= "000" then - blit_src_unaligned <= not blit_const_color_en; - blit_src_last_in_row <= '1'; - end if; + blit_src_first <= '0'; + blit_src_last <= '0'; blit_src_do_extra2 <= '0'; - elsif blit_src_reg_vld = '1' then - if blit_src_re = '1' then - blit_src_last_in_row <= '0'; - if blit_src_last_in_row = '0' then - if blit_src_row_cnt /= blit_nx then - blit_src_row_cnt <= blit_src_row_cnt + 1; - if blit_src_unaligned = '1' then - blit_src_do_extra2 <= '1'; - end if; - elsif blit_src_do_extra2 = '1' then - blit_src_do_extra2 <= '0'; - else - blit_src_row_cnt <= (others => '0'); - blit_src_last_in_row <= blit_src_unaligned; + if blit_src_addr (2 downto 0) /= "000" then + blit_src_unaligned <= not blit_const_color_en; + blit_src_first <= not blit_const_color_en; + blit_src_do_extra2 <= not blit_const_color_en; + end if; + elsif blit_src_re = '1' then + if blit_src_reg_vld = '1' then + blit_src_first <= '0'; + if blit_src_row_cnt /= blit_nx then + blit_src_row_cnt <= blit_src_row_cnt + 1; + if blit_src_unaligned = '1' then + blit_src_do_extra2 <= '1'; end if; + elsif blit_src_do_extra2 = '1' then + blit_src_do_extra2 <= '0'; + else + blit_src_row_cnt <= (others => '0'); + blit_src_first <= blit_src_unaligned; end if; end if; end if; @@ -704,9 +740,9 @@ inst_blitfifo_src: entity work.fifo_sync ); - blitfifo_src_we <= (blit_src_reg_vld and not blit_src_last_in_row) when blit_const_color_en = '0' else (blit_request and not blit_src_finish); + blitfifo_src_we <= (blit_src_reg_vld and not blit_src_first) when blit_const_color_en = '0' else (blit_request and not blit_src_finish); blitfifo_src_in <= blit_src_reg when blit_const_color_en = '0' else (blit_const_color & blit_const_color); - blitfifo_src_re <= blit_dst_re and not blit_dst_last_in_row; + blitfifo_src_re <= blit_dst_re; --------------------------------------------------------------------------------- ADDR_O_blit_src <= blit_addr_src_0(31 downto 3) & "000" + blit_src_offset; @@ -761,43 +797,25 @@ inst_align_dst : entity work.align eb => '1', ce => blit_dst_re, offset => blit_addr_dst(2 downto 0), - din_last_vld => blit_dst_last_in_row, + din_last_vld => '0', din_vld => blit_dst_we, din => blitfifo_src_out, dout_vld => blit_dst_reg_vld, dout => blit_dst_reg, - dout_be => blit_dst_reg_be + dout_be => open ); - blit_dst_we <= not blitfifo_src_empty and not blit_dst_last_in_row; - blit_dst_re <= CYC_O_blit_dst and bus_fifo_rdy; - -proc_blit_dst_counter: - process(CLK_I) - begin - if rising_edge(CLK_I) then - if blit_reset = '1' then - blit_dst_last_in_row <= '0'; - blit_dst_unaligned <= '0'; - if blit_addr_dst (2 downto 0) /= "000" then - blit_dst_unaligned <= '1'; - end if; - blit_dst_row_cnt <= (others => '0'); - elsif blit_dst_re = '1' then - blit_dst_last_in_row <= '0'; - if blit_dst_we = '1' then - if blit_dst_row_cnt /= blit_nx then - blit_dst_row_cnt <= blit_dst_row_cnt + 1; - else - blit_dst_row_cnt <= (others => '0'); - blit_dst_last_in_row <= blit_dst_unaligned; - end if; - end if; - end if; - end if; - end process; + eb <= '1'; + blit_dst_reg_be <= byte_en_rom(to_integer(not eb & blit_addr_dst(2 downto 0))) when blit_dst_first = '1' else + not byte_en_rom(to_integer(not eb & blit_addr_dst(2 downto 0))) when blit_dst_last = '1' else + (others => '1'); + + blit_dst_we <= not blitfifo_src_empty; + blit_dst_re <= CYC_O_blit_dst and bus_fifo_rdy and not blit_dst_last; + blit_dst_vld <= blit_dst_reg_vld or blit_dst_last; + --------------------------------------------------------------------------------- ADDR_O_blit_dst <= blit_addr_dst(31 downto 3) & "000" + blit_dst_offset; @@ -812,8 +830,16 @@ proc_blit_addr_dst: blit_dst_finish <= '0'; blit_dst_cnt_x <= (others => '0'); blit_dst_do_extra <= '0'; + blit_dst_first <= '1'; + blit_dst_last <= '0'; + blit_dst_unaligned <= '0'; + if blit_addr_dst (2 downto 0) /= "000" then + blit_dst_unaligned <= '1'; + end if; elsif blit_dst_finish = '0' and (STB_O_blit_dst = '1' and bus_fifo_rdy = '1') then - blit_dst_offset <= blit_dst_offset + 8; + blit_dst_first <= blit_dst_last; + blit_dst_last <= '0'; + blit_dst_offset <= blit_dst_offset + 8; if blit_dst_cnt_x /= blit_nx then blit_dst_cnt_x <= blit_dst_cnt_x + 1; if blit_dst_unaligned = '1' then @@ -821,6 +847,7 @@ proc_blit_addr_dst: end if; elsif blit_dst_do_extra = '1' then blit_dst_do_extra <= '0'; + blit_dst_last <= '1'; else if blit_dst_cnt_y /= blit_ny then blit_dst_cnt_x <= (others => '0');