diff options
Diffstat (limited to 'netfpga10g/hdl/pcie_rx.vhd')
-rw-r--r-- | netfpga10g/hdl/pcie_rx.vhd | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/netfpga10g/hdl/pcie_rx.vhd b/netfpga10g/hdl/pcie_rx.vhd new file mode 100644 index 0000000..c4ee177 --- /dev/null +++ b/netfpga10g/hdl/pcie_rx.vhd @@ -0,0 +1,98 @@ + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity pcie_rx is port ( + clk : in std_logic; + + frame : in std_logic_vector(63 downto 0); + sof : in std_logic; + eof : in std_logic; + valid : in std_logic; + + read : out std_logic := '0'; + write : out std_logic := '0'; + complete : out std_logic := '0'; + data : out std_logic_vector(63 downto 0) := (others => '0'); + address : out std_logic_vector(63 downto 3) := (others => '0'); + tag : out std_logic_vector(4 downto 0) := (others => '0'); + remote : out std_logic_vector(23 downto 0) := (others => '0'); + + bar0 : in std_logic +); +end pcie_rx; + +architecture arch of pcie_rx is + type state_t is (state_idle, state_read, state_write, state_write_head, + state_complete, state_complete_head); + + signal fmt : std_logic_vector(1 downto 0); + signal typ : std_logic_vector(4 downto 0); + signal status : std_logic_vector(2 downto 0); +begin + fmt <= frame(62 downto 61); + typ <= frame(60 downto 56); + status <= frame(15 downto 13); + + process (clk) + variable state : state_t := state_idle; + variable extra : std_logic_vector(31 downto 0) := (others => '0'); + begin + if rising_edge(clk) then + read <= '0'; + write <= '0'; + complete <= '0'; + + if valid = '0' then + -- nothing + + elsif state = state_idle and sof = '1' then + data <= (others => '0'); + address <= (others => '0'); + tag <= (others => '0'); + + if fmt = "00" and typ = "00000" and bar0 = '1' then + state := state_read; + remote <= frame(31 downto 8); + + elsif fmt = "10" and typ = "00000" and bar0 = '1' then + state := state_write_head; + + elsif fmt = "10" and typ = "01010" and status = "000" then + state := state_complete_head; + end if; + + elsif state = state_read then + state := state_idle; + read <= '1'; + address <= x"00000000" & frame(63 downto 35); + + elsif state = state_write_head then + state := state_write; + address <= x"00000000" & frame(63 downto 35); + extra := frame(31 downto 0); + + elsif state = state_write then + state := state_idle; + write <= '1'; + data <= extra & frame(63 downto 32); + + elsif state = state_complete_head then + state := state_complete; + tag <= frame(44 downto 40); + extra := frame(31 downto 0); + + elsif state = state_complete then + complete <= '1'; + data <= extra & frame(63 downto 32); + extra := frame(31 downto 0); + end if; + + if valid = '1' and eof = '1' then + state := state_idle; + end if; + end if; + end process; +end arch; + |