OpenCores
URL https://opencores.org/ocsvn/vga_lcd/vga_lcd/trunk

Subversion Repositories vga_lcd

[/] [vga_lcd/] [tags/] [rel_1/] [rtl/] [vhdl/] [wb_master.vhd] - Rev 62

Compare with Previous | Blame | View Log

--
-- File wb_master.vhd, WISHBONE MASTER interface (video-memory/clut memory)
-- Project: VGA
-- Author : Richard Herveille
-- rev.: 1.0 May 1st, 2001
-- rev.: 1.1 June  3rd, 2001. Changed address related sections.
-- rev.: 1.2 June 23nd, 2001. Removed unused "sel_vba", "vmem_offs" and "bl" signals.
-- rev.: 1.3 July  6th, 2001. Major bug fixes; core did not respond correctly to delayed ACK_I generation.
-- rev.: 1.4 July 15th, 2001. Added CLUT bank switching.
--                            Removed multiplier, replaced it by counters
--                            Fixed timing bug.
-- rev.: 1.5 July 17th, 2001. Fixed a weird condition where to core got stuck during a video memory access, caused by
--                            the image_done timers.
-- rev.: 1.6 July 31th, 2001. Fixed a bug where the video/clut banks would switch with a 1 frame delay.
--                            Fixed a bug where the data in the RGB-buffer could be overwritten.
--
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
 
library count;
use count.count.all;
 
entity wb_master is
	port(
		-- WISHBONE signals
		CLK_I : in std_logic;                        -- master clock input
		RST_I : in std_logic;                        -- synchronous active high reset
		nRESET : in std_logic;                       -- asynchronous active low reset
		CYC_O : out std_logic;                       -- cycle output
		STB_O : out std_logic;                       -- strobe output
		CAB_O : out std_logic;                       -- Consecutive Address Burst output
		WE_O  : out std_logic;                       -- write enable output
		ADR_O : out unsigned(31 downto 2);           -- address output
		SEL_O : out std_logic_vector(3 downto 0);    -- Byte Select outputs (only 32bit accesses are supported)
		ACK_I : in std_logic;                        -- WISHBONE cycle acknowledge signal
		ERR_I : in std_logic;                        -- oops, bus-error
		DAT_I : in std_logic_vector(31 downto 0);    -- WISHBONE data in
 
		SINT : out std_logic;                        -- Non recoverable error, interrupt host
 
		-- control register settings
		ctrl_Ven : in std_logic;                     -- video enable bit
		ctrl_cd : in std_logic_vector(1 downto 0);   -- color depth
		ctrl_pc : in std_logic;                      -- 8bpp pseudo color/bw
		ctrl_vbl : in std_logic_vector(1 downto 0);  -- burst length
		ctrl_vbsw : in std_logic;                    -- enable video bank switching
		ctrl_cbsw : in std_logic;                    -- enable clut bank switching
 
		-- video memory addresses
		VBAa,                                        -- Video Memory Base Address-A
		VBAb : in unsigned(31 downto 2);             -- Video Memory Base Address-B
		CBA : in unsigned(31 downto 11);             -- CLUT Base Address Register
 
		Thgate : in unsigned(15 downto 0);           -- horizontal visible area (in pixels)
		Tvgate : in unsigned(15 downto 0);           -- vertical visible area (in horizontal lines)
 
		stat_AVMP : out std_logic;                   -- active video memory page
		stat_ACMP : out std_logic;                   -- active color lookup table
		bs_req : out std_logic;                      -- bank-switch request: memory page switched (when enabled). bs_req is always generated
 
		-- to/from line fifo
		line_fifo_wreq : out std_logic;
		line_fifo_d : out std_logic_vector(23 downto 0);
		line_fifo_full : in std_logic
	);
end entity wb_master;
 
architecture structural of wb_master is
	--
	-- component declarations
	--
	-- FIFO
	component FIFO is
	generic(
		DEPTH : natural := 128;
		WIDTH : natural := 32
	);
	port(
		clk : in std_logic;                           -- clock input
		aclr : in std_logic := '1';                   -- active low asynchronous clear
		sclr : in std_logic := '0';                   -- active high synchronous clear
 
		D : in std_logic_vector(WIDTH -1 downto 0);   -- Data input
		wreq : in std_logic;                          -- write request
 
		Q : out std_logic_vector(WIDTH -1 downto 0);  -- Data output
		rreq : in std_logic;                          -- read request
 
		empty,                                        -- FIFO is empty
		hfull,                                        -- FIFO is half full
		full : out std_logic                          -- FIFO is full
	);
	end component FIFO;
 
	-- color processor (convert data from pixel buffer to RGB)
	component colproc is
	port(
		clk : in std_logic;                            -- master clock
		ctrl_Ven : in std_logic;                       -- Video Enable
 
		pixel_buffer_Di,                               -- Pixel Buffer data input
		WB_Di : in std_logic_vector(31 downto 0);      -- WISHBONE data input
 
		ColorDepth : in std_logic_vector(1 downto 0);  -- color depth (8bpp, 16bpp, 24bpp)
		PseudoColor : in std_logic;                    -- pseudo color enabled (only for 8bpp color depth)
 
		pixel_buffer_empty : in std_logic;
		pixel_buffer_rreq : buffer std_logic;          -- pixel buffer read request
 
		RGB_fifo_full : in std_logic;
		RGB_fifo_wreq : out std_logic;
		R,G,B : out std_logic_vector(7 downto 0);      -- pixel color (to RGB fifo)
 
		clut_req : out std_logic;                      -- CLUT access request
		clut_offs: out unsigned(7 downto 0);           -- offset into color lookup table
		clut_ack : in std_logic                        -- CLUT data acknowledge
	);
	end component colproc;
 
	signal nVen : std_logic;                                                 -- NOT ctrl_Ven (video enable)
	signal vmem_acc, clut_acc : std_logic;                                   -- video memory access // clut access
	signal clut_req, clut_ack : std_logic;                                   -- clut access request // clut access acknowledge
	signal clut_offs : unsigned(7 downto 0);                                 -- clut memory offset
	signal nvmem_req, vmem_ack : std_logic;                                  -- NOT video memory access request // video memory access acknowledge
	signal ImDoneStrb, dImDoneStrb : std_logic;                              -- image done (strobe signal)
	signal pixelbuf_rreq, pixelbuf_empty, pixelbuf_empty_flush, pixelbuf_flush, pixelbuf_hfull : std_logic;
	signal pixelbuf_q : std_logic_vector(31 downto 0);
	signal RGBbuf_rreq, RGBbuf_wreq, RGBbuf_empty, RGBbuf_full, fill_RGBfifo, RGB_fifo_full : std_logic;
	signal RGBbuf_d : std_logic_vector(23 downto 0);
begin
 
 
	--
	-- WISHBONE block
	--
	WB_block: block
		signal burst_cnt : unsigned(2 downto 0);               -- video memory burst access counter
		signal ImDone, dImDone, burst_done : std_logic;        -- Done reading image from video mem // delayed ImDone // completed burst access to video mem
		signal sel_VBA, sel_CBA : std_logic;                   -- select video memory base address // select clut base address
		signal vmemA, clutA : unsigned(31 downto 2);           -- video memory address // clut address
		signal hgate_cnt, vgate_cnt : unsigned(15 downto 0);   -- horizontal / vertical pixel counters
		signal hdone, vdone : std_logic;                       -- horizontal count done / vertical count done
	begin
		--
		-- wishbone access controller, video memory access request has highest priority (try to keep fifo full)
		--
		access_ctrl: process(CLK_I)
		begin
			if(CLK_I'event and CLK_I = '1') then
				if (ctrl_Ven = '0') then
					vmem_acc <= '0';
					clut_acc <= '0';
				else
					clut_acc <= clut_req and ( (nvmem_req and not vmem_acc) or clut_acc);
					vmem_acc <= (not nvmem_req or (vmem_acc and not (burst_done and vmem_ack) )) and not clut_acc;
				end if;
			end if;
		end process access_ctrl;
 
		vmem_ack <= ACK_I and vmem_acc;
		clut_ack <= ACK_I and clut_acc;
 
		SINT <= (vmem_acc or clut_acc) and ERR_I; -- Non recoverable error, interrupt host system
 
		-- select active memory page
		gen_sel_VBA: process(CLK_I)
		begin
			if(CLK_I'event and CLK_I = '1') then
				if (ctrl_Ven = '0') then
					sel_VBA <= '0';
				elsif (ctrl_vbsw = '1') then
					sel_VBA <= sel_VBA xor ImDoneStrb; -- select next video memory bank when finished reading current bank (and bank switch enabled)
				end if;
			end if;
		end process gen_sel_VBA;
		stat_AVMP <= sel_VBA; -- assign output
 
		gen_sel_CBA: process(CLK_I)
		begin
			if(CLK_I'event and CLK_I = '1') then
				if (ctrl_Ven = '0') then
					sel_CBA <= '0';
				elsif (ctrl_cbsw = '1') then
					sel_CBA <= sel_CBA xor ImDoneStrb; -- select next clut when finished reading current video bank
				end if;
			end if;
		end process gen_sel_CBA;
		stat_ACMP <= sel_CBA; -- assign output
 
		-- assign bank_switch_request (status register) output
		bs_req <= ImDoneStrb and ctrl_Ven; -- bank switch request
 
		-- generate burst counter
		gen_burst_cnt: process(CLK_I, ctrl_vbl, burst_cnt)
			variable bl  : unsigned(2 downto 0);
			variable val : unsigned(3 downto 0);
		begin
			case ctrl_vbl is
				when "00"   => bl := "000"; -- burst length 1
				when "01"   => bl := "001"; -- burst length 2
				when "10"   => bl := "011"; -- burst length 4
				when others => bl := "111"; -- burst length 8
			end case;
 
			val := ('0' & burst_cnt) -1;
 
			if (CLK_I'event and CLK_I = '1') then
				if ( ((burst_done = '1') and (vmem_ack = '1')) or (vmem_acc = '0')) then
					burst_cnt <= bl;
				elsif (vmem_ack = '1') then
					burst_cnt <= val(2 downto 0);
				end if;
			end if;
 
			burst_done <= val(3);
		end process gen_burst_cnt;
 
		--
		-- generate image counters
		--
 
		-- hgate counter
		hgate_count: process(CLK_I, hgate_cnt)
			variable val : unsigned(16 downto 0);
		begin
			val := ('0' & hgate_cnt) -1;
 
			if (CLK_I'event and CLK_I = '1') then
				if (ctrl_Ven = '0') then
					hgate_cnt <= Thgate;
				elsif (RGBbuf_wreq = '1') then
					if (hdone = '1') then
						hgate_cnt <= Thgate;
					else
						hgate_cnt <= val(15 downto 0);
					end if;
				end if;
			end if;
 
			hdone <= val(16);
		end process hgate_count;
 
		vgate_count: process(CLK_I, vgate_cnt)
			variable val : unsigned(16 downto 0);
		begin
			val := ('0' & vgate_cnt) -1;
 
			if (CLK_I'event and CLK_I = '1') then
				if (ctrl_Ven = '0') then
					vgate_cnt <= Tvgate;
				elsif ((hdone = '1') and (RGBbuf_wreq = '1')) then
					if (ImDone = '1') then
						vgate_cnt <= Tvgate;
					else
						vgate_cnt <= val(15 downto 0);
					end if;
				end if;
			end if;
 
			vdone <= val(16);
		end process vgate_count;
 
		ImDone <= hdone and vdone;
		ImDoneStrb <= ImDone and not dImDone;
 
		gen_pix_done: process(CLK_I)
		begin
			if (CLK_I'event and CLK_I = '1') then
				if (ctrl_Ven = '0') then
					dImDone <= '0';
				else
					dImDone <= ImDone;
				end if;
 
				dImDoneStrb <= ImDoneStrb;
			end if;
		end process gen_pix_done;
 
		--
		-- generate addresses
		--
		addr: process(CLK_I, sel_VBA, VBAa, VBAb)
		begin
			-- select video memory base address
			if (CLK_I'event and CLK_I = '1') then
				-- calculate video memory address
				if ((dImDoneStrb = '1') or (ctrl_Ven = '0')) then
					if (sel_VBA = '0') then
						vmemA <= VBAa;
					else
						vmemA <= VBAb;
					end if;
				elsif (vmem_ack = '1') then
					vmemA <= vmemA + 1;
				end if;
			end if;
		end process addr;
 
		-- calculate CLUT address
		clutA <= (CBA & sel_CBA & clut_offs);
 
		-- generate wishbone signals
		gen_wb_sigs: process(CLK_I, nRESET, vmemA, clutA, vmem_acc)
		begin
 
			-- assign wishbone address
			if (vmem_acc = '1') then
				ADR_O <= vmemA;
			else
				ADR_O <= clutA;
			end if;
 
			if (nRESET = '0') then
				CYC_O <= '0';
				STB_O <= '0';
				SEL_O <= "1111";
				CAB_O <= '0';
				WE_O  <= '0';
			elsif (CLK_I'event and CLK_I = '1') then
				if (RST_I = '1') then
					CYC_O <= '0';
					STB_O <= '0';
					SEL_O <= "1111";
					CAB_O <= '0';
					WE_O  <= '0';
				else
					CYC_O <= (clut_acc and clut_req and not ACK_I) or (vmem_acc and not (burst_done and vmem_ack and nvmem_req) );
					STB_O <= (clut_acc and clut_req and not ACK_I) or (vmem_acc and not (burst_done and vmem_ack and nvmem_req) ); -- same as CYC_O; only 1 register+logic needed
					SEL_O <= "1111"; -- only 32bit accesses are supported
					CAB_O <= vmem_acc and not (burst_done and vmem_ack and nvmem_req);
					WE_O  <= '0';    -- read only
				end if;
			end if;
		end process gen_wb_sigs;
	end block WB_block;
 
 
	nVen <= not ctrl_Ven;
	pixelbuf_flush <= nVen or ImDoneStrb;
 
	-- pixel buffer (temporary store data read from video memory)
	pixel_buf: FIFO generic map (DEPTH => 16, WIDTH => 32)
		port map(clk => CLK_I, sclr => pixelbuf_flush, D => DAT_I, wreq => vmem_ack, Q => pixelbuf_q, rreq => pixelbuf_rreq, 
						empty => pixelbuf_empty, hfull => pixelbuf_hfull);
 
	nvmem_req <= not (not pixelbuf_hfull and not ImDoneStrb);
 
	-- hookup color processor
	gen_fill_RGBfifo: process(CLK_I)
	begin
		if (CLK_I'event and CLK_I = '1') then
			if (ctrl_Ven = '0') then
				fill_RGBfifo <= '0';
			else
				fill_RGBfifo <= (RGBbuf_empty or fill_RGBfifo) and not RGBbuf_full;
			end if;
		end if;
	end process gen_fill_RGBfifo;
	RGB_fifo_full <= not (fill_RGBfifo and not RGBbuf_full); -- not fill_RGBfifo or RGBbuf_full
 
	pixelbuf_empty_flush <= pixelbuf_empty or pixelbuf_flush;
	color_proc: colproc port map (clk => CLK_I, ctrl_Ven => ctrl_Ven, pixel_buffer_di => pixelbuf_q, WB_Di => DAT_I, ColorDepth => ctrl_CD,
						PseudoColor => ctrl_PC, pixel_buffer_empty => pixelbuf_empty_flush, pixel_buffer_rreq => pixelbuf_rreq, 
						RGB_fifo_full => RGB_fifo_full, RGB_fifo_wreq => RGBbuf_wreq, R => RGBbuf_d(23 downto 16), G => RGBbuf_d(15 downto 8),
						B => RGBbuf_d(7 downto 0), clut_req => clut_req, clut_offs => clut_offs, clut_ack => clut_ack);
 
	-- hookup RGB buffer (temporary station between WISHBONE-clock-domain and pixel-clock-domain)
	RGB_buf: FIFO generic map (DEPTH => 8, WIDTH => 24)
		port map (clk => CLK_I, sclr => nVen, D => RGBbuf_d, wreq => RGBbuf_wreq, Q => line_fifo_d, rreq => RGBbuf_rreq, 
						empty => RGBbuf_empty, hfull => RGBbuf_full);
 
	-- hookup line fifo
	gen_lfifo_wreq: process(CLK_I)
	begin
		if (CLK_I'event and CLK_I = '1') then
			if (ctrl_Ven = '0') then
				RGBbuf_rreq <= '0';
			else
				RGBbuf_rreq <= not line_fifo_full and not RGBbuf_empty and not RGBbuf_rreq;
			end if;
		end if;
	end process gen_lfifo_wreq;
	line_fifo_wreq <= RGBbuf_rreq;
 
end architecture structural;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.