-- altera vhdl_input_version vhdl_2008 library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.math_real.all; entity LCDAvalonMaster is generic ( NWORDS_MAX : natural ); port ( clk : in std_logic; rst_n : in std_logic; waitreq : in std_logic; readdata : in std_logic_vector(31 downto 0); readdatavalid : in std_logic; address : out std_logic_vector(31 downto 0); burstcount : out std_logic_vector(4 downto 0); am_read : out std_logic; refresh : in std_logic; fifo_almost_empty : in std_logic; fifo_data : out std_logic_vector(31 downto 0); fifo_wr_req : out std_logic; baseaddress : in std_logic_vector(31 downto 0); nwords : in std_logic_vector(integer(ceil(log2(real(NWORDS_MAX)))) downto 0) ); end LCDAvalonMaster; architecture behavioral of LCDAvalonMaster is -- Generic constants constant BURST_COUNT : integer := 16; constant BURST_COUNT_SLV : std_logic_vector(burstcount'left downto 0) := std_logic_vector(to_unsigned(BURST_COUNT, burstcount'length)); -- Type definitions type State is (S_READY, S_BURSTREQ, S_BURSTRD, S_FIFOWAIT); subtype BurstCounter is integer range 0 to BURST_COUNT; subtype WordCounter is integer range 0 to NWORDS_MAX; -- Inferred registers signal rdaddr_reg, rdaddr_next : std_logic_vector(31 downto 0); signal state_reg, state_next : State; signal burstcnt_reg, burstcnt_next : BurstCounter; -- Counts # of words read during a single burst signal wordcnt_reg, wordcnt_next : WordCounter; -- Counts # of words read during a refresh cycle begin -- PROCESS state machine process(all) begin state_next <= state_reg; rdaddr_next <= rdaddr_reg; burstcnt_next <= burstcnt_reg; wordcnt_next <= wordcnt_reg; -- Avalon master default output signals burstcount <= BURST_COUNT_SLV; am_read <= '0'; case state_reg is when S_READY => -- ====================== AM STATE: READY ====================== if refresh = '1' then wordcnt_next <= integer(to_integer(unsigned(nwords))); state_next <= S_BURSTREQ; end if; when S_BURSTREQ => -- ================== AM STATE: BURST REQUEST ================== am_read <= '1'; if waitreq = '0' then -- Burst was accepted, state_next <= S_BURSTRD; -- Calculate the # of words we plan to read during this burst -- and update counters accordingly. if wordcnt_reg < BURST_COUNT then burstcnt_next <= wordcnt_reg; wordcnt_next <= 0; else burstcnt_next <= BURST_COUNT; wordcnt_next <= wordcnt_reg - BURST_COUNT; end if; end if; when S_BURSTRD => -- ==================== AM STATE: BURST READ =================== if readdatavalid = '1' then if burstcnt_reg = 1 then -- Got last word, burst read finished if wordcnt_reg = 0 then -- All nwords read state_next <= S_READY; else -- < nwords read state_next <= S_FIFOWAIT; end if; else burstcnt_next <= burstcnt_reg - 1; end if; end if; when S_FIFOWAIT => -- ==================== AM STATE: FIFO WAIT ==================== -- Await the assertion of fifo_almost_empty until reinitiating a -- burst read if fifo_almost_empty = '1' then state_next <= S_BURSTREQ; end if; end case; end process; -- FIFO data transfer routing fifo_wr_req <= '1' when state_reg = S_BURSTRD and readdatavalid = '1' else '0'; fifo_data <= readdata when state_reg = S_BURSTRD else (others => 'Z'); address <= std_logic_vector(unsigned(baseaddress) + resize((unsigned(nwords) - wordcnt_reg) * 4, address'length)) when state_reg = S_BURSTREQ else (others => 'Z'); -- Clocking process/register inferrence process(clk) begin if rising_edge(clk) then if rst_n = '0' then rdaddr_reg <= (others => '0'); state_reg <= S_READY; burstcnt_reg <= BURST_COUNT; wordcnt_reg <= 0; else rdaddr_reg <= rdaddr_next; state_reg <= state_next; burstcnt_reg <= burstcnt_next; wordcnt_reg <= wordcnt_next; end if; end if; end process; end behavioral;