I wrote the following and seems to be working so far.
-- This module:
-- * generates the beginbursttransfer signal, which is blatantly missing in qsys when exporting avalon-mm ports.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity beginburst_gen is
port (
rst : in std_logic;
clk : in std_logic;
burstcount : in std_logic_vector;
readreq : in std_logic;
writereq : in std_logic;
rdatavalid : in std_logic;
waitreq : in std_logic;
beginburst : out std_logic
);
end entity;
architecture rtl of beginburst_gen is
type state_t is (st_idle, st_wburst, st_rburstwait, st_rburst);
signal state : state_t;
signal bcnt : unsigned(burstcount'length-1 downto 0);
constant one_burstcount : std_logic_vector(burstcount'length-1 downto 0) := (0 => '1', others => '0');
begin
syn_proc : process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
state <= st_idle;
else
case state is
when st_idle =>
if readreq = '1' then
bcnt <= unsigned(burstcount);
if waitreq = '0' then
state <= st_rburst;
else
state <= st_rburstwait;
end if;
elsif writereq = '1' then
if waitreq = '1' then
bcnt <= unsigned(burstcount);
state <= st_wburst;
else
bcnt <= unsigned(burstcount)-1;
if burstcount /= one_burstcount then
state <= st_wburst;
end if;
end if;
end if;
when st_wburst =>
if writereq = '1' and waitreq = '0' then
bcnt <= bcnt-1;
if bcnt = 1 then
state <= st_idle;
end if;
end if;
when st_rburstwait =>
if waitreq = '0' then
state <= st_rburst;
end if;
when st_rburst =>
if rdatavalid = '1' then
bcnt <= bcnt-1;
if bcnt = 1 then
state <= st_idle;
end if;
end if;
when others =>
state <= st_idle;
end case;
end if;
end if;
end process;
comb_proc : process(state, readreq, writereq)
begin
beginburst <= '0';
if (state = st_idle) and (readreq or writereq) = '1' then
beginburst <= '1';
end if;
end process;
end architecture;