summaryrefslogtreecommitdiff
path: root/netfpga10g/hdl/buff.vhd
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/buff.vhd
parent8f258e469b1acea8e3ccf1485779e1db0bf5f772 (diff)
downloadraptor-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/buff.vhd')
-rw-r--r--netfpga10g/hdl/buff.vhd192
1 files changed, 192 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;
+