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/dma.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/dma.vhd')
-rw-r--r-- | netfpga10g/hdl/dma.vhd | 640 |
1 files changed, 640 insertions, 0 deletions
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; + |