diff --git a/.gitignore b/.gitignore index 71ab53f..f817422 100755 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,5 @@ xst/ _xmsgs/ planahead/ isim/ -xlnx_auto_0_xdb/ \ No newline at end of file +xlnx_auto_0_xdb/ +vga?*.bmp diff --git a/Makefile b/Makefile index 92a37b8..d283b60 100755 --- a/Makefile +++ b/Makefile @@ -86,7 +86,7 @@ FUSE=$(XILPATH)fuse .SECONDARY: -all: $(BITFILE) firmware/fw.elf +all: $(BITFILE) #firmware/fw.elf synth: $(NGCFILE) @@ -94,8 +94,8 @@ impl: $(NCDFILE_R) timing: $(TWRFILE) -firmware/fw.elf: - cd firmware && make fw.elf +#firmware/fw.elf: +# cd firmware && make fw.elf #%.vhd: %.psm # ../tools/picoasm/picoasm -t ../tools/picoasm/ROM_form.vhd -i $< diff --git a/coregen/vga_pixeldata_fifo.xco b/coregen/vga_pixeldata_fifo.xco index 99f5e01..6c51dd7 100644 --- a/coregen/vga_pixeldata_fifo.xco +++ b/coregen/vga_pixeldata_fifo.xco @@ -1,7 +1,7 @@ ############################################################## # # Xilinx Core Generator version 14.4 -# Date: Sat Mar 02 17:01:48 2013 +# Date: Thu Mar 07 19:42:24 2013 # ############################################################## # @@ -111,14 +111,14 @@ CSET fifo_implementation_wach=Common_Clock_Block_RAM CSET fifo_implementation_wdch=Common_Clock_Block_RAM CSET fifo_implementation_wrch=Common_Clock_Block_RAM CSET full_flags_reset_value=1 -CSET full_threshold_assert_value=496 +CSET full_threshold_assert_value=502 CSET full_threshold_assert_value_axis=1023 CSET full_threshold_assert_value_rach=1023 CSET full_threshold_assert_value_rdch=1023 CSET full_threshold_assert_value_wach=1023 CSET full_threshold_assert_value_wdch=1023 CSET full_threshold_assert_value_wrch=1023 -CSET full_threshold_negate_value=495 +CSET full_threshold_negate_value=501 CSET id_width=4 CSET inject_dbit_error=false CSET inject_dbit_error_axis=false @@ -134,7 +134,7 @@ CSET inject_sbit_error_rdch=false CSET inject_sbit_error_wach=false CSET inject_sbit_error_wdch=false CSET inject_sbit_error_wrch=false -CSET input_data_width=32 +CSET input_data_width=64 CSET input_depth=512 CSET input_depth_axis=1024 CSET input_depth_rach=16 @@ -144,7 +144,7 @@ CSET input_depth_wdch=1024 CSET input_depth_wrch=16 CSET interface_type=Native CSET output_data_width=16 -CSET output_depth=1024 +CSET output_depth=2048 CSET overflow_flag=false CSET overflow_flag_axi=false CSET overflow_sense=Active_High @@ -168,7 +168,7 @@ CSET rach_type=FIFO CSET rdch_type=FIFO CSET read_clock_frequency=1 CSET read_data_count=false -CSET read_data_count_width=10 +CSET read_data_count_width=11 CSET register_slice_mode_axis=Fully_Registered CSET register_slice_mode_rach=Fully_Registered CSET register_slice_mode_rdch=Fully_Registered @@ -210,4 +210,4 @@ CSET wuser_width=1 MISC pkg_timestamp=2012-11-19T12:39:56Z # END Extra information GENERATE -# CRC: 558db809 +# CRC: 1cbb4c67 diff --git a/src/clk_reset.vhd b/src/clk_reset.vhd index e6980b2..15862d9 100755 --- a/src/clk_reset.vhd +++ b/src/clk_reset.vhd @@ -32,39 +32,44 @@ library UNISIM; use UNISIM.VComponents.all; entity clk_reset is - Generic ( - reset_dcm_on_ext_reset : BOOLEAN := false + generic ( + reset_dcm_on_ext_reset : boolean := false + ); + port ( + clkIn50 : in std_logic; + sysClk50 : out std_logic; + sysClk25 : out std_logic; + rstIn : in std_logic; + sysRst50 : out std_logic ); - Port ( clkIn50 : in STD_ULOGIC; - sysClk50 : out STD_ULOGIC; - rstIn : in STD_ULOGIC; - sysRst50 : out STD_ULOGIC); end clk_reset; architecture Behavioral of clk_reset is -signal locked_int, rst_int : std_ulogic := '0'; -signal clkOut50_int : std_ulogic; +signal locked_int, rst_int : std_logic := '0'; +signal clkOut50_int, clkOut25_int : std_logic; constant reset_pulse_width : integer := 3; -signal rstIn_sync_dcm : std_ulogic_vector(2 downto 0) := "000"; -signal dcm_in_rst : std_ulogic := '0'; +signal rstIn_sync_dcm : std_logic_vector(2 downto 0) := "000"; +signal dcm_in_rst : std_logic := '0'; signal dcm_in_rst_ctr : natural range 0 to reset_pulse_width-1; -signal locked_prev : std_ulogic := '0'; +signal locked_prev : std_logic := '0'; -signal rstIn_sync_sys : std_ulogic_vector(2 downto 0) := "000"; -signal sys_in_rst : std_ulogic := '1'; +signal rstIn_sync_sys : std_logic_vector(2 downto 0) := "000"; +signal sys_in_rst : std_logic := '1'; signal sys_in_rst_ctr : natural range 0 to reset_pulse_width-1; begin dcm50 : DCM_SP generic map ( - CLKIN_PERIOD => 20.0 + CLKIN_PERIOD => 20.0, + CLKDV_DIVIDE => 2.0 ) port map ( CLKIN => clkIn50, CLKFB => clkOut50_int, CLK0 => clkOut50_int, + CLKDV => clkOut25_int, LOCKED => locked_int, RST => rst_int, @@ -128,4 +133,5 @@ sys_rst_gen : process(clkOut50_int, locked_int) end process sys_rst_gen; sysClk50 <= clkOut50_int; + sysClk25 <= clkOut25_int; end Behavioral; diff --git a/src/toplevel.vhd b/src/toplevel.vhd index 710d463..37cb74f 100755 --- a/src/toplevel.vhd +++ b/src/toplevel.vhd @@ -114,20 +114,37 @@ architecture Mixed of toplevel is end component; component vga + generic ( + h_total_pixels : integer; + h_front_porch : integer; + h_back_porch : integer; + h_sync_pulse : integer; + h_sync_pos : boolean; + h_active_pixels : integer; + v_total_lines : integer; + v_front_porch : integer; + v_back_porch : integer; + v_sync_pulse : integer; + v_sync_pos : boolean; + v_active_lines : integer; + framebuffer0_base : integer; + burst_length : integer; + burst_length_ln2 : integer; + addr_width : integer; + dontcare : std_logic); port ( - clk_in : in std_ulogic; - rst : in std_ulogic; - - enable_vga : in std_logic; - - wbm_i : in vga_wbm_i_type; - wbm_o : out vga_wbm_o_type; - - red : out std_ulogic_vector(3 downto 0); - green : out std_ulogic_vector(3 downto 0); - blue : out std_ulogic_vector(3 downto 0); - vsync : out std_ulogic; - hsync : out std_ulogic); + clk_in : in std_logic; + clk_vga : in std_logic; + rst : in std_logic; + mem_rdrq : out std_logic; + mem_adr : out std_logic_vector(19 downto 0); + mem_ack : in std_logic; + mem_dat_i : in std_logic_vector(31 downto 0); + red : out std_logic_vector(3 downto 0); + green : out std_logic_vector(3 downto 0); + blue : out std_logic_vector(3 downto 0); + vsync : out std_logic; + hsync : out std_logic); end component; component cpu_system @@ -169,7 +186,7 @@ architecture Mixed of toplevel is reset : in std_logic); end component; -signal sysClk, sysRst : std_logic; +signal sysClk, sysRst, vgaClk : std_logic; signal vga_wbm_i : vga_wbm_i_type; signal vga_wbm_o : vga_wbm_o_type; @@ -182,16 +199,22 @@ signal rom_wbs_i : rom_wbs_i_type; signal sdram_ctrl_wbs_i : sdram_ctrl_wbs_i_type; signal sdram_ctrl_wbs_o : sdram_ctrl_wbs_o_type; +signal vga_mem_rdrq : std_logic; +signal vga_mem_adr : std_logic_vector(19 downto 0); +signal vga_mem_ack : std_logic; +signal vga_mem_dat_i : std_logic_vector(31 downto 0); + signal enable_vga : std_logic; begin sys_clk_rst : clk_reset - port map ( - clkIn50 => clkin_50MHz, - rstIn => reset, - sysClk50 => sysClk, - sysRst50 => sysRst - ); + port map ( + clkIn50 => clkin_50MHz, + rstIn => reset, + sysClk50 => sysClk, + sysClk15 => vgaClk, + sysRst50 => sysRst + ); ddr_ctrl0 : wb_ddr_ctrl port map ( @@ -223,24 +246,40 @@ ddr_ctrl0 : wb_ddr_ctrl wbs_o => sdram_ctrl_wbs_o ); --- disable vga core for testing -enable_vga <= '0'; - -vga_inst: vga +vga_1: vga + generic map ( + h_total_pixels => h_total_pixels, + h_front_porch => h_front_porch, + h_back_porch => h_back_porch, + h_sync_pulse => h_sync_pulse, + h_sync_pos => h_sync_pos, + h_active_pixels => h_active_pixels, + v_total_lines => v_total_lines, + v_front_porch => v_front_porch, + v_back_porch => v_back_porch, + v_sync_pulse => v_sync_pulse, + v_sync_pos => v_sync_pos, + v_active_lines => v_active_lines, + framebuffer0_base => framebuffer0_base, + burst_length => burst_length, + burst_length_ln2 => burst_length_ln2, + addr_width => addr_width, + dontcare => dontcare) port map ( - clk_in => sysClk, - rst => sysRst, - - enable_vga => enable_vga, + clk_in => sysClk, + clk_vga => vgaClk, + rst => rst, - wbm_i => vga_wbm_i, - wbm_o => vga_wbm_o, + mem_rdrq => vga_mem_rdrq, + mem_adr => vga_mem_adr, + mem_ack => vga_mem_ack, + mem_dat_i => vga_mem_dat_i, - red => vga_r, - green => vga_g, - blue => vga_b, - vsync => vga_vsync, - hsync => vga_hsync); + red => vga_r, + green => vga_g, + blue => vga_b, + vsync => vga_vsync, + hsync => vga_hsync); wb_ram_inst: wb_ram port map ( diff --git a/src/vga.vhd b/src/vga.vhd index a096d04..fa38046 100644 --- a/src/vga.vhd +++ b/src/vga.vhd @@ -34,37 +34,72 @@ use IEEE.NUMERIC_STD.ALL; use work.intercon_package.all; entity vga is - port ( - clk_in : in std_ulogic; - rst : in std_ulogic; - - -- temporary, for debugging - enable_vga : in std_logic; + generic ( + -- 640x480@60Hz (with 25 MHz clk) + h_total_pixels : integer := 800; + h_front_porch : integer := 16; + h_back_porch : integer := 48; + h_sync_pulse : integer := 96; + h_sync_pos : boolean := false; + h_active_pixels : integer := 640; + v_total_lines : integer := 525; + v_front_porch : integer := 10; + v_back_porch : integer := 33; + v_sync_pulse : integer := 2; + v_sync_pos : boolean := false; + v_active_lines : integer := 480; - -- Wishbone master - wbm_i : in vga_wbm_i_type; - wbm_o : out vga_wbm_o_type; + framebuffer0_base : integer := 0; + burst_length : integer := 16; + burst_length_ln2 : integer := 4; + addr_width : integer := 24; + dontcare : std_logic := '-' + ); + port ( + clk_in : in std_logic; + clk_vga : in std_logic; + rst : in std_logic; + + -- to memory + mem_rdrq : out std_logic; + mem_adr : out std_logic_vector(19 downto 0); + mem_ack : in std_logic; + mem_dat_i : in std_logic_vector(31 downto 0); -- to vga - red : out std_ulogic_vector(3 downto 0); - green : out std_ulogic_vector(3 downto 0); - blue : out std_ulogic_vector(3 downto 0); - vsync : out std_ulogic; - hsync : out std_ulogic + red : out std_logic_vector(3 downto 0); + green : out std_logic_vector(3 downto 0); + blue : out std_logic_vector(3 downto 0); + vsync : out std_logic; + hsync : out std_logic ); end vga; architecture Structural of vga is component vga_pixelreader + generic ( + framebuffer0_base : integer; + burst_length : integer; + burst_length_ln2 : integer; + addr_width : integer; + dontcare : std_logic; + h_active_pixels : integer; + v_active_lines : integer + ); port ( - clk : in std_ulogic; - rst : in std_ulogic; + clk : in std_logic; + rst : in std_logic; + pixeldata : out std_logic_vector(31 downto 0); - fifo_write : out std_ulogic; - fifo_full16 : in std_ulogic; - - wbm_i : in vga_wbm_i_type; - wbm_o : out vga_wbm_o_type); + fifo_write : out std_logic; + fifo_full16 : in std_logic; + fifo_rst : out std_logic; + vsync : in std_logic; + + mem_rdrq : out std_logic; + mem_adr : out std_logic_vector(19 downto 0); + mem_ack : in std_logic; + mem_dat_i : in std_logic_vector(31 downto 0)); end component; component vga_pixeldata_fifo @@ -80,58 +115,77 @@ architecture Structural of vga is empty : OUT STD_LOGIC; prog_full : OUT STD_LOGIC); end component; - + component vga_syncgen generic ( - sync_out_delay : integer); + sync_out_delay : integer; + h_total_pixels : integer; + h_front_porch : integer; + h_back_porch : integer; + h_sync_pulse : integer; + h_sync_pos : boolean; + v_total_lines : integer; + v_front_porch : integer; + v_back_porch : integer; + v_sync_pulse : integer; + v_sync_pos : boolean); port ( clk : in std_ulogic; - vsync : out std_ulogic; - hsync : out std_ulogic; - column : out unsigned(9 downto 0); - row : out unsigned(9 downto 0)); + vsync : out std_logic := '1'; + hsync : out std_logic := '1'; + vid_en : out std_logic := '0'); end component; component vga_pixelgen port ( - clk : in std_ulogic; - row : in unsigned(9 downto 0); - column : in unsigned(9 downto 0); - pixeldata : in std_ulogic_vector(15 downto 0); - fifo_read : out std_ulogic; - fifo_empty : in std_ulogic; - red : out std_ulogic_vector(3 downto 0); - green : out std_ulogic_vector(3 downto 0); - blue : out std_ulogic_vector(3 downto 0)); + clk : in std_logic; + vid_en : in std_logic; + pixeldata : in std_logic_vector(15 downto 0); + fifo_read : out std_logic; + fifo_empty : in std_logic; + red : out std_logic_vector(3 downto 0); + green : out std_logic_vector(3 downto 0); + blue : out std_logic_vector(3 downto 0)); end component; signal in_pixeldata : std_logic_vector(31 downto 0); signal out_pixeldata : std_logic_vector(15 downto 0); - signal fifo_write, fifo_read, fifo_empty, fifo_full16 : std_ulogic; + signal fifo_write, fifo_read, fifo_empty, fifo_full16, fifo_rst : std_logic; - signal column, row : unsigned(9 downto 0); - - signal clk : std_logic := '0'; + signal vid_en : std_logic; + signal vsync_i : std_logic; + signal vsync_to_clk_in : std_logic_vector(1 downto 0); begin - - clk <= clk_in when enable_vga = '1' else '0'; vga_pixelreader_inst: vga_pixelreader + generic map ( + framebuffer0_base => framebuffer0_base, + burst_length => burst_length, + burst_length_ln2 => burst_length_ln2, + addr_width => addr_width, + dontcare => dontcare, + h_active_pixels => h_active_pixels, + v_active_lines => v_active_lines + ) port map ( - clk => clk, + clk => clk_in, rst => rst, pixeldata => in_pixeldata, fifo_write => fifo_write, fifo_full16 => fifo_full16, + fifo_rst => fifo_rst, + vsync => vsync_to_clk_in(1), - wbm_i => wbm_i, - wbm_o => wbm_o); + mem_rdrq => mem_rdrq, + mem_adr => mem_adr, + mem_ack => mem_ack, + mem_dat_i => mem_dat_i); vga_pixeldata_fifo_inst: vga_pixeldata_fifo port map ( - rst => rst, - wr_clk => clk, - rd_clk => clk, + rst => fifo_rst, + wr_clk => clk_in, + rd_clk => clk_vga, din => in_pixeldata, wr_en => fifo_write, rd_en => fifo_read, @@ -139,27 +193,44 @@ begin full => open, empty => fifo_empty, prog_full => fifo_full16); + + vsync_to_clk_in_ff : process(clk_in) + begin + if rising_edge(clk_in) then + vsync_to_clk_in <= vsync_to_clk_in(vsync_to_clk_in'left-1 downto 0) & vsync_i; + end if; + end process vsync_to_clk_in_ff; - vga_syncgen_inst: vga_syncgen + vga_syncgen_1: vga_syncgen generic map ( - sync_out_delay => 1) + sync_out_delay => 2, + h_total_pixels => h_total_pixels, + h_front_porch => h_front_porch, + h_back_porch => h_back_porch, + h_sync_pulse => h_sync_pulse, + h_sync_pos => h_sync_pos, + v_total_lines => v_total_lines, + v_front_porch => v_front_porch, + v_back_porch => v_back_porch, + v_sync_pulse => v_sync_pulse, + v_sync_pos => v_sync_pos) port map ( - clk => clk, - vsync => vsync, + clk => clk_vga, + vsync => vsync_i, hsync => hsync, - column => column, - row => row); + vid_en => vid_en); vga_pixelgen_inst: vga_pixelgen port map ( - clk => clk, - row => row, - column => column, - pixeldata => std_ulogic_vector(out_pixeldata), + clk => clk_vga, + vid_en => vid_en, + pixeldata => out_pixeldata, fifo_read => fifo_read, fifo_empty => fifo_empty, red => red, green => green, blue => blue); + + vsync <= vsync_i; end Structural; diff --git a/src/vga_pixelgen.vhd b/src/vga_pixelgen.vhd index c2b1f3b..b93b93b 100644 --- a/src/vga_pixelgen.vhd +++ b/src/vga_pixelgen.vhd @@ -33,47 +33,48 @@ use IEEE.NUMERIC_STD.ALL; entity vga_pixelgen is port ( - clk : in std_ulogic; + clk : in std_logic; -- from syncgen - row : in unsigned(9 downto 0); - column : in unsigned(9 downto 0); + vid_en : in std_logic; -- from fifo - pixeldata : in std_ulogic_vector(15 downto 0); - fifo_read : out std_ulogic; - fifo_empty : in std_ulogic; + pixeldata : in std_logic_vector(15 downto 0); + fifo_read : out std_logic; + fifo_empty : in std_logic; -- to vga - red : out std_ulogic_vector(3 downto 0); - green : out std_ulogic_vector(3 downto 0); - blue : out std_ulogic_vector(3 downto 0) + red : out std_logic_vector(3 downto 0); + green : out std_logic_vector(3 downto 0); + blue : out std_logic_vector(3 downto 0) ); end vga_pixelgen; architecture Behavioral of vga_pixelgen is + signal empty_dly : std_logic := '0'; + signal data_valid : std_logic := '0'; begin + fifo_read <= vid_en; + pixelgen : process(clk) + -- synthesis translate_off + variable firstframe : boolean := true; + variable underflowing : boolean := false; + -- synthesis translate_on begin if rising_edge(clk) then - if row <= 479 and column <= 640 then - fifo_read <= '1'; - else - fifo_read <= '0'; + data_valid <= not fifo_empty and vid_en; + empty_dly <= fifo_empty; + + if data_valid = '1' then + assert empty_dly = '0' report "Video output FIFO underflow" severity warning; end if; - if row <= 479 and column > 1 and column <= 641 then - if fifo_empty = '1' then - assert false report "Warning: VGA output FIFO underflow" severity warning; - red <= (others => '0'); - green <= (others => '0'); - blue <= (others => '0'); - else - red <= pixeldata(3 downto 0); - green <= pixeldata(7 downto 4); - blue <= pixeldata(11 downto 8); - end if; + if data_valid = '1' and empty_dly = '0' then + red <= pixeldata(11 downto 8); + green <= pixeldata(7 downto 4); + blue <= pixeldata(3 downto 0); else red <= (others => '0'); green <= (others => '0'); diff --git a/src/vga_pixelreader.vhd b/src/vga_pixelreader.vhd index 8f76904..73d6121 100644 --- a/src/vga_pixelreader.vhd +++ b/src/vga_pixelreader.vhd @@ -36,71 +36,88 @@ use work.intercon_package.all; entity vga_pixelreader is generic ( framebuffer0_base : integer := 0; - burst_length : integer := 16 + burst_length : integer := 16; + burst_length_ln2 : integer := 4; + addr_width : integer := 24; + dontcare : std_logic := '-'; + h_active_pixels : integer := 640; + v_active_lines : integer := 480 ); port ( - clk : in std_ulogic; - rst : in std_ulogic; - - -- from/to fifo - pixeldata : out std_logic_vector(31 downto 0); - fifo_write : out std_ulogic; - fifo_full16 : in std_ulogic; -- FIFO is 16 dwords from full (= 1 burst) - - -- Wishbone master - wbm_i : in vga_wbm_i_type; - wbm_o : out vga_wbm_o_type + clk : in std_logic; + rst : in std_logic; + + pixeldata : out std_logic_vector(31 downto 0); + fifo_write : out std_logic; + fifo_full16 : in std_logic; + fifo_rst : out std_logic; + vsync : in std_logic; + + mem_rdrq : out std_logic; + mem_adr : out std_logic_vector(19 downto 0); + mem_ack : in std_logic; + mem_dat_i : in std_logic_vector(31 downto 0) ); end vga_pixelreader; architecture Behavioral of vga_pixelreader is - type states is (S_IDLE, S_READ); - - signal state : states := S_IDLE; + type states is (S_INIT, S_IDLE, S_READ, S_WAIT_VSYNC, S_WAIT_VSYNC2); - signal addr_ctr : natural range 0 to 153599 := 0; + constant pixels : integer := h_active_pixels*v_active_lines; + + signal state : states := S_INIT; + + signal addr_ctr : natural range 0 to (pixels/(2*burst_length))-1 := 0; signal burst_ctr : natural range 0 to burst_length-1 := 0; begin +fifo_write <= mem_ack; +pixeldata <= mem_dat_i; + pixelreader : process(clk) begin if rising_edge(clk) then - fifo_write <= '0'; + mem_rdrq <= '0'; + fifo_rst <= '0'; + mem_adr <= (others => dontcare); + case state is + when S_INIT => + fifo_rst <= '1'; + if vsync = '0' then + state <= S_IDLE; + end if; when S_IDLE => if fifo_full16 = '0' then -- space in fifo for a burst of data - wbm_o.cyc_o <= '1'; - wbm_o.stb_o <= '1'; - wbm_o.cti_o <= "010"; - wbm_o.bte_o <= "00"; - wbm_o.sel_o <= (others => '1'); - wbm_o.adr_o <= std_logic_vector(to_unsigned(framebuffer0_base+addr_ctr*4, wbm_o.adr_o'length)); + mem_rdrq <= '1'; + mem_adr <= std_logic_vector(to_unsigned(framebuffer0_base/(burst_length*4)+addr_ctr, mem_adr'length)); + burst_ctr <= 0; - addr_ctr <= addr_ctr + 1; state <= S_READ; end if; when S_READ => - if wbm_i.ack_i = '1' then - pixeldata <= wbm_i.dat_i; - fifo_write <= '1'; - if burst_ctr = burst_length-2 then - wbm_o.cti_o <= "111"; - end if; + if mem_ack = '1' then if burst_ctr = burst_length-1 then - wbm_o.cyc_o <= '0'; - wbm_o.stb_o <= '0'; - state <= S_IDLE; - else - wbm_o.adr_o <= std_logic_vector(to_unsigned(framebuffer0_base+addr_ctr*4, wbm_o.adr_o'length)); - if addr_ctr = 153599 then + if addr_ctr = (pixels/(2*burst_length))-1 then addr_ctr <= 0; + state <= S_WAIT_VSYNC; else addr_ctr <= addr_ctr + 1; + state <= S_IDLE; end if; - + else burst_ctr <= burst_ctr + 1; end if; end if; + when S_WAIT_VSYNC => + if vsync = '0' then + fifo_rst <= '1'; + state <= S_WAIT_VSYNC2; + end if; + when S_WAIT_VSYNC2 => + if vsync = '1' then + state <= S_IDLE; + end if; end case; end if; end process pixelreader; diff --git a/src/vga_syncgen.vhd b/src/vga_syncgen.vhd index 1867a6d..820e979 100644 --- a/src/vga_syncgen.vhd +++ b/src/vga_syncgen.vhd @@ -33,62 +33,91 @@ use IEEE.NUMERIC_STD.ALL; entity vga_syncgen is generic ( - sync_out_delay : integer := 0 -- delay vsync/hsync this many clk cycles wrt - -- column/row + sync_out_delay : integer := 2; -- delay vsync/hsync this many clk cycles wrt + -- vid_en + -- 640x480@60Hz (with 25 MHz clk) + h_total_pixels : integer := 800; + h_front_porch : integer := 16; + h_back_porch : integer := 48; + h_sync_pulse : integer := 96; + h_sync_pos : boolean := false; + v_total_lines : integer := 525; + v_front_porch : integer := 10; + v_back_porch : integer := 33; + v_sync_pulse : integer := 2; + v_sync_pos : boolean := false ); port ( clk : in std_ulogic; - vsync : out std_ulogic := '1'; - hsync : out std_ulogic := '1'; - column : out unsigned(9 downto 0); - row : out unsigned(9 downto 0) + vsync : out std_logic := '1'; + hsync : out std_logic := '1'; + vid_en : out std_logic := '0' ); end vga_syncgen; architecture Behavioral of vga_syncgen is - signal row_i : natural range 0 to 524; - signal column_i : natural range 0 to 799; - signal vsync_i, hsync_i : std_ulogic := '1'; + signal row_i : natural range 0 to v_total_lines-1; + signal column_i : natural range 0 to h_total_pixels-1; + signal vsync_i, hsync_i : std_logic := '1'; begin - hsync_gen : process(clk) + sync_gen : process(clk) begin if rising_edge(clk) then - if column_i = 799 then + if column_i = h_total_pixels-1 then column_i <= 0; - else - column_i <= column_i + 1; - end if; - - if column_i >= 659 and column_i <= 754 then - hsync_i <= '0'; - else - hsync_i <= '1'; - end if; - end if; - end process hsync_gen; - - vsync_gen : process(clk) - begin - if rising_edge(clk) then - if column_i = 659 then - if row_i = 524 then + if row_i = v_total_lines-1 then row_i <= 0; else row_i <= row_i + 1; end if; + else + column_i <= column_i + 1; + end if; - if row_i = 493 then + if column_i < h_sync_pulse then + -- assert hsync + if h_sync_pos then + hsync_i <= '1'; + else + hsync_i <= '0'; + end if; + else + -- deassert hsync + if h_sync_pos then + hsync_i <= '0'; + else + hsync_i <= '1'; + end if; + end if; + + if row_i < v_sync_pulse then + -- assert vsync + if v_sync_pos then + vsync_i <= '1'; + else + vsync_i <= '0'; + end if; + else + -- deassert vsync + if v_sync_pos then vsync_i <= '0'; else vsync_i <= '1'; end if; end if; - end if; - end process vsync_gen; - column <= to_unsigned(column_i, 10); - row <= to_unsigned(row_i, 10); + if column_i >= h_sync_pulse + h_back_porch and + column_i < h_total_pixels - h_front_porch and + row_i >= v_sync_pulse + v_back_porch and + row_i < v_total_lines - v_front_porch then + vid_en <= '1'; + else + vid_en <= '0'; + end if; + + end if; + end process sync_gen; no_sync_delay : if sync_out_delay = 0 generate vsync <= vsync_i; diff --git a/src/wb_ddr_ctrl.vhd b/src/wb_ddr_ctrl.vhd index 4e37d06..8b8aab2 100755 --- a/src/wb_ddr_ctrl.vhd +++ b/src/wb_ddr_ctrl.vhd @@ -63,7 +63,13 @@ entity wb_ddr_ctrl is clk_i : in std_ulogic; rst_i : in std_ulogic; wbs_i : in sdram_ctrl_wbs_i_type; - wbs_o : out sdram_ctrl_wbs_o_type + wbs_o : out sdram_ctrl_wbs_o_type; + + -- Direct memctrl access for VGA + vga_mem_rdrq : in std_logic; + vga_mem_adr : in std_logic_vector(19 downto 0); + vga_mem_ack : out std_logic; + vga_mem_dat_i : out std_logic_vector(31 downto 0) ); end wb_ddr_ctrl; @@ -137,7 +143,13 @@ component wb_ddr_ctrl_wb is clk_i : in std_ulogic; rst_i : in std_ulogic; wbs_i : in sdram_ctrl_wbs_i_type; - wbs_o : out sdram_ctrl_wbs_o_type + wbs_o : out sdram_ctrl_wbs_o_type; + + -- Direct memctrl access for VGA + vga_mem_rdrq : in std_logic; + vga_mem_adr : in std_logic_vector(19 downto 0); + vga_mem_ack : out std_logic; + vga_mem_dat_i : out std_logic_vector(31 downto 0) ); end component; @@ -214,7 +226,12 @@ wb_0 : wb_ddr_ctrl_wb ctrl_ar_done => ctrl_ar_done, wbs_i => wbs_i, - wbs_o => wbs_o + wbs_o => wbs_o, + + vga_mem_rdrq => vga_mem_rdrq, + vga_mem_adr => vga_mem_adr, + vga_mem_ack => vga_mem_ack, + vga_mem_dat_i => vga_mem_dat_i ); end Behavioral; diff --git a/src/wb_ddr_ctrl_wb.vhd b/src/wb_ddr_ctrl_wb.vhd index 4e7a676..528bc7b 100755 --- a/src/wb_ddr_ctrl_wb.vhd +++ b/src/wb_ddr_ctrl_wb.vhd @@ -57,7 +57,13 @@ entity wb_ddr_ctrl_wb is clk_i : in std_ulogic; rst_i : in std_ulogic; wbs_i : in sdram_ctrl_wbs_i_type; - wbs_o : out sdram_ctrl_wbs_o_type + wbs_o : out sdram_ctrl_wbs_o_type; + + -- Direct memctrl access for VGA + vga_mem_rdrq : in std_logic; + vga_mem_adr : in std_logic_vector(19 downto 0); + vga_mem_ack : out std_logic; + vga_mem_dat_i : out std_logic_vector(31 downto 0) ); end wb_ddr_ctrl_wb; @@ -95,6 +101,12 @@ component wb_ddr_ctrl_wb_sc is rst_i : in std_ulogic; wbs_i : in sdram_ctrl_wbs_i_type; wbs_o : out sdram_ctrl_wbs_o_type; + + -- Direct memctrl access for VGA + vga_mem_rdrq : in std_logic; + vga_mem_adr : in std_logic_vector(19 downto 0); + vga_mem_ack : out std_logic; + vga_mem_dat_i : out std_logic_vector(31 downto 0); -- To/from ddr clock domain ddr_din : out std_logic_vector(63 downto 0); @@ -167,6 +179,11 @@ system_cd_inst : wb_ddr_ctrl_wb_sc rst_i => rst_i, wbs_i => wbs_i, wbs_o => wbs_o, + + vga_mem_rdrq => vga_mem_rdrq, + vga_mem_adr => vga_mem_adr, + vga_mem_ack => vga_mem_ack, + vga_mem_dat_i => vga_mem_dat_i, -- To/from ddr clock domain ddr_din => s2d_fifo_din(63 downto 0), diff --git a/src/wb_ddr_ctrl_wb_sc.vhd b/src/wb_ddr_ctrl_wb_sc.vhd index a04f448..9e92501 100755 --- a/src/wb_ddr_ctrl_wb_sc.vhd +++ b/src/wb_ddr_ctrl_wb_sc.vhd @@ -35,8 +35,8 @@ use work.intercon_package.all; entity wb_ddr_ctrl_wb_sc is generic ( - burst_length : integer := 16 -- Currently only read burst, for write burst - -- arbitrary length is supported + burst_length : integer := 16; + dontcare : std_logic := '-' ); port ( -- Wishbone slave @@ -44,6 +44,14 @@ entity wb_ddr_ctrl_wb_sc is rst_i : in std_ulogic; wbs_i : in sdram_ctrl_wbs_i_type; wbs_o : out sdram_ctrl_wbs_o_type; + wbs_cc_i : in sdram_ctrl_cc_wbs_i_type; + wbs_cc_o : out sdram_ctrl_cc_wbs_o_type; + + -- Direct memctrl access for VGA + vga_mem_rdrq : in std_logic; + vga_mem_adr : in std_logic_vector(19 downto 0); + vga_mem_ack : out std_logic; + vga_mem_dat_i : out std_logic_vector(63 downto 0); -- To/from ddr clock domain ddr_din : out std_logic_vector(63 downto 0); @@ -60,278 +68,137 @@ entity wb_ddr_ctrl_wb_sc is end wb_ddr_ctrl_wb_sc; architecture Behavioral of wb_ddr_ctrl_wb_sc is -type states is (S_IDLE, - S_WRITE_CLASSIC1, - S_WRITE_BURST1, S_WRITE_BURST2, S_WRITE_BURST_WAIT1, - S_WRITE_BURST_WAIT2, - S_READ_CLASSIC1, S_READ_CLASSIC2, - S_READ_BURST1,S_READ_BURST_NEEDDATA, S_READ_BURST_GOTDATA, - S_READ_BURST_END); -signal state : states := S_IDLE; + component wb_ddr_ctrl_wb_sc_fe + generic ( + line_size : integer; + lines : integer; + assoc : integer; + line_size_ln2 : integer; + lines_ln2 : integer; + assoc_ln2 : integer; + addr_width : integer); + port ( + clk_i : in std_logic; + rst_i : in std_logic; + wbs_i : in sdram_ctrl_wbs_i_type; + wbs_o : out sdram_ctrl_wbs_o_type; + wbs_cc_i : in sdram_ctrl_cc_wbs_i_type; + wbs_cc_o : out sdram_ctrl_cc_wbs_o_type; + mem_adr : out std_logic_vector(addr_width-line_size_ln2-1 downto 0); + mem_rdrq : out std_logic; + mem_wrrq : out std_logic; + mem_dat_o : out std_logic_vector(31 downto 0); + mem_ack : in std_logic; + mem_dat_i : in std_logic_vector(31 downto 0)); + end component; -signal fifo_from_ddr_read_int, fifo_from_ddr_valid : std_ulogic; - -signal burst_ctr : natural range 1 to burst_length; -signal burst_unaligned : std_ulogic; - -signal ddr_dout_high, ddr_dout_high_d : std_ulogic; + type states is (S_IDLE); + signal state : states := S_IDLE; + + signal cfe_mem_adr : std_logic_vector(addr_width-line_size_ln2-1 downto 0); + signal cfe_mem_rdrq : std_logic; + signal cfe_mem_wrrq : std_logic; + signal cfe_mem_dat_o : std_logic_vector(63 downto 0); + signal cfe_mem_ack : std_logic; + signal cfe_mem_dat_i : std_logic_vector(63 downto 0)); + signal vga_active, cfe_active, burst_ctr_inc, burst_ctr_rst : std_logic := '1'; + signal in_ctr, out_ctr : unsigned(2 downto 0) := to_unsigned(0, 3); + signal in_complete, out_complete, rq_complete : std_logic := '1'; begin + wb_ddr_ctrl_wb_sc_fe_1: wb_ddr_ctrl_wb_sc_fe + port map ( + clk_i => clk_i, + rst_i => rst_i, + wbs_i => wbs_i, + wbs_o => wbs_o, + wbs_cc_i => wbs_cc_i, + wbs_cc_o => wbs_cc_o, + mem_adr => cfe_mem_adr, + mem_rdrq => cfe_mem_rdrq, + mem_wrrq => cfe_mem_wrrq, + mem_dat_o => cfe_mem_dat_o, + mem_ack => cfe_mem_ack, + mem_dat_i => cfe_mem_dat_i); -fifo_from_ddr_read_int <= '1' when ((--(state = S_READ_CLASSIC1 and fifo_to_ddr_full = '0') or - (state = S_READ_CLASSIC1) or - -- (state = S_READ_BURST1 and fifo_to_ddr_full = '0' and - -- ((burst_unaligned = '1' and burst_ctr = burst_length/2) or - -- (burst_unaligned = '0' and burst_ctr = (burst_length/2)-1))) or - (state = S_READ_BURST_NEEDDATA) --or - -- (state = S_READ_BURST4) - ) and fifo_from_ddr_empty = '0') or rst_i = '1' else - '0'; - -is_fifo_from_ddr_valid : process(clk_i) - begin - if falling_edge(clk_i) then - fifo_from_ddr_valid <= fifo_from_ddr_read_int; - end if; - end process is_fifo_from_ddr_valid; - -fifo_from_ddr_read <= fifo_from_ddr_read_int; + cfe_mem_dat_i <= ddr_din; + vga_mem_dat_i <= ddr_din; -wbs_o.dat_o <= ddr_dout(63 downto 32) when ddr_dout_high = '1' else - ddr_dout(31 downto 0); + ddr_adr(22 downto 3) <= vga_mem_adr when vga_active = '1' else + cfe_mem_adr when cfe_active = '1' else + (others => dontcare); + ddr_adr(2 downto 0) <= std_logic_vector(burst_ctr); + + ddr_we <= '0' when vga_active = '1' else + dontcare; -ddr_dout_high_d <= wbs_i.adr_i(2) when (state = S_READ_CLASSIC1) else - '1' when (state = S_READ_BURST_NEEDDATA and burst_unaligned = '1' and burst_ctr = 1) else - '1' when (state = S_READ_BURST_GOTDATA) else - '0' when (state = S_READ_BURST_NEEDDATA) else - '-'; -ddr_dout_high_reg : process(clk_i) + fifo_to_ddr_write <= '1' when out_complete = '0' and fifo_to_ddr_full = '0' and + state /= S_IDLE else + '0'; + + mem_if : process(clk_i) begin if rising_edge(clk_i) then - ddr_dout_high <= ddr_dout_high_d; - end if; - end process ddr_dout_high_reg; - -wb_slave : process(clk_i) -begin - if rising_edge(clk_i) then - if rst_i = '1' then - ddr_din <= (others => '-'); - ddr_adr <= (others => '-'); - ddr_we <= '-'; - ddr_be <= (others => '-'); fifo_to_ddr_write <= '0'; - wbs_o.ack_o <= '0'; - state <= S_IDLE; - else - --ddr_din <= (others => '-'); - --ddr_adr <= (others => '-'); - ddr_we <= '-'; - --ddr_be <= (others => '-'); - fifo_to_ddr_write <= '0'; - wbs_o.ack_o <= '0'; + case state is when S_IDLE => - if wbs_i.stb_i = '1' then - if wbs_i.we_i = '1' then - if wbs_i.cti_i = "010" and wbs_i.bte_i = "00" then -- incrementing - -- linear burst - if fifo_to_ddr_full = '0' then - wbs_o.ack_o <= '1'; - if wbs_i.adr_i(2) = '0' then -- aligned start - ddr_din <= (others => '-'); - ddr_adr <= (others => '-'); - ddr_be <= (others => '-'); - state <= S_WRITE_BURST2; - else -- unaligned start - ddr_adr <= (others => '-'); - ddr_adr <= (others => '-'); - ddr_be(7 downto 4) <= (others => '-'); - ddr_be(3 downto 0) <= "1111"; - state <= S_WRITE_BURST1; - end if; - end if; - else -- classic cycle or unsupported - if fifo_to_ddr_full = '0' then - if wbs_i.adr_i(2) = '0' then - ddr_din(31 downto 0) <= wbs_i.dat_i; - ddr_din(63 downto 32) <= (others => '-'); - ddr_be <= "1111" & not wbs_i.sel_i; - else - ddr_din(31 downto 0) <= (others => '-'); - ddr_din(63 downto 32) <= wbs_i.dat_i; - ddr_be <= not wbs_i.sel_i & "1111"; - end if; - ddr_adr <= wbs_i.adr_i(25 downto 3); - ddr_we <= '1'; - - fifo_to_ddr_write <= '1'; - wbs_o.ack_o <= '1'; - state <= S_WRITE_CLASSIC1; - end if; - end if; - else - ddr_din <= (others => '-'); - ddr_be <= (others => '-'); - if wbs_i.cti_i = "010" and wbs_i.bte_i = "00" then -- incrementing - -- linear burst - if fifo_to_ddr_full = '0' then - ddr_din <= (others => '-'); - ddr_be <= (others => '-'); - ddr_adr <= wbs_i.adr_i(25 downto 3); - ddr_we <= '0'; - fifo_to_ddr_write <= '1'; - if wbs_i.adr_i(2) = '0' then - burst_unaligned <= '0'; - else - burst_unaligned <= '1'; - end if; - burst_ctr <= 1; - state <= S_READ_BURST1; - end if; - else -- classic cycle or unsupported - if fifo_to_ddr_full = '0' then - ddr_adr <= wbs_i.adr_i(25 downto 3); - ddr_we <= '0'; - fifo_to_ddr_write <= '1'; - state <= S_READ_CLASSIC1; - end if; - end if; - end if; - end if; - - when S_WRITE_CLASSIC1 => - ddr_adr <= (others => '-'); - state <= S_IDLE; - - when S_WRITE_BURST1 => -- high dword, commit - ddr_din(63 downto 32) <= wbs_i.dat_i; - ddr_be(7 downto 4) <= not wbs_i.sel_i; - ddr_adr <= wbs_i.adr_i(25 downto 3); - if fifo_to_ddr_full = '0' then - ddr_we <= '1'; - fifo_to_ddr_write <= '1'; - - if wbs_i.cti_i = "111" then -- EOB, aligned end - state <= S_IDLE; - wbs_o.ack_o <= '0'; - elsif wbs_i.stb_i = '0' then - assert false report "Unexpected wbs_i.stb_i deassertion during write burst" severity warning; - ddr_be(7 downto 4) <= (others => '1'); - state <= S_IDLE; - wbs_o.ack_o <= '0'; - else - state <= S_WRITE_BURST2; - wbs_o.ack_o <= '1'; - end if; - else -- FIFO full - state <= S_WRITE_BURST_WAIT1; - wbs_o.ack_o <= '0'; - end if; - when S_WRITE_BURST2 => -- low dword - ddr_adr <= (others => '-'); - ddr_din(63 downto 32) <= (others => '-'); - ddr_din(31 downto 0) <= wbs_i.dat_i; - ddr_be(7 downto 4) <= (others => '-'); - ddr_be(3 downto 0) <= not wbs_i.sel_i; - - if wbs_i.cti_i = "111" then -- EOB, unaligned end - ddr_be(7 downto 4) <= (others => '1'); - ddr_adr <= wbs_i.adr_i(25 downto 3); - if fifo_to_ddr_full = '1' then - ddr_we <= '1'; + if fifo_to_ddr_full = '0' then + if vga_mem_rdrq = '1' then fifo_to_ddr_write <= '1'; - state <= S_IDLE; - else - state <= S_WRITE_BURST_WAIT2; + state <= S_VGA_RDRQ; + elsif cfe_mem_rdrq = '1' then + elsif cfe_mem_wrrq = '1' then end if; - wbs_o.ack_o <= '0'; - elsif wbs_i.stb_i = '0' then - assert false report "Unexpected stb_i deassertion during write burst" severity warning; + end if; + when S_VGA_RDRQ_SEND => + if rq_complete = '1' then state <= S_IDLE; - wbs_o.ack_o <= '0'; - else - state <= S_WRITE_BURST1; - wbs_o.ack_o <= '1'; end if; - when S_WRITE_BURST_WAIT1 => - if fifo_to_ddr_full = '0' then - ddr_we <= '1'; - fifo_to_ddr_write <= '1'; - if wbs_i.cti_i = "111" then - state <= S_IDLE; - wbs_o.ack_o <= '0'; - else - state <= S_WRITE_BURST2; - wbs_o.ack_o <= '1'; - end if; - end if; - when S_WRITE_BURST_WAIT2 => - ddr_we <= '1'; - fifo_to_ddr_write <= '1'; - state <= S_IDLE; - - when S_READ_CLASSIC1 => - ddr_adr <= (others => '-'); - if fifo_from_ddr_valid = '1' then - wbs_o.ack_o <= '1'; - state <= S_READ_CLASSIC2; - end if; - when S_READ_CLASSIC2 => - ddr_adr <= (others => '-'); - state <= S_IDLE; - - when S_READ_BURST1 => - ddr_din <= (others => '-'); - ddr_be <= (others => '-'); - if fifo_to_ddr_full = '0' then - ddr_adr <= std_logic_vector(unsigned(wbs_i.adr_i(25 downto 3)) + burst_ctr); - ddr_we <= '0'; - fifo_to_ddr_write <= '1'; - if (burst_unaligned = '1' and burst_ctr = burst_length/2) or - (burst_unaligned = '0' and burst_ctr = (burst_length/2)-1) then - burst_ctr <= 1; - state <= S_READ_BURST_NEEDDATA; - else - burst_ctr <= burst_ctr + 1; - end if; - end if; - when S_READ_BURST_NEEDDATA => - ddr_din <= (others => '-'); - ddr_be <= (others => '-'); - ddr_adr <= (others => '-'); - if fifo_from_ddr_valid = '1' then - wbs_o.ack_o <= '1'; - if burst_ctr = burst_length then - state <= S_READ_BURST_END; - else - burst_ctr <= burst_ctr + 1; - if burst_unaligned = '1' and burst_ctr = 1 then - state <= S_READ_BURST_NEEDDATA; - else - state <= S_READ_BURST_GOTDATA; - end if; - end if; - end if; - when S_READ_BURST_GOTDATA => - ddr_din <= (others => '-'); - ddr_be <= (others => '-'); - ddr_adr <= (others => '-'); - - wbs_o.ack_o <= '1'; - if burst_ctr = burst_length then - state <= S_READ_BURST_END; - else - burst_ctr <= burst_ctr + 1; - state <= S_READ_BURST_NEEDDATA; - end if; - when S_READ_BURST_END => - state <= S_IDLE; - end case; end if; - end if; -end process wb_slave; - + end process mem_if; + vga_active <= '1' when state = S_VGA_RDRQ else + '0'; + cfe_active <= '1' when state = S_CFE_RDRQ or state = S_CFE_WRRQ else + '0'; + + out_ctr_in <= '1' when fifo_to_ddr_write = '1' and out_complete = '0' else + '0'; + + out_ctr_rst <= '1' when fifo_to_ddr_full = '0' and (vga_mem_rdrq = '1' or cfe_mem_rdrq = '1' or + cfe_mem_rdrq = '1') and state = S_IDLE else + '0'; + + rq_complete <= in_complete and out_complete; + + out_ctr_p : process(clk_i) + begin + if rising_edge(clk_i) then + if out_ctr_rst = '1' then + out_ctr <= to_unsigned(0, 3); + elsif out_ctr_inc = '1' then + out_ctr <= out_ctr + 1; + end if; + end if; + end process burst_ctr_p; + + out_complete_p : process(clk_i) + begin + if rising_edge(clk_i) then + if out_ctr_rst = '1' then + out_complete <= '0'; + elsif fifo_to_ddr_write = '1' and out_ctr = 7 then + out_complete <= '1'; + end if; + end if; + end process out_complete_p; + + in_complete_p : process(clk_i) + begin + if rising_edge(clk_i) then + if out_ctr_rst = '1' then + + end Behavioral; diff --git a/src/wb_ddr_ctrl_wb_sc_fe.vhd b/src/wb_ddr_ctrl_wb_sc_fe.vhd index 36dc9ae..f068366 100644 --- a/src/wb_ddr_ctrl_wb_sc_fe.vhd +++ b/src/wb_ddr_ctrl_wb_sc_fe.vhd @@ -45,13 +45,13 @@ use work.intercon_package.all; entity wb_ddr_ctrl_wb_sc_fe is generic ( - line_size : integer := 16; + line_size : integer := 8; lines : integer := 64; assoc : integer := 2; - line_size_ln2 : integer := 4; + line_size_ln2 : integer := 3; lines_ln2 : integer := 6; assoc_ln2 : integer := 1; - addr_width : integer := 24 + addr_width : integer := 23 ); port ( -- Wishbone slave @@ -66,9 +66,9 @@ entity wb_ddr_ctrl_wb_sc_fe is mem_adr : out std_logic_vector(addr_width-line_size_ln2-1 downto 0); mem_rdrq : out std_logic; mem_wrrq : out std_logic; - mem_dat_o : out std_logic_vector(31 downto 0); + mem_dat_o : out std_logic_vector(63 downto 0); mem_ack : in std_logic; - mem_dat_i : in std_logic_vector(31 downto 0) + mem_dat_i : in std_logic_vector(63 downto 0) ); end wb_ddr_ctrl_wb_sc_fe; @@ -144,13 +144,14 @@ architecture Behavioral of wb_ddr_ctrl_wb_sc_fe is signal tags : tag_a := (others => (others => '-')); -- Cache data signals / memory - type cache_arr is array(lines*line_size-1 downto 0) of std_logic_vector(31 downto 0); + type cache_arr is array(lines*line_size-1 downto 0) of std_logic_vector(63 downto 0); signal cache : cache_arr := (others => (others => '-')); attribute ram_style of cache : signal is "block"; -- signal cache_we : std_logic := '0'; signal cache_wr_addr, cache_rd_addr : unsigned(lines_ln2+line_size_ln2-1 downto 0) := (others => '0'); - signal cache_wr_data, cache_rd_data : std_logic_vector(31 downto 0) := (others => '-'); - signal cache_bwe : std_logic_vector(3 downto 0) := (others => '-'); + signal cache_wr_data, cache_rd_data : std_logic_vector(63 downto 0) := (others => '-'); + signal cache_bwe : std_logic_vector(7 downto 0) := (others => '-'); + signal cache_di7, cache_di6, cache_di5, cache_di4 : std_logic_vector(7 downto 0); signal cache_di3, cache_di2, cache_di1, cache_di0 : std_logic_vector(7 downto 0); -- Convenience variables for adr_i @@ -182,15 +183,40 @@ begin cache_wr_addr <= adr_index & adr_tag_eq_num & adr_offset when cache_from_mem = '0' else adr_index & eject_num & mem_offset; --cache_we <= cache_write or (cache_from_mem and mem_ack); - cache_wr_data <= wbs_i.dat_i when cache_write = '1' else + cache_wr_data <= wbs_i.dat_i & wbs_i.dat_i when cache_write = '1' else mem_dat_i when cache_from_mem = '1' else (others => '-'); - cache_bwe <= wbs_i.sel_i when cache_write = '1' else - "1111" when cache_from_mem = '1' and mem_ack = '1' else - "0000"; + cache_bwe <= "0000" & wbs_i.sel_i when cache_write = '1' and wbs_i.adr_i(2) = '0' else + wbs_i.sel_i & "0000" when cache_write = '1' and wbs_i.adr_i(2) = '1' else + "11111111" when cache_from_mem = '1' and mem_ack = '1' else + "00000000"; cache_din : process(cache_wr_data, cache_wr_addr, cache_bwe) begin + if cache_bwe(7) = '1' then + cache_di7 <= cache_wr_data(63 downto 56); + else + cache_di7 <= cache(to_integer(cache_wr_addr))(63 downto 56); + end if; + + if cache_bwe(6) = '1' then + cache_di6 <= cache_wr_data(55 downto 48); + else + cache_di6 <= cache(to_integer(cache_wr_addr))(55 downto 48); + end if; + + if cache_bwe(5) = '1' then + cache_di5 <= cache_wr_data(47 downto 40); + else + cache_di5 <= cache(to_integer(cache_wr_addr))(47 downto 40); + end if; + + if cache_bwe(4) = '1' then + cache_di4 <= cache_wr_data(39 downto 32); + else + cache_di4 <= cache(to_integer(cache_wr_addr))(39 downto 32); + end if; + if cache_bwe(3) = '1' then cache_di3 <= cache_wr_data(31 downto 24); else @@ -220,12 +246,14 @@ begin cache_mem : process(clk_i) begin if rising_edge(clk_i) then - cache(to_integer(cache_wr_addr)) <= cache_di3 & cache_di2 & cache_di1 & cache_di0; + cache(to_integer(cache_wr_addr)) <= cache_di7 & cache_di6 & cache_di5 & cache_di4 & + cache_di3 & cache_di2 & cache_di1 & cache_di0; cache_rd_data <= cache(to_integer(cache_rd_addr)); end if; end process cache_mem; - wbs_o.dat_o <= cache_rd_data; + wbs_o.dat_o <= cache_rd_data(63 downto 32) when wbs_i.adr_i(2) = '1' else + cache_rd_data(31 downto 0); mem_dat_o <= cache_rd_data; mem_adr <= adr_tag & std_logic_vector(adr_index) when cache_from_mem = '1' else @@ -279,13 +307,13 @@ begin end if; end process cc_mem; - assert addr_width+1 = wbs_i.adr_i'high report "Invalid address width, check parameters" severity error; - adr_index <= unsigned(wbs_cc_i.dat_i(offset_width+index_width+1 downto offset_width+2)) when user_cc = '1' else - unsigned(wbs_i.adr_i(offset_width+index_width+1 downto offset_width+2)) ; - adr_offset <= unsigned(wbs_cc_i.dat_i(offset_width+1 downto 2)) when user_cc = '1' else - unsigned(wbs_i.adr_i(offset_width+1 downto 2)); - adr_tag <= wbs_cc_i.dat_i(addr_width+1 downto offset_width+index_width+2) when user_cc = '1' else - wbs_i.adr_i(addr_width+1 downto offset_width+index_width+2); + assert addr_width = wbs_i.adr_i'high report "Invalid address width, check parameters" severity error; + adr_index <= unsigned(wbs_cc_i.dat_i(offset_width+index_width+2 downto offset_width+3)) when user_cc = '1' else + unsigned(wbs_i.adr_i(offset_width+index_width+2 downto offset_width+3)) ; + adr_offset <= unsigned(wbs_cc_i.dat_i(offset_width+2 downto 3)) when user_cc = '1' else + unsigned(wbs_i.adr_i(offset_width+2 downto 3)); + adr_tag <= wbs_cc_i.dat_i(addr_width+2 downto offset_width+index_width+3) when user_cc = '1' else + wbs_i.adr_i(addr_width+2 downto offset_width+index_width+3); tags_gen : for i in 0 to assoc-1 generate tags(i) <= cc_tag_rd_data((i+1)*tag_width-1 downto i*tag_width); diff --git a/src/wishbone.defines b/src/wishbone.defines index 0fbb96c..63f9aaa 100644 --- a/src/wishbone.defines +++ b/src/wishbone.defines @@ -37,20 +37,6 @@ master dummy priority_ram=1 end master dummy -master vga - type=ro - lock_o=0 - tga_o=1 - tgc_o=1 - tgd_o=0 - err_i=0 - rty_i=0 - priority_sdram_ctrl=3 - priority_sdram_ctrl_cc=0 - priority_rom=0 - priority_ram=0 -end master vga - # system controller master cpu type=rw diff --git a/tb/vga_tb.vhd b/tb/vga_tb.vhd new file mode 100644 index 0000000..56368dc --- /dev/null +++ b/tb/vga_tb.vhd @@ -0,0 +1,178 @@ +------------------------------------------------------------------------------- +-- Title : Testbench for design "vga" +-- Project : +------------------------------------------------------------------------------- +-- File : vga_tb.vhd +-- Author : +-- Company : +-- Created : 2013-03-07 +-- Last update: 2013-03-07 +-- Platform : +-- Standard : VHDL'87 +------------------------------------------------------------------------------- +-- Description: +------------------------------------------------------------------------------- +-- Copyright (c) 2013 +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2013-03-07 1.0 Matthias Created +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use work.sim_bmppack.all; +use ieee.numeric_std.all; + +------------------------------------------------------------------------------- + +entity vga_tb is + +end vga_tb; + +------------------------------------------------------------------------------- + +architecture testbench of vga_tb is + + component vga + port ( + clk_in : in std_logic; + clk_vga : in std_logic; + rst : in std_logic; + mem_rdrq : out std_logic; + mem_adr : out std_logic_vector(19 downto 0); + mem_ack : in std_logic; + mem_dat_i : in std_logic_vector(31 downto 0); + red : out std_logic_vector(3 downto 0); + green : out std_logic_vector(3 downto 0); + blue : out std_logic_vector(3 downto 0); + vsync : out std_logic; + hsync : out std_logic); + end component; + + -- component ports + signal clk_in, clk_vga : std_logic := '0'; + signal rst : std_logic := '1'; + signal mem_rdrq : std_logic; + signal mem_adr : std_logic_vector(19 downto 0); + signal mem_ack : std_logic; + signal mem_dat_i : std_logic_vector(31 downto 0); + signal red : std_logic_vector(3 downto 0); + signal green : std_logic_vector(3 downto 0); + signal blue : std_logic_vector(3 downto 0); + signal vsync : std_logic; + signal hsync : std_logic; + + signal sim_done : boolean := false; + +begin -- testbench + + -- component instantiation + DUT: vga + port map ( + clk_in => clk_in, + clk_vga => clk_vga, + rst => rst, + mem_rdrq => mem_rdrq, + mem_adr => mem_adr, + mem_ack => mem_ack, + mem_dat_i => mem_dat_i, + red => red, + green => green, + blue => blue, + vsync => vsync, + hsync => hsync); + + -- clock generation + clk_in <= not clk_in after 10 ns when not sim_done else + '0'; + clk_vga <= not clk_vga after 20 ns when not sim_done else + '0'; + + -- waveform generation + WaveGen_Proc: process + begin + -- insert signal assignments here + rst <= '1'; + wait until rising_edge(clk_in); + wait until rising_edge(clk_in); + rst <= '0'; + + wait; + end process WaveGen_Proc; + + memgen : process + variable row, column : integer; + variable r, g, b : boolean; + begin + mem_ack <= '0'; + wait until rst = '0'; + while true loop + wait until rising_edge(clk_in); + if mem_rdrq = '1' then + row := to_integer(unsigned(mem_adr))/20; + column := to_integer(unsigned(mem_adr)) mod 20; + wait until rising_edge(clk_in); + for i in 0 to 15 loop + -- draw colour bars + if column < 7 then + mem_dat_i <= x"0f000f00"; + elsif column < 13 then + mem_dat_i <= x"00f000f0"; + else + mem_dat_i <= x"000f000f"; + end if; + -- draw 1px white border + if row = 0 or row = 479 then + mem_dat_i <= x"0fff0fff"; + elsif column = 0 and i = 0 then + mem_dat_i(31 downto 16) <= x"0fff"; + elsif column = 19 and i = 15 then + mem_dat_i(15 downto 0) <= x"0fff"; + end if; + mem_dat_i(31 downto 16) <= std_logic_vector(to_unsigned(column*32+i*2, 16)); + mem_dat_i(15 downto 0) <= std_logic_vector(to_unsigned(column*32+i*2+1, 16)); + mem_ack <= '1'; + wait until rising_edge(clk_in); + end loop; + mem_ack <= '0'; + end if; + end loop; + end process memgen; + + VGARead: process + variable i: integer := 0; + variable pixeldata : std_logic_vector(23 downto 0); + begin + ReadFile("vga.bmp"); + + wait for 100 ns; -- wait for uut to stat + wait until rising_edge(vsync); -- wait for vga frame to start (depends + -- on latency of UUT) + wait for 1061.76 us; + + while true loop + for y in 479 downto 0 loop + for x in 0 to 639 loop + pixeldata := std_logic_vector(red) & "0000" & std_logic_vector(green) & "0000" & std_logic_vector(blue) & "0000"; + SetPixel(x, y, pixeldata); + wait for 40 ns; + end loop; -- x + wait for 6400 ns; + end loop; -- x + wait for 1440 us; + WriteFile("vga" & integer'image(i) & ".bmp"); + i := i + 1; + end loop; + end process; + +end testbench; + +------------------------------------------------------------------------------- + +configuration vga_tb_testbench_cfg of vga_tb is + for testbench + end for; +end vga_tb_testbench_cfg; + +------------------------------------------------------------------------------- diff --git a/vga_tb.wcfg b/vga_tb.wcfg new file mode 100644 index 0000000..05cd9a0 --- /dev/null +++ b/vga_tb.wcfg @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + clk_in + clk_in + + + clk_vga + clk_vga + + + rst + rst + + + mem_rdrq + mem_rdrq + + + mem_adr[19:0] + mem_adr[19:0] + + + mem_ack + mem_ack + + + mem_dat_i[31:0] + mem_dat_i[31:0] + HEXRADIX + + + red[3:0] + red[3:0] + + + green[3:0] + green[3:0] + + + blue[3:0] + blue[3:0] + + + vsync + vsync + + + hsync + hsync + + + vid_en + vid_en + + + in_pixeldata[31:0] + in_pixeldata[31:0] + HEXRADIX + + + out_pixeldata[15:0] + out_pixeldata[15:0] + UNSIGNEDDECRADIX + + + fifo_write + fifo_write + + + fifo_read + fifo_read + + + fifo_empty + fifo_empty + + + fifo_full16 + fifo_full16 + + + fifo_rst + fifo_rst + + + vsync_i + vsync_i + + + vsync_to_clk_in[1:0] + vsync_to_clk_in[1:0] + + + empty_dly + empty_dly + + + data_valid + data_valid + +