Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e98a75bc7a | ||
|
|
ddf628c7b5 |
@@ -1,8 +0,0 @@
|
|||||||
VHDL/lib/FIFO/src/async_fifo_ctrl.vhd
|
|
||||||
VHDL/lib/FIFO/src/fifo_async_ctrl.vhd
|
|
||||||
VHDL/lib/FIFO/src/fifo_async_ctrl.vhd
|
|
||||||
|
|
||||||
VHDL/lib/FIFO/src/fifo_sync_ctrl.vhd
|
|
||||||
|
|
||||||
VHDL/lib/FIFO/src/sync_fifo_ctrl.vhd
|
|
||||||
VHDL/lib/FIFO/src/fifo_sync_ctrl.vhd
|
|
||||||
@@ -1,248 +0,0 @@
|
|||||||
-------------------------------------------------------------------------
|
|
||||||
-- Project: FIFO, generic FIFOs written in VHDL
|
|
||||||
-- Release 1
|
|
||||||
--
|
|
||||||
-- Copyright (C) 2007 J. Ahrensfeld
|
|
||||||
--
|
|
||||||
-- This library is free software; you can redistribute it and/or
|
|
||||||
-- modify it under the terms of the GNU Lesser General Public
|
|
||||||
-- License as published by the Free Software Foundation; either
|
|
||||||
-- version 2.1 of the License, or (at your option) any later version.
|
|
||||||
--
|
|
||||||
-- This library is distributed in the hope that it will be useful,
|
|
||||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
-- Lesser General Public License for more details.
|
|
||||||
--
|
|
||||||
-- You should have received a copy of the GNU Lesser General Public
|
|
||||||
-- License along with this library; if not, write to the Free Software
|
|
||||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
--
|
|
||||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
|
||||||
--
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
|
|
||||||
library IEEE;
|
|
||||||
use IEEE.STD_LOGIC_1164.ALL;
|
|
||||||
use IEEE.numeric_std.ALL;
|
|
||||||
|
|
||||||
LIBRARY WORK;
|
|
||||||
USE WORK.FIFO_CTRL_PKG.ALL;
|
|
||||||
|
|
||||||
entity fifo_async_ctrl is
|
|
||||||
Generic
|
|
||||||
(
|
|
||||||
addr_width : integer := 3;
|
|
||||||
almost_full_thresh : integer := 6;
|
|
||||||
almost_empty_thresh : integer := 2
|
|
||||||
);
|
|
||||||
Port
|
|
||||||
(
|
|
||||||
rst : in STD_LOGIC;
|
|
||||||
clk_w : in STD_LOGIC;
|
|
||||||
clk_r : in STD_LOGIC;
|
|
||||||
winc : in STD_LOGIC;
|
|
||||||
rinc : in STD_LOGIC;
|
|
||||||
ptr_w : out unsigned (addr_width-1 downto 0);
|
|
||||||
ptr_r : out unsigned (addr_width-1 downto 0);
|
|
||||||
fifo_pre_full : out STD_LOGIC;
|
|
||||||
fifo_pre_empty : out STD_LOGIC;
|
|
||||||
fifo_full : out STD_LOGIC;
|
|
||||||
fifo_empty : out STD_LOGIC;
|
|
||||||
fifo_afull : out STD_LOGIC;
|
|
||||||
fifo_aempty : out STD_LOGIC
|
|
||||||
);
|
|
||||||
end fifo_async_ctrl;
|
|
||||||
|
|
||||||
architecture Behavioral of fifo_async_ctrl is
|
|
||||||
|
|
||||||
signal gcnt_w : unsigned (addr_width downto 0);
|
|
||||||
signal gcnt2_w : unsigned (addr_width downto 0);
|
|
||||||
signal bcnt2_aw : unsigned (addr_width downto 0);
|
|
||||||
signal bcnt_w : unsigned (addr_width downto 0);
|
|
||||||
signal gnxt_w : unsigned (addr_width downto 0);
|
|
||||||
signal bnxt_w : unsigned (addr_width downto 0);
|
|
||||||
signal gcnt_r : unsigned (addr_width downto 0);
|
|
||||||
signal gcnt2_r : unsigned (addr_width downto 0);
|
|
||||||
signal bcnt2_ar : unsigned (addr_width downto 0);
|
|
||||||
signal bcnt_r : unsigned (addr_width downto 0);
|
|
||||||
signal gnxt_r : unsigned (addr_width downto 0);
|
|
||||||
signal bnxt_r : unsigned (addr_width downto 0);
|
|
||||||
|
|
||||||
signal pre_empty, pre_full : std_logic;
|
|
||||||
signal full, empty : std_logic;
|
|
||||||
|
|
||||||
-- synthesis translate_off
|
|
||||||
signal diffw : signed (addr_width downto 0);
|
|
||||||
signal diffr : signed (addr_width downto 0);
|
|
||||||
-- synthesis translate_on
|
|
||||||
|
|
||||||
begin
|
|
||||||
|
|
||||||
ptr_w <= bcnt_w(addr_width-1 downto 0);
|
|
||||||
ptr_r <= bnxt_r(addr_width-1 downto 0);
|
|
||||||
fifo_full <= full;
|
|
||||||
fifo_empty <= empty;
|
|
||||||
fifo_pre_full <= pre_full;
|
|
||||||
fifo_pre_empty <= pre_empty;
|
|
||||||
|
|
||||||
proc_write_inhibit:
|
|
||||||
process(rst, clk_w)
|
|
||||||
begin
|
|
||||||
if rst = '1' then
|
|
||||||
full <= '0';
|
|
||||||
elsif rising_edge(clk_w) then
|
|
||||||
full <= pre_full;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
proc_read_inhibit:
|
|
||||||
process(rst, clk_r)
|
|
||||||
begin
|
|
||||||
if rst = '1' then
|
|
||||||
empty <= '1';
|
|
||||||
elsif rising_edge(clk_r) then
|
|
||||||
empty <= pre_empty;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
proc_sync_grptr:
|
|
||||||
process(clk_w)
|
|
||||||
variable p1, p2 : unsigned (addr_width downto 0);
|
|
||||||
begin
|
|
||||||
if rising_edge(clk_w) then
|
|
||||||
gcnt2_r <= p2;
|
|
||||||
p2 := p1;
|
|
||||||
p1 := gcnt_r;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
proc_ptr_gwptr:
|
|
||||||
process(clk_r)
|
|
||||||
variable p1, p2 : unsigned (addr_width downto 0);
|
|
||||||
begin
|
|
||||||
if rising_edge(clk_r) then
|
|
||||||
gcnt2_w <= p2;
|
|
||||||
p2 := p1;
|
|
||||||
p1 := gcnt_w;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
proc_status_full:
|
|
||||||
process(gnxt_w, gcnt2_r)
|
|
||||||
begin
|
|
||||||
if (gnxt_w = (not gcnt2_r(gcnt2_r'left downto gcnt2_r'left-1) & gcnt2_r(gcnt2_r'left-2 downto 0))) then
|
|
||||||
pre_full <= '1';
|
|
||||||
else
|
|
||||||
pre_full <= '0';
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
proc_status_empty:
|
|
||||||
process(gnxt_r, gcnt2_w)
|
|
||||||
begin
|
|
||||||
if (gnxt_r = gcnt2_w) then
|
|
||||||
pre_empty <= '1';
|
|
||||||
else
|
|
||||||
pre_empty <= '0';
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
proc_sync_arptr:
|
|
||||||
process(clk_w)
|
|
||||||
variable p1, p2 : unsigned (addr_width downto 0);
|
|
||||||
begin
|
|
||||||
if rising_edge(clk_w) then
|
|
||||||
bcnt2_ar <= p2;
|
|
||||||
p2 := p1;
|
|
||||||
p1 := bcnt_r;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
proc_ptr_awptr:
|
|
||||||
process(clk_r)
|
|
||||||
variable p1, p2 : unsigned (addr_width downto 0);
|
|
||||||
begin
|
|
||||||
if rising_edge(clk_r) then
|
|
||||||
bcnt2_aw <= p2;
|
|
||||||
p2 := p1;
|
|
||||||
p1 := bcnt_w;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
proc_status_almost_full:
|
|
||||||
process(rst, clk_w)
|
|
||||||
variable diff : unsigned (addr_width downto 0);
|
|
||||||
begin
|
|
||||||
-- synthesis translate_off
|
|
||||||
diffw <= signed(diff);
|
|
||||||
-- synthesis translate_on
|
|
||||||
if rst = '1' then
|
|
||||||
fifo_afull <= '0';
|
|
||||||
diff := (others => '0');
|
|
||||||
elsif rising_edge(clk_w) then
|
|
||||||
if diff >= almost_full_thresh-1 then
|
|
||||||
fifo_afull <= '1';
|
|
||||||
else
|
|
||||||
fifo_afull <= '0';
|
|
||||||
end if;
|
|
||||||
diff := unsigned(abs(signed(bnxt_w) - signed(bcnt2_ar)));
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
proc_status_almost_empty:
|
|
||||||
process(rst, clk_r)
|
|
||||||
variable diff : unsigned (addr_width downto 0);
|
|
||||||
begin
|
|
||||||
-- synthesis translate_off
|
|
||||||
diffr <= signed(diff);
|
|
||||||
-- synthesis translate_on
|
|
||||||
if rst = '1' then
|
|
||||||
fifo_aempty <= '1';
|
|
||||||
diff := (others => '0');
|
|
||||||
elsif rising_edge(clk_r) then
|
|
||||||
if diff <= almost_empty_thresh+1 then
|
|
||||||
fifo_aempty <= '1';
|
|
||||||
else
|
|
||||||
fifo_aempty <= '0';
|
|
||||||
end if;
|
|
||||||
diff := unsigned(abs(signed(bcnt2_aw) - signed(bnxt_r)));
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
inst_gray_counter_w : entity work.gray_counter
|
|
||||||
generic map
|
|
||||||
(
|
|
||||||
width => addr_width+1,
|
|
||||||
init_value => 0
|
|
||||||
)
|
|
||||||
port map
|
|
||||||
(
|
|
||||||
rst => rst,
|
|
||||||
clk => clk_w,
|
|
||||||
ce => winc,
|
|
||||||
bcnt => bcnt_w,
|
|
||||||
bnxt => bnxt_w,
|
|
||||||
gcnt => gcnt_w,
|
|
||||||
gnxt => gnxt_w
|
|
||||||
);
|
|
||||||
|
|
||||||
inst_gray_counter_r : entity work.gray_counter
|
|
||||||
generic map
|
|
||||||
(
|
|
||||||
width => addr_width+1,
|
|
||||||
init_value => 0
|
|
||||||
)
|
|
||||||
port map
|
|
||||||
(
|
|
||||||
rst => rst,
|
|
||||||
clk => clk_r,
|
|
||||||
ce => rinc,
|
|
||||||
bcnt => bcnt_r,
|
|
||||||
bnxt => bnxt_r,
|
|
||||||
gcnt => gcnt_r,
|
|
||||||
gnxt => gnxt_r
|
|
||||||
);
|
|
||||||
|
|
||||||
end Behavioral;
|
|
||||||
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
-------------------------------------------------------------------------
|
|
||||||
-- Project: FIFO, generic FIFOs written in VHDL
|
|
||||||
-- Release 1
|
|
||||||
--
|
|
||||||
-- Copyright (C) 2007 J. Ahrensfeld
|
|
||||||
--
|
|
||||||
-- This library is free software; you can redistribute it and/or
|
|
||||||
-- modify it under the terms of the GNU Lesser General Public
|
|
||||||
-- License as published by the Free Software Foundation; either
|
|
||||||
-- version 2.1 of the License, or (at your option) any later version.
|
|
||||||
--
|
|
||||||
-- This library is distributed in the hope that it will be useful,
|
|
||||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
-- Lesser General Public License for more details.
|
|
||||||
--
|
|
||||||
-- You should have received a copy of the GNU Lesser General Public
|
|
||||||
-- License along with this library; if not, write to the Free Software
|
|
||||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
--
|
|
||||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
|
||||||
--
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
|
|
||||||
LIBRARY IEEE;
|
|
||||||
USE IEEE.STD_LOGIC_1164.ALL;
|
|
||||||
USE IEEE.NUMERIC_STD.ALL;
|
|
||||||
|
|
||||||
use work.fifo_ctrl_pkg.all;
|
|
||||||
|
|
||||||
entity fifo_async is
|
|
||||||
Generic
|
|
||||||
(
|
|
||||||
addr_width : natural := 4;
|
|
||||||
data_width : natural := 8;
|
|
||||||
almost_full_thresh : integer := 12;
|
|
||||||
almost_empty_thresh : integer := 4;
|
|
||||||
allow_full_writes : boolean := false;
|
|
||||||
allow_empty_reads : boolean := false;
|
|
||||||
do_last_read_update : boolean := true
|
|
||||||
);
|
|
||||||
Port
|
|
||||||
(
|
|
||||||
rst : in STD_LOGIC;
|
|
||||||
clk_w : in STD_LOGIC;
|
|
||||||
clk_r : in STD_LOGIC;
|
|
||||||
we : in STD_LOGIC;
|
|
||||||
re : in STD_LOGIC;
|
|
||||||
fifo_full : out STD_LOGIC;
|
|
||||||
fifo_empty : out STD_LOGIC;
|
|
||||||
fifo_afull : out STD_LOGIC;
|
|
||||||
fifo_aempty : out STD_LOGIC;
|
|
||||||
data_w : in unsigned (data_width-1 downto 0);
|
|
||||||
data_r : out unsigned (data_width-1 downto 0)
|
|
||||||
);
|
|
||||||
end fifo_async;
|
|
||||||
|
|
||||||
architecture Behavioral of fifo_async is
|
|
||||||
|
|
||||||
signal mem_wr_en : STD_LOGIC;
|
|
||||||
signal mem_rd_en : STD_LOGIC;
|
|
||||||
signal ptr_w : unsigned (addr_width-1 downto 0);
|
|
||||||
signal ptr_r : unsigned (addr_width-1 downto 0);
|
|
||||||
signal full : std_logic;
|
|
||||||
signal empty : std_logic;
|
|
||||||
signal pre_full : STD_LOGIC;
|
|
||||||
signal pre_empty : STD_LOGIC;
|
|
||||||
signal rinc : std_logic;
|
|
||||||
|
|
||||||
begin
|
|
||||||
|
|
||||||
fifo_full <= full;
|
|
||||||
fifo_empty <= empty;
|
|
||||||
|
|
||||||
mem_wr_en <= (we and not full) when allow_full_writes = false else we;
|
|
||||||
rinc <= (re and not empty) when allow_empty_reads = false else re;
|
|
||||||
mem_rd_en <= not pre_empty when do_last_read_update = false else '1';
|
|
||||||
|
|
||||||
|
|
||||||
inst_fifo_async_ctrl: entity work.fifo_async_ctrl
|
|
||||||
GENERIC MAP
|
|
||||||
(
|
|
||||||
addr_width => addr_width,
|
|
||||||
almost_full_thresh => almost_full_thresh,
|
|
||||||
almost_empty_thresh => almost_empty_thresh
|
|
||||||
)
|
|
||||||
PORT MAP
|
|
||||||
(
|
|
||||||
rst => rst,
|
|
||||||
clk_w => clk_w,
|
|
||||||
clk_r => clk_r,
|
|
||||||
winc => mem_wr_en,
|
|
||||||
rinc => rinc,
|
|
||||||
ptr_w => ptr_w,
|
|
||||||
ptr_r => ptr_r,
|
|
||||||
fifo_full => full,
|
|
||||||
fifo_empty => empty,
|
|
||||||
fifo_pre_full => pre_full,
|
|
||||||
fifo_pre_empty => pre_empty,
|
|
||||||
fifo_afull => fifo_afull,
|
|
||||||
fifo_aempty => fifo_aempty
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
inst_dpram_1w1r: entity work.dpram_1w1r
|
|
||||||
GENERIC MAP
|
|
||||||
(
|
|
||||||
addr_width => addr_width,
|
|
||||||
data_width => data_width
|
|
||||||
)
|
|
||||||
PORT MAP(
|
|
||||||
clka => clk_w,
|
|
||||||
clkb => clk_r,
|
|
||||||
en_a => '1',
|
|
||||||
en_b => mem_rd_en,
|
|
||||||
we_a => mem_wr_en,
|
|
||||||
addr_a => ptr_w,
|
|
||||||
addr_b => ptr_r,
|
|
||||||
din_a => data_w,
|
|
||||||
dout_b => data_r
|
|
||||||
);
|
|
||||||
|
|
||||||
end Behavioral;
|
|
||||||
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
-------------------------------------------------------------------------
|
|
||||||
-- Project: FIFO, generic FIFOs written in VHDL
|
|
||||||
-- Release 1
|
|
||||||
--
|
|
||||||
-- Copyright (C) 2007 J. Ahrensfeld
|
|
||||||
--
|
|
||||||
-- This library is free software; you can redistribute it and/or
|
|
||||||
-- modify it under the terms of the GNU Lesser General Public
|
|
||||||
-- License as published by the Free Software Foundation; either
|
|
||||||
-- version 2.1 of the License, or (at your option) any later version.
|
|
||||||
--
|
|
||||||
-- This library is distributed in the hope that it will be useful,
|
|
||||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
-- Lesser General Public License for more details.
|
|
||||||
--
|
|
||||||
-- You should have received a copy of the GNU Lesser General Public
|
|
||||||
-- License along with this library; if not, write to the Free Software
|
|
||||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
--
|
|
||||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
|
||||||
--
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
|
|
||||||
LIBRARY IEEE;
|
|
||||||
USE IEEE.STD_LOGIC_1164.ALL;
|
|
||||||
USE IEEE.NUMERIC_STD.ALL;
|
|
||||||
|
|
||||||
package fifo_ctrl_pkg is
|
|
||||||
|
|
||||||
-- Constants
|
|
||||||
-- Types
|
|
||||||
|
|
||||||
-- Functions
|
|
||||||
function bin2gray(xb : unsigned) return unsigned;
|
|
||||||
function gray2bin(xg : unsigned) return unsigned;
|
|
||||||
|
|
||||||
end fifo_ctrl_pkg;
|
|
||||||
|
|
||||||
package body fifo_ctrl_pkg is
|
|
||||||
|
|
||||||
function bin2gray(xb : unsigned) return unsigned is
|
|
||||||
variable xg : unsigned(xb'left downto xb'right);
|
|
||||||
begin
|
|
||||||
|
|
||||||
xg(xg'left) := xb(xb'left);
|
|
||||||
for i in 1 to xb'left loop
|
|
||||||
xg(xg'left-i) := xb(xb'left-i+1) xor xb(xb'left-i);
|
|
||||||
end loop;
|
|
||||||
|
|
||||||
return xg;
|
|
||||||
end bin2gray;
|
|
||||||
|
|
||||||
function gray2bin(xg : unsigned) return unsigned is
|
|
||||||
variable xb : unsigned(xg'left downto xg'right);
|
|
||||||
begin
|
|
||||||
|
|
||||||
xb(xb'left) := xg(xg'left);
|
|
||||||
for i in 1 to xg'left loop
|
|
||||||
xb(xb'left-i) := xb(xb'left-i+1) xor xg(xg'left-i);
|
|
||||||
end loop;
|
|
||||||
|
|
||||||
return xb;
|
|
||||||
end gray2bin;
|
|
||||||
|
|
||||||
end fifo_ctrl_pkg;
|
|
||||||
|
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
-------------------------------------------------------------------------
|
|
||||||
-- Project: FIFO, generic FIFOs written in VHDL
|
|
||||||
-- Release 1
|
|
||||||
--
|
|
||||||
-- Copyright (C) 2007 J. Ahrensfeld
|
|
||||||
--
|
|
||||||
-- This library is free software; you can redistribute it and/or
|
|
||||||
-- modify it under the terms of the GNU Lesser General Public
|
|
||||||
-- License as published by the Free Software Foundation; either
|
|
||||||
-- version 2.1 of the License, or (at your option) any later version.
|
|
||||||
--
|
|
||||||
-- This library is distributed in the hope that it will be useful,
|
|
||||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
-- Lesser General Public License for more details.
|
|
||||||
--
|
|
||||||
-- You should have received a copy of the GNU Lesser General Public
|
|
||||||
-- License along with this library; if not, write to the Free Software
|
|
||||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
--
|
|
||||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
|
||||||
--
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
|
|
||||||
LIBRARY IEEE;
|
|
||||||
USE IEEE.STD_LOGIC_1164.ALL;
|
|
||||||
USE IEEE.NUMERIC_STD.ALL;
|
|
||||||
|
|
||||||
use work.fifo_ctrl_pkg.all;
|
|
||||||
|
|
||||||
entity fifo_sync is
|
|
||||||
Generic
|
|
||||||
(
|
|
||||||
addr_width : natural := 4;
|
|
||||||
data_width : natural := 8;
|
|
||||||
almost_full_thresh : integer := 12;
|
|
||||||
almost_empty_thresh : integer := 4;
|
|
||||||
allow_full_writes : boolean := false;
|
|
||||||
allow_empty_reads : boolean := false;
|
|
||||||
do_last_read_update : boolean := true
|
|
||||||
|
|
||||||
);
|
|
||||||
Port
|
|
||||||
(
|
|
||||||
rst : in STD_LOGIC;
|
|
||||||
clk : in STD_LOGIC;
|
|
||||||
we : in STD_LOGIC;
|
|
||||||
re : in STD_LOGIC;
|
|
||||||
fifo_full : out STD_LOGIC;
|
|
||||||
fifo_empty : out STD_LOGIC;
|
|
||||||
fifo_afull : out STD_LOGIC;
|
|
||||||
fifo_aempty : out STD_LOGIC;
|
|
||||||
data_w : in unsigned (data_width-1 downto 0);
|
|
||||||
data_r : out unsigned (data_width-1 downto 0)
|
|
||||||
);
|
|
||||||
end fifo_sync;
|
|
||||||
|
|
||||||
architecture Behavioral of fifo_sync is
|
|
||||||
|
|
||||||
signal mem_wr_en : STD_LOGIC;
|
|
||||||
signal mem_rd_en : STD_LOGIC;
|
|
||||||
signal ptr_w : unsigned (addr_width-1 downto 0);
|
|
||||||
signal ptr_r : unsigned (addr_width-1 downto 0);
|
|
||||||
signal full : STD_LOGIC;
|
|
||||||
signal empty : std_logic;
|
|
||||||
signal pre_full : STD_LOGIC;
|
|
||||||
signal pre_empty : STD_LOGIC;
|
|
||||||
signal rinc : std_logic;
|
|
||||||
|
|
||||||
begin
|
|
||||||
|
|
||||||
fifo_full <= full;
|
|
||||||
fifo_empty <= empty;
|
|
||||||
|
|
||||||
mem_wr_en <= (we and not full) when allow_full_writes = false else we;
|
|
||||||
rinc <= (re and not empty) when allow_empty_reads = false else re;
|
|
||||||
mem_rd_en <= not pre_empty when do_last_read_update = false else '1';
|
|
||||||
|
|
||||||
|
|
||||||
inst_fifo_sync_ctrl: entity work.fifo_sync_ctrl
|
|
||||||
GENERIC MAP
|
|
||||||
(
|
|
||||||
addr_width => addr_width,
|
|
||||||
almost_full_thresh => almost_full_thresh,
|
|
||||||
almost_empty_thresh => almost_empty_thresh
|
|
||||||
)
|
|
||||||
PORT MAP
|
|
||||||
(
|
|
||||||
rst => rst,
|
|
||||||
clk => clk,
|
|
||||||
winc => mem_wr_en,
|
|
||||||
rinc => rinc,
|
|
||||||
ptr_w => ptr_w,
|
|
||||||
ptr_r => ptr_r,
|
|
||||||
fifo_full => full,
|
|
||||||
fifo_empty => empty,
|
|
||||||
fifo_pre_full => pre_full,
|
|
||||||
fifo_pre_empty => pre_empty,
|
|
||||||
fifo_afull => fifo_afull,
|
|
||||||
fifo_aempty => fifo_aempty
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
inst_dpram_1w1r: entity work.dpram_1w1r
|
|
||||||
GENERIC MAP
|
|
||||||
(
|
|
||||||
addr_width => addr_width,
|
|
||||||
data_width => data_width
|
|
||||||
)
|
|
||||||
PORT MAP(
|
|
||||||
clka => clk,
|
|
||||||
clkb => clk,
|
|
||||||
en_a => '1',
|
|
||||||
en_b => mem_rd_en,
|
|
||||||
we_a => mem_wr_en,
|
|
||||||
addr_a => ptr_w,
|
|
||||||
addr_b => ptr_r,
|
|
||||||
din_a => data_w,
|
|
||||||
dout_b => data_r
|
|
||||||
);
|
|
||||||
|
|
||||||
end Behavioral;
|
|
||||||
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
-------------------------------------------------------------------------
|
|
||||||
-- Project: FIFO, generic FIFOs written in VHDL
|
|
||||||
-- Release 1
|
|
||||||
--
|
|
||||||
-- Copyright (C) 2007 J. Ahrensfeld
|
|
||||||
--
|
|
||||||
-- This library is free software; you can redistribute it and/or
|
|
||||||
-- modify it under the terms of the GNU Lesser General Public
|
|
||||||
-- License as published by the Free Software Foundation; either
|
|
||||||
-- version 2.1 of the License, or (at your option) any later version.
|
|
||||||
--
|
|
||||||
-- This library is distributed in the hope that it will be useful,
|
|
||||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
-- Lesser General Public License for more details.
|
|
||||||
--
|
|
||||||
-- You should have received a copy of the GNU Lesser General Public
|
|
||||||
-- License along with this library; if not, write to the Free Software
|
|
||||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
--
|
|
||||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
|
||||||
--
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
|
|
||||||
library IEEE;
|
|
||||||
use IEEE.STD_LOGIC_1164.ALL;
|
|
||||||
use IEEE.numeric_std.ALL;
|
|
||||||
|
|
||||||
LIBRARY WORK;
|
|
||||||
USE WORK.FIFO_CTRL_PKG.ALL;
|
|
||||||
|
|
||||||
entity gray_counter is
|
|
||||||
Generic (
|
|
||||||
width : natural := 3;
|
|
||||||
init_value : natural := 0
|
|
||||||
);
|
|
||||||
Port
|
|
||||||
(
|
|
||||||
rst : in STD_LOGIC;
|
|
||||||
clk : in STD_LOGIC;
|
|
||||||
ce : in STD_LOGIC;
|
|
||||||
bcnt : out unsigned (width-1 downto 0);
|
|
||||||
bnxt : out unsigned (width-1 downto 0);
|
|
||||||
gcnt : out unsigned (width-1 downto 0);
|
|
||||||
gnxt : out unsigned (width-1 downto 0)
|
|
||||||
);
|
|
||||||
end gray_counter;
|
|
||||||
|
|
||||||
architecture Behavioral of gray_counter is
|
|
||||||
|
|
||||||
signal cntg : unsigned (width-1 downto 0);
|
|
||||||
signal cntb : unsigned (width-1 downto 0);
|
|
||||||
signal nxtb : unsigned (width-1 downto 0);
|
|
||||||
signal nxtg : unsigned (width-1 downto 0);
|
|
||||||
|
|
||||||
begin
|
|
||||||
|
|
||||||
bnxt <= nxtb;
|
|
||||||
gnxt <= nxtg;
|
|
||||||
bcnt <= cntb;
|
|
||||||
gcnt <= cntg;
|
|
||||||
|
|
||||||
process(rst, clk, ce, cntb, nxtb)
|
|
||||||
begin
|
|
||||||
if rst = '1' then
|
|
||||||
cntb <= to_unsigned(init_value, width);
|
|
||||||
nxtb <= to_unsigned(init_value, width);
|
|
||||||
nxtg <= to_unsigned(init_value, width);
|
|
||||||
cntg <= to_unsigned(init_value, width);
|
|
||||||
else
|
|
||||||
if rising_edge(clk) then
|
|
||||||
cntg <= nxtg;
|
|
||||||
cntb <= nxtb;
|
|
||||||
end if;
|
|
||||||
nxtg <= bin2gray(nxtb);
|
|
||||||
nxtb <= cntb;
|
|
||||||
if ce = '1' then
|
|
||||||
nxtb <= cntb + 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
end Behavioral;
|
|
||||||
|
|
||||||
@@ -1,198 +0,0 @@
|
|||||||
-------------------------------------------------------------------------
|
|
||||||
-- Project: FIFO, generic FIFOs written in VHDL
|
|
||||||
-- Release 1
|
|
||||||
--
|
|
||||||
-- Copyright (C) 2007 J. Ahrensfeld
|
|
||||||
--
|
|
||||||
-- This library is free software; you can redistribute it and/or
|
|
||||||
-- modify it under the terms of the GNU Lesser General Public
|
|
||||||
-- License as published by the Free Software Foundation; either
|
|
||||||
-- version 2.1 of the License, or (at your option) any later version.
|
|
||||||
--
|
|
||||||
-- This library is distributed in the hope that it will be useful,
|
|
||||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
-- Lesser General Public License for more details.
|
|
||||||
--
|
|
||||||
-- You should have received a copy of the GNU Lesser General Public
|
|
||||||
-- License along with this library; if not, write to the Free Software
|
|
||||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
--
|
|
||||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
|
||||||
--
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
|
|
||||||
library IEEE;
|
|
||||||
use IEEE.STD_LOGIC_1164.ALL;
|
|
||||||
use IEEE.numeric_std.ALL;
|
|
||||||
|
|
||||||
entity fifo_sync_ctrl is
|
|
||||||
Generic
|
|
||||||
(
|
|
||||||
addr_width : integer := 3;
|
|
||||||
almost_full_thresh : integer := 6;
|
|
||||||
almost_empty_thresh : integer := 2
|
|
||||||
);
|
|
||||||
Port
|
|
||||||
(
|
|
||||||
rst : in STD_LOGIC;
|
|
||||||
clk : in STD_LOGIC;
|
|
||||||
winc : in STD_LOGIC;
|
|
||||||
rinc : in STD_LOGIC;
|
|
||||||
ptr_w : out unsigned (addr_width-1 downto 0);
|
|
||||||
ptr_r : out unsigned (addr_width-1 downto 0);
|
|
||||||
fifo_pre_full : out STD_LOGIC;
|
|
||||||
fifo_pre_empty : out STD_LOGIC;
|
|
||||||
fifo_full : out STD_LOGIC;
|
|
||||||
fifo_empty : out STD_LOGIC;
|
|
||||||
fifo_afull : out STD_LOGIC;
|
|
||||||
fifo_aempty : out STD_LOGIC
|
|
||||||
);
|
|
||||||
end fifo_sync_ctrl;
|
|
||||||
|
|
||||||
architecture Behavioral of fifo_sync_ctrl is
|
|
||||||
|
|
||||||
signal pW, pW_cnt, pW_next : unsigned (addr_width-1 downto 0);
|
|
||||||
signal pR, pR_cnt, pR_next : unsigned (addr_width-1 downto 0);
|
|
||||||
signal empty, full : std_logic;
|
|
||||||
signal pre_empty, pre_full : std_logic;
|
|
||||||
signal was_write : std_logic;
|
|
||||||
signal diff : unsigned (addr_width downto 0);
|
|
||||||
|
|
||||||
begin
|
|
||||||
|
|
||||||
fifo_full <= full;
|
|
||||||
fifo_empty <= empty;
|
|
||||||
fifo_pre_full <= pre_full;
|
|
||||||
fifo_pre_empty <= pre_empty;
|
|
||||||
|
|
||||||
|
|
||||||
proc_diff_gen:
|
|
||||||
process(rst, clk)
|
|
||||||
begin
|
|
||||||
if rst = '1' then
|
|
||||||
diff <= (others => '0');
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
if winc = '1' and rinc = '0' then
|
|
||||||
diff <= diff + 1;
|
|
||||||
elsif winc = '0' and rinc = '1' then
|
|
||||||
diff <= diff - 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
proc_status_almost_full:
|
|
||||||
process(rst, clk)
|
|
||||||
begin
|
|
||||||
if rst = '1' then
|
|
||||||
fifo_afull <= '0';
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
if diff >= almost_full_thresh-1 then
|
|
||||||
fifo_afull <= '1';
|
|
||||||
else
|
|
||||||
fifo_afull <= '0';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
proc_status_almost_empty:
|
|
||||||
process(rst, clk)
|
|
||||||
begin
|
|
||||||
if rst = '1' then
|
|
||||||
fifo_aempty <= '1';
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
if diff <= almost_empty_thresh+1 then
|
|
||||||
fifo_aempty <= '1';
|
|
||||||
else
|
|
||||||
fifo_aempty <= '0';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
proc_full_reg:
|
|
||||||
process(rst, clk)
|
|
||||||
begin
|
|
||||||
if rst = '1' then
|
|
||||||
full <= '0';
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
full <= pre_full;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
proc_empty_reg:
|
|
||||||
process(rst, clk)
|
|
||||||
begin
|
|
||||||
if rst = '1' then
|
|
||||||
empty <= '1';
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
empty <= pre_empty;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
proc_status_w:
|
|
||||||
process(was_write, pW_next, pR_next, pW, pR, winc, rinc)
|
|
||||||
begin
|
|
||||||
if (pW_next = pR) and (winc = '1' or was_write = '1') then
|
|
||||||
pre_full <= '1';
|
|
||||||
else
|
|
||||||
pre_full <= '0';
|
|
||||||
end if;
|
|
||||||
if (pR_next = pW) and (rinc = '1' or was_write = '0') then
|
|
||||||
pre_empty <= '1';
|
|
||||||
else
|
|
||||||
pre_empty <= '0';
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
proc_flag_write:
|
|
||||||
process(rst, clk)
|
|
||||||
begin
|
|
||||||
if rst = '1' then
|
|
||||||
was_write <= '0';
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
if winc = '1' then
|
|
||||||
was_write <= '1';
|
|
||||||
elsif rinc = '1' then
|
|
||||||
was_write <= '0';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
proc_ptr_w:
|
|
||||||
process(rst, clk, pW, winc)
|
|
||||||
begin
|
|
||||||
if rst = '1' then
|
|
||||||
pW <= to_unsigned(0, addr_width);
|
|
||||||
pW_next <= to_unsigned(0, addr_width);
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
if winc = '1' then
|
|
||||||
pW <= pW_next;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
pW_next <= pW;
|
|
||||||
if winc = '1' then
|
|
||||||
pW_next <= pW + 1;
|
|
||||||
end if;
|
|
||||||
ptr_w <= pW;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
proc_ptr_r:
|
|
||||||
process(rst, clk, pR_next, pR, rinc)
|
|
||||||
begin
|
|
||||||
if rst = '1' then
|
|
||||||
pR <= to_unsigned(0, addr_width);
|
|
||||||
pR_next <= to_unsigned(0, addr_width);
|
|
||||||
elsif rising_edge(clk) then
|
|
||||||
if rinc = '1' then
|
|
||||||
pR <= pR_next;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
pR_next <= pR;
|
|
||||||
if rinc = '1' then
|
|
||||||
pR_next <= pR + 1;
|
|
||||||
end if;
|
|
||||||
ptr_r <= pR_next;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
end Behavioral;
|
|
||||||
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
LIBRARY IEEE;
|
|
||||||
USE IEEE.STD_LOGIC_1164.ALL;
|
|
||||||
USE IEEE.NUMERIC_STD.ALL;
|
|
||||||
use std.textio.all; -- Imports the standard textio package.
|
|
||||||
|
|
||||||
use work.utils_pkg.all; -- Imports the standard textio package.
|
|
||||||
|
|
||||||
ENTITY crc32 IS
|
|
||||||
Generic
|
|
||||||
(
|
|
||||||
crc32_init : unsigned(31 downto 0) := X"00000000"
|
|
||||||
);
|
|
||||||
Port
|
|
||||||
(
|
|
||||||
rst : in STD_LOGIC;
|
|
||||||
clk : in STD_LOGIC;
|
|
||||||
din_vld : in STD_LOGIC;
|
|
||||||
din : in unsigned(7 downto 0);
|
|
||||||
crc32_vld : out STD_LOGIC;
|
|
||||||
crc32_out : out unsigned(31 downto 0)
|
|
||||||
|
|
||||||
);
|
|
||||||
END crc32;
|
|
||||||
|
|
||||||
ARCHITECTURE behavior OF crc32 IS
|
|
||||||
|
|
||||||
type crc_table_t is array (0 to 15) of unsigned(31 downto 0);
|
|
||||||
|
|
||||||
constant crc_table : crc_table_t :=
|
|
||||||
(
|
|
||||||
X"4DBDF21C", X"500AE278", X"76D3D2D4", X"6B64C2B0",
|
|
||||||
X"3B61B38C", X"26D6A3E8", X"000F9344", X"1DB88320",
|
|
||||||
X"A005713C", X"BDB26158", X"9B6B51F4", X"86DC4190",
|
|
||||||
X"D6D930AC", X"CB6E20C8", X"EDB71064", X"F0000000"
|
|
||||||
);
|
|
||||||
|
|
||||||
signal crc0 : unsigned(31 downto 0);
|
|
||||||
signal crc1 : unsigned(31 downto 0);
|
|
||||||
signal crc2 : unsigned(31 downto 0);
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
begin
|
|
||||||
|
|
||||||
crc1 <= X"0" & crc0(31 downto 4) xor crc_table(to_integer(crc0(3 downto 0) xor din(3 downto 0)));
|
|
||||||
crc2 <= X"0" & crc1(31 downto 4) xor crc_table(to_integer(crc1(3 downto 0) xor din(7 downto 4)));
|
|
||||||
|
|
||||||
crc32_out <= crc0;
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if rst = '1' then
|
|
||||||
crc0 <= crc32_init;
|
|
||||||
crc32_vld <= '0';
|
|
||||||
elsif din_vld = '1' then
|
|
||||||
crc0 <= crc2;
|
|
||||||
crc32_vld <= '1';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
end behavior;
|
|
||||||
@@ -1,559 +0,0 @@
|
|||||||
LIBRARY IEEE;
|
|
||||||
USE IEEE.STD_LOGIC_1164.ALL;
|
|
||||||
USE IEEE.NUMERIC_STD.ALL;
|
|
||||||
use std.textio.all; -- Imports the standard textio package.
|
|
||||||
|
|
||||||
use work.emac_types.all;
|
|
||||||
use work.utils_pkg.all;
|
|
||||||
|
|
||||||
ENTITY emac_rx IS
|
|
||||||
Generic
|
|
||||||
(
|
|
||||||
f_sysclk : real := 100.0;
|
|
||||||
RAM_SIZE : natural := 2048
|
|
||||||
);
|
|
||||||
Port
|
|
||||||
(
|
|
||||||
clk : in STD_LOGIC;
|
|
||||||
rst : in STD_LOGIC;
|
|
||||||
dout_vld : out STD_LOGIC;
|
|
||||||
dout : out unsigned(31 downto 0);
|
|
||||||
ctrl_in : in rx_ctrl_in_t;
|
|
||||||
ctrl_out : out rx_ctrl_out_t;
|
|
||||||
mii_rx_clk : in STD_LOGIC;
|
|
||||||
mii_rx_dv : in STD_LOGIC;
|
|
||||||
mii_rx_er : in STD_LOGIC;
|
|
||||||
mii_rx : in unsigned(7 downto 0);
|
|
||||||
mii_crs : in STD_LOGIC;
|
|
||||||
mii_col : in STD_LOGIC
|
|
||||||
|
|
||||||
);
|
|
||||||
END emac_rx;
|
|
||||||
|
|
||||||
ARCHITECTURE behavior OF emac_rx IS
|
|
||||||
|
|
||||||
constant RAM_ADDR_WIDTH : natural := NextExpBaseTwo(RAM_SIZE);
|
|
||||||
|
|
||||||
subtype word_ptr_t is unsigned(RAM_ADDR_WIDTH-1 downto 0);
|
|
||||||
|
|
||||||
-- Signals for EMAC connections
|
|
||||||
signal cmd_fifo_din : unsigned(2*word_ptr_t'length+2 downto 0);
|
|
||||||
signal cmd_fifo_dout : unsigned(2*word_ptr_t'length+2 downto 0);
|
|
||||||
signal cmd_fifo_we : std_logic;
|
|
||||||
signal cmd_fifo_re : std_logic;
|
|
||||||
signal cmd_fifo_empty : std_logic;
|
|
||||||
signal cmd_fifo_full : std_logic;
|
|
||||||
|
|
||||||
signal reset_en : std_logic;
|
|
||||||
|
|
||||||
signal host_ptr : word_ptr_t;
|
|
||||||
signal host_ram_limit : word_ptr_t;
|
|
||||||
signal host_ram_base : word_ptr_t;
|
|
||||||
|
|
||||||
signal commit_en : std_logic;
|
|
||||||
|
|
||||||
signal xfer_ram_limit : word_ptr_t;
|
|
||||||
signal xfer_ram_full : std_logic;
|
|
||||||
signal xfer_base : word_ptr_t;
|
|
||||||
signal xfer_ptr : word_ptr_t;
|
|
||||||
signal xfer_en : std_logic;
|
|
||||||
signal xfer_set : std_logic;
|
|
||||||
signal xfer_vld : std_logic;
|
|
||||||
signal xfer_promiscious : std_logic;
|
|
||||||
|
|
||||||
signal ram_en_a : std_logic;
|
|
||||||
signal ram_we_a : std_logic;
|
|
||||||
signal ram_addr_a : word_ptr_t;
|
|
||||||
signal ram_din_a : unsigned(31 downto 0);
|
|
||||||
signal ram_dout_b : unsigned(31 downto 0);
|
|
||||||
signal ram_en_b : std_logic;
|
|
||||||
signal ram_addr_b : word_ptr_t;
|
|
||||||
|
|
||||||
signal sipo32_din : unsigned(7 downto 0);
|
|
||||||
signal sipo32_din_vld : std_logic;
|
|
||||||
signal sipo32_dout : unsigned(31 downto 0);
|
|
||||||
signal sipo32_dout_be : unsigned(3 downto 0);
|
|
||||||
signal sipo32_dout_vld : std_logic;
|
|
||||||
signal sipo32_dout_en : std_logic;
|
|
||||||
signal sipo32_en : std_logic;
|
|
||||||
signal sipo32_rst : std_logic;
|
|
||||||
|
|
||||||
signal sipo8_dout : unsigned(7 downto 0);
|
|
||||||
signal sipo8_rst : std_logic;
|
|
||||||
signal sipo8_dout_vld : std_logic;
|
|
||||||
signal sipo8_dout_en : std_logic;
|
|
||||||
signal sipo8_en : std_logic;
|
|
||||||
|
|
||||||
signal byte_count_rst : std_logic;
|
|
||||||
signal byte_count : word_ptr_t;
|
|
||||||
|
|
||||||
signal reset_pipe : unsigned(31 downto 0);
|
|
||||||
|
|
||||||
signal preamble_en : std_logic;
|
|
||||||
signal preamble_rdy : std_logic;
|
|
||||||
signal preamble_bsy : std_logic;
|
|
||||||
signal preamble_OK : std_logic;
|
|
||||||
|
|
||||||
signal mac_chk_rdy : std_logic;
|
|
||||||
signal mac_chk_BC : std_logic;
|
|
||||||
signal mac_chk_OK : std_logic;
|
|
||||||
signal mac_chk_num_OK : natural range 0 to 6;
|
|
||||||
signal mac_chk_num_BC : natural range 0 to 6;
|
|
||||||
signal mac_chk_cnt : natural range 0 to 5;
|
|
||||||
signal mac_addr : mac_addr_t;
|
|
||||||
signal mac_chk_addr : mac_addr_t;
|
|
||||||
|
|
||||||
signal Gbps_en : std_logic;
|
|
||||||
signal fcs_chk_en : std_logic;
|
|
||||||
signal rx_en : std_logic;
|
|
||||||
|
|
||||||
signal fcs_vld : std_logic;
|
|
||||||
signal fcs_din_vld : std_logic;
|
|
||||||
signal fcs_din : unsigned(7 downto 0);
|
|
||||||
signal fcs : unsigned(31 downto 0);
|
|
||||||
signal fcs_chk_OK : std_logic;
|
|
||||||
|
|
||||||
type host_state_t is (host_init, host_flush, host_idle);
|
|
||||||
signal host_s, host_sn : host_state_t;
|
|
||||||
|
|
||||||
type xfer_state_t is (xfer_init, xfer_idle, xfer_preamble, xfer_setup, xfer_active, xfer_finish, xfer_commit);
|
|
||||||
signal xfer_s, xfer_sn : xfer_state_t;
|
|
||||||
|
|
||||||
alias cmd_mac_ok_in is cmd_fifo_din(cmd_fifo_din'left);
|
|
||||||
alias cmd_bcast_in is cmd_fifo_din(cmd_fifo_din'left-1);
|
|
||||||
alias cmd_pkt_valid_in is cmd_fifo_din(cmd_fifo_din'left-2);
|
|
||||||
alias cmd_nbytes_in is cmd_fifo_din(word_ptr_t'length-1 downto 0);
|
|
||||||
alias cmd_base_in is cmd_fifo_din(2*word_ptr_t'length-1 downto word_ptr_t'length);
|
|
||||||
|
|
||||||
alias cmd_mac_ok_out is cmd_fifo_dout(cmd_fifo_dout'left);
|
|
||||||
alias cmd_bcast_out is cmd_fifo_dout(cmd_fifo_dout'left-1);
|
|
||||||
alias cmd_pkt_valid_out is cmd_fifo_dout(cmd_fifo_dout'left-2);
|
|
||||||
alias cmd_nbytes_out is cmd_fifo_dout(word_ptr_t'length-1 downto 0);
|
|
||||||
alias cmd_base_out is cmd_fifo_dout(2*word_ptr_t'length-1 downto word_ptr_t'length);
|
|
||||||
|
|
||||||
begin
|
|
||||||
|
|
||||||
ctrl_out.rx_size <= resize(cmd_nbytes_out, 16);
|
|
||||||
ctrl_out.pkt_avail <= not cmd_fifo_empty;
|
|
||||||
ctrl_out.pkt_valid <= cmd_pkt_valid_out;
|
|
||||||
ctrl_out.pkt_bcast <= cmd_bcast_out;
|
|
||||||
ctrl_out.pkt_mac_match <= cmd_mac_ok_out;
|
|
||||||
ctrl_out.reset_busy <= reset_en;
|
|
||||||
|
|
||||||
dout <= ram_dout_b;
|
|
||||||
|
|
||||||
ram_en_b <= '1';
|
|
||||||
ram_addr_b <= host_ptr;
|
|
||||||
|
|
||||||
ram_en_a <= '1';
|
|
||||||
ram_din_a <= sipo32_dout;
|
|
||||||
ram_addr_a <= xfer_ptr;
|
|
||||||
ram_we_a <= xfer_en and sipo32_dout_vld;
|
|
||||||
|
|
||||||
xfer_vld <= (mac_chk_OK or mac_chk_BC or xfer_promiscious) and (not fcs_chk_en or fcs_chk_OK);
|
|
||||||
cmd_fifo_we <= commit_en and xfer_vld;
|
|
||||||
cmd_fifo_re <= ctrl_in.pkt_free_en;
|
|
||||||
|
|
||||||
cmd_pkt_valid_in <= fcs_chk_OK;
|
|
||||||
cmd_mac_ok_in <= mac_chk_OK;
|
|
||||||
cmd_bcast_in <= mac_chk_BC;
|
|
||||||
cmd_nbytes_in <= byte_count;
|
|
||||||
cmd_base_in <= xfer_base;
|
|
||||||
|
|
||||||
|
|
||||||
reset_en <= reset_pipe(reset_pipe'left);
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
reset_gen:
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if rst = '1' or ctrl_in.reset = '1' then
|
|
||||||
reset_pipe <= (others => '1');
|
|
||||||
else
|
|
||||||
reset_pipe <= reset_pipe(reset_pipe'left-1 downto 0) & '0';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
-- Fill stuff
|
|
||||||
------------------------------------------------------------------
|
|
||||||
fill_pointer:
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
dout_vld <= ctrl_in.pkt_read_en;
|
|
||||||
if ctrl_in.pkt_req_en = '1' then
|
|
||||||
host_ptr <= cmd_base_out;
|
|
||||||
elsif ctrl_in.pkt_read_en = '1' then
|
|
||||||
host_ptr <= host_ptr + 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
-- Transfer stuff
|
|
||||||
------------------------------------------------------------------
|
|
||||||
host2xfer_sync_register:
|
|
||||||
process(mii_rx_clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(mii_rx_clk) then
|
|
||||||
xfer_promiscious <= ctrl_in.promiscious;
|
|
||||||
Gbps_en <= ctrl_in.Gbps_en;
|
|
||||||
fcs_chk_en <= ctrl_in.fcs_chk_en;
|
|
||||||
mac_addr <= ctrl_in.mac_addr;
|
|
||||||
xfer_ram_limit <= host_ram_limit;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
host_limit_register:
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
host_ram_base <= xfer_base;
|
|
||||||
if cmd_fifo_empty = '1' then
|
|
||||||
host_ram_limit <= host_ram_base - 1;
|
|
||||||
else
|
|
||||||
host_ram_limit <= cmd_base_out - 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
end process;
|
|
||||||
|
|
||||||
xfer_ram_full_detect:
|
|
||||||
process(mii_rx_clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(mii_rx_clk) then
|
|
||||||
if xfer_set = '1' or reset_en = '1' then
|
|
||||||
xfer_ram_full <= '0';
|
|
||||||
elsif xfer_en = '1' and sipo32_dout_vld = '1' then
|
|
||||||
if xfer_ptr = xfer_ram_limit then
|
|
||||||
xfer_ram_full <= '1';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
end process;
|
|
||||||
|
|
||||||
xfer_base_logic:
|
|
||||||
process(mii_rx_clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(mii_rx_clk) then
|
|
||||||
if reset_en = '1' then
|
|
||||||
xfer_base <= (others => '0');
|
|
||||||
elsif commit_en = '1' and xfer_vld = '1' then
|
|
||||||
xfer_base <= xfer_ptr;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
xfer_pointer:
|
|
||||||
process(mii_rx_clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(mii_rx_clk) then
|
|
||||||
if xfer_set = '1' then
|
|
||||||
xfer_ptr <= xfer_base;
|
|
||||||
elsif xfer_en = '1' and sipo32_dout_vld = '1' then
|
|
||||||
xfer_ptr <= xfer_ptr + 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
byte_counter:
|
|
||||||
process(mii_rx_clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(mii_rx_clk) then
|
|
||||||
if byte_count_rst = '1' then
|
|
||||||
if fcs_chk_en = '0' then
|
|
||||||
byte_count <= to_unsigned(0, RAM_ADDR_WIDTH);
|
|
||||||
else
|
|
||||||
byte_count <= unsigned(to_signed(-4, RAM_ADDR_WIDTH));
|
|
||||||
end if;
|
|
||||||
elsif sipo32_en = '1' and sipo32_din_vld = '1' then
|
|
||||||
byte_count <= byte_count + 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
preamble_sync_logic:
|
|
||||||
process(mii_rx_clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(mii_rx_clk) then
|
|
||||||
if preamble_en = '0' then
|
|
||||||
preamble_rdy <= '0';
|
|
||||||
preamble_bsy <= '0';
|
|
||||||
preamble_OK <= '0';
|
|
||||||
elsif sipo32_din_vld = '1' then
|
|
||||||
if preamble_bsy = '1' then
|
|
||||||
if sipo32_din = X"D5" then
|
|
||||||
preamble_OK <= '1';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
if sipo32_din /= X"55" then
|
|
||||||
preamble_bsy <= '0';
|
|
||||||
preamble_rdy <= preamble_bsy;
|
|
||||||
else
|
|
||||||
preamble_bsy <= '1';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
mac_check_logic:
|
|
||||||
process(mii_rx_clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(mii_rx_clk) then
|
|
||||||
if byte_count_rst = '1' then
|
|
||||||
mac_chk_rdy <= '0';
|
|
||||||
mac_chk_OK <= '0';
|
|
||||||
mac_chk_BC <= '0';
|
|
||||||
mac_chk_cnt <= 0;
|
|
||||||
mac_chk_num_OK <= 0;
|
|
||||||
mac_chk_num_BC <= 0;
|
|
||||||
mac_chk_addr <= mac_addr;
|
|
||||||
elsif mac_chk_rdy = '1' then
|
|
||||||
if mac_chk_num_OK = 6 then
|
|
||||||
mac_chk_OK <= '1';
|
|
||||||
end if;
|
|
||||||
if mac_chk_num_BC = 6 then
|
|
||||||
mac_chk_BC <= '1';
|
|
||||||
end if;
|
|
||||||
elsif sipo32_din_vld = '1' and sipo32_en = '1' then
|
|
||||||
if sipo32_din = mac_chk_addr(mac_chk_cnt) then
|
|
||||||
mac_chk_num_OK <= mac_chk_num_OK + 1;
|
|
||||||
end if;
|
|
||||||
if sipo32_din = X"FF" then
|
|
||||||
mac_chk_num_BC <= mac_chk_num_BC + 1;
|
|
||||||
end if;
|
|
||||||
if mac_chk_cnt /= 5 then
|
|
||||||
mac_chk_cnt <= mac_chk_cnt + 1;
|
|
||||||
else
|
|
||||||
mac_chk_rdy <= '1';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
xfer_state_next:
|
|
||||||
process(mii_rx_clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(mii_rx_clk) then
|
|
||||||
if reset_en = '1' then
|
|
||||||
xfer_s <= xfer_init;
|
|
||||||
else
|
|
||||||
xfer_s <= xfer_sn;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
xfer_state:
|
|
||||||
process(xfer_s, rx_en, sipo32_dout_en, preamble_bsy, preamble_OK, xfer_ram_full)
|
|
||||||
begin
|
|
||||||
|
|
||||||
commit_en <= '0';
|
|
||||||
xfer_set <= '0';
|
|
||||||
xfer_en <= '0';
|
|
||||||
sipo32_rst <= '0';
|
|
||||||
sipo32_en <= '0';
|
|
||||||
byte_count_rst <= '0';
|
|
||||||
preamble_en <= '0';
|
|
||||||
|
|
||||||
xfer_sn <= xfer_s;
|
|
||||||
|
|
||||||
case xfer_s is
|
|
||||||
|
|
||||||
when xfer_init =>
|
|
||||||
sipo32_rst <= '1';
|
|
||||||
if rx_en = '0' then
|
|
||||||
xfer_sn <= xfer_idle;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when xfer_idle =>
|
|
||||||
preamble_en <= rx_en;
|
|
||||||
if preamble_bsy = '1' then
|
|
||||||
xfer_sn <= xfer_preamble;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when xfer_preamble =>
|
|
||||||
preamble_en <= rx_en;
|
|
||||||
byte_count_rst <= preamble_bsy;
|
|
||||||
sipo32_en <= rx_en and not preamble_bsy;
|
|
||||||
if preamble_bsy = '0' then
|
|
||||||
xfer_sn <= xfer_init;
|
|
||||||
if preamble_OK = '1' then
|
|
||||||
xfer_sn <= xfer_setup;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when xfer_setup =>
|
|
||||||
xfer_set <= '1';
|
|
||||||
sipo32_en <= rx_en;
|
|
||||||
xfer_en <= sipo32_dout_en;
|
|
||||||
xfer_sn <= xfer_active;
|
|
||||||
|
|
||||||
when xfer_active =>
|
|
||||||
xfer_en <= sipo32_dout_en;
|
|
||||||
sipo32_en <= rx_en;
|
|
||||||
if xfer_ram_full = '1' then
|
|
||||||
xfer_sn <= xfer_init;
|
|
||||||
elsif rx_en = '0' then
|
|
||||||
xfer_sn <= xfer_finish;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when xfer_finish =>
|
|
||||||
xfer_en <= sipo32_dout_en;
|
|
||||||
if sipo32_dout_en = '0' then
|
|
||||||
xfer_sn <= xfer_commit;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when xfer_commit =>
|
|
||||||
commit_en <= '1';
|
|
||||||
xfer_sn <= xfer_init;
|
|
||||||
|
|
||||||
when others =>
|
|
||||||
xfer_sn <= xfer_init;
|
|
||||||
end case;
|
|
||||||
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
-- Instantiate synchronous FIFO
|
|
||||||
inst_cmd_fifo: entity work.fifo_async
|
|
||||||
GENERIC MAP
|
|
||||||
(
|
|
||||||
addr_width => NextExpBaseTwo(RAM_SIZE) - 4, -- RAMSIZE(words)/MIN_PACKET_LEN(words)
|
|
||||||
data_width => cmd_fifo_din'length,
|
|
||||||
do_last_read_update => false
|
|
||||||
)
|
|
||||||
PORT MAP
|
|
||||||
(
|
|
||||||
rst => reset_en,
|
|
||||||
clk_w => mii_rx_clk,
|
|
||||||
clk_r => clk,
|
|
||||||
we => cmd_fifo_we,
|
|
||||||
re => cmd_fifo_re,
|
|
||||||
fifo_full => cmd_fifo_full,
|
|
||||||
fifo_empty => cmd_fifo_empty,
|
|
||||||
fifo_afull => open,
|
|
||||||
fifo_aempty => open,
|
|
||||||
data_w => cmd_fifo_din,
|
|
||||||
data_r => cmd_fifo_dout
|
|
||||||
);
|
|
||||||
|
|
||||||
inst_ram : entity work.dpram_1w1r
|
|
||||||
GENERIC MAP
|
|
||||||
(
|
|
||||||
addr_width => RAM_ADDR_WIDTH,
|
|
||||||
data_width => 32
|
|
||||||
)
|
|
||||||
PORT MAP
|
|
||||||
(
|
|
||||||
clka => mii_rx_clk,
|
|
||||||
clkb => clk,
|
|
||||||
en_a => ram_en_a,
|
|
||||||
en_b => ram_en_b,
|
|
||||||
we_a => ram_we_a,
|
|
||||||
addr_a => ram_addr_a,
|
|
||||||
addr_b => ram_addr_b,
|
|
||||||
din_a => ram_din_a,
|
|
||||||
dout_b => ram_dout_b
|
|
||||||
);
|
|
||||||
|
|
||||||
inst_sipo32 : entity work.sipo
|
|
||||||
GENERIC MAP
|
|
||||||
(
|
|
||||||
data_width_in => 8,
|
|
||||||
data_width_out => 32,
|
|
||||||
msb_first => true
|
|
||||||
)
|
|
||||||
PORT MAP
|
|
||||||
(
|
|
||||||
rst => sipo32_rst,
|
|
||||||
clk => mii_rx_clk,
|
|
||||||
din_vld => sipo32_din_vld,
|
|
||||||
din_en => sipo32_en,
|
|
||||||
din => sipo32_din,
|
|
||||||
dout_be => sipo32_dout_be,
|
|
||||||
dout_vld => sipo32_dout_vld,
|
|
||||||
dout => sipo32_dout,
|
|
||||||
dout_en => sipo32_dout_en
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
inst_fcs: entity work.crc32
|
|
||||||
GENERIC MAP
|
|
||||||
(
|
|
||||||
crc32_init => X"00000000"
|
|
||||||
)
|
|
||||||
PORT MAP
|
|
||||||
(
|
|
||||||
rst => byte_count_rst,
|
|
||||||
clk => mii_rx_clk,
|
|
||||||
din_vld => fcs_din_vld,
|
|
||||||
din => fcs_din,
|
|
||||||
crc32_vld => fcs_vld,
|
|
||||||
crc32_out => fcs
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
fcs_din <= sipo32_din;
|
|
||||||
fcs_din_vld <= sipo32_en and sipo32_din_vld;
|
|
||||||
|
|
||||||
fcs_chk_register:
|
|
||||||
process(mii_rx_clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(mii_rx_clk) then
|
|
||||||
if fcs_vld = '1' then
|
|
||||||
fcs_chk_OK <= '0';
|
|
||||||
if fcs = X"2144DF1C" then
|
|
||||||
fcs_chk_OK <= '1';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
mii_input_register:
|
|
||||||
process(mii_rx_clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(mii_rx_clk) then
|
|
||||||
if Gbps_en = '1' then
|
|
||||||
sipo32_din <= mii_rx;
|
|
||||||
sipo32_din_vld <= not mii_rx_er;
|
|
||||||
rx_en <= mii_rx_dv;
|
|
||||||
else
|
|
||||||
sipo32_din <= sipo8_dout;
|
|
||||||
sipo32_din_vld <= sipo8_dout_vld;
|
|
||||||
rx_en <= sipo8_dout_en;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
inst_sipo_8bit : entity work.sipo
|
|
||||||
GENERIC MAP
|
|
||||||
(
|
|
||||||
data_width_in => 4,
|
|
||||||
data_width_out => 8,
|
|
||||||
msb_first => false
|
|
||||||
)
|
|
||||||
PORT MAP
|
|
||||||
(
|
|
||||||
rst => sipo8_rst,
|
|
||||||
clk => mii_rx_clk,
|
|
||||||
din_vld => mii_rx_dv,
|
|
||||||
din_en => mii_rx_dv,
|
|
||||||
din => mii_rx(3 downto 0),
|
|
||||||
dout_be => open,
|
|
||||||
dout_vld => sipo8_dout_vld,
|
|
||||||
dout => sipo8_dout,
|
|
||||||
dout_en => sipo8_dout_en
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
sipo8_rst <= reset_en or not (mii_rx_dv or sipo8_dout_en);
|
|
||||||
sipo8_en <= not mii_rx_er;
|
|
||||||
|
|
||||||
end behavior;
|
|
||||||
@@ -1,305 +0,0 @@
|
|||||||
LIBRARY IEEE;
|
|
||||||
USE IEEE.STD_LOGIC_1164.ALL;
|
|
||||||
USE IEEE.NUMERIC_STD.ALL;
|
|
||||||
use std.textio.all; -- Imports the standard textio package.
|
|
||||||
|
|
||||||
use work.emac_types.all;
|
|
||||||
use work.utils_pkg.all;
|
|
||||||
|
|
||||||
ENTITY emac_top_jb IS
|
|
||||||
Generic
|
|
||||||
(
|
|
||||||
f_sysclk : real := 100.0;
|
|
||||||
TX_RAM_SIZE : natural := 2048;
|
|
||||||
RX_RAM_SIZE : natural := 2048
|
|
||||||
);
|
|
||||||
Port
|
|
||||||
(
|
|
||||||
CLK_I : in STD_LOGIC;
|
|
||||||
RST_I : in STD_LOGIC;
|
|
||||||
INT_O : out STD_LOGIC;
|
|
||||||
CYC_I : in STD_LOGIC;
|
|
||||||
STB_I : in STD_LOGIC;
|
|
||||||
SEL_I : in unsigned(3 downto 0);
|
|
||||||
WE_I : in STD_LOGIC;
|
|
||||||
ACK_O : out STD_LOGIC;
|
|
||||||
SRDY_O : out STD_LOGIC;
|
|
||||||
MRDY_I : in STD_LOGIC;
|
|
||||||
ADDR_I : in unsigned(31 downto 0);
|
|
||||||
DAT_I : in unsigned(31 downto 0);
|
|
||||||
DAT_O : out unsigned(31 downto 0);
|
|
||||||
mii_rx_clk : in STD_LOGIC;
|
|
||||||
mii_rx_dv : in STD_LOGIC;
|
|
||||||
mii_rx_er : in STD_LOGIC;
|
|
||||||
mii_rx : in unsigned(7 downto 0);
|
|
||||||
mii_tx_clk : in STD_LOGIC;
|
|
||||||
mii_tx_en : out STD_LOGIC;
|
|
||||||
mii_tx_er : out STD_LOGIC;
|
|
||||||
mii_tx : out unsigned(7 downto 0);
|
|
||||||
mii_gtx_clk : out STD_LOGIC;
|
|
||||||
mii_crs : in STD_LOGIC;
|
|
||||||
mii_col : in STD_LOGIC
|
|
||||||
|
|
||||||
);
|
|
||||||
END emac_top_jb;
|
|
||||||
|
|
||||||
ARCHITECTURE behavior OF emac_top_jb IS
|
|
||||||
|
|
||||||
-- Signals for EMAC connections
|
|
||||||
signal tx_ctrl_in : tx_ctrl_in_t;
|
|
||||||
signal tx_ctrl_out : tx_ctrl_out_t;
|
|
||||||
signal tx_din : unsigned(31 downto 0);
|
|
||||||
signal tx_din_vld : std_logic;
|
|
||||||
|
|
||||||
signal rx_ctrl_in : rx_ctrl_in_t;
|
|
||||||
signal rx_ctrl_out : rx_ctrl_out_t;
|
|
||||||
|
|
||||||
signal rx_dout : unsigned(31 downto 0);
|
|
||||||
signal rx_dout_vld : std_logic;
|
|
||||||
|
|
||||||
signal rx_int_en : std_logic;
|
|
||||||
signal tx_int_en : std_logic;
|
|
||||||
signal irq_rx : std_logic;
|
|
||||||
signal irq_tx : std_logic;
|
|
||||||
|
|
||||||
signal ready : std_logic;
|
|
||||||
|
|
||||||
signal read : std_logic;
|
|
||||||
signal write : std_logic;
|
|
||||||
signal data_read : std_logic;
|
|
||||||
signal data_write : std_logic;
|
|
||||||
signal reg_read : std_logic;
|
|
||||||
signal reg_write : std_logic;
|
|
||||||
|
|
||||||
signal reg_addr : unsigned(3 downto 0);
|
|
||||||
|
|
||||||
begin
|
|
||||||
|
|
||||||
mii_gtx_clk <= '0';
|
|
||||||
|
|
||||||
SRDY_O <= CYC_I and ready;
|
|
||||||
read <= STB_I and CYC_I and not WE_I;
|
|
||||||
write <= STB_I and CYC_I and WE_I;
|
|
||||||
data_read <= read and ADDR_I(15);
|
|
||||||
data_write <= write and ADDR_I(15);
|
|
||||||
reg_read <= read and not ADDR_I(15);
|
|
||||||
reg_write <= write and not ADDR_I(15);
|
|
||||||
reg_addr <= ADDR_I(5 downto 2);
|
|
||||||
|
|
||||||
ready <= not tx_ctrl_in.pkt_alloc_en;
|
|
||||||
|
|
||||||
tx_din_vld <= data_write;
|
|
||||||
tx_din <= DAT_I;
|
|
||||||
|
|
||||||
rx_ctrl_in.pkt_read_en <= data_read;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
registers_write:
|
|
||||||
process(CLK_I)
|
|
||||||
begin
|
|
||||||
if rising_edge(CLK_I) then
|
|
||||||
tx_ctrl_in.pkt_alloc_en <= '0';
|
|
||||||
tx_ctrl_in.pkt_commit_en <= '0';
|
|
||||||
tx_ctrl_in.reset <= '0';
|
|
||||||
rx_ctrl_in.pkt_free_en <= '0';
|
|
||||||
rx_ctrl_in.pkt_req_en <= '0';
|
|
||||||
rx_ctrl_in.reset <= '0';
|
|
||||||
if RST_I = '1' then
|
|
||||||
rx_int_en <= '0';
|
|
||||||
tx_int_en <= '0';
|
|
||||||
tx_ctrl_in.tx_size <= (others => '0');
|
|
||||||
rx_ctrl_in.mac_addr <= (X"03", X"02", X"01", X"00", X"07", X"06");
|
|
||||||
rx_ctrl_in.promiscious <= '0';
|
|
||||||
tx_ctrl_in.Gbps_en <= '0';
|
|
||||||
rx_ctrl_in.Gbps_en <= '0';
|
|
||||||
tx_ctrl_in.fcs_gen_en <= '0';
|
|
||||||
rx_ctrl_in.fcs_chk_en <= '0';
|
|
||||||
elsif reg_write = '1' then
|
|
||||||
|
|
||||||
-- 0x0000 .. 0x003C
|
|
||||||
case reg_addr is
|
|
||||||
|
|
||||||
-- 0x0000
|
|
||||||
when "0000" =>
|
|
||||||
rx_ctrl_in.reset <= DAT_I(31);
|
|
||||||
rx_ctrl_in.Gbps_en <= DAT_I(30);
|
|
||||||
rx_ctrl_in.fcs_chk_en <= DAT_I(29);
|
|
||||||
rx_ctrl_in.promiscious <= DAT_I(23);
|
|
||||||
rx_ctrl_in.pkt_req_en <= DAT_I(17);
|
|
||||||
rx_ctrl_in.pkt_free_en <= DAT_I(16);
|
|
||||||
rx_int_en <= DAT_I(4);
|
|
||||||
|
|
||||||
-- 0x0004
|
|
||||||
-- rx_size R/O
|
|
||||||
|
|
||||||
-- 0x0008
|
|
||||||
when "0010" =>
|
|
||||||
tx_ctrl_in.reset <= DAT_I(31);
|
|
||||||
tx_ctrl_in.Gbps_en <= DAT_I(30);
|
|
||||||
tx_ctrl_in.fcs_gen_en <= DAT_I(29);
|
|
||||||
tx_ctrl_in.pkt_alloc_en <= DAT_I(17);
|
|
||||||
tx_ctrl_in.pkt_commit_en <= DAT_I(16);
|
|
||||||
tx_int_en <= DAT_I(4);
|
|
||||||
|
|
||||||
-- 0x000C
|
|
||||||
when "0011" =>
|
|
||||||
tx_ctrl_in.tx_size <= DAT_I(15 downto 0);
|
|
||||||
|
|
||||||
-- 0x0010
|
|
||||||
-- Gap
|
|
||||||
|
|
||||||
-- 0x0014
|
|
||||||
-- Gap
|
|
||||||
|
|
||||||
-- 0x0018
|
|
||||||
when "0110" =>
|
|
||||||
rx_ctrl_in.mac_addr(0) <= DAT_I(31 downto 24);
|
|
||||||
rx_ctrl_in.mac_addr(1) <= DAT_I(23 downto 16);
|
|
||||||
rx_ctrl_in.mac_addr(2) <= DAT_I(15 downto 8);
|
|
||||||
rx_ctrl_in.mac_addr(3) <= DAT_I(7 downto 0);
|
|
||||||
|
|
||||||
-- 0x001C
|
|
||||||
when "0111" =>
|
|
||||||
rx_ctrl_in.mac_addr(4) <= DAT_I(31 downto 24);
|
|
||||||
rx_ctrl_in.mac_addr(5) <= DAT_I(23 downto 16);
|
|
||||||
|
|
||||||
-- 0x0020 .. 0x003C
|
|
||||||
-- Gap
|
|
||||||
when others => null;
|
|
||||||
|
|
||||||
end case;
|
|
||||||
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
registers_read:
|
|
||||||
process(CLK_I)
|
|
||||||
begin
|
|
||||||
if rising_edge(CLK_I) then
|
|
||||||
ACK_O <= rx_dout_vld;
|
|
||||||
DAT_O <= rx_dout;
|
|
||||||
if reg_read = '1' then
|
|
||||||
|
|
||||||
-- 0x0000 .. 0x003C
|
|
||||||
case reg_addr is
|
|
||||||
|
|
||||||
-- 0x0000
|
|
||||||
when "0000" =>
|
|
||||||
ACK_O <= ready;
|
|
||||||
DAT_O <= (others => '0');
|
|
||||||
DAT_O(31) <= rx_ctrl_out.reset_busy;
|
|
||||||
DAT_O(30) <= rx_ctrl_in.Gbps_en;
|
|
||||||
DAT_O(29) <= rx_ctrl_in.fcs_chk_en;
|
|
||||||
DAT_O(23) <= rx_ctrl_in.promiscious;
|
|
||||||
DAT_O(19) <= rx_ctrl_out.pkt_bcast;
|
|
||||||
DAT_O(18) <= rx_ctrl_out.pkt_mac_match;
|
|
||||||
DAT_O(17) <= rx_ctrl_out.pkt_valid;
|
|
||||||
DAT_O(16) <= rx_ctrl_out.pkt_avail;
|
|
||||||
DAT_O(4) <= rx_int_en;
|
|
||||||
|
|
||||||
-- 0x0004
|
|
||||||
when "0001" =>
|
|
||||||
ACK_O <= '1';
|
|
||||||
DAT_O <= X"0000" & rx_ctrl_out.rx_size;
|
|
||||||
|
|
||||||
-- 0x0008
|
|
||||||
when "0010" =>
|
|
||||||
ACK_O <= ready;
|
|
||||||
DAT_O <= (others => '0');
|
|
||||||
DAT_O(31) <= tx_ctrl_out.reset_busy;
|
|
||||||
DAT_O(30) <= tx_ctrl_in.Gbps_en;
|
|
||||||
DAT_O(29) <= tx_ctrl_in.fcs_gen_en;
|
|
||||||
DAT_O(24) <= tx_ctrl_out.pkt_done;
|
|
||||||
DAT_O(17) <= tx_ctrl_out.pkt_alloc_req;
|
|
||||||
DAT_O(16) <= tx_ctrl_out.pkt_armed;
|
|
||||||
DAT_O(4) <= tx_int_en;
|
|
||||||
|
|
||||||
-- 0x000C
|
|
||||||
when "0011" =>
|
|
||||||
ACK_O <= '1';
|
|
||||||
DAT_O <= X"0000" & tx_ctrl_out.tx_size;
|
|
||||||
|
|
||||||
-- 0x0010
|
|
||||||
-- Gap
|
|
||||||
|
|
||||||
-- 0x0014
|
|
||||||
-- Gap
|
|
||||||
|
|
||||||
-- 0x0018
|
|
||||||
when "0110" =>
|
|
||||||
ACK_O <= '1';
|
|
||||||
DAT_O <= rx_ctrl_in.mac_addr(0) & rx_ctrl_in.mac_addr(1) & rx_ctrl_in.mac_addr(2) & rx_ctrl_in.mac_addr(3);
|
|
||||||
|
|
||||||
-- 0x001C
|
|
||||||
when "0111" =>
|
|
||||||
ACK_O <= '1';
|
|
||||||
DAT_O <= rx_ctrl_in.mac_addr(4) & rx_ctrl_in.mac_addr(5) & X"0000";
|
|
||||||
|
|
||||||
-- 0x0020 .. 0x003C
|
|
||||||
-- Gap
|
|
||||||
when others => null;
|
|
||||||
|
|
||||||
end case;
|
|
||||||
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
irq_register:
|
|
||||||
process(CLK_I)
|
|
||||||
begin
|
|
||||||
if rising_edge(CLK_I) then
|
|
||||||
INT_O <= irq_rx or irq_tx;
|
|
||||||
irq_tx <= tx_int_en and tx_ctrl_out.pkt_done;
|
|
||||||
irq_rx <= rx_int_en and rx_ctrl_out.pkt_avail;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
inst_emac_rx : entity work.emac_rx
|
|
||||||
GENERIC MAP
|
|
||||||
(
|
|
||||||
f_sysclk => f_sysclk,
|
|
||||||
RAM_SIZE => RX_RAM_SIZE
|
|
||||||
)
|
|
||||||
PORT MAP
|
|
||||||
(
|
|
||||||
clk => CLK_I,
|
|
||||||
rst => RST_I,
|
|
||||||
dout_vld => rx_dout_vld,
|
|
||||||
dout => rx_dout,
|
|
||||||
ctrl_in => rx_ctrl_in,
|
|
||||||
ctrl_out => rx_ctrl_out,
|
|
||||||
mii_rx_clk => mii_rx_clk,
|
|
||||||
mii_rx_dv => mii_rx_dv,
|
|
||||||
mii_rx_er => mii_rx_er,
|
|
||||||
mii_rx => mii_rx,
|
|
||||||
mii_crs => mii_crs,
|
|
||||||
mii_col => mii_col
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
inst_emac_tx : entity work.emac_tx
|
|
||||||
GENERIC MAP
|
|
||||||
(
|
|
||||||
f_sysclk => f_sysclk,
|
|
||||||
RAM_SIZE => TX_RAM_SIZE
|
|
||||||
)
|
|
||||||
PORT MAP
|
|
||||||
(
|
|
||||||
clk => CLK_I,
|
|
||||||
rst => RST_I,
|
|
||||||
din_vld => tx_din_vld,
|
|
||||||
din => tx_din,
|
|
||||||
ctrl_in => tx_ctrl_in,
|
|
||||||
ctrl_out => tx_ctrl_out,
|
|
||||||
mii_tx_clk => mii_tx_clk,
|
|
||||||
mii_tx_en => mii_tx_en,
|
|
||||||
mii_tx_er => mii_tx_er,
|
|
||||||
mii_tx => mii_tx
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
end behavior;
|
|
||||||
@@ -1,751 +0,0 @@
|
|||||||
LIBRARY IEEE;
|
|
||||||
USE IEEE.STD_LOGIC_1164.ALL;
|
|
||||||
USE IEEE.NUMERIC_STD.ALL;
|
|
||||||
use std.textio.all; -- Imports the standard textio package.
|
|
||||||
|
|
||||||
use work.emac_types.all;
|
|
||||||
use work.utils_pkg.all;
|
|
||||||
|
|
||||||
ENTITY emac_tx IS
|
|
||||||
Generic
|
|
||||||
(
|
|
||||||
f_sysclk : real := 100.0;
|
|
||||||
RAM_SIZE : natural := 2048
|
|
||||||
);
|
|
||||||
Port
|
|
||||||
(
|
|
||||||
clk : in STD_LOGIC;
|
|
||||||
rst : in STD_LOGIC;
|
|
||||||
din_vld : in STD_LOGIC;
|
|
||||||
din : in unsigned(31 downto 0);
|
|
||||||
ctrl_in : in tx_ctrl_in_t;
|
|
||||||
ctrl_out : out tx_ctrl_out_t;
|
|
||||||
mii_tx_clk : in STD_LOGIC;
|
|
||||||
mii_tx_en : out STD_LOGIC;
|
|
||||||
mii_tx_er : out STD_LOGIC;
|
|
||||||
mii_tx : out unsigned(7 downto 0)
|
|
||||||
|
|
||||||
);
|
|
||||||
END emac_tx;
|
|
||||||
|
|
||||||
ARCHITECTURE behavior OF emac_tx IS
|
|
||||||
|
|
||||||
constant RAM_ADDR_WIDTH : natural := NextExpBaseTwo(RAM_SIZE);
|
|
||||||
|
|
||||||
subtype word_ptr_t is unsigned(RAM_ADDR_WIDTH-1 downto 0);
|
|
||||||
|
|
||||||
signal cmd_fifo_din : unsigned(2*word_ptr_t'length-1 downto 0);
|
|
||||||
signal cmd_fifo_dout : unsigned(2*word_ptr_t'length-1 downto 0);
|
|
||||||
signal cmd_fifo_we : std_logic;
|
|
||||||
signal cmd_fifo_re : std_logic;
|
|
||||||
signal cmd_fifo_empty : std_logic;
|
|
||||||
signal cmd_fifo_full : std_logic;
|
|
||||||
|
|
||||||
signal reset_en : std_logic;
|
|
||||||
|
|
||||||
signal fill_base : word_ptr_t;
|
|
||||||
signal fill_size : word_ptr_t;
|
|
||||||
signal fill_cnt : word_ptr_t;
|
|
||||||
signal fill_ptr : word_ptr_t;
|
|
||||||
signal fill_pre_rdy : std_logic;
|
|
||||||
signal fill_bsy : std_logic;
|
|
||||||
signal fill_remain : unsigned(1 downto 0);
|
|
||||||
signal fill_set : std_logic;
|
|
||||||
signal fill_en : std_logic;
|
|
||||||
signal fill_cnt_en : std_logic;
|
|
||||||
|
|
||||||
signal alloc_OK : std_logic;
|
|
||||||
signal alloc_req : std_logic;
|
|
||||||
signal alloc_ack : std_logic;
|
|
||||||
signal alloc_size : word_ptr_t;
|
|
||||||
signal alloc_remain : unsigned(1 downto 0);
|
|
||||||
|
|
||||||
signal commit_en : std_logic;
|
|
||||||
signal uncommit_en : std_logic;
|
|
||||||
signal mem_alloc_en : std_logic;
|
|
||||||
signal mem_free_en : std_logic;
|
|
||||||
signal nwords_free : word_ptr_t;
|
|
||||||
signal mem_free_req : std_logic;
|
|
||||||
signal mem_free_ack : unsigned(1 downto 0);
|
|
||||||
|
|
||||||
signal xfer_size : word_ptr_t;
|
|
||||||
signal xfer_ptr : word_ptr_t;
|
|
||||||
signal xfer_cnt : word_ptr_t;
|
|
||||||
signal xfer_set : std_logic;
|
|
||||||
signal xfer_en : std_logic;
|
|
||||||
signal xfer_cnt_en : std_logic;
|
|
||||||
signal xfer_bsy : std_logic;
|
|
||||||
signal xfer_free_en : std_logic;
|
|
||||||
|
|
||||||
signal ram_en_a : std_logic;
|
|
||||||
signal ram_we_a : std_logic;
|
|
||||||
signal ram_addr_a : word_ptr_t;
|
|
||||||
signal ram_din_a : unsigned(35 downto 0);
|
|
||||||
signal ram_en_b : std_logic;
|
|
||||||
signal ram_addr_b : word_ptr_t;
|
|
||||||
signal ram_dout_b : unsigned(35 downto 0);
|
|
||||||
|
|
||||||
signal piso32_din : unsigned(31 downto 0);
|
|
||||||
signal piso32_din_be : unsigned(3 downto 0);
|
|
||||||
signal piso32_din_rdy : std_logic;
|
|
||||||
signal piso32_din_vld : std_logic;
|
|
||||||
|
|
||||||
signal piso32_dout : unsigned(7 downto 0);
|
|
||||||
signal piso32_dout_vld : std_logic;
|
|
||||||
signal piso32_dout_en : std_logic;
|
|
||||||
|
|
||||||
signal piso8_dout_vld : std_logic;
|
|
||||||
signal piso8_din_rdy : std_logic;
|
|
||||||
signal piso8_din_vld : std_logic;
|
|
||||||
signal piso8_dout : unsigned(3 downto 0);
|
|
||||||
signal piso8_din : unsigned(7 downto 0);
|
|
||||||
|
|
||||||
signal reset_pipe : unsigned(31 downto 0);
|
|
||||||
signal Gbps_en : std_logic;
|
|
||||||
signal fcs_gen_en : std_logic;
|
|
||||||
|
|
||||||
signal fcs_inject_en : std_logic;
|
|
||||||
signal fcs_rst : std_logic;
|
|
||||||
signal fcs_en : unsigned(7 downto 0);
|
|
||||||
signal fcs_vld : std_logic;
|
|
||||||
signal fcs_din_vld : std_logic;
|
|
||||||
signal fcs : unsigned(31 downto 0);
|
|
||||||
signal fcs_rev_endian : unsigned(31 downto 0);
|
|
||||||
|
|
||||||
signal mii_fifo_we : std_logic;
|
|
||||||
signal mii_fifo_re : std_logic;
|
|
||||||
signal mii_fifo_full : std_logic;
|
|
||||||
signal mii_fifo_empty : std_logic;
|
|
||||||
signal mii_fifo_re_dly : unsigned(23 downto 0);
|
|
||||||
|
|
||||||
signal mii_bsy : std_logic;
|
|
||||||
|
|
||||||
type host_state_t is (host_init, host_idle, host_alloc, host_setup, host_arm, host_fill, host_commit);
|
|
||||||
signal host_s, host_sn : host_state_t;
|
|
||||||
|
|
||||||
type xfer_state_t is (xfer_init, xfer_idle, xfer_start, xfer_preamble0, xfer_preamble1, xfer_active, xfer_crc, xfer_stop, xfer_finish);
|
|
||||||
signal xfer_s, xfer_sn : xfer_state_t;
|
|
||||||
|
|
||||||
type piso_byte_mask_array_t is array (0 to 3) of unsigned (3 downto 0);
|
|
||||||
constant piso_byte_mask_rom : piso_byte_mask_array_t :=
|
|
||||||
(
|
|
||||||
"1111",
|
|
||||||
"1000",
|
|
||||||
"1100",
|
|
||||||
"1110"
|
|
||||||
);
|
|
||||||
|
|
||||||
signal preamble_en : std_logic;
|
|
||||||
signal preamble_addr : natural range 0 to 1;
|
|
||||||
type preamble_t is array (0 to 1) of unsigned(31 downto 0);
|
|
||||||
constant preamble : preamble_t :=
|
|
||||||
(
|
|
||||||
X"55555555",
|
|
||||||
X"555555D5"
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
begin
|
|
||||||
|
|
||||||
ctrl_out.pkt_alloc_req <= alloc_req;
|
|
||||||
ctrl_out.pkt_done <= cmd_fifo_empty;
|
|
||||||
ctrl_out.reset_busy <= reset_en;
|
|
||||||
|
|
||||||
ram_en_a <= din_vld;
|
|
||||||
ram_we_a <= fill_bsy;
|
|
||||||
ram_din_a(31 downto 0) <= din;
|
|
||||||
ram_din_a(35 downto 32) <= piso_byte_mask_rom(to_integer(fill_remain)) when fill_pre_rdy = '1' else "1111";
|
|
||||||
ram_addr_a <= fill_ptr;
|
|
||||||
|
|
||||||
piso32_din <= preamble(preamble_addr) when preamble_en = '1' else fcs_rev_endian when fcs_inject_en = '1' else ram_dout_b(31 downto 0);
|
|
||||||
piso32_din_be <= "1111" when (preamble_en = '1' or fcs_inject_en = '1') else ram_dout_b(35 downto 32);
|
|
||||||
|
|
||||||
cmd_fifo_we <= commit_en;
|
|
||||||
cmd_fifo_re <= uncommit_en;
|
|
||||||
cmd_fifo_din <= fill_size & fill_base;
|
|
||||||
ram_en_b <= piso32_din_rdy;
|
|
||||||
ram_addr_b <= xfer_ptr;
|
|
||||||
|
|
||||||
reset_en <= reset_pipe(reset_pipe'left);
|
|
||||||
|
|
||||||
xfer_cnt_en <= xfer_bsy and piso32_din_rdy;
|
|
||||||
fill_cnt_en <= fill_bsy and din_vld;
|
|
||||||
mem_free_en <= not mem_free_ack(0) and mem_free_ack(1);
|
|
||||||
|
|
||||||
fcs_rev_endian <= fcs(7 downto 0) & fcs(15 downto 8) & fcs(23 downto 16) & fcs(31 downto 24);
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
reset_gen:
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if rst = '1' or ctrl_in.reset = '1' then
|
|
||||||
reset_pipe <= (others => '1');
|
|
||||||
else
|
|
||||||
reset_pipe <= reset_pipe(reset_pipe'left-1 downto 0) & '0';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
host_state_next:
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if reset_en = '1' then
|
|
||||||
host_s <= host_init;
|
|
||||||
else
|
|
||||||
host_s <= host_sn;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
host_state:
|
|
||||||
process(host_s, alloc_OK, fill_bsy, ctrl_in.pkt_commit_en, alloc_req, mem_free_ack)
|
|
||||||
begin
|
|
||||||
|
|
||||||
fill_set <= '0';
|
|
||||||
fill_en <= '0';
|
|
||||||
commit_en <= '0';
|
|
||||||
alloc_ack <= '0';
|
|
||||||
mem_alloc_en <= '0';
|
|
||||||
|
|
||||||
host_sn <= host_s;
|
|
||||||
|
|
||||||
case host_s is
|
|
||||||
|
|
||||||
when host_init =>
|
|
||||||
host_sn <= host_idle;
|
|
||||||
|
|
||||||
when host_idle =>
|
|
||||||
if alloc_req = '1' then
|
|
||||||
host_sn <= host_alloc;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when host_alloc =>
|
|
||||||
if alloc_OK = '1' then
|
|
||||||
host_sn <= host_setup;
|
|
||||||
else
|
|
||||||
host_sn <= host_idle;
|
|
||||||
alloc_ack <= '1';
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when host_setup =>
|
|
||||||
fill_set <= '1';
|
|
||||||
host_sn <= host_arm;
|
|
||||||
|
|
||||||
when host_arm =>
|
|
||||||
fill_en <= '1';
|
|
||||||
alloc_ack <= '1';
|
|
||||||
host_sn <= host_fill;
|
|
||||||
|
|
||||||
when host_fill =>
|
|
||||||
fill_en <= '1';
|
|
||||||
if alloc_req = '1' then
|
|
||||||
host_sn <= host_alloc;
|
|
||||||
elsif ctrl_in.pkt_commit_en = '1' then
|
|
||||||
host_sn <= host_commit;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when host_commit =>
|
|
||||||
if mem_free_ack = "00" then
|
|
||||||
commit_en <= '1';
|
|
||||||
mem_alloc_en <= '1';
|
|
||||||
host_sn <= host_idle;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when others =>
|
|
||||||
host_sn <= host_idle;
|
|
||||||
end case;
|
|
||||||
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
-- Allocation stuff
|
|
||||||
------------------------------------------------------------------
|
|
||||||
alloc_request_logic:
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if reset_en = '1' then
|
|
||||||
alloc_req <= '0';
|
|
||||||
elsif ctrl_in.pkt_alloc_en = '1' and alloc_req = '0' then
|
|
||||||
alloc_req <= '1';
|
|
||||||
alloc_remain <= ctrl_in.tx_size(1 downto 0);
|
|
||||||
alloc_size <= ctrl_in.tx_size(word_ptr_t'left+2 downto 2);
|
|
||||||
if ctrl_in.tx_size(1 downto 0) /= "00" then
|
|
||||||
alloc_size <= ctrl_in.tx_size(word_ptr_t'left+2 downto 2) + 1;
|
|
||||||
end if;
|
|
||||||
ctrl_out.tx_size <= resize(ctrl_in.tx_size(word_ptr_t'left downto 0), 16);
|
|
||||||
elsif alloc_ack = '1' then
|
|
||||||
alloc_req <= '0';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
host_alloc_armed_register:
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if reset_en = '1' or commit_en = '1' then
|
|
||||||
ctrl_out.pkt_armed <= '0';
|
|
||||||
elsif alloc_ack = '1' then
|
|
||||||
ctrl_out.pkt_armed <= alloc_OK;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
alloc_eval_logic:
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
alloc_OK <= '0';
|
|
||||||
if alloc_size < nwords_free then
|
|
||||||
alloc_OK <= '1';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
fill_base_logic:
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if reset_en = '1' then
|
|
||||||
fill_base <= (others => '0');
|
|
||||||
elsif commit_en = '1' then
|
|
||||||
fill_base <= fill_ptr;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
mem_free_counter:
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if reset_en = '1' then
|
|
||||||
nwords_free <= (others => '1');
|
|
||||||
elsif mem_alloc_en = '1' then
|
|
||||||
nwords_free <= nwords_free - fill_size;
|
|
||||||
elsif mem_free_en = '1' then
|
|
||||||
nwords_free <= nwords_free + xfer_size;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
mem_free_mii:
|
|
||||||
process(mii_tx_clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(mii_tx_clk) then
|
|
||||||
if reset_en = '1' then
|
|
||||||
mem_free_req <= '0';
|
|
||||||
elsif mem_free_ack(0) = '0' then
|
|
||||||
if xfer_free_en = '1' then
|
|
||||||
mem_free_req <= '1';
|
|
||||||
end if;
|
|
||||||
else
|
|
||||||
mem_free_req <= '0';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
mem_free_host:
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
mem_free_ack(1) <= mem_free_ack(0);
|
|
||||||
if reset_en = '1' then
|
|
||||||
mem_free_ack <= "00";
|
|
||||||
elsif mem_free_req = '1' then
|
|
||||||
if mem_alloc_en = '0' then
|
|
||||||
mem_free_ack(0) <= '1';
|
|
||||||
end if;
|
|
||||||
else
|
|
||||||
mem_free_ack(0) <= '0';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
-- Fill stuff
|
|
||||||
------------------------------------------------------------------
|
|
||||||
fill_counter:
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if fill_set = '1' then
|
|
||||||
fill_bsy <= '0';
|
|
||||||
fill_pre_rdy <= '0';
|
|
||||||
fill_cnt <= alloc_size;
|
|
||||||
fill_size <= alloc_size;
|
|
||||||
fill_remain <= alloc_remain;
|
|
||||||
elsif fill_en = '1' then
|
|
||||||
fill_bsy <= '1';
|
|
||||||
if fill_cnt_en = '1' or fill_bsy = '0' then
|
|
||||||
if fill_cnt /= 1 then
|
|
||||||
fill_cnt <= fill_cnt - 1;
|
|
||||||
else
|
|
||||||
fill_pre_rdy <= '1';
|
|
||||||
end if;
|
|
||||||
if fill_pre_rdy = '1' then
|
|
||||||
fill_bsy <= '0';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
fill_pointer:
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if fill_set = '1' then
|
|
||||||
fill_ptr <= fill_base;
|
|
||||||
elsif fill_cnt_en = '1' then
|
|
||||||
fill_ptr <= fill_ptr + 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
-- Transfer stuff
|
|
||||||
------------------------------------------------------------------
|
|
||||||
host2xfer_sync_register:
|
|
||||||
process(mii_tx_clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(mii_tx_clk) then
|
|
||||||
Gbps_en <= ctrl_in.Gbps_en;
|
|
||||||
fcs_gen_en <= ctrl_in.fcs_gen_en;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
xfer_counter:
|
|
||||||
process(mii_tx_clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(mii_tx_clk) then
|
|
||||||
xfer_bsy <= '0';
|
|
||||||
if xfer_set = '1' then
|
|
||||||
xfer_cnt <= cmd_fifo_dout(cmd_fifo_dout'left downto word_ptr_t'length);
|
|
||||||
xfer_size <= (others => '0');
|
|
||||||
elsif xfer_en = '1' then
|
|
||||||
xfer_bsy <= '1';
|
|
||||||
if xfer_cnt_en = '1' or xfer_bsy = '0' then
|
|
||||||
if xfer_cnt /= 0 then
|
|
||||||
xfer_cnt <= xfer_cnt - 1;
|
|
||||||
xfer_size <= xfer_size + 1;
|
|
||||||
else
|
|
||||||
xfer_bsy <= '0';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
xfer_pointer:
|
|
||||||
process(mii_tx_clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(mii_tx_clk) then
|
|
||||||
if xfer_set = '1' then
|
|
||||||
xfer_ptr <= cmd_fifo_dout(xfer_ptr'left downto 0);
|
|
||||||
elsif xfer_en = '1' then
|
|
||||||
if xfer_bsy = '0' or xfer_cnt_en = '1' then
|
|
||||||
xfer_ptr <= xfer_ptr + 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
xfer_state_next:
|
|
||||||
process(mii_tx_clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(mii_tx_clk) then
|
|
||||||
if reset_en = '1' then
|
|
||||||
xfer_s <= xfer_init;
|
|
||||||
else
|
|
||||||
xfer_s <= xfer_sn;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
xfer_state:
|
|
||||||
process(xfer_s, mii_bsy, cmd_fifo_empty, piso32_din_rdy, piso32_dout_vld, xfer_bsy, fcs_gen_en)
|
|
||||||
begin
|
|
||||||
|
|
||||||
piso32_din_vld <= '0';
|
|
||||||
preamble_en <= '0';
|
|
||||||
preamble_addr <= 0;
|
|
||||||
xfer_set <= '0';
|
|
||||||
xfer_en <= '0';
|
|
||||||
xfer_free_en <= '0';
|
|
||||||
fcs_rst <= '0';
|
|
||||||
fcs_inject_en <= '0';
|
|
||||||
uncommit_en <= '0';
|
|
||||||
|
|
||||||
xfer_sn <= xfer_s;
|
|
||||||
|
|
||||||
case xfer_s is
|
|
||||||
|
|
||||||
when xfer_init =>
|
|
||||||
xfer_sn <= xfer_idle;
|
|
||||||
|
|
||||||
when xfer_idle =>
|
|
||||||
if cmd_fifo_empty = '0' and mii_bsy = '0' then
|
|
||||||
xfer_sn <= xfer_start;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when xfer_start =>
|
|
||||||
if cmd_fifo_empty = '0' then
|
|
||||||
xfer_sn <= xfer_preamble0;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when xfer_preamble0 =>
|
|
||||||
xfer_set <= '1';
|
|
||||||
fcs_rst <= '1';
|
|
||||||
preamble_addr <= 0;
|
|
||||||
preamble_en <= '1';
|
|
||||||
piso32_din_vld <= '1';
|
|
||||||
if piso32_din_rdy = '1' then
|
|
||||||
xfer_sn <= xfer_preamble1;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when xfer_preamble1 =>
|
|
||||||
preamble_addr <= 1;
|
|
||||||
preamble_en <= '1';
|
|
||||||
piso32_din_vld <= '1';
|
|
||||||
if piso32_din_rdy = '1' then
|
|
||||||
xfer_sn <= xfer_active;
|
|
||||||
xfer_en <= '1';
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when xfer_active =>
|
|
||||||
piso32_din_vld <= xfer_bsy;
|
|
||||||
xfer_en <= '1';
|
|
||||||
if xfer_bsy = '0' then
|
|
||||||
xfer_sn <= xfer_stop;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when xfer_stop =>
|
|
||||||
if piso32_dout_vld = '0' then
|
|
||||||
xfer_sn <= xfer_finish;
|
|
||||||
if fcs_gen_en = '1' then
|
|
||||||
xfer_sn <= xfer_crc;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when xfer_crc =>
|
|
||||||
fcs_inject_en <= piso32_din_rdy;
|
|
||||||
piso32_din_vld <= '1';
|
|
||||||
if piso32_din_rdy = '1' then
|
|
||||||
xfer_sn <= xfer_finish;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when xfer_finish =>
|
|
||||||
uncommit_en <= '1';
|
|
||||||
xfer_free_en <= '1';
|
|
||||||
xfer_sn <= xfer_idle;
|
|
||||||
|
|
||||||
when others =>
|
|
||||||
xfer_sn <= xfer_idle;
|
|
||||||
end case;
|
|
||||||
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
inst_ram : entity work.dpram_1w1r
|
|
||||||
GENERIC MAP
|
|
||||||
(
|
|
||||||
addr_width => RAM_ADDR_WIDTH,
|
|
||||||
data_width => ram_din_a'length
|
|
||||||
)
|
|
||||||
PORT MAP
|
|
||||||
(
|
|
||||||
clka => clk,
|
|
||||||
clkb => mii_tx_clk,
|
|
||||||
en_a => ram_en_a,
|
|
||||||
en_b => ram_en_b,
|
|
||||||
we_a => ram_we_a,
|
|
||||||
addr_a => ram_addr_a,
|
|
||||||
addr_b => ram_addr_b,
|
|
||||||
din_a => ram_din_a,
|
|
||||||
dout_b => ram_dout_b
|
|
||||||
);
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
-- Instantiate synchronous FIFO
|
|
||||||
inst_cmd_fifo: entity work.fifo_async
|
|
||||||
GENERIC MAP
|
|
||||||
(
|
|
||||||
addr_width => NextExpBaseTwo(RAM_SIZE) - 4, -- RAMSIZE(words)/MIN_PACKET_LEN(words)
|
|
||||||
data_width => cmd_fifo_din'length,
|
|
||||||
do_last_read_update => true
|
|
||||||
)
|
|
||||||
PORT MAP
|
|
||||||
(
|
|
||||||
rst => reset_en,
|
|
||||||
clk_w => clk,
|
|
||||||
clk_r => mii_tx_clk,
|
|
||||||
we => cmd_fifo_we,
|
|
||||||
re => cmd_fifo_re,
|
|
||||||
fifo_full => cmd_fifo_full,
|
|
||||||
fifo_empty => cmd_fifo_empty,
|
|
||||||
fifo_afull => open,
|
|
||||||
fifo_aempty => open,
|
|
||||||
data_w => cmd_fifo_din,
|
|
||||||
data_r => cmd_fifo_dout
|
|
||||||
);
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
inst_piso32 : entity work.piso
|
|
||||||
GENERIC MAP
|
|
||||||
(
|
|
||||||
data_width_in => 32,
|
|
||||||
data_width_out => 8,
|
|
||||||
msb_first => true
|
|
||||||
)
|
|
||||||
PORT MAP
|
|
||||||
(
|
|
||||||
rst => reset_en,
|
|
||||||
clk => mii_tx_clk,
|
|
||||||
din_vld => piso32_din_vld,
|
|
||||||
din_rdy => piso32_din_rdy,
|
|
||||||
din_be => piso32_din_be,
|
|
||||||
din => piso32_din,
|
|
||||||
dout_vld => piso32_dout_vld,
|
|
||||||
dout_en => piso32_dout_en,
|
|
||||||
dout => piso32_dout
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
piso32_dout_en <= not mii_fifo_full; --'1' when Gbps_en = '1' else piso8_din_rdy;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
fcs_enable_gen:
|
|
||||||
process(mii_tx_clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(mii_tx_clk) then
|
|
||||||
if fcs_rst = '1' then
|
|
||||||
fcs_en <= (others => '0');
|
|
||||||
elsif piso32_dout_vld = '1' then
|
|
||||||
fcs_en <= fcs_en(fcs_en'left-1 downto 0) & '1';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
inst_fcs: entity work.crc32
|
|
||||||
GENERIC MAP
|
|
||||||
(
|
|
||||||
crc32_init => X"00000000"
|
|
||||||
)
|
|
||||||
PORT MAP
|
|
||||||
(
|
|
||||||
rst => fcs_rst,
|
|
||||||
clk => mii_tx_clk,
|
|
||||||
din_vld => fcs_din_vld,
|
|
||||||
din => piso32_dout,
|
|
||||||
crc32_vld => fcs_vld,
|
|
||||||
crc32_out => fcs
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
fcs_din_vld <= fcs_en(fcs_en'left) and piso32_dout_vld and piso32_dout_en;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
-- ensures continous MII-data stream and also acts as Inter Frame Gap delay
|
|
||||||
mii_fifo_re_dly_gen:
|
|
||||||
process(mii_tx_clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(mii_tx_clk) then
|
|
||||||
if mii_fifo_empty = '1' then
|
|
||||||
if Gbps_en = '0' then
|
|
||||||
mii_fifo_re_dly <= X"000000"; -- 100 mbps
|
|
||||||
else
|
|
||||||
mii_fifo_re_dly <= X"000FFF"; -- Gigabit
|
|
||||||
end if;
|
|
||||||
else
|
|
||||||
mii_fifo_re_dly <= mii_fifo_re_dly(mii_fifo_re_dly'left-1 downto 0) & not mii_fifo_empty;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
mii_bsy <= mii_fifo_re_dly(mii_fifo_re_dly'left);
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
-- Instantiate synchronous FIFO
|
|
||||||
inst_mii_fifo: entity work.fifo_sync
|
|
||||||
GENERIC MAP
|
|
||||||
(
|
|
||||||
addr_width => 4,
|
|
||||||
data_width => piso32_dout'length,
|
|
||||||
do_last_read_update => true
|
|
||||||
)
|
|
||||||
PORT MAP
|
|
||||||
(
|
|
||||||
rst => reset_en,
|
|
||||||
clk => mii_tx_clk,
|
|
||||||
we => mii_fifo_we,
|
|
||||||
re => mii_fifo_re,
|
|
||||||
fifo_full => mii_fifo_full,
|
|
||||||
fifo_empty => mii_fifo_empty,
|
|
||||||
fifo_afull => open,
|
|
||||||
fifo_aempty => open,
|
|
||||||
data_w => piso32_dout,
|
|
||||||
data_r => piso8_din
|
|
||||||
);
|
|
||||||
|
|
||||||
mii_fifo_re <= mii_bsy when Gbps_en = '1' else (piso8_din_rdy and mii_bsy);
|
|
||||||
mii_fifo_we <= piso32_dout_vld;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
inst_piso8 : entity work.piso
|
|
||||||
GENERIC MAP
|
|
||||||
(
|
|
||||||
data_width_in => 8,
|
|
||||||
data_width_out => 4,
|
|
||||||
msb_first => false
|
|
||||||
)
|
|
||||||
PORT MAP
|
|
||||||
(
|
|
||||||
rst => reset_en,
|
|
||||||
clk => mii_tx_clk,
|
|
||||||
din_vld => piso8_din_vld,
|
|
||||||
din_rdy => piso8_din_rdy,
|
|
||||||
din_be => "11",
|
|
||||||
din => piso8_din,
|
|
||||||
dout_vld => piso8_dout_vld,
|
|
||||||
dout_en => '1',
|
|
||||||
dout => piso8_dout
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
piso8_din_vld <= not mii_fifo_empty and mii_bsy;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
mii_output_register:
|
|
||||||
process(mii_tx_clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(mii_tx_clk) then
|
|
||||||
mii_tx_er <= '0';
|
|
||||||
if Gbps_en = '1' then
|
|
||||||
mii_tx_en <= piso8_din_vld;
|
|
||||||
mii_tx <= piso8_din;
|
|
||||||
else
|
|
||||||
mii_tx_en <= piso8_dout_vld;
|
|
||||||
mii_tx <= "0000" & piso8_dout;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
end behavior;
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
-- Package File Template
|
|
||||||
--
|
|
||||||
-- Purpose: This package defines supplemental types, subtypes,
|
|
||||||
-- constants, and functions
|
|
||||||
|
|
||||||
|
|
||||||
library IEEE;
|
|
||||||
use IEEE.STD_LOGIC_1164.ALL;
|
|
||||||
use IEEE.NUMERIC_STD.ALL;
|
|
||||||
use IEEE.MATH_REAL.ALL;
|
|
||||||
|
|
||||||
package emac_types is
|
|
||||||
|
|
||||||
-- Constants
|
|
||||||
type mac_addr_t is array (0 to 5) of unsigned (7 downto 0);
|
|
||||||
|
|
||||||
-- Types
|
|
||||||
type tx_ctrl_in_t is record
|
|
||||||
Gbps_en : std_logic;
|
|
||||||
reset : std_logic;
|
|
||||||
fcs_gen_en : std_logic;
|
|
||||||
tx_size : unsigned(15 downto 0);
|
|
||||||
pkt_commit_en : std_logic;
|
|
||||||
pkt_alloc_en : std_logic;
|
|
||||||
end record;
|
|
||||||
|
|
||||||
type tx_ctrl_out_t is record
|
|
||||||
tx_size : unsigned(15 downto 0);
|
|
||||||
pkt_done : std_logic;
|
|
||||||
pkt_alloc_req : std_logic;
|
|
||||||
pkt_armed : std_logic;
|
|
||||||
reset_busy : std_logic;
|
|
||||||
end record;
|
|
||||||
|
|
||||||
type rx_ctrl_in_t is record
|
|
||||||
Gbps_en : std_logic;
|
|
||||||
reset : std_logic;
|
|
||||||
fcs_chk_en : std_logic;
|
|
||||||
pkt_read_en : std_logic;
|
|
||||||
pkt_req_en : std_logic;
|
|
||||||
pkt_free_en : std_logic;
|
|
||||||
mac_addr : mac_addr_t;
|
|
||||||
promiscious : std_logic;
|
|
||||||
end record;
|
|
||||||
|
|
||||||
type rx_ctrl_out_t is record
|
|
||||||
pkt_avail : std_logic;
|
|
||||||
pkt_valid : std_logic;
|
|
||||||
pkt_bcast : std_logic;
|
|
||||||
pkt_mac_match : std_logic;
|
|
||||||
rx_size : unsigned(15 downto 0);
|
|
||||||
reset_busy : std_logic;
|
|
||||||
end record;
|
|
||||||
|
|
||||||
-- Functions
|
|
||||||
|
|
||||||
end emac_types;
|
|
||||||
|
|
||||||
|
|
||||||
package body emac_types is
|
|
||||||
|
|
||||||
end emac_types;
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
LIBRARY IEEE;
|
|
||||||
USE IEEE.STD_LOGIC_1164.ALL;
|
|
||||||
USE IEEE.NUMERIC_STD.ALL;
|
|
||||||
use std.textio.all; -- Imports the standard textio package.
|
|
||||||
|
|
||||||
use work.utils_pkg.all; -- Imports the standard textio package.
|
|
||||||
|
|
||||||
ENTITY piso IS
|
|
||||||
Generic
|
|
||||||
(
|
|
||||||
data_width_in : natural := 32;
|
|
||||||
data_width_out : natural := 8;
|
|
||||||
msb_first : boolean := false
|
|
||||||
);
|
|
||||||
Port
|
|
||||||
(
|
|
||||||
rst : in STD_LOGIC;
|
|
||||||
clk : in STD_LOGIC;
|
|
||||||
din_vld : in STD_LOGIC;
|
|
||||||
din_rdy : out STD_LOGIC;
|
|
||||||
din_be : in unsigned(data_width_in/data_width_out-1 downto 0);
|
|
||||||
din : in unsigned(data_width_in-1 downto 0);
|
|
||||||
dout_vld : out STD_LOGIC;
|
|
||||||
dout_en : in STD_LOGIC;
|
|
||||||
dout : out unsigned(data_width_out-1 downto 0)
|
|
||||||
|
|
||||||
);
|
|
||||||
END piso;
|
|
||||||
|
|
||||||
ARCHITECTURE behavior OF piso IS
|
|
||||||
|
|
||||||
constant num_shifts : natural := data_width_in/data_width_out;
|
|
||||||
signal pre_fin : STD_LOGIC;
|
|
||||||
signal shift_cnt_pipe : unsigned(num_shifts-1 downto 0);
|
|
||||||
signal shift_pipe : unsigned(data_width_in-1 downto 0);
|
|
||||||
signal vld_pipe : unsigned(num_shifts-1 downto 0);
|
|
||||||
signal din_reg : unsigned(data_width_in-1 downto 0);
|
|
||||||
signal din_be_reg : unsigned(num_shifts-1 downto 0);
|
|
||||||
signal din_reg_empty : STD_LOGIC;
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
begin
|
|
||||||
|
|
||||||
pre_fin <= shift_cnt_pipe(shift_cnt_pipe'left-1);
|
|
||||||
din_rdy <= din_reg_empty;
|
|
||||||
dout_vld <= vld_pipe(vld_pipe'left) when msb_first else vld_pipe(0);
|
|
||||||
dout <= shift_pipe(shift_pipe'left downto shift_pipe'left-data_width_out+1) when msb_first
|
|
||||||
else shift_pipe(data_width_out-1 downto 0);
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if rst = '1' then
|
|
||||||
din_reg_empty <= '1';
|
|
||||||
elsif din_reg_empty = '1' then
|
|
||||||
if din_vld = '1' then
|
|
||||||
din_reg_empty <= '0';
|
|
||||||
end if;
|
|
||||||
elsif pre_fin = '1' and dout_en = '1' then
|
|
||||||
din_reg_empty <= '1';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if din_vld = '1' and din_reg_empty = '1' then
|
|
||||||
din_reg <= din;
|
|
||||||
din_be_reg <= din_be;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if rst = '1' then
|
|
||||||
shift_cnt_pipe <= (others => '1');
|
|
||||||
elsif (pre_fin = '1' and dout_en = '1' and din_reg_empty = '0') then
|
|
||||||
shift_cnt_pipe <= (others => '0');
|
|
||||||
elsif dout_en = '1' then
|
|
||||||
shift_cnt_pipe <= shift_cnt_pipe(shift_cnt_pipe'left-1 downto 0) & '1';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if (pre_fin = '1' and dout_en = '1' and din_reg_empty = '0') then
|
|
||||||
shift_pipe <= din_reg;
|
|
||||||
elsif dout_en = '1' then
|
|
||||||
if (msb_first) then
|
|
||||||
shift_pipe <= shift_pipe(shift_pipe'left-data_width_out downto 0) & (data_width_out-1 downto 0 => '0');
|
|
||||||
else
|
|
||||||
shift_pipe <= (data_width_out-1 downto 0 => '0') & shift_pipe(shift_pipe'left downto data_width_out);
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if rst = '1' then
|
|
||||||
vld_pipe <= (others => '0');
|
|
||||||
elsif (pre_fin = '1' and dout_en = '1' and din_reg_empty = '0') then
|
|
||||||
vld_pipe <= din_be_reg;
|
|
||||||
elsif dout_en = '1' then
|
|
||||||
if (msb_first) then
|
|
||||||
vld_pipe <= vld_pipe(vld_pipe'left-1 downto 0) & '0';
|
|
||||||
else
|
|
||||||
vld_pipe <= '0' & vld_pipe(vld_pipe'left downto 1);
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
end behavior;
|
|
||||||
@@ -1,230 +0,0 @@
|
|||||||
LIBRARY IEEE;
|
|
||||||
USE IEEE.STD_LOGIC_1164.ALL;
|
|
||||||
USE IEEE.NUMERIC_STD.ALL;
|
|
||||||
USE IEEE.MATH_REAL.ALL;
|
|
||||||
use std.textio.all; -- Imports the standard textio package.
|
|
||||||
|
|
||||||
use work.emac_types.all;
|
|
||||||
use work.utils_pkg.all;
|
|
||||||
|
|
||||||
ENTITY pkt_gen IS
|
|
||||||
Generic
|
|
||||||
(
|
|
||||||
f_sysclk : real := 100.0;
|
|
||||||
TX_RAM_SIZE : natural := 2048;
|
|
||||||
PKT_SIZE_MIN : natural := 64;
|
|
||||||
PKT_SIZE_MAX : natural := 1518
|
|
||||||
|
|
||||||
);
|
|
||||||
Port
|
|
||||||
(
|
|
||||||
clk : in STD_LOGIC;
|
|
||||||
rst : in STD_LOGIC;
|
|
||||||
en : in STD_LOGIC;
|
|
||||||
gigabit_en : in STD_LOGIC;
|
|
||||||
fcs_gen_en : in STD_LOGIC;
|
|
||||||
mii_tx_clk : in STD_LOGIC;
|
|
||||||
mii_tx_en : out STD_LOGIC;
|
|
||||||
mii_tx_er : out STD_LOGIC;
|
|
||||||
mii_tx : out unsigned(7 downto 0)
|
|
||||||
|
|
||||||
);
|
|
||||||
END pkt_gen;
|
|
||||||
|
|
||||||
ARCHITECTURE behavior OF pkt_gen IS
|
|
||||||
|
|
||||||
subtype word_ptr_t is unsigned(15 downto 0);
|
|
||||||
|
|
||||||
signal pkt_data : unsigned(31 downto 0);
|
|
||||||
signal pkt_nbytes : word_ptr_t := X"0040";
|
|
||||||
signal pkt_nwords : word_ptr_t := X"0010";
|
|
||||||
|
|
||||||
signal fill_size : word_ptr_t;
|
|
||||||
signal fill_cnt : word_ptr_t;
|
|
||||||
signal fill_rdy : std_logic;
|
|
||||||
signal fill_set : std_logic;
|
|
||||||
signal fill_en : std_logic;
|
|
||||||
|
|
||||||
signal tx_packets : natural;
|
|
||||||
signal tx_bytes : natural;
|
|
||||||
|
|
||||||
signal tx_ctrl_in : tx_ctrl_in_t;
|
|
||||||
signal tx_ctrl_out : tx_ctrl_out_t;
|
|
||||||
signal tx_din : unsigned(31 downto 0);
|
|
||||||
signal tx_din_vld : std_logic;
|
|
||||||
|
|
||||||
type host_state_t is (host_init, host_idle, host_alloc, host_setup, host_arm, host_fill, host_commit);
|
|
||||||
signal host_s, host_sn : host_state_t;
|
|
||||||
|
|
||||||
begin
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
host_state_next:
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if rst = '1' then
|
|
||||||
host_s <= host_init;
|
|
||||||
else
|
|
||||||
host_s <= host_sn;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
host_state:
|
|
||||||
process(host_s, tx_ctrl_out, pkt_nbytes, fill_rdy, en, gigabit_en, fcs_gen_en)
|
|
||||||
begin
|
|
||||||
|
|
||||||
tx_ctrl_in.pkt_alloc_en <= '0';
|
|
||||||
tx_ctrl_in.pkt_commit_en <= '0';
|
|
||||||
tx_ctrl_in.reset <= '0';
|
|
||||||
tx_ctrl_in.Gbps_en <= gigabit_en;
|
|
||||||
tx_ctrl_in.fcs_gen_en <= fcs_gen_en;
|
|
||||||
tx_ctrl_in.tx_size <= pkt_nbytes;
|
|
||||||
fill_set <= '0';
|
|
||||||
fill_en <= '0';
|
|
||||||
|
|
||||||
host_sn <= host_s;
|
|
||||||
|
|
||||||
case host_s is
|
|
||||||
|
|
||||||
when host_init =>
|
|
||||||
if tx_ctrl_out.reset_busy = '0' then
|
|
||||||
host_sn <= host_idle;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when host_idle =>
|
|
||||||
if tx_ctrl_out.pkt_alloc_req = '0' and en = '1' then
|
|
||||||
tx_ctrl_in.pkt_alloc_en <= '1';
|
|
||||||
host_sn <= host_alloc;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when host_alloc =>
|
|
||||||
if tx_ctrl_out.pkt_alloc_req = '0' then
|
|
||||||
if tx_ctrl_out.pkt_armed = '1' then
|
|
||||||
host_sn <= host_setup;
|
|
||||||
else
|
|
||||||
host_sn <= host_idle;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when host_setup =>
|
|
||||||
fill_set <= '1';
|
|
||||||
host_sn <= host_fill;
|
|
||||||
|
|
||||||
when host_fill =>
|
|
||||||
fill_en <= '1';
|
|
||||||
if fill_rdy = '1' then
|
|
||||||
host_sn <= host_commit;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when host_commit =>
|
|
||||||
tx_ctrl_in.pkt_commit_en <= '1';
|
|
||||||
host_sn <= host_idle;
|
|
||||||
|
|
||||||
when others =>
|
|
||||||
host_sn <= host_idle;
|
|
||||||
end case;
|
|
||||||
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
pkt_generator:
|
|
||||||
process(clk)
|
|
||||||
variable size : word_ptr_t;
|
|
||||||
variable krand : real;
|
|
||||||
variable seed1 : integer;
|
|
||||||
variable seed2 : integer;
|
|
||||||
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if rst = '1' then
|
|
||||||
size := to_unsigned(PKT_SIZE_MIN, word_ptr_t'length);
|
|
||||||
seed1 := 31101970;
|
|
||||||
seed2 := 12586901;
|
|
||||||
tx_packets <= 0;
|
|
||||||
tx_bytes <= 0;
|
|
||||||
elsif tx_ctrl_in.pkt_commit_en = '1' then
|
|
||||||
uniform(seed1, seed2, krand);
|
|
||||||
size := to_unsigned(PKT_SIZE_MIN + natural(real(PKT_SIZE_MAX-PKT_SIZE_MIN)*krand), word_ptr_t'length);
|
|
||||||
tx_packets <= tx_packets + 1;
|
|
||||||
tx_bytes <= tx_bytes + to_integer(pkt_nbytes);
|
|
||||||
end if;
|
|
||||||
pkt_nbytes <= size;
|
|
||||||
if size(1 downto 0) = 0 then
|
|
||||||
pkt_nwords <= "00" & size(word_ptr_t'left downto 2);
|
|
||||||
else
|
|
||||||
pkt_nwords <= "00" & size(word_ptr_t'left downto 2) + 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
pkt_data_gen:
|
|
||||||
process(clk)
|
|
||||||
variable data : unsigned(7 downto 0);
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
tx_din_vld <= fill_en;
|
|
||||||
if fill_set = '1' then
|
|
||||||
data := X"00";
|
|
||||||
tx_din <= X"03020100";
|
|
||||||
elsif fill_en = '1' then
|
|
||||||
tx_din(7 downto 0) <= data;
|
|
||||||
data := data + 1;
|
|
||||||
tx_din(15 downto 8) <= data;
|
|
||||||
data := data + 1;
|
|
||||||
tx_din(23 downto 16) <= data;
|
|
||||||
data := data + 1;
|
|
||||||
tx_din(31 downto 24) <= data;
|
|
||||||
data := data + 1;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
pkt_data_counter:
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if fill_set = '1' then
|
|
||||||
fill_size <= (others => '0');
|
|
||||||
fill_rdy <= '0';
|
|
||||||
fill_cnt <= pkt_nwords;
|
|
||||||
elsif fill_en = '1' then
|
|
||||||
if fill_cnt /= 0 then
|
|
||||||
fill_cnt <= fill_cnt - 1;
|
|
||||||
fill_size <= fill_size + 1;
|
|
||||||
else
|
|
||||||
fill_rdy <= '1';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
inst_emac_tx : entity work.emac_tx
|
|
||||||
GENERIC MAP
|
|
||||||
(
|
|
||||||
f_sysclk => f_sysclk,
|
|
||||||
RAM_SIZE => TX_RAM_SIZE
|
|
||||||
)
|
|
||||||
PORT MAP
|
|
||||||
(
|
|
||||||
clk => clk,
|
|
||||||
rst => rst,
|
|
||||||
din_vld => tx_din_vld,
|
|
||||||
din => tx_din,
|
|
||||||
ctrl_in => tx_ctrl_in,
|
|
||||||
ctrl_out => tx_ctrl_out,
|
|
||||||
mii_tx_clk => mii_tx_clk,
|
|
||||||
mii_tx_en => mii_tx_en,
|
|
||||||
mii_tx_er => mii_tx_er,
|
|
||||||
mii_tx => mii_tx
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
end behavior;
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
LIBRARY IEEE;
|
|
||||||
USE IEEE.STD_LOGIC_1164.ALL;
|
|
||||||
USE IEEE.NUMERIC_STD.ALL;
|
|
||||||
use std.textio.all; -- Imports the standard textio package.
|
|
||||||
|
|
||||||
use work.utils_pkg.all; -- Imports the standard textio package.
|
|
||||||
|
|
||||||
ENTITY sipo IS
|
|
||||||
Generic
|
|
||||||
(
|
|
||||||
data_width_in : natural := 8;
|
|
||||||
data_width_out : natural := 32;
|
|
||||||
msb_first : boolean := false
|
|
||||||
);
|
|
||||||
Port
|
|
||||||
(
|
|
||||||
rst : in STD_LOGIC;
|
|
||||||
clk : in STD_LOGIC;
|
|
||||||
din_en : in STD_LOGIC;
|
|
||||||
din_vld : in STD_LOGIC;
|
|
||||||
din : in unsigned(data_width_in-1 downto 0);
|
|
||||||
dout_en : out STD_LOGIC;
|
|
||||||
dout_vld : out STD_LOGIC;
|
|
||||||
dout : out unsigned(data_width_out-1 downto 0);
|
|
||||||
dout_be : out unsigned(data_width_out/data_width_in-1 downto 0)
|
|
||||||
|
|
||||||
);
|
|
||||||
END sipo;
|
|
||||||
|
|
||||||
ARCHITECTURE behavior OF sipo IS
|
|
||||||
|
|
||||||
constant num_shifts : natural := data_width_out/data_width_in;
|
|
||||||
signal pre_fin : STD_LOGIC;
|
|
||||||
signal shift_cnt_pipe : unsigned(num_shifts-1 downto 0);
|
|
||||||
signal shift_pipe : unsigned(data_width_out-1 downto 0);
|
|
||||||
signal out_en : STD_LOGIC;
|
|
||||||
signal out_vld : STD_LOGIC;
|
|
||||||
signal din_vld_r : STD_LOGIC;
|
|
||||||
signal abort : STD_LOGIC;
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
begin
|
|
||||||
|
|
||||||
pre_fin <= shift_cnt_pipe(shift_cnt_pipe'left) when msb_first else shift_cnt_pipe(0);
|
|
||||||
dout_en <= out_en;
|
|
||||||
dout_vld <= out_vld;
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if rst = '1' or pre_fin = '1' then
|
|
||||||
abort <= '0';
|
|
||||||
elsif din_vld_r = '1' and din_en = '0' then
|
|
||||||
abort <= '1';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
din_vld_r <= din_vld and din_en;
|
|
||||||
if rst = '1' then
|
|
||||||
out_en <= '0';
|
|
||||||
elsif out_en = '0' then
|
|
||||||
out_en <= pre_fin and din_en;
|
|
||||||
elsif out_vld = '1' then
|
|
||||||
out_en <= din_en;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
out_vld <= pre_fin;
|
|
||||||
if pre_fin = '1' then
|
|
||||||
dout <= shift_pipe;
|
|
||||||
dout_be <= shift_cnt_pipe;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if rst = '1' or pre_fin = '1' then
|
|
||||||
if (msb_first) then
|
|
||||||
shift_cnt_pipe <= (shift_cnt_pipe'left downto 1 => '0') & (din_en and din_vld);
|
|
||||||
else
|
|
||||||
shift_cnt_pipe <= (din_en and din_vld) & (shift_cnt_pipe'left downto 1 => '0');
|
|
||||||
end if;
|
|
||||||
elsif din_vld = '1' or abort = '1' then
|
|
||||||
if (msb_first) then
|
|
||||||
shift_cnt_pipe <= shift_cnt_pipe(shift_cnt_pipe'left-1 downto 0) & din_en;
|
|
||||||
else
|
|
||||||
shift_cnt_pipe <= din_en & shift_cnt_pipe(shift_cnt_pipe'left downto 1);
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
process(clk)
|
|
||||||
begin
|
|
||||||
if rising_edge(clk) then
|
|
||||||
if din_vld = '1' or abort = '1' then
|
|
||||||
if (msb_first) then
|
|
||||||
shift_pipe <= shift_pipe(shift_pipe'left-data_width_in downto 0) & din;
|
|
||||||
else
|
|
||||||
shift_pipe <= din & shift_pipe(shift_pipe'left downto data_width_in);
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
end behavior;
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
-------------------------------------------------------------------------
|
|
||||||
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
|
|
||||||
-- This file: Dual-ported register file with asynchrous read
|
|
||||||
|
|
||||||
-- Copyright (C) 2007 J. Ahrensfeld
|
|
||||||
|
|
||||||
-- This library is free software; you can redistribute it and/or
|
|
||||||
-- modify it under the terms of the GNU Lesser General Public
|
|
||||||
-- License as published by the Free Software Foundation; either
|
|
||||||
-- version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
-- This library is distributed in the hope that it will be useful,
|
|
||||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
-- Lesser General Public License for more details.
|
|
||||||
|
|
||||||
-- You should have received a copy of the GNU Lesser General Public
|
|
||||||
-- License along with this library; if not, write to the Free Software
|
|
||||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
-- $Header: /tmp/cvsroot/VHDL/lib/misc/dpram_1w1r.vhd,v 1.1 2008-08-23 08:20:29 Jens Exp $
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
|
|
||||||
LIBRARY IEEE;
|
|
||||||
USE IEEE.STD_LOGIC_1164.ALL;
|
|
||||||
USE IEEE.NUMERIC_STD.ALL;
|
|
||||||
|
|
||||||
entity dpram_1w1r is
|
|
||||||
Generic (
|
|
||||||
addr_width : integer := 3;
|
|
||||||
data_width : integer := 8
|
|
||||||
);
|
|
||||||
Port (
|
|
||||||
clka : in STD_LOGIC;
|
|
||||||
clkb : in STD_LOGIC;
|
|
||||||
en_a : in STD_LOGIC;
|
|
||||||
en_b : in STD_LOGIC;
|
|
||||||
we_a : in STD_LOGIC;
|
|
||||||
addr_a : in unsigned (addr_width-1 downto 0);
|
|
||||||
addr_b : in unsigned (addr_width-1 downto 0);
|
|
||||||
din_a : in unsigned (data_width-1 downto 0);
|
|
||||||
dout_b : out unsigned (data_width-1 downto 0)
|
|
||||||
);
|
|
||||||
end dpram_1w1r;
|
|
||||||
|
|
||||||
architecture Behavioral of dpram_1w1r is
|
|
||||||
|
|
||||||
constant depth : integer := 2**addr_width;
|
|
||||||
type RAMtype is array (0 to depth-1) of unsigned (data_width-1 downto 0);
|
|
||||||
signal RAM : RAMtype;
|
|
||||||
|
|
||||||
begin
|
|
||||||
|
|
||||||
process (clka)
|
|
||||||
begin
|
|
||||||
if clka'event and clka = '1' then
|
|
||||||
if en_a = '1' then
|
|
||||||
if we_a = '1' then
|
|
||||||
RAM(to_integer(addr_a)) <= din_a;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
process (clkb)
|
|
||||||
begin
|
|
||||||
if clkb'event and clkb = '1' then
|
|
||||||
if en_b = '1' then
|
|
||||||
dout_b <= RAM(to_integer(addr_b));
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
|
|
||||||
end Behavioral;
|
|
||||||
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
-------------------------------------------------------------------------
|
|
||||||
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
|
|
||||||
-- This file: Dual-ported register file with asynchrous read
|
|
||||||
|
|
||||||
-- Copyright (C) 2007 J. Ahrensfeld
|
|
||||||
|
|
||||||
-- This library is free software; you can redistribute it and/or
|
|
||||||
-- modify it under the terms of the GNU Lesser General Public
|
|
||||||
-- License as published by the Free Software Foundation; either
|
|
||||||
-- version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
-- This library is distributed in the hope that it will be useful,
|
|
||||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
-- Lesser General Public License for more details.
|
|
||||||
|
|
||||||
-- You should have received a copy of the GNU Lesser General Public
|
|
||||||
-- License along with this library; if not, write to the Free Software
|
|
||||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
-- $Header: /tmp/cvsroot/VHDL/lib/misc/dpram_2w2r.vhd,v 1.2 2009-01-14 20:26:29 Jens Exp $
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
|
|
||||||
library IEEE;
|
|
||||||
use IEEE.STD_LOGIC_1164.ALL;
|
|
||||||
use IEEE.numeric_std.ALL;
|
|
||||||
|
|
||||||
entity dpram_2w2r is
|
|
||||||
Generic
|
|
||||||
(
|
|
||||||
addr_width : integer := 3;
|
|
||||||
data_width : integer := 8
|
|
||||||
);
|
|
||||||
Port
|
|
||||||
(
|
|
||||||
clk_a : in STD_LOGIC;
|
|
||||||
clk_b : in STD_LOGIC;
|
|
||||||
en_a : in STD_LOGIC;
|
|
||||||
en_b : in STD_LOGIC;
|
|
||||||
we_a : in STD_LOGIC;
|
|
||||||
we_b : in STD_LOGIC;
|
|
||||||
addr_a : in unsigned (addr_width-1 downto 0);
|
|
||||||
addr_b : in unsigned (addr_width-1 downto 0);
|
|
||||||
din_a : in unsigned (data_width-1 downto 0);
|
|
||||||
din_b : in unsigned (data_width-1 downto 0);
|
|
||||||
dout_a : out unsigned (data_width-1 downto 0);
|
|
||||||
dout_b : out unsigned (data_width-1 downto 0)
|
|
||||||
);
|
|
||||||
end dpram_2w2r;
|
|
||||||
|
|
||||||
architecture Behavioral of dpram_2w2r is
|
|
||||||
|
|
||||||
constant depth : integer := 2**addr_width;
|
|
||||||
type RAMtype is array (0 to depth-1) of unsigned (data_width-1 downto 0);
|
|
||||||
shared variable RAM : RAMtype;
|
|
||||||
|
|
||||||
begin
|
|
||||||
|
|
||||||
process (clk_a)
|
|
||||||
begin
|
|
||||||
if clk_a'event and clk_a = '1' then
|
|
||||||
if en_a = '1' then
|
|
||||||
if we_a = '1' then
|
|
||||||
RAM(to_integer(addr_a)) := din_a;
|
|
||||||
end if;
|
|
||||||
dout_a <= RAM(to_integer(addr_a));
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
process (clk_b)
|
|
||||||
begin
|
|
||||||
if clk_b'event and clk_b = '1' then
|
|
||||||
if en_b = '1' then
|
|
||||||
if we_b = '1' then
|
|
||||||
RAM(to_integer(addr_b)) := din_b;
|
|
||||||
end if;
|
|
||||||
dout_b <= RAM(to_integer(addr_b));
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
|
|
||||||
end Behavioral;
|
|
||||||
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
-----------------------------------------------------------------------
|
||||||
|
-- $Header: /tmp/cvsroot/VHDL/lib/misc/pkg_template.vhd,v 1.1.4.1 2013-08-18 07:10:17 jens Exp $
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
LIBRARY IEEE;
|
||||||
|
USE IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
USE IEEE.NUMERIC_STD.ALL;
|
||||||
|
|
||||||
|
package template_pkg is
|
||||||
|
|
||||||
|
-- Constants
|
||||||
|
-- Types
|
||||||
|
-- Functions
|
||||||
|
|
||||||
|
end template_pkg;
|
||||||
|
|
||||||
|
package body template_pkg is
|
||||||
|
|
||||||
|
end template_pkg;
|
||||||
|
|
||||||
@@ -1,196 +0,0 @@
|
|||||||
-----------------------------------------------------------------------
|
|
||||||
-- $Header: /tmp/cvsroot/VHDL/lib/misc/utils_pkg.vhd,v 1.6 2010-03-22 07:25:40 Jens Exp $
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
|
|
||||||
library IEEE;
|
|
||||||
use IEEE.STD_LOGIC_1164.ALL;
|
|
||||||
use IEEE.NUMERIC_STD.ALL;
|
|
||||||
use IEEE.MATH_REAL.ALL;
|
|
||||||
|
|
||||||
package utils_pkg is
|
|
||||||
|
|
||||||
-- Constants
|
|
||||||
|
|
||||||
-- Functions
|
|
||||||
function MIN (X, Y: INTEGER) return INTEGER;
|
|
||||||
function MAX (X, Y: INTEGER) return INTEGER;
|
|
||||||
|
|
||||||
function NextPowerOfTwo(x : real) return real;
|
|
||||||
function NextExpBaseTwo(x : real) return real;
|
|
||||||
function NextPowerOfTwo(x : natural) return natural;
|
|
||||||
function NextExpBaseTwo(x : natural) return natural;
|
|
||||||
function GCD(a, b : natural) return natural;
|
|
||||||
function LCM(a, b : natural) return natural;
|
|
||||||
function UTILS_PERIOD_NS(f_in_MHz : real) return real;
|
|
||||||
function UTILS_FREQ_M(f_in_MHz, f_out_MHz : real) return natural;
|
|
||||||
function UTILS_FREQ_D(f_in_MHz, f_out_MHz : real) return natural;
|
|
||||||
function f_correct(f : real) return natural;
|
|
||||||
|
|
||||||
end utils_pkg;
|
|
||||||
|
|
||||||
|
|
||||||
package body utils_pkg is
|
|
||||||
|
|
||||||
-------------------------------------------------------------
|
|
||||||
function MIN (X, Y: INTEGER) return INTEGER is
|
|
||||||
variable res : integer := X;
|
|
||||||
begin
|
|
||||||
if Y < X then
|
|
||||||
res := Y;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
return res;
|
|
||||||
|
|
||||||
end MIN;
|
|
||||||
|
|
||||||
-------------------------------------------------------------
|
|
||||||
function MAX (X, Y: INTEGER) return INTEGER is
|
|
||||||
variable res : integer := X;
|
|
||||||
begin
|
|
||||||
if Y > X then
|
|
||||||
res := Y;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
return res;
|
|
||||||
|
|
||||||
end MAX;
|
|
||||||
|
|
||||||
-------------------------------------------------------------
|
|
||||||
function NextExpBaseTwo(x : real) return real is
|
|
||||||
begin
|
|
||||||
return ceil(log2(x));
|
|
||||||
end NextExpBaseTwo;
|
|
||||||
|
|
||||||
-------------------------------------------------------------
|
|
||||||
function NextPowerOfTwo(x : real) return real is
|
|
||||||
begin
|
|
||||||
|
|
||||||
return 2.0**NextExpBaseTwo(x);
|
|
||||||
end NextPowerOfTwo;
|
|
||||||
|
|
||||||
-------------------------------------------------------------
|
|
||||||
function NextExpBaseTwo(x : natural) return natural is
|
|
||||||
begin
|
|
||||||
return natural(NextExpBaseTwo(real(x)));
|
|
||||||
end NextExpBaseTwo;
|
|
||||||
|
|
||||||
-------------------------------------------------------------
|
|
||||||
function NextPowerOfTwo(x : natural) return natural is
|
|
||||||
begin
|
|
||||||
|
|
||||||
return 2**NextExpBaseTwo(x);
|
|
||||||
end NextPowerOfTwo;
|
|
||||||
|
|
||||||
-------------------------------------------------------------
|
|
||||||
function GCD(a, b : natural) return natural is
|
|
||||||
variable aa : natural;
|
|
||||||
variable bb : natural;
|
|
||||||
begin
|
|
||||||
aa := a;
|
|
||||||
bb := b;
|
|
||||||
while bb /= 0 loop
|
|
||||||
if aa > bb then
|
|
||||||
aa := aa - bb;
|
|
||||||
else
|
|
||||||
bb := bb - aa;
|
|
||||||
end if;
|
|
||||||
end loop;
|
|
||||||
|
|
||||||
return aa;
|
|
||||||
|
|
||||||
end GCD;
|
|
||||||
|
|
||||||
-------------------------------------------------------------
|
|
||||||
function LCM(a, b : natural) return natural is
|
|
||||||
begin
|
|
||||||
|
|
||||||
return (a * b)/GCD(a, b);
|
|
||||||
|
|
||||||
end LCM;
|
|
||||||
|
|
||||||
-------------------------------------------------------------
|
|
||||||
function UTILS_PERIOD_NS(f_in_MHz : real) return real is
|
|
||||||
begin
|
|
||||||
|
|
||||||
return 1.0E3/f_in_MHz;
|
|
||||||
|
|
||||||
end UTILS_PERIOD_NS;
|
|
||||||
|
|
||||||
-------------------------------------------------------------
|
|
||||||
function UTILS_FREQ_M(f_in_MHz, f_out_MHz : real) return natural is
|
|
||||||
variable f_in : natural;
|
|
||||||
variable f_out : natural;
|
|
||||||
variable C : natural;
|
|
||||||
variable M : natural;
|
|
||||||
variable D : natural;
|
|
||||||
begin
|
|
||||||
C := f_correct(f_out_MHz);
|
|
||||||
if C < 2 then
|
|
||||||
C := f_correct(f_in_MHz);
|
|
||||||
end if;
|
|
||||||
|
|
||||||
f_out := natural(ceil(real(C)*f_out_MHz));
|
|
||||||
f_in := natural(ceil(real(C)*f_in_MHz));
|
|
||||||
|
|
||||||
M := LCM(f_in, f_out)/f_in;
|
|
||||||
D := f_in/GCD(f_in, f_out);
|
|
||||||
|
|
||||||
assert (M*D) /= (f_in*f_out) report "Finding M and D failed!" severity failure;
|
|
||||||
|
|
||||||
if M = 1 then
|
|
||||||
M := 2;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
return M;
|
|
||||||
|
|
||||||
end UTILS_FREQ_M;
|
|
||||||
|
|
||||||
-------------------------------------------------------------
|
|
||||||
function UTILS_FREQ_D(f_in_MHz, f_out_MHz : real) return natural is
|
|
||||||
variable f_in : natural;
|
|
||||||
variable f_out : natural;
|
|
||||||
variable C : natural;
|
|
||||||
variable M : natural;
|
|
||||||
variable D : natural;
|
|
||||||
begin
|
|
||||||
C := f_correct(f_out_MHz);
|
|
||||||
if C < 2 then
|
|
||||||
C := f_correct(f_in_MHz);
|
|
||||||
end if;
|
|
||||||
|
|
||||||
f_out := natural(ceil(real(C)*f_out_MHz));
|
|
||||||
f_in := natural(ceil(real(C)*f_in_MHz));
|
|
||||||
|
|
||||||
M := LCM(f_in, f_out)/f_in;
|
|
||||||
D := f_in/GCD(f_in, f_out);
|
|
||||||
|
|
||||||
assert (M*D) /= (f_in*f_out) report "Finding M and D failed!" severity failure;
|
|
||||||
|
|
||||||
if M = 1 then
|
|
||||||
D := 2*D;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
return D;
|
|
||||||
|
|
||||||
end UTILS_FREQ_D;
|
|
||||||
|
|
||||||
-------------------------------------------------------------
|
|
||||||
function f_correct(f : real) return natural is
|
|
||||||
constant MAX_ITER : positive := 100;
|
|
||||||
constant MAX_ERR : real := 0.01;
|
|
||||||
variable fpart : real;
|
|
||||||
variable err : real;
|
|
||||||
begin
|
|
||||||
for i in 1 to MAX_ITER loop
|
|
||||||
fpart := real(i)*f - ceil(real(i)*f);
|
|
||||||
err := abs(fpart);
|
|
||||||
if err < max_err then
|
|
||||||
return i;
|
|
||||||
end if;
|
|
||||||
end loop;
|
|
||||||
end f_correct;
|
|
||||||
|
|
||||||
-------------------------------------------------------------
|
|
||||||
end utils_pkg;
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user