Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
13 years ago

Frame Buffer VHDL Template

Hello every body,

I'm trying to code a frame buffer using VHDL to perform some operation on an entire frame then store the result into DDR2 memory.

I used the Avalon MM Master VHDL Template but I didn't manage to make it run as desired

Can anyone provide me with a Frame Buffer VHDL Template ??

Thank you for your help

3 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi and thank you for responding.

    I used the Avalon MM Master VHDL template and a custom core that enable the master when there is a valid data:

    a simple Avalon ST Interface which enables the master using this code :

    
    PROCESS (CLOCK,RESET)
    IF CLOCK'EVENT AND CLOCK='1' THEN
    IF AST_DIN_VALID = '1' THEN 
         IF AST_DIN_SOP = '0' AND AST_DIN_EOP = '0' THEN
                 ENABLE = '1';
         ELSE
                 ENABLE = '0';
         END IF;
    END IF;
    END IF;
    END PROCESS;
    PROCESS (CLOCK,ENABLE) 
        BEGIN
        IF ENABLE = '1' THEN
            --START the master:
            avs_csr_write <= '1';
            avs_csr_address <= "00";
            avs_csr_writedata <= "00000000000000000000000000000001";
            DATA_To_Write <= AST_DIN_DATA;
        ELSE
            avs_csr_write <= '0';
            avs_csr_address <= "00";
            avs_csr_writedata <= (others => '0');
            DATA_To_Write <= (others => '0');
        END IF;
    END PROCESS;
    

    and the master template :

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_unsigned.all;
    entity simple_example is
    port (
    	-- clock interface
    	csi_clock_clk : in std_logic;
    	csi_clock_reset : in std_logic;
    	
    	-- read master
    	avm_read_master_read : out std_logic;
    	avm_read_master_address : out std_logic_vector (31 downto 0);
    	avm_read_master_readdata : in std_logic_vector (31 downto 0);
    	avm_read_master_waitrequest : in std_logic;
    	
    	-- write master
    	avm_write_master_write : out std_logic;
    	avm_write_master_address : out std_logic_vector (31 downto 0);
    	avm_write_master_writedata : out std_logic_vector (31 downto 0);
    	avm_write_master_waitrequest : in std_logic;
    	
    	-- control & status registers (CSR) slave
    	avs_csr_address : in std_logic_vector (1 downto 0);
    	avs_csr_readdata : out std_logic_vector (31 downto 0);
    	avs_csr_write : in std_logic;
    	avs_csr_writedata : in std_logic_vector (31 downto 0)
    );
    end simple_example;
    architecture a of simple_example is
    -- the FIFO component was generated using the Quartus II MegaWizard Plug-In Manager
    component example_master_fifo
    port (
    	aclr : in std_logic;
    	clock : in std_logic;
    	data : in std_logic_vector (31 downto 0);
    	rdreq : in std_logic;
    	wrreq : in std_logic;
    	empty : out std_logic;
    	full : out std_logic;
    	q : out std_logic_vector (31 downto 0);
    	usedw : out std_logic_vector (5 downto 0)
    );
    end component;
    -- fifo instantiation signals
    signal fifo_read, fifo_write : std_logic;
    signal fifo_empty, fifo_full : std_logic;
    -- state machine states
    type read_states_T is (idle, running, stopping);
    type write_states_T is (idle, running);
    signal read_state : read_states_T;
    signal write_state : write_states_T;
    -- extra read master signals
    signal read_address : std_logic_vector (31 downto 0);         -- the current read address
    signal words_read : std_logic_vector (8 downto 0);            -- tracks the words read
    -- extra write master signals
    signal write_address : std_logic_vector (31 downto 0);        -- the current write address
    -- CSR registers
    signal csr_status : std_logic_vector (31 downto 0);           -- the status word that will be read from the status register
    signal csr_rd_addr : std_logic_vector (31 downto 0);          -- the read start address register
    signal csr_wr_addr : std_logic_vector (31 downto 0);          -- the write start address register
    signal csr_go_flag : std_logic;                               -- used to start the DMA (when logic 1)
    signal active_flag : std_logic;                               -- logic 1 if either state machines are active
    begin
    -------------------------------------------------------------------------------
    -- FIFO INSTATIATION
    -------------------------------------------------------------------------------
    fifo_inst: example_master_fifo
    port map (
    	aclr => csi_clock_reset,
    	clock => csi_clock_clk,
    	data => avm_read_master_readdata,
    	rdreq => fifo_read,
    	wrreq => fifo_write,
    	empty => fifo_empty,
    	full => fifo_full,
    	q => avm_write_master_writedata,
    	usedw => open
    );
    read_FSM: process (csi_clock_clk, csi_clock_reset)
    begin
    	if csi_clock_reset = '1' then
    		read_state <= idle;
    		read_address <= (others => '0');
    		words_read <= (others => '0');
    	elsif rising_edge (csi_clock_clk) then
    		case read_state is
    			
    			-- IDLE
    			-- When idle just sit and wait for the go flag.
    			-- Only start if the write state machine is idle as it may be
    			-- finishing a previous data transfer.
    			-- Start the machine by moving to the running state and initialising address and counters.
    			when idle =>
    				if write_state = idle and csr_go_flag = '1' then
    					read_state <= running;
    					read_address <= csr_rd_addr;
    					words_read <= (others => '0');
    				end if;
    				
    			-- RUNNING
    			-- Count reads, inc address and check for completion
    			-- The read signal is held inactive by comb logic if fifo full so do nothing if fifo full
    			-- also do nothing if waitrequest is active as this means signals need to be held
    			when running =>
    				-- if waitrequest is active or fifo full do nothing, otherwise...
    				if avm_read_master_waitrequest /= '1' and fifo_full /= '1' then
    					read_address <= read_address + 4;  -- add 4 per word as masters use byte addressing					
    					words_read <= words_read + 1;
    					if words_read = 255 then  -- 256 in total (255 previous plus this one)
    						read_state <= stopping;
    					end if;	
    				end if;
    			when stopping =>
    				read_state <= idle;
    		
    		end case;
    	end if;
    end process;
    	-- read when in in running state and fifo not full
    	avm_read_master_read <= '1' when read_state = running and fifo_full = '0' else '0';
    	
    	-- simply write data into the fifo as it comes in (read asserted and waitrequest not active)
    	fifo_write <= '1' when read_state = running and avm_read_master_waitrequest = '0' and fifo_full = '0' else '0';
    	
    	-- this maps the internal address directly to the external port
    	avm_read_master_address <= read_address;
    write_FSM: process (csi_clock_clk, csi_clock_reset)
    begin
    	if csi_clock_reset = '1' then
    		write_state <= idle;
    	elsif rising_edge (csi_clock_clk) then
    		case write_state is
    			
    			-- IDLE
    			-- Just sit and wait for the go flag
    			-- When the go flag is set start by moving to the writing state and 
    			-- set the address.
    			when idle =>
    				if csr_go_flag = '1' then
    					write_state <= running;
    					write_address <= csr_wr_addr;
    				end if;
    			when running =>
    				if avm_write_master_waitrequest /= '1' and fifo_empty /= '1' then
    					write_address <= write_address + 4;  -- Masters use byte addressing so inc by 4 for next word
    				end if;
    				if fifo_empty = '1' and read_state = idle then
    					write_state <= idle;
    				end if;			
    		end case;
    	end if;
    end process;
    	-- the write signal is active if in running state and fifo not empty
    	avm_write_master_write <= '1' when write_state = running and fifo_empty = '0' else '0';
    	-- this maps the internal address directly to the external port	
    	avm_write_master_address <= write_address;
    	
    	-- the fifo_read signal takes data from the fifo and updates it's output with the next word
    	-- should be 1 when writing and not in waitrequest
    	fifo_read <= '1' when write_state = running and fifo_empty = '0' and avm_write_master_waitrequest = '0' else '0';
    -- control and status registers
    --
    -- address map
    --  00 control (write only)
    --  01 status (read only)
    --  10 read start address
    --  11 write start address
    --
    -- control register 
    --  bit 0 : start control (pulse 1 to start)
    --
    -- status register
    --  bit 0 : active flag (1 when DMA active)
    -- write control of read and write address registers
    csr: process (csi_clock_clk, csi_clock_reset)
    begin
    	if csi_clock_reset = '1' then
    		csr_rd_addr <= (others => '0');
    		csr_wr_addr <= (others => '0');
    	elsif rising_edge (csi_clock_clk) then
    		if avs_csr_write = '1' then
    			case avs_csr_address is
    				when "10" =>
    					csr_rd_addr <= avs_csr_writedata (31 downto 2) & "00";
    					-- ignore 2 lsbs as this component only supports word aligned data
    				when "11" =>
    					csr_wr_addr <= avs_csr_writedata (31 downto 2) & "00";
    					-- ignore 2 lsbs as this component only supports word aligned data
    				when others =>
    			end case;
    		end if;
    	end if;
    end process;		
    csr_go_flag <= avs_csr_writedata(0) when avs_csr_write = '1' and avs_csr_address = "00" else '0';
    -- readdata mux
    active_flag <= '0' when read_state = idle and write_state = idle else '1';
    csr_status <= "0000000000000000000000000000000" & active_flag;
    read_mux: process (avs_csr_address, csr_status, csr_rd_addr, csr_wr_addr)
    begin
    	case avs_csr_address is
    		when "10" =>
    			avs_csr_readdata <= csr_rd_addr;
    		when "11" =>
    			avs_csr_readdata <= csr_wr_addr;
    		when others =>
    			avs_csr_readdata <= csr_status;
    	end case;
    end process;
    -------------------------------------------------------------------------------
    end a;

    I don't knwo what's wrong ! I actually can't tell what data is written in the memory !

    I don't know how to map the DATA_To_Write signal because I can't figure out what data is written to the memory !

    Thank you.