2022-04-07 18:46:57 +02:00

136 lines
5.1 KiB
VHDL

-- 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;