summaryrefslogtreecommitdiff
path: root/netfpga10g/hdl
diff options
context:
space:
mode:
authorAlexander D'hoore <dhoore.alexander@gmail.com>2017-12-15 15:37:58 +0100
committerDimitri Staessens <dimitri.staessens@ugent.be>2017-12-15 15:37:58 +0100
commitd1a1059d748955ed93a8e87c437c7eae1258293c (patch)
tree9137bc921db74bb3797b8b0f05e7a69022412522 /netfpga10g/hdl
parent8f258e469b1acea8e3ccf1485779e1db0bf5f772 (diff)
downloadraptor-d1a1059d748955ed93a8e87c437c7eae1258293c.zip
raptor-d1a1059d748955ed93a8e87c437c7eae1258293c.tar.gz
Add the linux device driver and netfpga files
This adds the device driver and netfpga files from the master thesis (in Dutch) "Implementatie van de Recursive Internet Architecture op een FPGA platform" by Alexander D'hoore.
Diffstat (limited to 'netfpga10g/hdl')
-rw-r--r--netfpga10g/hdl/buff.vhd192
-rw-r--r--netfpga10g/hdl/dma.vhd640
-rw-r--r--netfpga10g/hdl/engine.vhd570
-rw-r--r--netfpga10g/hdl/eth.vhd219
-rw-r--r--netfpga10g/hdl/eth_rx.vhd84
-rw-r--r--netfpga10g/hdl/eth_tx.vhd68
-rw-r--r--netfpga10g/hdl/mdio.vhd223
-rw-r--r--netfpga10g/hdl/pcie.vhd268
-rw-r--r--netfpga10g/hdl/pcie_rx.vhd98
-rw-r--r--netfpga10g/hdl/pcie_tx.vhd178
-rw-r--r--netfpga10g/hdl/pcie_wrapper.vhd358
-rw-r--r--netfpga10g/hdl/port_fifo.vhd94
-rw-r--r--netfpga10g/hdl/recv_mux.vhd86
-rw-r--r--netfpga10g/hdl/rx_eth.vhd168
-rw-r--r--netfpga10g/hdl/send_mux.vhd77
-rw-r--r--netfpga10g/hdl/system_loop.vhd253
-rw-r--r--netfpga10g/hdl/top.vhd243
-rw-r--r--netfpga10g/hdl/tx_eth.vhd96
18 files changed, 3915 insertions, 0 deletions
diff --git a/netfpga10g/hdl/buff.vhd b/netfpga10g/hdl/buff.vhd
new file mode 100644
index 0000000..39b3a80
--- /dev/null
+++ b/netfpga10g/hdl/buff.vhd
@@ -0,0 +1,192 @@
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.NUMERIC_STD.ALL;
+library UNISIM;
+use UNISIM.VComponents.all;
+
+entity buff is
+ Port ( wr_clk : in STD_LOGIC;
+ wr_en : in STD_LOGIC;
+ wr_data : in STD_LOGIC_VECTOR (63 downto 0);
+ wr_done : in STD_LOGIC;
+ wr_cancel : in std_logic := '0';
+ wr_accept : out STD_LOGIC;
+ rd_clk : in STD_LOGIC;
+ rd_en : in STD_LOGIC;
+ rd_data : out STD_LOGIC_VECTOR (63 downto 0) := (others => '0');
+ rd_length : out STD_LOGIC_VECTOR (8 downto 0) := (others => '0');
+ rd_valid : out STD_LOGIC := '0');
+end buff;
+
+architecture arch of buff is
+
+ COMPONENT ram_4kB
+ PORT (
+ clka : IN STD_LOGIC;
+ wea : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
+ addra : IN STD_LOGIC_VECTOR(8 DOWNTO 0);
+ dina : IN STD_LOGIC_VECTOR(63 DOWNTO 0);
+ clkb : IN STD_LOGIC;
+ addrb : IN STD_LOGIC_VECTOR(8 DOWNTO 0);
+ doutb : OUT STD_LOGIC_VECTOR(63 DOWNTO 0)
+ );
+ END COMPONENT;
+
+ signal ram_wr_en : std_logic_vector(0 downto 0);
+ signal ram_wr_addr : std_logic_vector(8 downto 0);
+ signal ram_wr_data : std_logic_vector(63 downto 0);
+
+ signal ram_rd_addr : std_logic_vector(8 downto 0);
+ signal ram_rd_data : std_logic_vector(63 downto 0);
+
+ constant W1 : std_logic_vector(1 downto 0) := "00";
+ constant W2 : std_logic_vector(1 downto 0) := "11";
+ constant R1 : std_logic_vector(1 downto 0) := "01";
+ constant R2 : std_logic_vector(1 downto 0) := "10";
+
+ signal wr_owner : std_logic_vector(1 downto 0) := W1;
+ signal rd_owner : std_logic_vector(1 downto 0) := W1;
+ signal wr_owner_tmp : std_logic_vector(1 downto 0) := W1;
+ signal wr_owner_sync : std_logic_vector(1 downto 0) := W1;
+
+ -- MAX: 256 bytes less than 4kB, for ouroboros
+ -- 4kB = 512 x 64 bits
+ -- 256 bytes = 32 x 64 bits
+ -- 512 - 32 = 480
+ -- 480 = "111100000"
+
+ constant MAX : std_logic_vector(8 downto 0) := "111100000";
+ constant ZERO : std_logic_vector(8 downto 0) := "000000000";
+ constant ONE : std_logic_vector(8 downto 0) := "000000001";
+
+ type state_t is (state_empty, state_wait, state_full, state_first, state_valid);
+
+ signal rd_state : state_t := state_empty;
+ signal rd_addr : std_logic_vector(8 downto 0) := MAX;
+
+begin
+
+ ram : ram_4kB
+ PORT MAP (
+ clka => wr_clk,
+ wea => ram_wr_en,
+ addra => ram_wr_addr,
+ dina => ram_wr_data,
+ clkb => rd_clk,
+ addrb => ram_rd_addr,
+ doutb => ram_rd_data
+ );
+
+ wr_accept <= '1' when (wr_owner = W1 or wr_owner = W2) and wr_done = '0' and wr_cancel = '0' else '0';
+
+ process (wr_clk)
+ variable wr_count : std_logic_vector(8 downto 0) := ZERO;
+ begin
+ if rising_edge(wr_clk) then
+ ram_wr_en(0) <= '0';
+ ram_wr_addr <= (others => '0');
+ ram_wr_data <= (others => '0');
+
+ if wr_owner = W1 or wr_owner = W2 then
+ if wr_cancel = '1' then
+ wr_count := ZERO;
+
+ elsif wr_done = '1' then
+ if wr_count /= ZERO then
+ if wr_owner = W1 then
+ wr_owner <= R1;
+ ram_wr_data(1 downto 0) <= R1;
+ else
+ wr_owner <= R2;
+ ram_wr_data(1 downto 0) <= R2;
+ end if;
+
+ ram_wr_en(0) <= '1';
+ ram_wr_addr <= MAX;
+ ram_wr_data(10 downto 2) <= wr_count;
+ wr_count := ZERO;
+ end if;
+
+ elsif wr_en = '1' then
+ if wr_count /= MAX then
+ ram_wr_en(0) <= '1';
+ ram_wr_addr <= wr_count;
+ ram_wr_data <= wr_data;
+ wr_count := std_logic_vector(unsigned(wr_count) + 1);
+ end if;
+ end if;
+ elsif wr_owner = R1 then
+ if wr_owner_sync = W2 then
+ wr_owner <= W2;
+ end if;
+ elsif wr_owner = R2 then
+ if wr_owner_sync = W1 then
+ wr_owner <= W1;
+ end if;
+ end if;
+
+ wr_owner_tmp <= rd_owner;
+ wr_owner_sync <= wr_owner_tmp;
+ end if;
+ end process;
+
+ ram_rd_addr <= std_logic_vector(unsigned(rd_addr) + 1)
+ when rd_state = state_valid and rd_en = '1'
+ else rd_addr;
+
+ process (rd_clk)
+ variable rd_count : std_logic_vector(8 downto 0) := ZERO;
+ variable tmp : std_logic_vector(1 downto 0);
+ begin
+ if rising_edge(rd_clk) then
+ if rd_state = state_empty then
+ rd_state <= state_wait;
+
+ elsif rd_state = state_wait then
+ tmp := ram_rd_data(1 downto 0);
+
+ if (rd_owner = W1 and tmp = R1) or
+ (rd_owner = W2 and tmp = R2) then
+
+ rd_state <= state_full;
+ rd_addr <= ZERO;
+ rd_count := ram_rd_data(10 downto 2);
+ rd_owner <= tmp;
+ end if;
+
+ elsif rd_state = state_full then
+ rd_state <= state_first;
+ rd_addr <= ONE;
+
+ elsif rd_state = state_first then
+ rd_state <= state_valid;
+ rd_valid <= '1';
+ rd_data <= ram_rd_data;
+ rd_length <= rd_count;
+
+ elsif rd_state = state_valid then
+ if rd_en = '1' then
+ if rd_addr = rd_count then
+ rd_state <= state_empty;
+ rd_addr <= MAX;
+ rd_valid <= '0';
+ rd_data <= (others => '0');
+ rd_length <= ZERO;
+ rd_count := ZERO;
+
+ if rd_owner = R1 then
+ rd_owner <= W2;
+ else
+ rd_owner <= W1;
+ end if;
+ else
+ rd_addr <= ram_rd_addr;
+ rd_data <= ram_rd_data;
+ end if;
+ end if;
+ end if;
+ end if;
+ end process;
+end arch;
+
diff --git a/netfpga10g/hdl/dma.vhd b/netfpga10g/hdl/dma.vhd
new file mode 100644
index 0000000..4c7e4f8
--- /dev/null
+++ b/netfpga10g/hdl/dma.vhd
@@ -0,0 +1,640 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity dma is
+generic (
+ BITS : integer := 14
+);
+port (
+ clk : in std_logic;
+ reset : in std_logic;
+
+ rx_read : in std_logic;
+ rx_write : in std_logic;
+ rx_complete : in std_logic;
+ rx_data : in std_logic_vector(63 downto 0);
+ rx_address : in std_logic_vector(28 downto 0);
+
+ tx_read : out std_logic;
+ tx_write : out std_logic;
+ tx_complete : out std_logic;
+ tx_data : out std_logic_vector(63 downto 0);
+ tx_address : out std_logic_vector(28 downto 0);
+ tx_length : out std_logic_vector(8 downto 0);
+ tx_accept : in std_logic;
+ tx_done : in std_logic;
+
+ port0_read : out std_logic;
+ port0_rd_data : in std_logic_vector(63 downto 0);
+ port0_rd_empty : in std_logic;
+ port0_rd_count : in std_logic_vector(BITS downto 0);
+
+ port0_write : out std_logic;
+ port0_wr_data : out std_logic_vector(63 downto 0);
+ port0_wr_full : in std_logic;
+ port0_wr_count : in std_logic_vector(BITS downto 0);
+
+ port1_read : out std_logic;
+ port1_rd_data : in std_logic_vector(63 downto 0);
+ port1_rd_empty : in std_logic;
+ port1_rd_count : in std_logic_vector(BITS downto 0);
+
+ port1_write : out std_logic;
+ port1_wr_data : out std_logic_vector(63 downto 0);
+ port1_wr_full : in std_logic;
+ port1_wr_count : in std_logic_vector(BITS downto 0);
+
+ port2_read : out std_logic;
+ port2_rd_data : in std_logic_vector(63 downto 0);
+ port2_rd_empty : in std_logic;
+ port2_rd_count : in std_logic_vector(BITS downto 0);
+
+ port2_write : out std_logic;
+ port2_wr_data : out std_logic_vector(63 downto 0);
+ port2_wr_full : in std_logic;
+ port2_wr_count : in std_logic_vector(BITS downto 0);
+
+ port3_read : out std_logic;
+ port3_rd_data : in std_logic_vector(63 downto 0);
+ port3_rd_empty : in std_logic;
+ port3_rd_count : in std_logic_vector(BITS downto 0);
+
+ port3_write : out std_logic;
+ port3_wr_data : out std_logic_vector(63 downto 0);
+ port3_wr_full : in std_logic;
+ port3_wr_count : in std_logic_vector(BITS downto 0);
+
+ max_read : in std_logic_vector(2 downto 0);
+ max_write : in std_logic_vector(2 downto 0);
+
+ interrupt : out std_logic;
+ interrupt_rdy : in std_logic;
+
+ mdio_command : out std_logic_vector(0 to 27);
+ mdio_data : in std_logic_vector(0 to 15);
+ mdio_enable : out std_logic;
+ mdio_done : in std_logic;
+
+ leds : out std_logic_vector(2 downto 0)
+);
+end dma;
+
+architecture arch of dma is
+ type state_t is (state_idle, state_tx_read, state_tx_write, state_tx_complete, state_rx_complete,
+ state_dma_read, state_dma_write, state_interrupt, state_command,
+ state_test_write_head, state_test_write,
+ state_test_read_head, state_test_read, state_test_complete,
+ state_mdio);
+ signal state : state_t;
+
+ signal fifo_read : std_logic;
+ signal fifo_write : std_logic;
+ signal fifo_din : std_logic_vector(63 downto 0);
+ signal fifo_dout : std_logic_vector(63 downto 0);
+ signal fifo_full : std_logic;
+ signal fifo_empty : std_logic;
+ signal fifo_count : std_logic_vector(BITS downto 0);
+
+ component simple_fifo port (
+ clk : in std_logic;
+ rst : in std_logic;
+ rd_en : in std_logic;
+ wr_en : in std_logic;
+ din : in std_logic_vector(63 downto 0);
+ dout : out std_logic_vector(63 downto 0);
+ full : out std_logic;
+ empty : out std_logic;
+ data_count : out std_logic_vector(BITS downto 0)
+ );
+ end component;
+
+ signal cmd_read : std_logic;
+ signal cmd_write : std_logic;
+ signal cmd_din : std_logic_vector(63 downto 0);
+ signal cmd_dout : std_logic_vector(63 downto 0);
+ signal cmd_full : std_logic;
+ signal cmd_empty : std_logic;
+
+ component cmd_fifo port (
+ clk : in std_logic;
+ rst : in std_logic;
+ rd_en : in std_logic;
+ wr_en : in std_logic;
+ din : in std_logic_vector(63 downto 0);
+ dout : out std_logic_vector(63 downto 0);
+ full : out std_logic;
+ empty : out std_logic
+ );
+ end component;
+
+ signal test_completion : std_logic_vector(63 downto 0);
+begin
+ process (clk, reset)
+ variable bar_addr : unsigned(BITS downto 0);
+ variable dma_addr : unsigned(28 downto 0);
+ variable length : unsigned(BITS downto 0);
+ variable remain : unsigned(BITS downto 0);
+ variable cycles : unsigned(BITS downto 0);
+ variable backup_addr : unsigned(28 downto 0);
+ variable backup_length : unsigned(BITS downto 0);
+ begin
+ if reset = '1' then
+ state <= state_idle;
+ tx_read <= '0';
+ tx_write <= '0';
+ tx_complete <= '0';
+ tx_data <= (others => '0');
+ tx_address <= (others => '0');
+ tx_length <= (others => '0');
+ fifo_read <= '0';
+ fifo_write <= '0';
+ fifo_din <= (others => '0');
+ interrupt <= '0';
+ cmd_read <= '0';
+ cmd_write <= '0';
+ cmd_din <= (others => '0');
+ test_completion <= (others => '0');
+ port0_read <= '0';
+ port0_write <= '0';
+ port0_wr_data <= (others => '0');
+ port1_read <= '0';
+ port1_write <= '0';
+ port1_wr_data <= (others => '0');
+ port2_read <= '0';
+ port2_write <= '0';
+ port2_wr_data <= (others => '0');
+ port3_read <= '0';
+ port3_write <= '0';
+ port3_wr_data <= (others => '0');
+ mdio_enable <= '0';
+ mdio_command <= (others => '0');
+
+ elsif rising_edge(clk) then
+ fifo_read <= '0';
+ fifo_write <= '0';
+ fifo_din <= (others => '0');
+ cmd_read <= '0';
+ cmd_write <= '0';
+ cmd_din <= (others => '0');
+ port0_read <= '0';
+ port0_write <= '0';
+ port1_read <= '0';
+ port1_write <= '0';
+ port2_read <= '0';
+ port2_write <= '0';
+ port3_read <= '0';
+ port3_write <= '0';
+
+ -- bar read
+ if state = state_idle and rx_read = '1' then
+ state <= state_tx_complete;
+ tx_complete <= '1';
+ tx_data <= (others => '0');
+ tx_address <= rx_address;
+ bar_addr := unsigned(rx_address(BITS downto 0));
+
+ -- read fifo
+ if bar_addr = 0 then
+ if fifo_empty = '1' then
+ tx_data <= (others => '1');
+ else
+ tx_data <= fifo_dout;
+ fifo_read <= '1';
+ end if;
+
+ -- read command
+ elsif bar_addr = 1 then
+ if cmd_empty = '1' then
+ tx_data <= (others => '1');
+ else
+ tx_data <= cmd_dout;
+ cmd_read <= '1';
+ end if;
+
+ -- other
+ elsif bar_addr = 3 then
+ tx_data(BITS downto 0) <= fifo_count;
+
+ elsif bar_addr = 4 then
+ tx_data(2 downto 0) <= max_read;
+
+ elsif bar_addr = 5 then
+ tx_data(2 downto 0) <= max_write;
+
+ elsif bar_addr = 6 then
+ tx_data <= test_completion;
+
+ -- read ports
+ elsif bar_addr = 10 then
+ if port0_rd_empty = '1' then
+ tx_data <= (others => '1');
+ else
+ tx_data <= port0_rd_data;
+ port0_read <= '1';
+ end if;
+
+ elsif bar_addr = 11 then
+ if port1_rd_empty = '1' then
+ tx_data <= (others => '1');
+ else
+ tx_data <= port1_rd_data;
+ port1_read <= '1';
+ end if;
+
+ elsif bar_addr = 12 then
+ if port2_rd_empty = '1' then
+ tx_data <= (others => '1');
+ else
+ tx_data <= port2_rd_data;
+ port2_read <= '1';
+ end if;
+
+ elsif bar_addr = 13 then
+ if port3_rd_empty = '1' then
+ tx_data <= (others => '1');
+ else
+ tx_data <= port3_rd_data;
+ port3_read <= '1';
+ end if;
+
+ -- read counts
+ elsif bar_addr = 20 then
+ tx_data(BITS downto 0) <= port0_rd_count;
+
+ elsif bar_addr = 21 then
+ tx_data(BITS downto 0) <= port0_wr_count;
+
+ elsif bar_addr = 22 then
+ tx_data(BITS downto 0) <= port1_rd_count;
+
+ elsif bar_addr = 23 then
+ tx_data(BITS downto 0) <= port1_wr_count;
+
+ elsif bar_addr = 24 then
+ tx_data(BITS downto 0) <= port2_rd_count;
+
+ elsif bar_addr = 25 then
+ tx_data(BITS downto 0) <= port2_wr_count;
+
+ elsif bar_addr = 26 then
+ tx_data(BITS downto 0) <= port3_rd_count;
+
+ elsif bar_addr = 27 then
+ tx_data(BITS downto 0) <= port3_wr_count;
+
+ -- read mdio
+ elsif bar_addr = 30 then
+ tx_data(15 downto 0) <= mdio_data;
+ end if;
+
+ elsif state = state_tx_complete then
+ if tx_done = '1' then
+ state <= state_idle;
+ end if;
+
+ -- bar write
+ elsif state = state_idle and rx_write = '1' then
+ bar_addr := unsigned(rx_address(BITS downto 0));
+
+ -- write fifo
+ if bar_addr = 0 then
+ if fifo_full = '0' then
+ fifo_din <= rx_data;
+ fifo_write <= '1';
+ end if;
+
+ -- write command
+ elsif bar_addr = 1 then
+ if cmd_full = '0' then
+ cmd_din <= rx_data;
+ cmd_write <= '1';
+ end if;
+
+ if rx_data(0) = '1' then
+ state <= state_command;
+ end if;
+
+ -- write test
+ elsif bar_addr = 2 then
+ dma_addr := unsigned(rx_data(31 downto 3));
+ length := unsigned(rx_data(BITS+32 downto 32));
+ cycles := unsigned(rx_data(BITS+48 downto 48));
+ backup_addr := dma_addr;
+ backup_length := length;
+
+ if rx_data(1) = '0' then
+ state <= state_test_read_head;
+ else
+ state <= state_test_write_head;
+ end if;
+
+ -- write ports
+ elsif bar_addr = 10 then
+ if port0_wr_full = '0' then
+ port0_wr_data <= rx_data;
+ port0_write <= '1';
+ end if;
+
+ elsif bar_addr = 11 then
+ if port1_wr_full = '0' then
+ port1_wr_data <= rx_data;
+ port1_write <= '1';
+ end if;
+
+ elsif bar_addr = 12 then
+ if port2_wr_full = '0' then
+ port2_wr_data <= rx_data;
+ port2_write <= '1';
+ end if;
+
+ elsif bar_addr = 13 then
+ if port3_wr_full = '0' then
+ port3_wr_data <= rx_data;
+ port3_write <= '1';
+ end if;
+
+ -- write mdio
+ elsif bar_addr = 30 then
+ state <= state_mdio;
+ mdio_enable <= '1';
+ mdio_command <= rx_data(27 downto 0);
+ end if;
+
+ -- mdio
+ elsif state = state_mdio then
+ if mdio_done = '1' then
+ mdio_enable <= '0';
+ state <= state_interrupt;
+ interrupt <= '1';
+ end if;
+
+ -- test read
+ elsif state = state_test_read_head then
+ remain := 16 - resize(dma_addr(3 downto 0), remain'length);
+
+ if max_read = "001" then
+ remain := 32 - resize(dma_addr(4 downto 0), remain'length);
+ elsif max_read = "010" then
+ remain := 64 - resize(dma_addr(5 downto 0), remain'length);
+ elsif max_read = "011" then
+ remain := 128 - resize(dma_addr(6 downto 0), remain'length);
+ elsif max_read = "100" then
+ remain := 256 - resize(dma_addr(7 downto 0), remain'length);
+ elsif max_read = "101" then
+ remain := 512 - resize(dma_addr(8 downto 0), remain'length);
+ end if;
+
+ if remain > length then
+ remain := length;
+ end if;
+
+ state <= state_test_read;
+ tx_read <= '1';
+ tx_address <= std_logic_vector(dma_addr);
+ tx_length <= std_logic_vector(remain(8 downto 0));
+ length := length - remain;
+ dma_addr := dma_addr + remain;
+
+ elsif state = state_test_read then
+ if tx_done = '1' then
+ state <= state_test_complete;
+ end if;
+
+ elsif state = state_test_complete then
+ if rx_complete = '1' then
+ test_completion <= rx_data;
+ remain := remain - 1;
+
+ if remain = 0 then
+ if length > 0 then
+ state <= state_test_read_head;
+
+ elsif cycles > 1 then
+ state <= state_test_read_head;
+ dma_addr := backup_addr;
+ length := backup_length;
+ cycles := cycles - 1;
+ else
+ state <= state_interrupt;
+ interrupt <= '1';
+ end if;
+ end if;
+ end if;
+
+ -- test write
+ elsif state = state_test_write_head then
+ remain := 16 - resize(dma_addr(3 downto 0), remain'length);
+
+ if max_write = "001" then
+ remain := 32 - resize(dma_addr(4 downto 0), remain'length);
+ elsif max_write = "010" then
+ remain := 64 - resize(dma_addr(5 downto 0), remain'length);
+ elsif max_write = "011" then
+ remain := 128 - resize(dma_addr(6 downto 0), remain'length);
+ elsif max_write = "100" then
+ remain := 256 - resize(dma_addr(7 downto 0), remain'length);
+ elsif max_write = "101" then
+ remain := 512 - resize(dma_addr(8 downto 0), remain'length);
+ end if;
+
+ if remain > length then
+ remain := length;
+ end if;
+
+ state <= state_test_write;
+ tx_write <= '1';
+ tx_data <= x"FFEEDDCC00000000";
+ tx_address <= std_logic_vector(dma_addr);
+ tx_length <= std_logic_vector(remain(8 downto 0));
+ length := length - remain;
+ dma_addr := dma_addr + remain;
+
+ elsif state = state_test_write then
+ if tx_done = '1' then
+ if length > 0 then
+ state <= state_test_write_head;
+
+ elsif cycles > 1 then
+ state <= state_test_write_head;
+ dma_addr := backup_addr;
+ length := backup_length;
+ cycles := cycles - 1;
+ else
+ state <= state_interrupt;
+ interrupt <= '1';
+ end if;
+ end if;
+
+ -- command
+ elsif state = state_command then
+ if cmd_empty = '1' then
+ state <= state_interrupt;
+ interrupt <= '1';
+ else
+ cmd_read <= '1';
+
+ if cmd_dout(1) = '0' then
+ state <= state_dma_read;
+ dma_addr := unsigned(cmd_dout(31 downto 3));
+ length := unsigned(cmd_dout(BITS+32 downto 32));
+ fifo_din <= std_logic_vector(resize(length, fifo_din'length));
+ fifo_write <= '1';
+ else
+ state <= state_dma_write;
+ dma_addr := unsigned(cmd_dout(31 downto 3));
+ length := unsigned(fifo_dout(BITS downto 0)) + 1;
+ end if;
+ end if;
+
+ elsif state = state_interrupt then
+ if interrupt_rdy = '1' then
+ state <= state_idle;
+ interrupt <= '0';
+ end if;
+
+ -- dma read
+ elsif state = state_dma_read then
+ remain := 16 - resize(dma_addr(3 downto 0), remain'length);
+
+ if max_read = "001" then
+ remain := 32 - resize(dma_addr(4 downto 0), remain'length);
+ elsif max_read = "010" then
+ remain := 64 - resize(dma_addr(5 downto 0), remain'length);
+ elsif max_read = "011" then
+ remain := 128 - resize(dma_addr(6 downto 0), remain'length);
+ elsif max_read = "100" then
+ remain := 256 - resize(dma_addr(7 downto 0), remain'length);
+ elsif max_read = "101" then
+ remain := 512 - resize(dma_addr(8 downto 0), remain'length);
+ end if;
+
+ if remain > length then
+ remain := length;
+ end if;
+
+ state <= state_tx_read;
+ tx_read <= '1';
+ tx_address <= std_logic_vector(dma_addr);
+ tx_length <= std_logic_vector(remain(8 downto 0));
+ length := length - remain;
+ dma_addr := dma_addr + remain;
+
+ elsif state = state_tx_read then
+ if tx_done = '1' then
+ state <= state_rx_complete;
+ end if;
+
+ elsif state = state_rx_complete then
+ if rx_complete = '1' then
+ fifo_din <= rx_data;
+ fifo_write <= '1';
+ remain := remain - 1;
+
+ if remain = 0 then
+ if length > 0 then
+ state <= state_dma_read;
+ else
+ state <= state_command;
+ end if;
+ end if;
+ end if;
+
+ -- dma write
+ elsif state = state_dma_write then
+ remain := 16 - resize(dma_addr(3 downto 0), remain'length);
+
+ if max_write = "001" then
+ remain := 32 - resize(dma_addr(4 downto 0), remain'length);
+ elsif max_write = "010" then
+ remain := 64 - resize(dma_addr(5 downto 0), remain'length);
+ elsif max_write = "011" then
+ remain := 128 - resize(dma_addr(6 downto 0), remain'length);
+ elsif max_write = "100" then
+ remain := 256 - resize(dma_addr(7 downto 0), remain'length);
+ elsif max_write = "101" then
+ remain := 512 - resize(dma_addr(8 downto 0), remain'length);
+ end if;
+
+ if remain > length then
+ remain := length;
+ end if;
+
+ state <= state_tx_write;
+ tx_write <= '1';
+ tx_data <= fifo_dout;
+ tx_address <= std_logic_vector(dma_addr);
+ tx_length <= std_logic_vector(remain(8 downto 0));
+ fifo_read <= '1';
+ length := length - remain;
+ dma_addr := dma_addr + remain;
+ remain := remain - 1;
+
+ elsif state = state_tx_write then
+ if tx_done = '1' then
+ if length > 0 then
+ state <= state_dma_write;
+ else
+ state <= state_command;
+ end if;
+
+ elsif tx_accept = '1' and remain > 0 then
+ tx_data <= fifo_dout;
+ fifo_read <= '1';
+ remain := remain - 1;
+ end if;
+ end if;
+
+ if tx_done = '1' then
+ tx_read <= '0';
+ tx_write <= '0';
+ tx_complete <= '0';
+ tx_data <= (others => '0');
+ tx_address <= (others => '0');
+ tx_length <= (others => '0');
+ end if;
+ end if;
+ end process;
+
+ fifo : entity work.port_fifo port map (
+ reset => reset,
+
+ rd_clk => clk,
+ rd_read => fifo_read,
+ rd_data => fifo_dout,
+ rd_empty => fifo_empty,
+ rd_count => fifo_count,
+
+ wr_write => fifo_write,
+ wr_data => fifo_din,
+ wr_full => fifo_full
+ --wr_count => wr_count
+ );
+
+ commands : cmd_fifo port map (
+ clk => clk,
+ rst => reset,
+ rd_en => cmd_read,
+ wr_en => cmd_write,
+ din => cmd_din,
+ dout => cmd_dout,
+ full => cmd_full,
+ empty => cmd_empty
+ );
+
+ leds <= "000" when state = state_idle else
+ -- bar read
+ "001" when state = state_tx_complete else
+ -- dma read
+ "010" when state = state_dma_read or state = state_tx_read or state = state_rx_complete else
+ -- dma write
+ "011" when state = state_dma_write or state = state_tx_write else
+ -- mdio
+ "100" when state = state_mdio else
+ -- interrupt
+ "101" when state = state_interrupt else
+ -- other
+ "111";
+end arch;
+
diff --git a/netfpga10g/hdl/engine.vhd b/netfpga10g/hdl/engine.vhd
new file mode 100644
index 0000000..16f0a8b
--- /dev/null
+++ b/netfpga10g/hdl/engine.vhd
@@ -0,0 +1,570 @@
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.NUMERIC_STD.ALL;
+library UNISIM;
+use UNISIM.VComponents.all;
+
+entity engine is
+generic (
+ BUFF_COUNT : integer := 16;
+ BUFF_BITS : integer := 4; -- 2^4 = 16
+ BAR_BITS : integer := 17;
+ TIME_BITS : integer := 20
+);
+port (
+ clk : in STD_LOGIC;
+
+ rd_buff : out STD_LOGIC_VECTOR (BUFF_BITS - 1 downto 0) := (others => '0');
+ rd_en : out STD_LOGIC := '0';
+ rd_data : in STD_LOGIC_VECTOR (63 downto 0);
+ rd_length : in STD_LOGIC_VECTOR (8 downto 0);
+ rd_valid : in STD_LOGIC_VECTOR (BUFF_COUNT - 1 downto 0);
+
+ wr_buff : out STD_LOGIC_VECTOR (BUFF_BITS - 1 downto 0) := (others => '0');
+ wr_en : out STD_LOGIC := '0';
+ wr_data : out STD_LOGIC_VECTOR (63 downto 0) := (others => '0');
+ wr_done : out STD_LOGIC := '0';
+ wr_cancel : out STD_LOGIC_VECTOR (BUFF_COUNT - 1 downto 0);
+ wr_accept : in STD_LOGIC_VECTOR (BUFF_COUNT - 1 downto 0);
+
+ rx_read : in STD_LOGIC;
+ rx_write : in STD_LOGIC;
+ rx_complete : in STD_LOGIC;
+ rx_data : in STD_LOGIC_VECTOR (63 downto 0);
+ rx_address : in STD_LOGIC_VECTOR (63 downto 3);
+ rx_tag : in std_logic_vector(4 downto 0);
+
+ tx_read : out STD_LOGIC := '0';
+ tx_write : out STD_LOGIC := '0';
+ tx_complete : out STD_LOGIC := '0';
+ tx_data : out STD_LOGIC_VECTOR (63 downto 0) := (others => '0');
+ tx_address : out STD_LOGIC_VECTOR (63 downto 3) := (others => '0');
+ tx_length : out STD_LOGIC_VECTOR (8 downto 0) := (others => '0');
+ tx_tag : out std_logic_vector(4 downto 0) := (others => '0');
+ tx_accept : in STD_LOGIC;
+ tx_done : in STD_LOGIC;
+
+ interrupt : out std_logic := '0';
+ interrupt_rdy : in std_logic;
+
+ max_read : in std_logic_vector(2 downto 0);
+ max_write : in std_logic_vector(2 downto 0);
+
+ mdio_command : out std_logic_vector(0 to 27) := (others => '0');
+ mdio_data : in std_logic_vector(0 to 15);
+ mdio_enable : out std_logic := '0';
+ mdio_done : in std_logic
+);
+end engine;
+
+architecture arch of engine is
+
+ constant BUFF_EMPTY : std_logic_vector(1 downto 0) := "00";
+ constant BUFF_ADDR : std_logic_vector(1 downto 0) := "01";
+ constant BUFF_DATA : std_logic_vector(1 downto 0) := "10";
+ constant BUFF_FULL : std_logic_vector(1 downto 0) := "11";
+
+ type buff_t is array (0 to BUFF_COUNT - 1) of std_logic_vector(1 downto 0);
+ type length_t is array (0 to BUFF_COUNT - 1) of unsigned(8 downto 0);
+ type address_t is array (0 to BUFF_COUNT - 1) of unsigned(63 downto 3);
+ type time_t is array (0 to BUFF_COUNT - 1) of unsigned(TIME_BITS - 1 downto 0);
+
+ type rx_state_t is (rx_state_idle, rx_state_write_done, rx_state_mdio);
+ type tx_state_t is (tx_state_idle, tx_state_read, tx_state_write,
+ tx_state_complete, tx_state_interrupt);
+
+ signal rx_state : rx_state_t := rx_state_idle;
+ signal tx_state : tx_state_t := tx_state_idle;
+
+ signal tx_data_i : std_logic_vector(63 downto 0) := (others => '0');
+
+ constant CMD_STATUS : std_logic_vector(1 downto 0) := "00";
+ constant CMD_SEND : std_logic_vector(1 downto 0) := "01";
+ constant CMD_RECV : std_logic_vector(1 downto 0) := "10";
+ constant CMD_MDIO : std_logic_vector(1 downto 0) := "11";
+
+ signal send_buff : buff_t := (others => BUFF_FULL);
+ signal send_length : length_t := (others => (others => '0'));
+ signal send_remain : length_t := (others => (others => '0'));
+ signal send_address : address_t := (others => (others => '0'));
+ signal send_read_time : time_t := (others => (others => '0'));
+
+ signal recv_buff : buff_t := (others => BUFF_EMPTY);
+ signal recv_address0 : unsigned(63 downto 3);
+ signal recv_address1 : unsigned(63 downto 3);
+ signal recv_address2 : unsigned(63 downto 3);
+ signal recv_address3 : unsigned(63 downto 3);
+ signal recv_address4 : unsigned(63 downto 3);
+ signal recv_address5 : unsigned(63 downto 3);
+ signal recv_address6 : unsigned(63 downto 3);
+ signal recv_address7 : unsigned(63 downto 3);
+ signal recv_address8 : unsigned(63 downto 3);
+ signal recv_address9 : unsigned(63 downto 3);
+ signal recv_address10 : unsigned(63 downto 3);
+ signal recv_address11 : unsigned(63 downto 3);
+ signal recv_address12 : unsigned(63 downto 3);
+ signal recv_address13 : unsigned(63 downto 3);
+ signal recv_address14 : unsigned(63 downto 3);
+ signal recv_address15 : unsigned(63 downto 3);
+
+ signal send_int : std_logic := '0';
+ signal send_int_needed : std_logic := '0';
+ signal send_read : std_logic := '0';
+ signal send_read_done : std_logic := '0';
+ signal send_read_buff : integer range 0 to BUFF_COUNT - 1 := 0;
+ signal send_read_length : unsigned(8 downto 0);
+ signal send_read_remain : unsigned(8 downto 0);
+ signal send_read_address : unsigned(63 downto 3);
+ signal send_write : std_logic := '0';
+ signal send_write_new : std_logic := '0';
+ signal send_write_buff : integer range 0 to BUFF_COUNT - 1 := 0;
+ signal send_write_length : unsigned(8 downto 0);
+ signal send_write_address : unsigned(63 downto 3);
+
+ signal debug_address : std_logic_vector(63 downto 3) := (others => '0');
+ signal debug_data : std_logic_vector(63 downto 0) := (others => '0');
+ signal debug_cmd : std_logic_vector(1 downto 0) := (others => '0');
+ signal debug_buff : std_logic_vector(BUFF_BITS - 1 downto 0) := (others => '0');
+ signal debug_length : std_logic_vector(8 downto 0) := std_logic_vector(to_unsigned(42, 9));
+
+ signal debug_cmpl_count : unsigned(7 downto 0) := (others => '0');
+ signal debug_cmpl_data : std_logic_vector(63 downto 0) := (others => '0');
+ signal debug_cmpl_tag : std_logic_vector(4 downto 0) := (others => '0');
+ signal debug_cmpl_state : std_logic_vector(7 downto 0) := x"FF";
+
+ signal debug_write_count : unsigned(7 downto 0) := (others => '0');
+ signal debug_write_length : std_logic_vector(8 downto 0) := (others => '0');
+ signal debug_write_addr : std_logic_vector(63 downto 3) := (others => '0');
+ signal debug_write_data : std_logic_vector(63 downto 0) := (others => '0');
+
+ signal debug_accept_count : unsigned(7 downto 0) := (others => '0');
+ signal debug_done_count : unsigned(7 downto 0) := (others => '0');
+
+ signal timer : unsigned(TIME_BITS - 1 downto 0) := (others => '0');
+begin
+ rd_en <= tx_accept when tx_state = tx_state_write else '0';
+
+ tx_data <= rd_data when tx_state = tx_state_write else tx_data_i;
+
+ process (clk)
+ variable bar_read : std_logic := '0';
+ variable bar_read_address : std_logic_vector(63 downto 3) := (others => '0');
+
+ variable tmp_cmd : std_logic_vector(1 downto 0);
+ variable tmp_buff : integer range 0 to BUFF_COUNT - 1;
+ variable tmp_length : unsigned(8 downto 0);
+ variable tmp_remain : unsigned(8 downto 0);
+ variable tmp_address : unsigned(63 downto 3);
+ variable tmp_bar : unsigned(BAR_BITS - 1 downto 0);
+
+ -- see 'metered reads' in pcie core manual (xilinx)
+ -- a maximum of 8 openstanding reads is allowed
+ constant READ_MAX : unsigned(3 downto 0) := x"8";
+ variable read_count : unsigned(3 downto 0) := (others => '0');
+ variable read_decr : std_logic;
+ variable read_incr : std_logic;
+ begin
+ if rising_edge(clk) then
+ wr_en <= '0';
+ wr_data <= (others => '0');
+ wr_done <= '0';
+ wr_cancel <= (others => '0');
+ read_decr := '0';
+ read_incr := '0';
+
+ timer <= timer + 1;
+
+ -- ENGINE: RX
+ if rx_state = rx_state_idle then
+ if rx_read = '1' then
+ bar_read := '1';
+ bar_read_address := rx_address;
+
+ elsif rx_write = '1' then
+ tmp_cmd := rx_address(4 downto 3);
+ tmp_buff := to_integer(unsigned(rx_address(5 + BUFF_BITS - 1 downto 5)));
+ tmp_length := unsigned(rx_address(18 downto 10));
+ tmp_address := unsigned(rx_data(63 downto 3));
+
+ debug_address <= rx_address;
+ debug_data <= rx_data;
+ debug_cmd <= tmp_cmd;
+ debug_buff <= std_logic_vector(to_unsigned(tmp_buff, debug_buff'length));
+ debug_length <= std_logic_vector(tmp_length);
+
+ if tmp_cmd = CMD_SEND then
+ if send_buff(tmp_buff) = BUFF_EMPTY then
+ send_buff(tmp_buff) <= BUFF_ADDR;
+ send_address(tmp_buff) <= tmp_address;
+ send_length(tmp_buff) <= tmp_length;
+ end if;
+
+ elsif tmp_cmd = CMD_RECV then
+ if recv_buff(tmp_buff) = BUFF_FULL then
+ recv_buff(tmp_buff) <= BUFF_ADDR;
+
+ if tmp_buff = 0 then
+ recv_address0 <= tmp_address;
+ elsif tmp_buff = 1 then
+ recv_address1 <= tmp_address;
+ elsif tmp_buff = 2 then
+ recv_address2 <= tmp_address;
+ elsif tmp_buff = 3 then
+ recv_address3 <= tmp_address;
+ elsif tmp_buff = 4 then
+ recv_address4 <= tmp_address;
+ elsif tmp_buff = 5 then
+ recv_address5 <= tmp_address;
+ elsif tmp_buff = 6 then
+ recv_address6 <= tmp_address;
+ elsif tmp_buff = 7 then
+ recv_address7 <= tmp_address;
+ elsif tmp_buff = 8 then
+ recv_address8 <= tmp_address;
+ elsif tmp_buff = 9 then
+ recv_address9 <= tmp_address;
+ elsif tmp_buff = 10 then
+ recv_address10 <= tmp_address;
+ elsif tmp_buff = 11 then
+ recv_address11 <= tmp_address;
+ elsif tmp_buff = 12 then
+ recv_address12 <= tmp_address;
+ elsif tmp_buff = 13 then
+ recv_address13 <= tmp_address;
+ elsif tmp_buff = 14 then
+ recv_address14 <= tmp_address;
+ elsif tmp_buff = 15 then
+ recv_address15 <= tmp_address;
+ end if;
+ end if;
+
+ elsif tmp_cmd = CMD_MDIO then
+ rx_state <= rx_state_mdio;
+ mdio_enable <= '1';
+ mdio_command <= rx_data(27 downto 0);
+ end if;
+
+ elsif rx_complete = '1' then
+ tmp_buff := to_integer(unsigned(rx_tag(BUFF_BITS - 1 downto 0)));
+
+ debug_cmpl_count <= debug_cmpl_count + 1;
+ debug_cmpl_data <= rx_data;
+ debug_cmpl_tag <= rx_tag;
+ debug_cmpl_state <= x"00";
+
+ if send_buff(tmp_buff) = BUFF_DATA then
+ wr_en <= '1';
+ wr_data <= rx_data;
+ wr_buff <= std_logic_vector(to_unsigned(tmp_buff, BUFF_BITS));
+ send_remain(tmp_buff) <= send_remain(tmp_buff) - 1;
+ debug_cmpl_state <= x"01";
+
+ if send_remain(tmp_buff) = 1 then
+ read_decr := '1';
+
+ if send_length(tmp_buff) = 0 then
+ rx_state <= rx_state_write_done;
+ debug_cmpl_state <= x"02";
+ else
+ send_buff(tmp_buff) <= BUFF_ADDR;
+ debug_cmpl_state <= x"03";
+ end if;
+ end if;
+ end if;
+ end if;
+
+ elsif rx_state = rx_state_write_done then
+ rx_state <= rx_state_idle;
+ wr_done <= '1';
+
+ elsif rx_state = rx_state_mdio then
+ if mdio_done = '1' then
+ rx_state <= rx_state_idle;
+ mdio_enable <= '0';
+ end if;
+ end if;
+
+ -- ENGINE: TX
+ if send_read_done = '1' then
+ send_read_done <= '0';
+ send_buff(send_read_buff) <= BUFF_DATA;
+ send_length(send_read_buff) <= send_read_length - send_read_remain;
+ send_remain(send_read_buff) <= send_read_remain;
+ send_address(send_read_buff) <= send_read_address + send_read_remain;
+ send_read_time(send_read_buff) <= timer;
+ end if;
+
+ if tx_state = tx_state_idle or
+ (tx_state = tx_state_read and tx_done = '1') or
+ (tx_state = tx_state_write and tx_done = '1') or
+ (tx_state = tx_state_complete and tx_done = '1') or
+ (tx_state = tx_state_interrupt and interrupt_rdy = '1') then
+
+ tx_state <= tx_state_idle;
+ tx_read <= '0';
+ tx_write <= '0';
+ tx_complete <= '0';
+ tx_data_i <= (others => '0');
+ tx_address <= (others => '0');
+ tx_length <= (others => '0');
+ tx_tag <= (others => '0');
+ interrupt <= '0';
+
+ if bar_read = '1' then
+ tx_state <= tx_state_complete;
+ tx_complete <= '1';
+ tx_address <= bar_read_address;
+ tmp_cmd := bar_read_address(4 downto 3);
+ tmp_bar := unsigned(bar_read_address(3 + BAR_BITS - 1 downto 3));
+ bar_read := '0';
+
+ if tmp_bar = 0 then
+ --if tmp_cmd = CMD_STATUS then
+ for i in 0 to BUFF_COUNT - 1 loop
+ tx_data_i(i*4 + 1 downto i*4 + 0) <= send_buff(i);
+ tx_data_i(i*4 + 3 downto i*4 + 2) <= recv_buff(i);
+ end loop;
+ send_int <= '0';
+ send_int_needed <= '1';
+
+ elsif tmp_bar = 1 then
+ tx_data_i(63 downto 3) <= debug_address;
+
+ elsif tmp_bar = 2 then
+ tx_data_i <= debug_data;
+
+ elsif tmp_bar = 3 then
+ tx_data_i(1 downto 0) <= debug_cmd;
+
+ elsif tmp_bar = 4 then
+ tx_data_i(BUFF_BITS - 1 downto 0) <= debug_buff;
+
+ elsif tmp_bar = 5 then
+ tx_data_i(8 downto 0) <= debug_length;
+
+ elsif tmp_bar = 10 then
+ tx_data_i(7 downto 0) <= std_logic_vector(debug_cmpl_count);
+
+ elsif tmp_bar = 11 then
+ tx_data_i <= debug_cmpl_data;
+
+ elsif tmp_bar = 12 then
+ tx_data_i(4 downto 0) <= debug_cmpl_tag;
+
+ elsif tmp_bar = 13 then
+ tx_data_i(7 downto 0) <= debug_cmpl_state;
+
+ elsif tmp_bar = 20 then
+ tx_data_i(7 downto 0) <= std_logic_vector(debug_write_count);
+
+ elsif tmp_bar = 21 then
+ tx_data_i(8 downto 0) <= debug_write_length;
+
+ elsif tmp_bar = 22 then
+ tx_data_i(63 downto 3) <= debug_write_addr;
+
+ elsif tmp_bar = 23 then
+ tx_data_i(63 downto 0) <= debug_write_data;
+
+ elsif tmp_bar = 24 then
+ tx_data_i(7 downto 0) <= std_logic_vector(debug_accept_count);
+
+ elsif tmp_bar = 25 then
+ tx_data_i(7 downto 0) <= std_logic_vector(debug_done_count);
+
+ elsif tmp_bar = 30 then
+ tx_data_i(15 downto 0) <= mdio_data;
+
+ else
+ tx_data_i(63 downto 3) <= bar_read_address;
+ end if;
+
+ elsif send_int = '1' and send_int_needed = '1' then
+ tx_state <= tx_state_interrupt;
+ interrupt <= '1';
+ send_int_needed <= '0';
+
+ elsif send_read = '1' and read_count < READ_MAX then
+ tmp_buff := send_read_buff;
+ tmp_length := send_read_length;
+ tmp_address := send_read_address;
+ tmp_remain := 16 - resize(tmp_address(6 downto 3), tmp_remain'length);
+
+ if max_read = "001" then
+ tmp_remain := 32 - resize(tmp_address(7 downto 3), tmp_remain'length);
+ elsif max_read = "010" then
+ tmp_remain := 64 - resize(tmp_address(8 downto 3), tmp_remain'length);
+ elsif max_read = "011" then
+ tmp_remain := 128 - resize(tmp_address(9 downto 3), tmp_remain'length);
+ elsif max_read = "100" then
+ tmp_remain := 256 - resize(tmp_address(10 downto 3), tmp_remain'length);
+ elsif max_read = "101" then
+ tmp_remain := 512 - resize(tmp_address(11 downto 3), tmp_remain'length);
+ end if;
+
+ if tmp_remain > tmp_length then
+ tmp_remain := tmp_length;
+ end if;
+
+ tx_state <= tx_state_read;
+ tx_read <= '1';
+ tx_address <= std_logic_vector(tmp_address);
+ tx_length <= std_logic_vector(tmp_remain);
+ tx_tag <= std_logic_vector(to_unsigned(tmp_buff, tx_tag'length));
+
+ send_read <= '0';
+ send_read_done <= '1';
+ send_read_remain <= tmp_remain;
+ read_incr := '1';
+
+ elsif send_write = '1' then
+ if send_write_new = '1' then
+ tmp_length := unsigned(rd_length);
+ else
+ tmp_length := send_write_length;
+ end if;
+ tmp_address := send_write_address;
+ tmp_remain := 16 - resize(tmp_address(6 downto 3), tmp_remain'length);
+
+ if max_write = "001" then
+ tmp_remain := 32 - resize(tmp_address(7 downto 3), tmp_remain'length);
+ elsif max_write = "010" then
+ tmp_remain := 64 - resize(tmp_address(8 downto 3), tmp_remain'length);
+ elsif max_write = "011" then
+ tmp_remain := 128 - resize(tmp_address(9 downto 3), tmp_remain'length);
+ elsif max_write = "100" then
+ tmp_remain := 256 - resize(tmp_address(10 downto 3), tmp_remain'length);
+ elsif max_write = "101" then
+ tmp_remain := 512 - resize(tmp_address(11 downto 3), tmp_remain'length);
+ end if;
+
+ if tmp_remain > tmp_length then
+ tmp_remain := tmp_length;
+ end if;
+
+ tx_state <= tx_state_write;
+ tx_write <= '1';
+ tx_address <= std_logic_vector(tmp_address);
+ tx_length <= std_logic_vector(tmp_remain);
+
+ debug_write_count <= debug_write_count + 1;
+ debug_write_length <= std_logic_vector(tmp_remain);
+ debug_write_addr <= std_logic_vector(tmp_address);
+ debug_write_data <= rd_data;
+
+ tmp_length := tmp_length - tmp_remain;
+ tmp_address := tmp_address + tmp_remain;
+
+ send_write_length <= tmp_length;
+ send_write_address <= tmp_address;
+ send_write_new <= '0';
+
+ if tmp_length = 0 then
+ send_write <= '0';
+ end if;
+ end if;
+ end if;
+
+ if read_decr = '1' and read_incr = '0' then
+ read_count := read_count - 1;
+ elsif read_decr = '0' and read_incr = '1' then
+ read_count := read_count + 1;
+ end if;
+
+ if tx_accept = '1' then
+ debug_accept_count <= debug_accept_count + 1;
+ end if;
+ if tx_done = '1' then
+ debug_done_count <= debug_done_count + 1;
+ end if;
+
+ for i in 0 to BUFF_COUNT - 1 loop
+ if send_buff(i) = BUFF_DATA and wr_accept(i) = '0' then
+ send_buff(i) <= BUFF_FULL;
+ -- no send_int here
+ end if;
+ if send_buff(i) = BUFF_FULL and wr_accept(i) = '1' then
+ send_buff(i) <= BUFF_EMPTY;
+ send_int <= '1';
+ end if;
+ if recv_buff(i) = BUFF_EMPTY and rd_valid(i) = '1' then
+ recv_buff(i) <= BUFF_FULL;
+ send_int <= '1';
+ end if;
+ if recv_buff(i) = BUFF_DATA and rd_valid(i) = '0' then
+ recv_buff(i) <= BUFF_EMPTY;
+ send_int <= '1';
+ end if;
+
+ if send_buff(i) = BUFF_DATA and send_read_time(i) = timer then
+ -- read timeout
+ wr_cancel(i) <= '1';
+ end if;
+ end loop;
+
+ if send_read = '0' and send_read_done = '0' then
+ for i in 0 to BUFF_COUNT - 1 loop
+ tmp_buff := (send_read_buff + i) mod BUFF_COUNT;
+
+ if send_buff(tmp_buff) = BUFF_ADDR then
+ send_read <= '1';
+ send_read_buff <= tmp_buff;
+ send_read_length <= send_length(tmp_buff);
+ send_read_address <= send_address(tmp_buff);
+ exit;
+ end if;
+ end loop;
+ end if;
+
+ if send_write = '0' and (tx_state /= tx_state_write or tx_done = '1') then
+ for i in 0 to BUFF_COUNT - 1 loop
+ tmp_buff := (send_write_buff + i) mod BUFF_COUNT;
+
+ if recv_buff(tmp_buff) = BUFF_ADDR then
+ recv_buff(tmp_buff) <= BUFF_DATA;
+ send_write <= '1';
+ send_write_new <= '1';
+ send_write_buff <= tmp_buff;
+ rd_buff <= std_logic_vector(to_unsigned(tmp_buff, BUFF_BITS));
+
+ if tmp_buff = 0 then
+ send_write_address <= recv_address0;
+ elsif tmp_buff = 1 then
+ send_write_address <= recv_address1;
+ elsif tmp_buff = 2 then
+ send_write_address <= recv_address2;
+ elsif tmp_buff = 3 then
+ send_write_address <= recv_address3;
+ elsif tmp_buff = 4 then
+ send_write_address <= recv_address4;
+ elsif tmp_buff = 5 then
+ send_write_address <= recv_address5;
+ elsif tmp_buff = 6 then
+ send_write_address <= recv_address6;
+ elsif tmp_buff = 7 then
+ send_write_address <= recv_address7;
+ elsif tmp_buff = 8 then
+ send_write_address <= recv_address8;
+ elsif tmp_buff = 9 then
+ send_write_address <= recv_address9;
+ elsif tmp_buff = 10 then
+ send_write_address <= recv_address10;
+ elsif tmp_buff = 11 then
+ send_write_address <= recv_address11;
+ elsif tmp_buff = 12 then
+ send_write_address <= recv_address12;
+ elsif tmp_buff = 13 then
+ send_write_address <= recv_address13;
+ elsif tmp_buff = 14 then
+ send_write_address <= recv_address14;
+ elsif tmp_buff = 15 then
+ send_write_address <= recv_address15;
+ end if;
+ exit;
+ end if;
+ end loop;
+ end if;
+ end if;
+ end process;
+end arch;
diff --git a/netfpga10g/hdl/eth.vhd b/netfpga10g/hdl/eth.vhd
new file mode 100644
index 0000000..8034ceb
--- /dev/null
+++ b/netfpga10g/hdl/eth.vhd
@@ -0,0 +1,219 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity eth is
+generic (
+ BITS : integer := 14;
+ REVERSE_LANES : std_logic := '0'
+);
+port (
+ clk : in std_logic;
+ reset : in std_logic;
+ clk156_out : out std_logic;
+
+ read : out std_logic;
+ rd_data : in std_logic_vector(63 downto 0);
+ rd_empty : in std_logic;
+ rd_count : in std_logic_vector(BITS downto 0);
+
+ write : out std_logic;
+ wr_data : out std_logic_vector(63 downto 0);
+ wr_full : in std_logic;
+ wr_count : in std_logic_vector(BITS downto 0);
+
+ xaui_clk_p : in std_logic;
+ xaui_clk_n : in std_logic;
+ xaui_dclk : in std_logic;
+ xaui_tx_l0_p : out std_logic;
+ xaui_tx_l0_n : out std_logic;
+ xaui_tx_l1_p : out std_logic;
+ xaui_tx_l1_n : out std_logic;
+ xaui_tx_l2_p : out std_logic;
+ xaui_tx_l2_n : out std_logic;
+ xaui_tx_l3_p : out std_logic;
+ xaui_tx_l3_n : out std_logic;
+ xaui_rx_l0_p : in std_logic;
+ xaui_rx_l0_n : in std_logic;
+ xaui_rx_l1_p : in std_logic;
+ xaui_rx_l1_n : in std_logic;
+ xaui_rx_l2_p : in std_logic;
+ xaui_rx_l2_n : in std_logic;
+ xaui_rx_l3_p : in std_logic;
+ xaui_rx_l3_n : in std_logic
+);
+end eth;
+
+architecture arch of eth is
+ type state_t is (state_idle, state_length, state_data, state_end);
+
+ signal xgmii_txd : std_logic_vector(63 downto 0);
+ signal xgmii_txc : std_logic_vector(7 downto 0);
+ signal xgmii_rxd : std_logic_vector(63 downto 0);
+ signal xgmii_rxc : std_logic_vector(7 downto 0);
+
+ signal clk156 : std_logic;
+
+ signal rx_data : std_logic_vector(63 downto 0);
+ signal rx_start : std_logic;
+ signal rx_end : std_logic;
+ signal rx_rem : integer range 0 to 7;
+
+ signal tx_data : std_logic_vector(63 downto 0);
+ signal tx_start : std_logic;
+ signal tx_end : std_logic;
+ signal tx_rem : integer range 0 to 7;
+begin
+ clk156_out <= clk156;
+
+ -- sending
+ process (clk, reset)
+ variable state : state_t;
+ variable length : unsigned(BITS downto 0);
+ begin
+ if reset = '1' then
+ state := state_idle;
+ read <= '0';
+ tx_data <= (others => '0');
+ tx_start <= '0';
+ tx_end <= '0';
+ tx_rem <= 0;
+
+ elsif rising_edge(clk) then
+ read <= '0';
+ tx_data <= (others => '0');
+ tx_start <= '0';
+ tx_end <= '0';
+ tx_rem <= 0;
+
+ if state = state_idle then
+ if rd_empty = '0' then
+ length := unsigned(rd_data(BITS downto 0)) + 1;
+
+ if length <= unsigned(rd_count) then
+ state := state_data;
+ read <= '1';
+ tx_start <= '1';
+ end if;
+ end if;
+
+ elsif state = state_data then
+ tx_data <= rd_data;
+ length := length - 1;
+
+ if length > 0 then
+ read <= '1';
+ else
+ state := state_end;
+ end if;
+
+ elsif state = state_end then
+ state := state_idle;
+ tx_end <= '1';
+ tx_rem <= 0;
+ end if;
+ end if;
+ end process;
+
+ -- receiving
+ process (clk, reset)
+ variable state : state_t;
+ variable length : unsigned(BITS downto 0);
+ begin
+ if reset = '1' then
+ state := state_idle;
+ write <= '0';
+ wr_data <= (others => '0');
+
+ elsif rising_edge(clk) then
+ write <= '0';
+ wr_data <= (others => '0');
+
+ if state = state_idle then
+ if rx_start = '1' and rx_end = '0' then
+ state := state_length;
+ end if;
+
+ elsif state = state_length then
+ state := state_idle;
+
+ if rx_end = '0' and
+ unsigned(rx_data) <= 511 and
+ 16384 - unsigned(wr_count) >= 512
+ then
+ state := state_data;
+ length := unsigned(rx_data(BITS downto 0)) + 1;
+ end if;
+ end if;
+
+ if state = state_data then
+ write <= '1';
+ wr_data <= rx_data;
+ length := length - 1;
+
+ if length = 0 then
+ state := state_idle;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ xaui : entity work.xaui_top
+ generic map (
+ REVERSE_LANES => REVERSE_LANES
+ )
+ port map (
+ dclk => xaui_dclk,
+ reset => reset,
+ xgmii_txd => xgmii_txd,
+ xgmii_txc => xgmii_txc,
+ xgmii_rxd => xgmii_rxd,
+ xgmii_rxc => xgmii_rxc,
+ clk156_out => clk156,
+ refclk_p => xaui_clk_p,
+ refclk_n => xaui_clk_n,
+ xaui_tx_l0_p => xaui_tx_l0_p,
+ xaui_tx_l0_n => xaui_tx_l0_n,
+ xaui_tx_l1_p => xaui_tx_l1_p,
+ xaui_tx_l1_n => xaui_tx_l1_n,
+ xaui_tx_l2_p => xaui_tx_l2_p,
+ xaui_tx_l2_n => xaui_tx_l2_n,
+ xaui_tx_l3_p => xaui_tx_l3_p,
+ xaui_tx_l3_n => xaui_tx_l3_n,
+ xaui_rx_l0_p => xaui_rx_l0_p,
+ xaui_rx_l0_n => xaui_rx_l0_n,
+ xaui_rx_l1_p => xaui_rx_l1_p,
+ xaui_rx_l1_n => xaui_rx_l1_n,
+ xaui_rx_l2_p => xaui_rx_l2_p,
+ xaui_rx_l2_n => xaui_rx_l2_n,
+ xaui_rx_l3_p => xaui_rx_l3_p,
+ xaui_rx_l3_n => xaui_rx_l3_n
+ );
+
+ rx_eth : entity work.rx_eth port map (
+ clk => clk,
+ reset => reset,
+
+ xgmii_rxd => xgmii_rxd,
+ xgmii_rxc => xgmii_rxc,
+
+ rx_data => rx_data,
+ rx_start => rx_start,
+ rx_end => rx_end,
+ rx_rem => rx_rem
+ );
+
+ tx_eth : entity work.tx_eth port map (
+ clk => clk,
+ reset => reset,
+
+ xgmii_txd => xgmii_txd,
+ xgmii_txc => xgmii_txc,
+
+ tx_data => tx_data,
+ tx_start => tx_start,
+ tx_end => tx_end,
+ tx_rem => tx_rem
+ );
+end arch;
diff --git a/netfpga10g/hdl/eth_rx.vhd b/netfpga10g/hdl/eth_rx.vhd
new file mode 100644
index 0000000..bcd395f
--- /dev/null
+++ b/netfpga10g/hdl/eth_rx.vhd
@@ -0,0 +1,84 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity eth_rx is port (
+ clk : in std_logic;
+
+ wr_en : out std_logic := '0';
+ wr_data : out std_logic_vector (63 downto 0) := (others => '0');
+ wr_done : out std_logic := '0';
+ wr_accept : in std_logic;
+
+ xgmii_rxd : in std_logic_vector(63 downto 0);
+ xgmii_rxc : in std_logic_vector(7 downto 0)
+);
+end eth_rx;
+
+architecture arch of eth_rx is
+ constant IDLE : std_logic_vector(7 downto 0) := x"07";
+ constant START : std_logic_vector(7 downto 0) := x"FB";
+ constant TERMINATE : std_logic_vector(7 downto 0) := x"FD";
+ constant ERR : std_logic_vector(7 downto 0) := x"FE";
+
+ type lanes_t is array (0 to 7) of std_logic_vector(7 downto 0);
+ signal lanes_a : lanes_t;
+ signal lanes_b : lanes_t;
+
+ signal control_a : std_logic_vector(7 downto 0);
+ signal control_b : std_logic_vector(7 downto 0);
+
+ type state_t is (state_idle, state_a, state_b);
+ signal state : state_t := state_idle;
+begin
+ gen_a : for i in 0 to 7 generate
+ lanes_a(i) <= xgmii_rxd(7+8*i downto 8*i);
+ control_a(i) <= xgmii_rxc(i);
+ end generate gen_a;
+
+ lanes_b(4 to 7) <= lanes_a(0 to 3);
+ control_b(7 downto 4) <= control_a(3 downto 0);
+
+ process (clk)
+ begin
+ if rising_edge(clk) then
+ wr_en <= '0';
+ wr_data <= (others => '0');
+ wr_done <= '0';
+
+ lanes_b(0 to 3) <= lanes_a(4 to 7);
+ control_b(3 downto 0) <= control_a(7 downto 4);
+
+ if state = state_idle and wr_accept = '1' then
+ if control_a(0) = '1' and lanes_a(0) = START then
+ state <= state_a;
+ elsif control_b(0) = '1' and lanes_b(0) = START then
+ state <= state_b;
+ end if;
+
+ elsif state = state_a then
+ wr_en <= '1';
+ for i in 0 to 7 loop
+ wr_data(63-8*i downto 56-8*i) <= lanes_a(i);
+
+ if control_a(i) = '1' and (lanes_a(i) = TERMINATE or lanes_a(i) = ERR) then
+ state <= state_idle;
+ wr_done <= '1';
+ end if;
+ end loop;
+
+ elsif state = state_b then
+ wr_en <= '1';
+ for i in 0 to 7 loop
+ wr_data(63-8*i downto 56-8*i) <= lanes_b(i);
+
+ if control_b(i) = '1' and (lanes_b(i) = TERMINATE or lanes_b(i) = ERR) then
+ state <= state_idle;
+ wr_done <= '1';
+ end if;
+ end loop;
+ end if;
+ end if;
+ end process;
+end arch;
diff --git a/netfpga10g/hdl/eth_tx.vhd b/netfpga10g/hdl/eth_tx.vhd
new file mode 100644
index 0000000..cf0081d
--- /dev/null
+++ b/netfpga10g/hdl/eth_tx.vhd
@@ -0,0 +1,68 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity eth_tx is port (
+ clk : in std_logic;
+
+ rd_en : out std_logic;
+ rd_data : in std_logic_vector (63 downto 0);
+ rd_valid : in std_logic;
+
+ xgmii_txd : out std_logic_vector(63 downto 0);
+ xgmii_txc : out std_logic_vector(7 downto 0)
+);
+end eth_tx;
+
+architecture arch of eth_tx is
+ constant IDLE : std_logic_vector(7 downto 0) := x"07";
+ constant START : std_logic_vector(7 downto 0) := x"FB";
+ constant TERMINATE : std_logic_vector(7 downto 0) := x"FD";
+
+ constant PREAMBLE : std_logic_vector(7 downto 0) := "01010101";
+ constant SFD : std_logic_vector(7 downto 0) := "11010101";
+
+ type lanes_t is array (0 to 7) of std_logic_vector(7 downto 0);
+ signal lanes : lanes_t := (others => IDLE);
+ signal control : std_logic_vector(7 downto 0) := (others => '1');
+
+ type state_t is (state_idle, state_data);
+ signal state : state_t := state_idle;
+begin
+ lanes_gen : for i in 0 to 7 generate
+ xgmii_txd(7+8*i downto 8*i) <= lanes(i);
+ xgmii_txc(i) <= control(i);
+ end generate lanes_gen;
+
+ rd_en <= '1' when state = state_data else '0';
+
+ process (clk)
+ begin
+ if rising_edge(clk) then
+ lanes <= (others => IDLE);
+ control <= (others => '1');
+
+ if state = state_idle then
+ if rd_valid = '1' then
+ state <= state_data;
+ lanes(0) <= START;
+ lanes(1 to 6) <= (others => PREAMBLE);
+ lanes(7) <= SFD;
+ control(7 downto 1) <= (others => '0');
+ end if;
+
+ elsif state = state_data then
+ if rd_valid = '1' then
+ for i in 0 to 7 loop
+ lanes(i) <= rd_data(63-8*i downto 56-8*i);
+ control(i) <= '0';
+ end loop;
+ else
+ state <= state_idle;
+ lanes(0) <= TERMINATE;
+ end if;
+ end if;
+ end if;
+ end process;
+end arch;
diff --git a/netfpga10g/hdl/mdio.vhd b/netfpga10g/hdl/mdio.vhd
new file mode 100644
index 0000000..1cb34fa
--- /dev/null
+++ b/netfpga10g/hdl/mdio.vhd
@@ -0,0 +1,223 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity mdio is port (
+ clk125 : in std_logic;
+ reset125 : in std_logic;
+
+ command : in std_logic_vector(0 to 27); -- operation(2) & phyaddr(5) & devaddr(5) & data_in(16)
+ data_out : out std_logic_vector(0 to 15);
+ enable : in std_logic;
+ done : out std_logic;
+
+ mdio_in : in std_logic;
+ mdio_out : out std_logic;
+ mdio_Z : out std_logic;
+ mdc : out std_logic;
+ phy_reset_n : out std_logic;
+
+ total_count : out std_logic_vector(31 downto 0);
+ address_count : out std_logic_vector(31 downto 0);
+ write_count : out std_logic_vector(31 downto 0);
+ read_count : out std_logic_vector(31 downto 0);
+ read_incr_count : out std_logic_vector(31 downto 0)
+);
+end mdio;
+
+architecture arch of mdio is
+ type state_t is (state_idle, state_preamble, state_start, state_operation,
+ state_phyaddr, state_devaddr, state_turnaround, state_data);
+
+ signal state : state_t;
+ signal state_count : natural range 0 to 32;
+
+ signal operation : std_logic_vector(0 to 1);
+ signal phyaddr : std_logic_vector(0 to 4);
+ signal devaddr : std_logic_vector(0 to 4);
+ signal data_in : std_logic_vector(0 to 15);
+
+ signal mdc_count : natural range 0 to 25;
+ signal mdc_i : std_logic;
+
+ signal total_count_i : unsigned(31 downto 0);
+ signal address_count_i : unsigned(31 downto 0);
+ signal write_count_i : unsigned(31 downto 0);
+ signal read_count_i : unsigned(31 downto 0);
+ signal read_incr_count_i : unsigned(31 downto 0);
+
+ signal done_i : std_logic;
+begin
+ phy_reset_n <= not reset125;
+ mdc <= mdc_i;
+
+ operation <= command(0 to 1);
+ phyaddr <= command(2 to 6);
+ devaddr <= command(7 to 11);
+ data_in <= command(12 to 27);
+
+ done <= done_i;
+
+ process (clk125, reset125) begin
+ if reset125 = '1' then
+ mdc_i <= '0';
+ mdc_count <= 0;
+ done_i <= '0';
+
+ elsif rising_edge(clk125) then
+ done_i <= '0';
+
+ if mdc_count = 25 - 1 then
+ mdc_count <= 0;
+ mdc_i <= not mdc_i; -- 2.5 MHz
+
+ if mdc_i = '0' then -- rising edge
+ if state = state_data and state_count = 15 then
+ done_i <= '1';
+ end if;
+ end if;
+ else
+ mdc_count <= mdc_count + 1;
+ end if;
+ end if;
+ end process;
+
+ process (mdc_i, reset125) begin
+ if reset125 = '1' then
+ state <= state_idle;
+ state_count <= 0;
+ data_out <= (others => '0');
+
+ elsif rising_edge(mdc_i) then
+ state_count <= state_count + 1;
+
+ if state = state_preamble then
+ if state_count = 31 then
+ state <= state_start;
+ state_count <= 0;
+ end if;
+ elsif state = state_start then
+ if state_count = 1 then
+ state <= state_operation;
+ state_count <= 0;
+ end if;
+ elsif state = state_operation then
+ if state_count = 1 then
+ state <= state_phyaddr;
+ state_count <= 0;
+ end if;
+ elsif state = state_phyaddr then
+ if state_count = 4 then
+ state <= state_devaddr;
+ state_count <= 0;
+ end if;
+ elsif state = state_devaddr then
+ if state_count = 4 then
+ state <= state_turnaround;
+ state_count <= 0;
+ end if;
+ elsif state = state_turnaround then
+ if state_count = 1 then
+ state <= state_data;
+ state_count <= 0;
+ end if;
+ elsif state = state_data then
+ data_out(state_count) <= mdio_in;
+
+ if state_count = 15 then
+ state <= state_idle;
+ state_count <= 0;
+ end if;
+ else -- state = state_idle
+ if enable = '1' then
+ state <= state_preamble;
+ state_count <= 0;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ process (mdc_i, reset125) begin
+ if reset125 = '1' then
+ mdio_out <= '0';
+ mdio_Z <= '1';
+
+ elsif falling_edge(mdc_i) then
+ mdio_out <= '0';
+ mdio_Z <= '1';
+
+ if state = state_preamble then
+ mdio_out <= '1';
+ mdio_Z <= '0';
+
+ elsif state = state_start then
+ mdio_out <= '0';
+ mdio_Z <= '0';
+
+ elsif state = state_operation then
+ mdio_out <= operation(state_count);
+ mdio_Z <= '0';
+
+ elsif state = state_phyaddr then
+ mdio_out <= phyaddr(state_count);
+ mdio_Z <= '0';
+
+ elsif state = state_devaddr then
+ mdio_out <= devaddr(state_count);
+ mdio_Z <= '0';
+
+ elsif state = state_turnaround then
+ if operation(0) = '0' then -- write or address
+ mdio_Z <= '0';
+
+ if state_count = 0 then
+ mdio_out <= '1';
+ else
+ mdio_out <= '0';
+ end if;
+ end if;
+
+ elsif state = state_data then
+ if operation(0) = '0' then -- write or address
+ mdio_Z <= '0';
+ mdio_out <= data_in(state_count);
+ end if;
+ end if;
+ end if;
+ end process;
+
+ total_count <= std_logic_vector(total_count_i);
+ address_count <= std_logic_vector(address_count_i);
+ write_count <= std_logic_vector(write_count_i);
+ read_count <= std_logic_vector(read_count_i);
+ read_incr_count <= std_logic_vector(read_incr_count_i);
+
+ process (clk125, reset125) begin
+ if reset125 = '1' then
+ total_count_i <= (others => '0');
+ address_count_i <= (others => '0');
+ write_count_i <= (others => '0');
+ read_count_i <= (others => '0');
+ read_incr_count_i <= (others => '0');
+
+ elsif rising_edge(clk125) then
+ if done_i = '1' then
+ total_count_i <= total_count_i + 1;
+
+ if operation = "00" then
+ address_count_i <= address_count_i + 1;
+ end if;
+ if operation = "01" then
+ write_count_i <= write_count_i + 1;
+ end if;
+ if operation = "11" then
+ read_count_i <= read_count_i + 1;
+ end if;
+ if operation = "10" then
+ read_incr_count_i <= read_incr_count_i + 1;
+ end if;
+ end if;
+ end if;
+ end process;
+end arch;
diff --git a/netfpga10g/hdl/pcie.vhd b/netfpga10g/hdl/pcie.vhd
new file mode 100644
index 0000000..6dd99cf
--- /dev/null
+++ b/netfpga10g/hdl/pcie.vhd
@@ -0,0 +1,268 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity pcie is
+generic (
+ BITS : integer := 14
+);
+port (
+ pcie_clk_p : in std_logic;
+ pcie_clk_n : in std_logic;
+ reset25 : in std_logic;
+
+ clk125_out : out std_logic;
+ reset125_out : out std_logic;
+
+ pci_exp_rxn : in std_logic_vector(7 downto 0);
+ pci_exp_rxp : in std_logic_vector(7 downto 0);
+ pci_exp_txn : out std_logic_vector(7 downto 0);
+ pci_exp_txp : out std_logic_vector(7 downto 0);
+
+ port0_read : out std_logic;
+ port0_rd_data : in std_logic_vector(63 downto 0);
+ port0_rd_empty : in std_logic;
+ port0_rd_count : in std_logic_vector(BITS downto 0);
+
+ port0_write : out std_logic;
+ port0_wr_data : out std_logic_vector(63 downto 0);
+ port0_wr_full : in std_logic;
+ port0_wr_count : in std_logic_vector(BITS downto 0);
+
+ port1_read : out std_logic;
+ port1_rd_data : in std_logic_vector(63 downto 0);
+ port1_rd_empty : in std_logic;
+ port1_rd_count : in std_logic_vector(BITS downto 0);
+
+ port1_write : out std_logic;
+ port1_wr_data : out std_logic_vector(63 downto 0);
+ port1_wr_full : in std_logic;
+ port1_wr_count : in std_logic_vector(BITS downto 0);
+
+ port2_read : out std_logic;
+ port2_rd_data : in std_logic_vector(63 downto 0);
+ port2_rd_empty : in std_logic;
+ port2_rd_count : in std_logic_vector(BITS downto 0);
+
+ port2_write : out std_logic;
+ port2_wr_data : out std_logic_vector(63 downto 0);
+ port2_wr_full : in std_logic;
+ port2_wr_count : in std_logic_vector(BITS downto 0);
+
+ port3_read : out std_logic;
+ port3_rd_data : in std_logic_vector(63 downto 0);
+ port3_rd_empty : in std_logic;
+ port3_rd_count : in std_logic_vector(BITS downto 0);
+
+ port3_write : out std_logic;
+ port3_wr_data : out std_logic_vector(63 downto 0);
+ port3_wr_full : in std_logic;
+ port3_wr_count : in std_logic_vector(BITS downto 0);
+
+ mdio_command : out std_logic_vector(0 to 27);
+ mdio_data : in std_logic_vector(0 to 15);
+ mdio_enable : out std_logic;
+ mdio_done : in std_logic;
+
+ leds : out std_logic_vector(2 downto 0)
+);
+end pcie;
+
+architecture arch of pcie is
+ signal clk125 : std_logic;
+ signal reset125 : std_logic;
+
+ signal rx_frame : std_logic_vector(63 downto 0);
+ signal rx_sof : std_logic;
+ signal rx_eof : std_logic;
+ signal rx_valid : std_logic;
+
+ signal rx_read : std_logic;
+ signal rx_write : std_logic;
+ signal rx_complete : std_logic;
+ signal rx_data : std_logic_vector(63 downto 0);
+ signal rx_address : std_logic_vector(28 downto 0);
+
+ signal tx_frame : std_logic_vector(63 downto 0);
+ signal tx_sof : std_logic;
+ signal tx_eof : std_logic;
+ signal tx_half : std_logic;
+ signal tx_valid : std_logic;
+ signal tx_ready : std_logic;
+
+ signal tx_read : std_logic;
+ signal tx_write : std_logic;
+ signal tx_complete : std_logic;
+ signal tx_data : std_logic_vector(63 downto 0);
+ signal tx_address : std_logic_vector(28 downto 0);
+ signal tx_length : std_logic_vector(8 downto 0);
+ signal tx_accept : std_logic;
+ signal tx_done : std_logic;
+
+ signal bus_dev_func : std_logic_vector(15 downto 0);
+ signal transaction_id : std_logic_vector(23 downto 0);
+
+ signal max_read : std_logic_vector(2 downto 0);
+ signal max_write : std_logic_vector(2 downto 0);
+
+ signal interrupt : std_logic;
+ signal interrupt_rdy : std_logic;
+
+ signal bar0 : std_logic;
+begin
+ clk125_out <= clk125;
+ reset125_out <= reset125;
+
+ pcie_wrapper : entity work.pcie_wrapper port map (
+ pcie_clk_p => pcie_clk_p,
+ pcie_clk_n => pcie_clk_n,
+ reset25 => reset25,
+
+ clk125 => clk125,
+ reset125 => reset125,
+
+ pci_exp_rxn => pci_exp_rxn,
+ pci_exp_rxp => pci_exp_rxp,
+ pci_exp_txn => pci_exp_txn,
+ pci_exp_txp => pci_exp_txp,
+
+ rx_frame => rx_frame,
+ rx_sof => rx_sof,
+ rx_eof => rx_eof,
+ rx_valid => rx_valid,
+
+ tx_frame => tx_frame,
+ tx_sof => tx_sof,
+ tx_eof => tx_eof,
+ tx_half => tx_half,
+ tx_valid => tx_valid,
+ tx_ready => tx_ready,
+
+ bus_dev_func => bus_dev_func,
+
+ max_read => max_read,
+ max_write => max_write,
+
+ interrupt => interrupt,
+ interrupt_rdy => interrupt_rdy,
+
+ bar0 => bar0
+ );
+
+ pcie_rx : entity work.pcie_rx port map (
+ clk => clk125,
+ reset => reset125,
+
+ frame => rx_frame,
+ sof => rx_sof,
+ eof => rx_eof,
+ valid => rx_valid,
+
+ read => rx_read,
+ write => rx_write,
+ complete => rx_complete,
+ data => rx_data,
+ address => rx_address,
+
+ transaction_id => transaction_id,
+ bar0 => bar0
+ );
+
+ pcie_tx : entity work.pcie_tx port map (
+ clk => clk125,
+ reset => reset125,
+
+ frame => tx_frame,
+ sof => tx_sof,
+ eof => tx_eof,
+ half => tx_half,
+ valid => tx_valid,
+ ready => tx_ready,
+
+ read => tx_read,
+ write => tx_write,
+ complete => tx_complete,
+ data => tx_data,
+ address => tx_address,
+ length => tx_length,
+ accept => tx_accept,
+ done => tx_done,
+
+ transaction_id => transaction_id,
+ bus_dev_func => bus_dev_func
+ );
+
+ dma : entity work.dma port map (
+ clk => clk125,
+ reset => reset125,
+
+ rx_read => rx_read,
+ rx_write => rx_write,
+ rx_complete => rx_complete,
+ rx_data => rx_data,
+ rx_address => rx_address,
+
+ tx_read => tx_read,
+ tx_write => tx_write,
+ tx_complete => tx_complete,
+ tx_data => tx_data,
+ tx_address => tx_address,
+ tx_length => tx_length,
+ tx_accept => tx_accept,
+ tx_done => tx_done,
+
+ port0_read => port0_read,
+ port0_rd_data => port0_rd_data,
+ port0_rd_empty => port0_rd_empty,
+ port0_rd_count => port0_rd_count,
+
+ port0_write => port0_write,
+ port0_wr_data => port0_wr_data,
+ port0_wr_full => port0_wr_full,
+ port0_wr_count => port0_wr_count,
+
+ port1_read => port1_read,
+ port1_rd_data => port1_rd_data,
+ port1_rd_empty => port1_rd_empty,
+ port1_rd_count => port1_rd_count,
+
+ port1_write => port1_write,
+ port1_wr_data => port1_wr_data,
+ port1_wr_full => port1_wr_full,
+ port1_wr_count => port1_wr_count,
+
+ port2_read => port2_read,
+ port2_rd_data => port2_rd_data,
+ port2_rd_empty => port2_rd_empty,
+ port2_rd_count => port2_rd_count,
+
+ port2_write => port2_write,
+ port2_wr_data => port2_wr_data,
+ port2_wr_full => port2_wr_full,
+ port2_wr_count => port2_wr_count,
+
+ port3_read => port3_read,
+ port3_rd_data => port3_rd_data,
+ port3_rd_empty => port3_rd_empty,
+ port3_rd_count => port3_rd_count,
+
+ port3_write => port3_write,
+ port3_wr_data => port3_wr_data,
+ port3_wr_full => port3_wr_full,
+ port3_wr_count => port3_wr_count,
+
+ max_read => max_read,
+ max_write => max_write,
+
+ interrupt => interrupt,
+ interrupt_rdy => interrupt_rdy,
+
+ mdio_command => mdio_command,
+ mdio_data => mdio_data,
+ mdio_enable => mdio_enable,
+ mdio_done => mdio_done,
+
+ leds => leds
+ );
+end arch;
+
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;
+
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;
+
diff --git a/netfpga10g/hdl/pcie_wrapper.vhd b/netfpga10g/hdl/pcie_wrapper.vhd
new file mode 100644
index 0000000..35c6047
--- /dev/null
+++ b/netfpga10g/hdl/pcie_wrapper.vhd
@@ -0,0 +1,358 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+library unisim;
+use unisim.vcomponents.all;
+
+entity pcie_wrapper is port (
+ pcie_clk_p : in std_logic;
+ pcie_clk_n : in std_logic;
+ reset25 : in std_logic;
+
+ clk125 : out std_logic;
+ reset125 : out std_logic;
+
+ pci_exp_rxn : in std_logic_vector(7 downto 0);
+ pci_exp_rxp : in std_logic_vector(7 downto 0);
+ pci_exp_txn : out std_logic_vector(7 downto 0);
+ pci_exp_txp : out std_logic_vector(7 downto 0);
+
+ rx_frame : out std_logic_vector(63 downto 0);
+ rx_sof : out std_logic;
+ rx_eof : out std_logic;
+ rx_valid : out std_logic;
+
+ tx_frame : in std_logic_vector(63 downto 0);
+ tx_sof : in std_logic;
+ tx_eof : in std_logic;
+ tx_half : in std_logic;
+ tx_valid : in std_logic;
+ tx_ready : out std_logic;
+
+ bus_dev_func : out std_logic_vector(15 downto 0);
+
+ max_read : out std_logic_vector(2 downto 0);
+ max_write : out std_logic_vector(2 downto 0);
+
+ interrupt : in std_logic;
+ interrupt_rdy : out std_logic;
+
+ bar0 : out std_logic
+);
+end pcie_wrapper;
+
+architecture arch of pcie_wrapper is
+
+ component pcie_core port (
+ pci_exp_rxn : in std_logic_vector(7 downto 0);
+ pci_exp_rxp : in std_logic_vector(7 downto 0);
+ pci_exp_txn : out std_logic_vector(7 downto 0);
+ pci_exp_txp : out std_logic_vector(7 downto 0);
+
+ sys_clk : in std_logic;
+ sys_reset_n : in std_logic;
+
+ refclkout : out std_logic;
+
+ trn_clk : out std_logic;
+ trn_reset_n : out std_logic;
+ trn_lnk_up_n : out std_logic;
+
+ trn_rd : out std_logic_vector(63 downto 0);
+ trn_rrem_n : out std_logic_vector(7 downto 0);
+ trn_rsof_n : out std_logic;
+ trn_reof_n : out std_logic;
+ trn_rsrc_dsc_n : out std_logic;
+ trn_rsrc_rdy_n : out std_logic;
+ trn_rbar_hit_n : out std_logic_vector(6 downto 0);
+ trn_rdst_rdy_n : in std_logic;
+ trn_rerrfwd_n : out std_logic;
+ trn_rnp_ok_n : in std_logic;
+ trn_rfc_npd_av : out std_logic_vector(11 downto 0);
+ trn_rfc_nph_av : out std_logic_vector(7 downto 0);
+ trn_rfc_pd_av : out std_logic_vector(11 downto 0);
+ trn_rfc_ph_av : out std_logic_vector(7 downto 0);
+ trn_rcpl_streaming_n : in std_logic;
+
+ trn_td : in std_logic_vector(63 downto 0);
+ trn_trem_n : in std_logic_vector(7 downto 0);
+ trn_tsof_n : in std_logic;
+ trn_teof_n : in std_logic;
+ trn_tsrc_dsc_n : in std_logic;
+ trn_tsrc_rdy_n : in std_logic;
+ trn_tdst_dsc_n : out std_logic;
+ trn_tdst_rdy_n : out std_logic;
+ trn_terrfwd_n : in std_logic ;
+ trn_tbuf_av : out std_logic_vector(3 downto 0);
+
+ cfg_do : out std_logic_vector(31 downto 0);
+ cfg_rd_wr_done_n : out std_logic;
+ cfg_di : in std_logic_vector(31 downto 0);
+ cfg_byte_en_n : in std_logic_vector(3 downto 0);
+ cfg_dwaddr : in std_logic_vector(9 downto 0);
+ cfg_wr_en_n : in std_logic;
+ cfg_rd_en_n : in std_logic;
+
+ cfg_err_cor_n : in std_logic;
+ cfg_err_cpl_abort_n : in std_logic;
+ cfg_err_cpl_timeout_n : in std_logic;
+ cfg_err_cpl_unexpect_n : in std_logic;
+ cfg_err_ecrc_n : in std_logic;
+ cfg_err_posted_n : in std_logic;
+ cfg_err_tlp_cpl_header : in std_logic_vector(47 downto 0);
+ cfg_err_ur_n : in std_logic;
+ cfg_err_cpl_rdy_n : out std_logic;
+ cfg_err_locked_n : in std_logic;
+ cfg_interrupt_n : in std_logic;
+ cfg_interrupt_rdy_n : out std_logic;
+ cfg_pm_wake_n : in std_logic;
+ cfg_pcie_link_state_n : out std_logic_vector(2 downto 0);
+ cfg_to_turnoff_n : out std_logic;
+ cfg_interrupt_assert_n : in std_logic;
+ cfg_interrupt_di : in std_logic_vector(7 downto 0);
+ cfg_interrupt_do : out std_logic_vector(7 downto 0);
+ cfg_interrupt_mmenable : out std_logic_vector(2 downto 0);
+ cfg_interrupt_msienable : out std_logic;
+
+ cfg_trn_pending_n : in std_logic;
+ cfg_bus_number : out std_logic_vector(7 downto 0);
+ cfg_device_number : out std_logic_vector(4 downto 0);
+ cfg_function_number : out std_logic_vector(2 downto 0);
+ cfg_status : out std_logic_vector(15 downto 0);
+ cfg_command : out std_logic_vector(15 downto 0);
+ cfg_dstatus : out std_logic_vector(15 downto 0);
+ cfg_dcommand : out std_logic_vector(15 downto 0);
+ cfg_lstatus : out std_logic_vector(15 downto 0);
+ cfg_lcommand : out std_logic_vector(15 downto 0);
+ cfg_dsn : in std_logic_vector(63 downto 0);
+
+ fast_train_simulation_only : in std_logic
+ );
+ end component;
+
+ signal sys_reset_n : std_logic;
+
+ signal trn_clk : std_logic;
+ signal trn_reset_n : std_logic;
+ signal trn_lnk_up_n : std_logic;
+
+ signal trn_rd : std_logic_vector(63 downto 0);
+ signal trn_rrem_n : std_logic_vector(7 downto 0);
+ signal trn_rsof_n : std_logic;
+ signal trn_reof_n : std_logic;
+ signal trn_rsrc_dsc_n : std_logic;
+ signal trn_rsrc_rdy_n : std_logic;
+ signal trn_rbar_hit_n : std_logic_vector(6 downto 0);
+ signal trn_rdst_rdy_n : std_logic;
+ signal trn_rerrfwd_n : std_logic;
+ signal trn_rnp_ok_n : std_logic;
+ signal trn_rfc_npd_av : std_logic_vector(11 downto 0);
+ signal trn_rfc_nph_av : std_logic_vector(7 downto 0);
+ signal trn_rfc_pd_av : std_logic_vector(11 downto 0);
+ signal trn_rfc_ph_av : std_logic_vector(7 downto 0);
+ signal trn_rcpl_streaming_n : std_logic;
+
+ signal trn_td : std_logic_vector(63 downto 0);
+ signal trn_trem_n : std_logic_vector(7 downto 0);
+ signal trn_tsof_n : std_logic;
+ signal trn_teof_n : std_logic;
+ signal trn_tsrc_dsc_n : std_logic;
+ signal trn_tsrc_rdy_n : std_logic;
+ signal trn_tdst_dsc_n : std_logic;
+ signal trn_tdst_rdy_n : std_logic;
+ signal trn_terrfwd_n : std_logic;
+ signal trn_tbuf_av : std_logic_vector(3 downto 0);
+
+ signal cfg_do : std_logic_vector(31 downto 0);
+ signal cfg_rd_wr_done_n : std_logic;
+ signal cfg_di : std_logic_vector(31 downto 0);
+ signal cfg_byte_en_n : std_logic_vector(3 downto 0);
+ signal cfg_dwaddr : std_logic_vector(9 downto 0);
+ signal cfg_wr_en_n : std_logic;
+ signal cfg_rd_en_n : std_logic;
+
+ signal cfg_err_cor_n : std_logic;
+ signal cfg_err_cpl_abort_n : std_logic;
+ signal cfg_err_cpl_timeout_n : std_logic;
+ signal cfg_err_cpl_unexpect_n : std_logic;
+ signal cfg_err_ecrc_n : std_logic;
+ signal cfg_err_posted_n : std_logic;
+ signal cfg_err_tlp_cpl_header : std_logic_vector(47 downto 0);
+ signal cfg_err_ur_n : std_logic;
+ signal cfg_err_cpl_rdy_n : std_logic;
+ signal cfg_err_locked_n : std_logic;
+ signal cfg_interrupt_n : std_logic;
+ signal cfg_interrupt_rdy_n : std_logic;
+ signal cfg_pm_wake_n : std_logic;
+ signal cfg_pcie_link_state_n : std_logic_vector(2 downto 0);
+ signal cfg_to_turnoff_n : std_logic;
+ signal cfg_interrupt_assert_n : std_logic;
+ signal cfg_interrupt_di : std_logic_vector(7 downto 0);
+ signal cfg_interrupt_do : std_logic_vector(7 downto 0);
+ signal cfg_interrupt_mmenable : std_logic_vector(2 downto 0);
+ signal cfg_interrupt_msienable : std_logic;
+
+ signal cfg_trn_pending_n : std_logic;
+ signal cfg_bus_number : std_logic_vector(7 downto 0);
+ signal cfg_device_number : std_logic_vector(4 downto 0);
+ signal cfg_function_number : std_logic_vector(2 downto 0);
+ signal cfg_status : std_logic_vector(15 downto 0);
+ signal cfg_command : std_logic_vector(15 downto 0);
+ signal cfg_dstatus : std_logic_vector(15 downto 0);
+ signal cfg_dcommand : std_logic_vector(15 downto 0);
+ signal cfg_lstatus : std_logic_vector(15 downto 0);
+ signal cfg_lcommand : std_logic_vector(15 downto 0);
+ signal cfg_dsn : std_logic_vector(63 downto 0);
+
+ signal pcie_clk : std_logic;
+begin
+ pcie_clk_ibuf : IBUFDS port map (
+ O => pcie_clk,
+ I => pcie_clk_p,
+ IB => pcie_clk_n
+ );
+
+ sys_reset_n <= not reset25;
+
+ trn_rdst_rdy_n <= '0';
+ trn_rnp_ok_n <= '0';
+ trn_rcpl_streaming_n <= '1';
+
+ trn_tsrc_dsc_n <= '1';
+ trn_terrfwd_n <= '1';
+
+ cfg_di <= (others => '0');
+ cfg_byte_en_n <= (others => '1');
+ cfg_dwaddr <= (others => '0');
+ cfg_wr_en_n <= '1';
+ cfg_rd_en_n <= '1';
+
+ cfg_err_cor_n <= '1';
+ cfg_err_cpl_abort_n <= '1';
+ cfg_err_cpl_timeout_n <= '1';
+ cfg_err_cpl_unexpect_n <= '1';
+ cfg_err_ecrc_n <= '1';
+ cfg_err_posted_n <= '1';
+ cfg_err_tlp_cpl_header <= (others => '0');
+ cfg_err_ur_n <= '1';
+ cfg_err_locked_n <= '1';
+ cfg_interrupt_n <= not interrupt;
+ cfg_pm_wake_n <= '1';
+ cfg_interrupt_assert_n <= '1';
+ cfg_interrupt_di <= (others => '0');
+ interrupt_rdy <= not cfg_interrupt_rdy_n;
+
+ cfg_trn_pending_n <= '1';
+ cfg_dsn <= (others => '0');
+
+ ep : pcie_core port map (
+ pci_exp_rxn => pci_exp_rxn,
+ pci_exp_rxp => pci_exp_rxp,
+ pci_exp_txn => pci_exp_txn,
+ pci_exp_txp => pci_exp_txp,
+
+ sys_clk => pcie_clk,
+ sys_reset_n => sys_reset_n,
+
+ refclkout => open,
+
+ trn_clk => trn_clk,
+ trn_reset_n => trn_reset_n,
+ trn_lnk_up_n => trn_lnk_up_n,
+
+ trn_rd => trn_rd,
+ trn_rrem_n => trn_rrem_n,
+ trn_rsof_n => trn_rsof_n,
+ trn_reof_n => trn_reof_n,
+ trn_rsrc_dsc_n => trn_rsrc_dsc_n,
+ trn_rsrc_rdy_n => trn_rsrc_rdy_n,
+ trn_rbar_hit_n => trn_rbar_hit_n,
+ trn_rdst_rdy_n => trn_rdst_rdy_n,
+ trn_rerrfwd_n => trn_rerrfwd_n,
+ trn_rnp_ok_n => trn_rnp_ok_n,
+ trn_rfc_npd_av => trn_rfc_npd_av,
+ trn_rfc_nph_av => trn_rfc_nph_av,
+ trn_rfc_pd_av => trn_rfc_pd_av,
+ trn_rfc_ph_av => trn_rfc_ph_av,
+ trn_rcpl_streaming_n => trn_rcpl_streaming_n,
+
+ trn_td => trn_td,
+ trn_trem_n => trn_trem_n,
+ trn_tsof_n => trn_tsof_n,
+ trn_teof_n => trn_teof_n,
+ trn_tsrc_dsc_n => trn_tsrc_dsc_n,
+ trn_tsrc_rdy_n => trn_tsrc_rdy_n,
+ trn_tdst_dsc_n => trn_tdst_dsc_n,
+ trn_tdst_rdy_n => trn_tdst_rdy_n,
+ trn_terrfwd_n => trn_terrfwd_n,
+ trn_tbuf_av => trn_tbuf_av,
+
+ cfg_do => cfg_do,
+ cfg_rd_wr_done_n => cfg_rd_wr_done_n,
+ cfg_di => cfg_di,
+ cfg_byte_en_n => cfg_byte_en_n,
+ cfg_dwaddr => cfg_dwaddr,
+ cfg_wr_en_n => cfg_wr_en_n,
+ cfg_rd_en_n => cfg_rd_en_n,
+
+ cfg_err_cor_n => cfg_err_cor_n,
+ cfg_err_cpl_abort_n => cfg_err_cpl_abort_n,
+ cfg_err_cpl_timeout_n => cfg_err_cpl_timeout_n,
+ cfg_err_cpl_unexpect_n => cfg_err_cpl_unexpect_n,
+ cfg_err_ecrc_n => cfg_err_ecrc_n,
+ cfg_err_posted_n => cfg_err_posted_n,
+ cfg_err_tlp_cpl_header => cfg_err_tlp_cpl_header,
+ cfg_err_ur_n => cfg_err_ur_n,
+ cfg_err_cpl_rdy_n => cfg_err_cpl_rdy_n,
+ cfg_err_locked_n => cfg_err_locked_n,
+ cfg_interrupt_n => cfg_interrupt_n,
+ cfg_interrupt_rdy_n => cfg_interrupt_rdy_n,
+ cfg_pm_wake_n => cfg_pm_wake_n,
+ cfg_pcie_link_state_n => cfg_pcie_link_state_n,
+ cfg_to_turnoff_n => cfg_to_turnoff_n,
+ cfg_interrupt_assert_n => cfg_interrupt_assert_n,
+ cfg_interrupt_di => cfg_interrupt_di,
+ cfg_interrupt_do => cfg_interrupt_do,
+ cfg_interrupt_mmenable => cfg_interrupt_mmenable,
+ cfg_interrupt_msienable => cfg_interrupt_msienable,
+
+ cfg_trn_pending_n => cfg_trn_pending_n,
+ cfg_bus_number => cfg_bus_number,
+ cfg_device_number => cfg_device_number,
+ cfg_function_number => cfg_function_number,
+ cfg_status => cfg_status,
+ cfg_command => cfg_command,
+ cfg_dstatus => cfg_dstatus,
+ cfg_dcommand => cfg_dcommand,
+ cfg_lstatus => cfg_lstatus,
+ cfg_lcommand => cfg_lcommand,
+ cfg_dsn => cfg_dsn,
+
+ fast_train_simulation_only => '0'
+ );
+
+ clk125 <= trn_clk;
+ reset125 <= not trn_reset_n;
+
+ rx_frame <= trn_rd;
+ rx_sof <= not trn_rsof_n;
+ rx_eof <= not trn_reof_n;
+ rx_valid <= not trn_rsrc_rdy_n;
+
+ trn_td <= tx_frame;
+ trn_tsof_n <= not tx_sof;
+ trn_teof_n <= not tx_eof;
+ trn_tsrc_rdy_n <= not tx_valid;
+ trn_trem_n <= x"0F" when tx_half = '1' else x"00";
+
+ tx_ready <= not trn_tdst_rdy_n;
+
+ bus_dev_func <= cfg_bus_number & cfg_device_number & cfg_function_number;
+
+ max_read <= cfg_dcommand(14 downto 12);
+ max_write <= cfg_dcommand(7 downto 5);
+
+ bar0 <= not trn_rbar_hit_n(0);
+end arch;
+
diff --git a/netfpga10g/hdl/port_fifo.vhd b/netfpga10g/hdl/port_fifo.vhd
new file mode 100644
index 0000000..ff8c93a
--- /dev/null
+++ b/netfpga10g/hdl/port_fifo.vhd
@@ -0,0 +1,94 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity port_fifo is
+generic (
+ BITS : integer := 14
+);
+port (
+ reset : in std_logic;
+
+ rd_clk : in std_logic;
+ rd_read : in std_logic;
+ rd_data : out std_logic_vector(63 downto 0);
+ rd_empty : out std_logic;
+ rd_count : out std_logic_vector(BITS downto 0);
+
+ wr_clk : in std_logic;
+ wr_write : in std_logic;
+ wr_data : in std_logic_vector(63 downto 0);
+ wr_full : out std_logic;
+ wr_count : out std_logic_vector(BITS downto 0)
+);
+end port_fifo;
+
+architecture arch of port_fifo is
+
+ component data_fifo port (
+ rst : in std_logic;
+ rd_clk : in std_logic;
+ rd_en : in std_logic;
+ dout : out std_logic_vector(63 downto 0);
+ empty : out std_logic;
+ rd_data_count : out std_logic_vector(BITS downto 0);
+ wr_clk : in std_logic;
+ wr_en : in std_logic;
+ din : in std_logic_vector(63 downto 0);
+ full : out std_logic;
+ wr_data_count : out std_logic_vector(BITS downto 0)
+ );
+ end component;
+
+ signal raw_read : std_logic;
+ signal raw_data : std_logic_vector(63 downto 0);
+ signal raw_empty : std_logic;
+ signal raw_count : std_logic_vector(BITS downto 0);
+
+ signal has_extra : std_logic;
+ signal extra : std_logic_vector(63 downto 0);
+begin
+ rd_data <= extra when has_extra = '1' and rd_read = '0' else raw_data;
+ rd_empty <= '0' when has_extra = '1' and rd_read = '0' else '1';
+ rd_count <= std_logic_vector(unsigned(raw_count) + 1) when has_extra = '1' and rd_read = '0' else raw_count;
+
+ raw_read <= '0' when has_extra = '1' and rd_read = '0' else '1';
+
+ process (rd_clk, reset)
+ begin
+ if reset = '1' then
+ has_extra <= '0';
+ extra <= (others => '0');
+
+ elsif rising_edge(rd_clk) then
+ if has_extra = '1' then
+ if rd_read = '1' then
+ has_extra <= not raw_empty;
+ extra <= raw_data;
+ end if;
+ else
+ if rd_read = '0' then
+ has_extra <= not raw_empty;
+ extra <= raw_data;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ fifo : data_fifo port map (
+ rst => reset,
+
+ rd_clk => rd_clk,
+ rd_en => raw_read,
+ dout => raw_data,
+ empty => raw_empty,
+ rd_data_count => raw_count,
+
+ wr_clk => wr_clk,
+ wr_en => wr_write,
+ din => wr_data,
+ full => wr_full,
+ wr_data_count => wr_count
+ );
+end arch;
diff --git a/netfpga10g/hdl/recv_mux.vhd b/netfpga10g/hdl/recv_mux.vhd
new file mode 100644
index 0000000..42932af
--- /dev/null
+++ b/netfpga10g/hdl/recv_mux.vhd
@@ -0,0 +1,86 @@
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.NUMERIC_STD.ALL;
+
+entity recv_mux is
+generic (
+ BUFF_COUNT : integer := 16;
+ BUFF_BITS : integer := 4 -- 2^4 = 16
+);
+port (
+ rd_clk : in std_logic;
+ rd_buff : in std_logic_vector (BUFF_BITS - 1 downto 0);
+ rd_en : in std_logic;
+ rd_data : out std_logic_vector (63 downto 0) := (others => '0');
+ rd_length : out std_logic_vector (8 downto 0) := (others => '0');
+ rd_valid : out std_logic_vector (BUFF_COUNT - 1 downto 0) := (others => '0');
+
+ wr_clk : in std_logic;
+ wr_en : in std_logic;
+ wr_data : in std_logic_vector (63 downto 0);
+ wr_done : in std_logic;
+ wr_accept : out std_logic := '0'
+);
+end recv_mux;
+
+architecture arch of recv_mux is
+ type rd_data_t is array (0 to BUFF_COUNT - 1) of std_logic_vector(63 downto 0);
+ type rd_length_t is array (0 to BUFF_COUNT - 1) of std_logic_vector(8 downto 0);
+
+ signal wr_en_i : std_logic_vector(BUFF_COUNT - 1 downto 0) := (others => '0');
+ signal wr_done_i : std_logic_vector(BUFF_COUNT - 1 downto 0) := (others => '0');
+ signal wr_accept_i : std_logic_vector(BUFF_COUNT - 1 downto 0) := (others => '0');
+ signal wr_buff : integer range 0 to BUFF_COUNT - 1 := 0;
+
+ signal rd_en_i : std_logic_vector(BUFF_COUNT - 1 downto 0) := (others => '0');
+ signal rd_data_i : rd_data_t := (others => (others => '0'));
+ signal rd_length_i : rd_length_t := (others => (others => '0'));
+ signal rd_buff_i : integer range 0 to BUFF_COUNT - 1 := 0;
+begin
+ rd_buff_i <= to_integer(unsigned(rd_buff));
+
+ recv_gen: for i in 0 to BUFF_COUNT - 1 generate
+ recv_buff : entity work.buff port map (
+ wr_clk => wr_clk,
+ wr_en => wr_en_i(i),
+ wr_data => wr_data,
+ wr_done => wr_done_i(i),
+ wr_accept => wr_accept_i(i),
+
+ rd_clk => rd_clk,
+ rd_en => rd_en_i(i),
+ rd_data => rd_data_i(i),
+ rd_length => rd_length_i(i),
+ rd_valid => rd_valid(i)
+ );
+
+ wr_en_i(i) <= wr_en when wr_buff = i else '0';
+ wr_done_i(i) <= wr_done when wr_buff = i else '0';
+
+ rd_en_i(i) <= rd_en when rd_buff_i = i else '0';
+ end generate recv_gen;
+
+ rd_data <= rd_data_i(rd_buff_i);
+ rd_length <= rd_length_i(rd_buff_i);
+
+ wr_accept <= wr_accept_i(wr_buff);
+
+ process (wr_clk)
+ variable tmp_buff : integer range 0 to BUFF_COUNT - 1;
+ begin
+ if rising_edge(wr_clk) then
+ if wr_accept_i(wr_buff) = '0' then
+ for i in 0 to BUFF_COUNT - 1 loop
+ tmp_buff := (i + wr_buff) mod BUFF_COUNT;
+
+ if wr_accept_i(tmp_buff) = '1' then
+ wr_buff <= tmp_buff;
+ exit;
+ end if;
+ end loop;
+ end if;
+ end if;
+ end process;
+end arch;
+
diff --git a/netfpga10g/hdl/rx_eth.vhd b/netfpga10g/hdl/rx_eth.vhd
new file mode 100644
index 0000000..fe6e65e
--- /dev/null
+++ b/netfpga10g/hdl/rx_eth.vhd
@@ -0,0 +1,168 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity rx_eth is port (
+ clk : in std_logic;
+ reset : in std_logic;
+
+ xgmii_rxd : in std_logic_vector(63 downto 0);
+ xgmii_rxc : in std_logic_vector(7 downto 0);
+
+ rx_data : out std_logic_vector(63 downto 0);
+ rx_start : out std_logic;
+ rx_end : out std_logic;
+ rx_rem : out integer range 0 to 7;
+
+ start_count_out : out std_logic_vector(31 downto 0);
+ end_count_out : out std_logic_vector(31 downto 0)
+);
+end rx_eth;
+
+architecture arch of rx_eth is
+ constant IDLE : std_logic_vector(7 downto 0) := x"07";
+ constant START : std_logic_vector(7 downto 0) := x"FB";
+ constant TERMINATE : std_logic_vector(7 downto 0) := x"FD";
+ constant ERR : std_logic_vector(7 downto 0) := x"FE";
+
+ constant PREAMBLE : std_logic_vector(7 downto 0) := "01010101";
+ constant SFD : std_logic_vector(7 downto 0) := "11010101";
+
+ type lanes_t is array (0 to 7) of std_logic_vector(7 downto 0);
+ signal lanes_a : lanes_t;
+ signal lanes_b : lanes_t;
+
+ signal control_a : std_logic_vector(7 downto 0);
+ signal control_b : std_logic_vector(7 downto 0);
+
+ signal use_a : std_logic;
+
+ signal start_count : unsigned(31 downto 0);
+ signal end_count : unsigned(31 downto 0);
+begin
+ start_count_out <= std_logic_vector(start_count);
+ end_count_out <= std_logic_vector(end_count);
+
+ rx_lanes_gen : for i in 0 to 7 generate
+ lanes_a(i) <= xgmii_rxd(7+8*i downto 8*i);
+ end generate rx_lanes_gen;
+
+ control_a <= xgmii_rxc;
+ lanes_b(4) <= lanes_a(0);
+ lanes_b(5) <= lanes_a(1);
+ lanes_b(6) <= lanes_a(2);
+ lanes_b(7) <= lanes_a(3);
+ control_b(4) <= control_a(0);
+ control_b(5) <= control_a(1);
+ control_b(6) <= control_a(2);
+ control_b(7) <= control_a(3);
+
+ rx_logic : process (clk, reset) begin
+ if reset = '1' then
+ rx_data <= (others => '0');
+ rx_start <= '0';
+ rx_end <= '0';
+ rx_rem <= 0;
+ start_count <= (others => '0');
+ end_count <= (others => '0');
+ lanes_b(0) <= (others => '0');
+ lanes_b(1) <= (others => '0');
+ lanes_b(2) <= (others => '0');
+ lanes_b(3) <= (others => '0');
+ control_b(3 downto 0) <= (others => '0');
+ use_a <= '1';
+
+ elsif rising_edge(clk) then
+ rx_start <= '0';
+ rx_end <= '0';
+ rx_rem <= 0;
+
+ lanes_b(0) <= lanes_a(4);
+ lanes_b(1) <= lanes_a(5);
+ lanes_b(2) <= lanes_a(6);
+ lanes_b(3) <= lanes_a(7);
+ control_b(3 downto 0) <= control_a(7 downto 4);
+
+ for i in 0 to 7 loop
+ if use_a = '1' then
+ rx_data(63-8*i downto 56-8*i) <= lanes_a(i);
+ else
+ rx_data(63-8*i downto 56-8*i) <= lanes_b(i);
+ end if;
+ end loop;
+
+ if control_a(0) = '1' and lanes_a(0) = START then
+ rx_start <= '1';
+ use_a <= '1';
+ elsif control_b(0) = '1' and lanes_b(0) = START then
+ rx_start <= '1';
+ use_a <= '0';
+ start_count <= start_count + 1;
+ end if;
+
+ if use_a = '1' then
+ if control_a(0) = '1' and (lanes_a(0) = TERMINATE or lanes_a(0) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 0;
+ elsif control_a(1) = '1' and (lanes_a(1) = TERMINATE or lanes_a(1) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 1;
+ elsif control_a(2) = '1' and (lanes_a(2) = TERMINATE or lanes_a(2) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 2;
+ elsif control_a(3) = '1' and (lanes_a(3) = TERMINATE or lanes_a(3) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 3;
+ elsif control_a(4) = '1' and (lanes_a(4) = TERMINATE or lanes_a(4) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 4;
+ elsif control_a(5) = '1' and (lanes_a(5) = TERMINATE or lanes_a(5) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 5;
+ elsif control_a(6) = '1' and (lanes_a(6) = TERMINATE or lanes_a(6) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 6;
+ elsif control_a(7) = '1' and (lanes_a(7) = TERMINATE or lanes_a(7) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 7;
+ end if;
+ else
+ if control_b(0) = '1' and (lanes_b(0) = TERMINATE or lanes_b(0) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 0;
+ end_count <= end_count + 1;
+ elsif control_b(1) = '1' and (lanes_b(1) = TERMINATE or lanes_b(1) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 1;
+ end_count <= end_count + 1;
+ elsif control_b(2) = '1' and (lanes_b(2) = TERMINATE or lanes_b(2) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 2;
+ end_count <= end_count + 1;
+ elsif control_b(3) = '1' and (lanes_b(3) = TERMINATE or lanes_b(3) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 3;
+ end_count <= end_count + 1;
+ elsif control_b(4) = '1' and (lanes_b(4) = TERMINATE or lanes_b(4) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 4;
+ end_count <= end_count + 1;
+ elsif control_b(5) = '1' and (lanes_b(5) = TERMINATE or lanes_b(5) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 5;
+ end_count <= end_count + 1;
+ elsif control_b(6) = '1' and (lanes_b(6) = TERMINATE or lanes_b(6) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 6;
+ end_count <= end_count + 1;
+ elsif control_b(7) = '1' and (lanes_b(7) = TERMINATE or lanes_b(7) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 7;
+ end_count <= end_count + 1;
+ end if;
+ end if;
+ end if;
+ end process;
+end arch;
+
diff --git a/netfpga10g/hdl/send_mux.vhd b/netfpga10g/hdl/send_mux.vhd
new file mode 100644
index 0000000..8d9f667
--- /dev/null
+++ b/netfpga10g/hdl/send_mux.vhd
@@ -0,0 +1,77 @@
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.NUMERIC_STD.ALL;
+
+entity send_mux is
+generic (
+ BUFF_COUNT : integer := 16;
+ BUFF_BITS : integer := 4 -- 2^4 = 16
+);
+ Port ( wr_clk : in STD_LOGIC;
+ wr_buff : in STD_LOGIC_VECTOR (BUFF_BITS - 1 downto 0);
+ wr_en : in STD_LOGIC;
+ wr_data : in STD_LOGIC_VECTOR (63 downto 0);
+ wr_done : in STD_LOGIC;
+ wr_cancel : in STD_LOGIC_VECTOR (BUFF_COUNT - 1 downto 0);
+ wr_accept : out STD_LOGIC_VECTOR (BUFF_COUNT - 1 downto 0) := (others => '0');
+ rd_clk : in STD_LOGIC;
+ rd_en : in STD_LOGIC;
+ rd_data : out STD_LOGIC_VECTOR (63 downto 0) := (others => '0');
+ rd_valid : out STD_LOGIC := '0');
+end send_mux;
+
+architecture arch of send_mux is
+ type rd_data_t is array (0 to BUFF_COUNT - 1) of std_logic_vector(63 downto 0);
+
+ signal wr_en_i : std_logic_vector(BUFF_COUNT - 1 downto 0) := (others => '0');
+ signal wr_done_i : std_logic_vector(BUFF_COUNT - 1 downto 0) := (others => '0');
+
+ signal rd_en_i : std_logic_vector(BUFF_COUNT - 1 downto 0) := (others => '0');
+ signal rd_data_i : rd_data_t := (others => (others => '0'));
+ signal rd_valid_i : std_logic_vector(BUFF_COUNT - 1 downto 0) := (others => '0');
+ signal rd_buff : integer range 0 to BUFF_COUNT - 1 := 0;
+begin
+ send_gen: for i in 0 to BUFF_COUNT - 1 generate
+ send_buff : entity work.buff port map (
+ wr_clk => wr_clk,
+ wr_en => wr_en_i(i),
+ wr_data => wr_data,
+ wr_done => wr_done_i(i),
+ wr_cancel => wr_cancel(i),
+ wr_accept => wr_accept(i),
+
+ rd_clk => rd_clk,
+ rd_en => rd_en_i(i),
+ rd_data => rd_data_i(i),
+ rd_length => open,
+ rd_valid => rd_valid_i(i)
+ );
+
+ wr_en_i(i) <= wr_en when to_integer(unsigned(wr_buff)) = i else '0';
+ wr_done_i(i) <= wr_done when to_integer(unsigned(wr_buff)) = i else '0';
+
+ rd_en_i(i) <= rd_en when rd_buff = i else '0';
+ end generate send_gen;
+
+ rd_data <= rd_data_i(rd_buff);
+ rd_valid <= rd_valid_i(rd_buff);
+
+ process (rd_clk)
+ variable tmp_buff : integer range 0 to BUFF_COUNT - 1;
+ begin
+ if rising_edge(rd_clk) then
+ if rd_valid_i(rd_buff) = '0' then
+ for i in 0 to BUFF_COUNT - 1 loop
+ tmp_buff := (i + rd_buff) mod BUFF_COUNT;
+
+ if rd_valid_i(tmp_buff) = '1' then
+ rd_buff <= tmp_buff;
+ exit;
+ end if;
+ end loop;
+ end if;
+ end if;
+ end process;
+end arch;
+
diff --git a/netfpga10g/hdl/system_loop.vhd b/netfpga10g/hdl/system_loop.vhd
new file mode 100644
index 0000000..79031c3
--- /dev/null
+++ b/netfpga10g/hdl/system_loop.vhd
@@ -0,0 +1,253 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+library unisim;
+use unisim.vcomponents.all;
+
+entity system_loop is
+generic (
+ BUFF_COUNT : integer := 16;
+ BUFF_BITS : integer := 4 -- 2^4 = 16
+);
+port (
+ eth_clk : in std_logic;
+ pcie_clk : in std_logic;
+
+ rx_frame : in std_logic_vector(63 downto 0);
+ rx_sof : in std_logic;
+ rx_eof : in std_logic;
+ rx_valid : in std_logic;
+ rx_bar0 : in std_logic;
+
+ tx_frame : out std_logic_vector(63 downto 0);
+ tx_sof : out std_logic;
+ tx_eof : out std_logic;
+ tx_half : out std_logic;
+ tx_valid : out std_logic;
+ tx_ready : in std_logic;
+
+ interrupt : out std_logic;
+ interrupt_rdy : in std_logic;
+
+ max_read : in std_logic_vector(2 downto 0);
+ max_write : in std_logic_vector(2 downto 0);
+
+ local : in std_logic_vector(15 downto 0);
+
+ xgmii_rxd : in std_logic_vector(63 downto 0);
+ xgmii_rxc : in std_logic_vector(7 downto 0);
+
+ xgmii_txd : out std_logic_vector(63 downto 0);
+ xgmii_txc : out std_logic_vector(7 downto 0);
+
+ mdio_command : out std_logic_vector(0 to 27);
+ mdio_data : in std_logic_vector(0 to 15);
+ mdio_enable : out std_logic;
+ mdio_done : in std_logic
+);
+end system_loop;
+
+architecture arch of system_loop is
+ -- send mux
+ signal send_rd_en : std_logic;
+ signal send_rd_data : std_logic_vector (63 downto 0);
+ signal send_rd_valid : std_logic;
+
+ signal send_wr_buff : std_logic_vector (BUFF_BITS - 1 downto 0) := (others => '0');
+ signal send_wr_en : std_logic := '0';
+ signal send_wr_data : std_logic_vector (63 downto 0) := (others => '0');
+ signal send_wr_done : std_logic := '0';
+ signal send_wr_cancel : std_logic_vector (BUFF_COUNT - 1 downto 0);
+ signal send_wr_accept : std_logic_vector (BUFF_COUNT - 1 downto 0);
+
+ -- recv mux
+ signal recv_wr_en : std_logic;
+ signal recv_wr_data : std_logic_vector (63 downto 0);
+ signal recv_wr_done : std_logic;
+ signal recv_wr_accept : std_logic;
+
+ signal recv_rd_buff : std_logic_vector (BUFF_BITS - 1 downto 0) := (others => '0');
+ signal recv_rd_en : std_logic := '0';
+ signal recv_rd_data : std_logic_vector (63 downto 0);
+ signal recv_rd_length : std_logic_vector (8 downto 0);
+ signal recv_rd_valid : std_logic_vector (BUFF_COUNT - 1 downto 0);
+
+ -- pcie_rx
+ signal rx_read : std_logic;
+ signal rx_write : std_logic;
+ signal rx_complete : std_logic;
+ signal rx_data : std_logic_vector(63 downto 0);
+ signal rx_address : std_logic_vector(63 downto 3);
+ signal rx_tag : std_logic_vector(4 downto 0);
+
+ signal remote : std_logic_vector(23 downto 0);
+
+ -- pcie_tx
+ signal tx_read : std_logic;
+ signal tx_write : std_logic;
+ signal tx_complete : std_logic;
+ signal tx_data : std_logic_vector(63 downto 0);
+ signal tx_address : std_logic_vector(63 downto 3);
+ signal tx_length : std_logic_vector(8 downto 0);
+ signal tx_tag : std_logic_vector(4 downto 0);
+ signal tx_accept : std_logic;
+ signal tx_done : std_logic;
+begin
+ eth_rx : entity work.eth_rx port map (
+ clk => eth_clk,
+
+ wr_en => recv_wr_en,
+ wr_data => recv_wr_data,
+ wr_done => recv_wr_done,
+ wr_accept => recv_wr_accept,
+
+ xgmii_rxd => xgmii_rxd,
+ xgmii_rxc => xgmii_rxc
+ );
+
+ eth_tx : entity work.eth_tx port map (
+ clk => eth_clk,
+
+ rd_en => send_rd_en,
+ rd_data => send_rd_data,
+ rd_valid => send_rd_valid,
+
+ xgmii_txd => xgmii_txd,
+ xgmii_txc => xgmii_txc
+ );
+
+ send_mux : entity work.send_mux
+ generic map (
+ BUFF_COUNT => BUFF_COUNT,
+ BUFF_BITS => BUFF_BITS
+ )
+ port map (
+ wr_clk => pcie_clk,
+ wr_buff => send_wr_buff,
+ wr_en => send_wr_en,
+ wr_data => send_wr_data,
+ wr_done => send_wr_done,
+ wr_cancel => send_wr_cancel,
+ wr_accept => send_wr_accept,
+
+ rd_clk => eth_clk,
+ rd_en => send_rd_en,
+ rd_data => send_rd_data,
+ rd_valid => send_rd_valid
+ );
+
+ recv_mux : entity work.recv_mux
+ generic map (
+ BUFF_COUNT => BUFF_COUNT,
+ BUFF_BITS => BUFF_BITS
+ )
+ port map (
+ rd_clk => pcie_clk,
+ rd_buff => recv_rd_buff,
+ rd_en => recv_rd_en,
+ rd_data => recv_rd_data,
+ rd_length => recv_rd_length,
+ rd_valid => recv_rd_valid,
+
+ wr_clk => eth_clk,
+ wr_en => recv_wr_en,
+ wr_data => recv_wr_data,
+ wr_done => recv_wr_done,
+ wr_accept => recv_wr_accept
+ );
+
+ engine : entity work.engine
+ generic map (
+ BUFF_COUNT => BUFF_COUNT,
+ BUFF_BITS => BUFF_BITS
+ )
+ port map (
+ clk => pcie_clk,
+
+ rd_buff => recv_rd_buff,
+ rd_en => recv_rd_en,
+ rd_data => recv_rd_data,
+ rd_length => recv_rd_length,
+ rd_valid => recv_rd_valid,
+
+ wr_buff => send_wr_buff,
+ wr_en => send_wr_en,
+ wr_data => send_wr_data,
+ wr_done => send_wr_done,
+ wr_cancel => send_wr_cancel,
+ wr_accept => send_wr_accept,
+
+ rx_read => rx_read,
+ rx_write => rx_write,
+ rx_complete => rx_complete,
+ rx_data => rx_data,
+ rx_address => rx_address,
+ rx_tag => rx_tag,
+
+ tx_read => tx_read,
+ tx_write => tx_write,
+ tx_complete => tx_complete,
+ tx_data => tx_data,
+ tx_address => tx_address,
+ tx_length => tx_length,
+ tx_tag => tx_tag,
+ tx_accept => tx_accept,
+ tx_done => tx_done,
+
+ interrupt => interrupt,
+ interrupt_rdy => interrupt_rdy,
+
+ max_read => max_read,
+ max_write => max_write,
+
+ mdio_command => mdio_command,
+ mdio_data => mdio_data,
+ mdio_enable => mdio_enable,
+ mdio_done => mdio_done
+ );
+
+ pcie_rx : entity work.pcie_rx port map (
+ clk => pcie_clk,
+
+ frame => rx_frame,
+ sof => rx_sof,
+ eof => rx_eof,
+ valid => rx_valid,
+
+ read => rx_read,
+ write => rx_write,
+ complete => rx_complete,
+ data => rx_data,
+ address => rx_address,
+ tag => rx_tag,
+ remote => remote,
+
+ bar0 => rx_bar0
+ );
+
+ pcie_tx : entity work.pcie_tx port map (
+ clk => pcie_clk,
+
+ frame => tx_frame,
+ sof => tx_sof,
+ eof => tx_eof,
+ half => tx_half,
+ valid => tx_valid,
+ ready => tx_ready,
+
+ read => tx_read,
+ write => tx_write,
+ complete => tx_complete,
+ data => tx_data,
+ address => tx_address,
+ length => tx_length,
+ tag => tx_tag,
+ local => local,
+ remote => remote,
+ accept => tx_accept,
+ done => tx_done
+ );
+
+end arch;
+
diff --git a/netfpga10g/hdl/top.vhd b/netfpga10g/hdl/top.vhd
new file mode 100644
index 0000000..83a5002
--- /dev/null
+++ b/netfpga10g/hdl/top.vhd
@@ -0,0 +1,243 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+Library UNISIM;
+use UNISIM.vcomponents.all;
+
+entity top is port (
+ led1 : out std_logic;
+ led2 : out std_logic;
+ led3 : out std_logic;
+
+ pcie_clk_p : in std_logic;
+ pcie_clk_n : in std_logic;
+ clk25 : in std_logic;
+ clk100 : in std_logic;
+
+ pci_exp_rxn : in std_logic_vector(7 downto 0);
+ pci_exp_rxp : in std_logic_vector(7 downto 0);
+ pci_exp_txn : out std_logic_vector(7 downto 0);
+ pci_exp_txp : out std_logic_vector(7 downto 0);
+
+ mdio : inout std_logic;
+ mdc : out std_logic;
+ phy_reset_n : out std_logic;
+
+ xaui0_clk_p : in std_logic;
+ xaui0_clk_n : in std_logic;
+ xaui0_tx_l0_p : out std_logic;
+ xaui0_tx_l0_n : out std_logic;
+ xaui0_tx_l1_p : out std_logic;
+ xaui0_tx_l1_n : out std_logic;
+ xaui0_tx_l2_p : out std_logic;
+ xaui0_tx_l2_n : out std_logic;
+ xaui0_tx_l3_p : out std_logic;
+ xaui0_tx_l3_n : out std_logic;
+ xaui0_rx_l0_p : in std_logic;
+ xaui0_rx_l0_n : in std_logic;
+ xaui0_rx_l1_p : in std_logic;
+ xaui0_rx_l1_n : in std_logic;
+ xaui0_rx_l2_p : in std_logic;
+ xaui0_rx_l2_n : in std_logic;
+ xaui0_rx_l3_p : in std_logic;
+ xaui0_rx_l3_n : in std_logic
+);
+end top;
+
+architecture arch of top is
+ signal clk125 : std_logic;
+ signal reset125 : std_logic;
+
+ signal count25 : unsigned(6 downto 0) := (others => '0');
+ signal reset25 : std_logic := '1';
+
+ signal clk50 : std_logic;
+ signal clk156 : std_logic;
+
+ signal rx_frame : std_logic_vector(63 downto 0);
+ signal rx_sof : std_logic;
+ signal rx_eof : std_logic;
+ signal rx_valid : std_logic;
+ signal rx_bar0 : std_logic;
+
+ signal tx_frame : std_logic_vector(63 downto 0);
+ signal tx_sof : std_logic;
+ signal tx_eof : std_logic;
+ signal tx_half : std_logic;
+ signal tx_valid : std_logic;
+ signal tx_ready : std_logic;
+
+ signal interrupt : std_logic;
+ signal interrupt_rdy : std_logic;
+
+ signal max_read : std_logic_vector(2 downto 0);
+ signal max_write : std_logic_vector(2 downto 0);
+
+ signal local : std_logic_vector(15 downto 0);
+
+ signal xgmii_rxd : std_logic_vector(63 downto 0);
+ signal xgmii_rxc : std_logic_vector(7 downto 0);
+ signal xgmii_txd : std_logic_vector(63 downto 0);
+ signal xgmii_txc : std_logic_vector(7 downto 0);
+
+ signal mdio_command : std_logic_vector(0 to 27);
+ signal mdio_data : std_logic_vector(0 to 15);
+ signal mdio_enable : std_logic;
+ signal mdio_done : std_logic;
+
+ signal mdio_in : std_logic;
+ signal mdio_out : std_logic;
+ signal mdio_Z : std_logic;
+begin
+ led1 <= '1';
+ led2 <= '0';
+ led3 <= '1';
+
+ process (clk25) begin
+ if rising_edge(clk25) then
+ if count25 = 100 then
+ reset25 <= '0';
+ else
+ count25 <= count25 + 1;
+ end if;
+ end if;
+ end process;
+
+ process (clk100, reset125) begin
+ if reset125 = '1' then
+ clk50 <= '0';
+ elsif rising_edge(clk100) then
+ clk50 <= not clk50;
+ end if;
+ end process;
+
+ pcie_wrapper : entity work.pcie_wrapper port map (
+ pcie_clk_p => pcie_clk_p,
+ pcie_clk_n => pcie_clk_n,
+ reset25 => reset25,
+
+ clk125 => clk125,
+ reset125 => reset125,
+
+ pci_exp_rxn => pci_exp_rxn,
+ pci_exp_rxp => pci_exp_rxp,
+ pci_exp_txn => pci_exp_txn,
+ pci_exp_txp => pci_exp_txp,
+
+ rx_frame => rx_frame,
+ rx_sof => rx_sof,
+ rx_eof => rx_eof,
+ rx_valid => rx_valid,
+
+ tx_frame => tx_frame,
+ tx_sof => tx_sof,
+ tx_eof => tx_eof,
+ tx_half => tx_half,
+ tx_valid => tx_valid,
+ tx_ready => tx_ready,
+
+ bus_dev_func => local,
+
+ max_read => max_read,
+ max_write => max_write,
+
+ interrupt => interrupt,
+ interrupt_rdy => interrupt_rdy,
+
+ bar0 => rx_bar0
+ );
+
+ system_loop: entity work.system_loop port map (
+ eth_clk => clk156,
+ pcie_clk => clk125,
+
+ rx_frame => rx_frame,
+ rx_sof => rx_sof,
+ rx_eof => rx_eof,
+ rx_valid => rx_valid,
+ rx_bar0 => rx_bar0,
+
+ tx_frame => tx_frame,
+ tx_sof => tx_sof,
+ tx_eof => tx_eof,
+ tx_half => tx_half,
+ tx_valid => tx_valid,
+ tx_ready => tx_ready,
+
+ interrupt => interrupt,
+ interrupt_rdy => interrupt_rdy,
+
+ max_read => max_read,
+ max_write => max_write,
+
+ local => local,
+
+ xgmii_rxd => xgmii_rxd,
+ xgmii_rxc => xgmii_rxc,
+
+ xgmii_txd => xgmii_txd,
+ xgmii_txc => xgmii_txc,
+
+ mdio_command => mdio_command,
+ mdio_data => mdio_data,
+ mdio_enable => mdio_enable,
+ mdio_done => mdio_done
+ );
+
+ xaui : entity work.xaui_top
+ generic map (
+ REVERSE_LANES => '1'
+ )
+ port map (
+ dclk => clk50,
+ reset => reset125,
+ xgmii_txd => xgmii_txd,
+ xgmii_txc => xgmii_txc,
+ xgmii_rxd => xgmii_rxd,
+ xgmii_rxc => xgmii_rxc,
+ clk156_out => clk156,
+ refclk_p => xaui0_clk_p,
+ refclk_n => xaui0_clk_n,
+ xaui_tx_l0_p => xaui0_tx_l0_p,
+ xaui_tx_l0_n => xaui0_tx_l0_n,
+ xaui_tx_l1_p => xaui0_tx_l1_p,
+ xaui_tx_l1_n => xaui0_tx_l1_n,
+ xaui_tx_l2_p => xaui0_tx_l2_p,
+ xaui_tx_l2_n => xaui0_tx_l2_n,
+ xaui_tx_l3_p => xaui0_tx_l3_p,
+ xaui_tx_l3_n => xaui0_tx_l3_n,
+ xaui_rx_l0_p => xaui0_rx_l0_p,
+ xaui_rx_l0_n => xaui0_rx_l0_n,
+ xaui_rx_l1_p => xaui0_rx_l1_p,
+ xaui_rx_l1_n => xaui0_rx_l1_n,
+ xaui_rx_l2_p => xaui0_rx_l2_p,
+ xaui_rx_l2_n => xaui0_rx_l2_n,
+ xaui_rx_l3_p => xaui0_rx_l3_p,
+ xaui_rx_l3_n => xaui0_rx_l3_n
+ );
+
+ mdio_iobuf : IOBUF port map (
+ O => mdio_in,
+ IO => mdio,
+ I => mdio_out,
+ T => mdio_Z
+ );
+
+ mdio_module : entity work.mdio port map (
+ clk125 => clk125,
+ reset125 => reset125,
+
+ command => mdio_command,
+ data_out => mdio_data,
+ enable => mdio_enable,
+ done => mdio_done,
+
+ mdio_in => mdio_in,
+ mdio_out => mdio_out,
+ mdio_Z => mdio_Z,
+ mdc => mdc,
+ phy_reset_n => phy_reset_n
+ );
+end arch;
diff --git a/netfpga10g/hdl/tx_eth.vhd b/netfpga10g/hdl/tx_eth.vhd
new file mode 100644
index 0000000..fab9cac
--- /dev/null
+++ b/netfpga10g/hdl/tx_eth.vhd
@@ -0,0 +1,96 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity tx_eth is port (
+ clk : in std_logic;
+ reset : in std_logic;
+
+ xgmii_txd : out std_logic_vector(63 downto 0);
+ xgmii_txc : out std_logic_vector(7 downto 0);
+
+ tx_data : in std_logic_vector(63 downto 0);
+ tx_start : in std_logic;
+ tx_end : in std_logic;
+ tx_rem : in integer range 0 to 7;
+
+ start_count_out : out std_logic_vector(31 downto 0);
+ end_count_out : out std_logic_vector(31 downto 0)
+);
+end tx_eth;
+
+architecture arch of tx_eth is
+ constant IDLE : std_logic_vector(7 downto 0) := x"07";
+ constant START : std_logic_vector(7 downto 0) := x"FB";
+ constant TERMINATE : std_logic_vector(7 downto 0) := x"FD";
+
+ constant PREAMBLE : std_logic_vector(7 downto 0) := "01010101";
+ constant SFD : std_logic_vector(7 downto 0) := "11010101";
+
+ type lanes_t is array (0 to 7) of std_logic_vector(7 downto 0);
+ signal lanes : lanes_t;
+
+ signal in_packet : std_logic;
+
+ signal start_count : unsigned(31 downto 0);
+ signal end_count : unsigned(31 downto 0);
+begin
+ start_count_out <= std_logic_vector(start_count);
+ end_count_out <= std_logic_vector(end_count);
+
+ tx_lanes_gen : for i in 0 to 7 generate
+ xgmii_txd(7+8*i downto 8*i) <= lanes(i);
+ end generate tx_lanes_gen;
+
+ tx_logic : process (clk, reset) begin
+ if reset = '1' then
+ in_packet <= '0';
+ start_count <= (others => '0');
+ end_count <= (others => '0');
+
+ for i in 0 to 7 loop
+ lanes(i) <= IDLE;
+ xgmii_txc(i) <= '1';
+ end loop;
+
+ elsif rising_edge(clk) then
+ for i in 0 to 7 loop
+ lanes(i) <= IDLE;
+ xgmii_txc(i) <= '1';
+ end loop;
+
+ if tx_start = '1' then
+ in_packet <= '1';
+ lanes(0) <= START;
+ xgmii_txc(0) <= '1';
+ lanes(1 to 6) <= (others => PREAMBLE);
+ xgmii_txc(6 downto 1) <= (others => '0');
+ lanes(7) <= SFD;
+ xgmii_txc(7) <= '0';
+ start_count <= start_count + 1;
+
+ elsif tx_end = '1' then
+ in_packet <= '0';
+ end_count <= end_count + 1;
+
+ for i in 0 to 7 loop
+ if i < tx_rem then
+ lanes(i) <= tx_data(63-8*i downto 56-8*i);
+ xgmii_txc(i) <= '0';
+ elsif i = tx_rem then
+ lanes(i) <= TERMINATE;
+ xgmii_txc(i) <= '1';
+ end if;
+ end loop;
+
+ elsif in_packet = '1' then
+ for i in 0 to 7 loop
+ lanes(i) <= tx_data(63-8*i downto 56-8*i);
+ xgmii_txc(i) <= '0';
+ end loop;
+ end if;
+ end if;
+ end process;
+end arch;
+