library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity pcie_tx is port ( clk : in std_logic; frame : out std_logic_vector(63 downto 0) := (others => '0'); sof : out std_logic := '0'; eof : out std_logic := '0'; half : out std_logic := '0'; valid : out std_logic := '0'; ready : in std_logic; read : in std_logic; write : in std_logic; complete : in std_logic; data : in std_logic_vector(63 downto 0); address : in std_logic_vector(63 downto 3); length : in std_logic_vector(8 downto 0); tag : in std_logic_vector(4 downto 0); local : in std_logic_vector(15 downto 0); remote : in std_logic_vector(23 downto 0); accept : out std_logic; done : out std_logic ); end pcie_tx; architecture arch of pcie_tx is type state_t is (state_idle, state_read_32, state_read_64, state_write_32, state_write_64, state_write_end_32, state_write_head_64, state_complete, state_complete_head, state_done); signal state : state_t := state_idle; begin accept <= ready when state = state_write_32 or state = state_write_64 else '0'; done <= ready when state = state_done else '0'; process (clk) variable extra : std_logic_vector(31 downto 0) := (others => '0'); variable remain : unsigned(8 downto 0) := (others => '0'); begin if rising_edge(clk) and (ready = '1' or state = state_idle) then frame <= (others => '0'); sof <= '0'; eof <= '0'; half <= '0'; valid <= '0'; -- read if state = state_idle and read = '1' then if unsigned(length) = 0 then state <= state_done; else if address(63 downto 32) = x"00000000" then state <= state_read_32; frame <= "0" & "00" & "00000" & x"00" & "000000" & length & "0" & local & "000" & tag & x"FF"; else state <= state_read_64; frame <= "0" & "01" & "00000" & x"00" & "000000" & length & "0" & local & "000" & tag & x"FF"; end if; sof <= '1'; valid <= '1'; end if; elsif state = state_read_32 then state <= state_done; frame <= address(31 downto 3) & "000" & x"00000000"; eof <= '1'; half <= '1'; valid <= '1'; elsif state = state_read_64 then state <= state_done; frame <= address & "000"; eof <= '1'; valid <= '1'; -- write elsif state = state_idle and write = '1' then if unsigned(length) = 0 then state <= state_done; else if address(63 downto 32) = x"00000000" then state <= state_write_32; frame <= "0" & "10" & "00000" & x"00" & "000000" & length & "0" & local & x"00" & x"FF"; extra := address(31 downto 3) & "000"; else state <= state_write_head_64; frame <= "0" & "11" & "00000" & x"00" & "000000" & length & "0" & local & x"00" & x"FF"; end if; sof <= '1'; valid <= '1'; remain := unsigned(length); end if; elsif state = state_write_32 then frame <= extra & data(63 downto 32); extra := data(31 downto 0); valid <= '1'; remain := remain - 1; if remain = 0 then state <= state_write_end_32; end if; elsif state = state_write_end_32 then state <= state_done; frame <= extra & x"00000000"; eof <= '1'; half <= '1'; valid <= '1'; elsif state = state_write_head_64 then state <= state_write_64; frame <= address & "000"; valid <= '1'; elsif state = state_write_64 then frame <= data; valid <= '1'; remain := remain - 1; if remain = 0 then state <= state_done; eof <= '1'; end if; -- complete elsif state = state_idle and complete = '1' then state <= state_complete_head; frame <= "0" & "10" & "01010" & x"00" & x"0002" & local & x"0008"; sof <= '1'; valid <= '1'; elsif state = state_complete_head then state <= state_complete; frame <= remote & "0" & address(6 downto 3) & "000" & data(63 downto 32); valid <= '1'; elsif state = state_complete then state <= state_done; frame <= data(31 downto 0) & x"00000000"; eof <= '1'; half <= '1'; valid <= '1'; -- done elsif state = state_done then state <= state_idle; end if; end if; end process; end arch;