summaryrefslogtreecommitdiff
path: root/netfpga10g/hdl/pcie_tx.vhd
diff options
context:
space:
mode:
Diffstat (limited to 'netfpga10g/hdl/pcie_tx.vhd')
-rw-r--r--netfpga10g/hdl/pcie_tx.vhd178
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;
+