diff options
Diffstat (limited to 'netfpga10g/hdl/pcie_tx.vhd')
-rw-r--r-- | netfpga10g/hdl/pcie_tx.vhd | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/netfpga10g/hdl/pcie_tx.vhd b/netfpga10g/hdl/pcie_tx.vhd new file mode 100644 index 0000000..dc892b4 --- /dev/null +++ b/netfpga10g/hdl/pcie_tx.vhd @@ -0,0 +1,178 @@ + +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; + |