diff options
author | Alexander D'hoore <[email protected]> | 2017-12-15 15:37:58 +0100 |
---|---|---|
committer | Dimitri Staessens <[email protected]> | 2017-12-15 15:37:58 +0100 |
commit | d1a1059d748955ed93a8e87c437c7eae1258293c (patch) | |
tree | 9137bc921db74bb3797b8b0f05e7a69022412522 /netfpga10g/hdl/engine.vhd | |
parent | 8f258e469b1acea8e3ccf1485779e1db0bf5f772 (diff) | |
download | raptor-d1a1059d748955ed93a8e87c437c7eae1258293c.tar.gz raptor-d1a1059d748955ed93a8e87c437c7eae1258293c.zip |
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/engine.vhd')
-rw-r--r-- | netfpga10g/hdl/engine.vhd | 570 |
1 files changed, 570 insertions, 0 deletions
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; |