phy: Refactor to use records for the application interface
This commit is contained in:
parent
cf6fb61195
commit
cfac94136a
@ -22,22 +22,15 @@ entity bench_trashernet_mac is
|
|||||||
end entity bench_trashernet_mac;
|
end entity bench_trashernet_mac;
|
||||||
|
|
||||||
architecture bench of bench_trashernet_mac is
|
architecture bench of bench_trashernet_mac is
|
||||||
signal clk : std_logic;
|
signal clk : std_logic;
|
||||||
signal phy_clk : std_logic;
|
signal phy_clk : std_logic;
|
||||||
signal rst : std_logic;
|
signal rst : std_logic;
|
||||||
signal rx_data : std_logic_vector(7 downto 0);
|
|
||||||
signal rx_data_valid : std_logic;
|
signal phy_out : phy_out_t;
|
||||||
signal rx_active : std_logic;
|
signal phy_in : phy_in_t;
|
||||||
signal tx_data : std_logic_vector(7 downto 0);
|
signal rx_p : std_logic;
|
||||||
signal tx_data_en : std_logic;
|
signal tx_p : std_logic;
|
||||||
signal tx_data_ack : std_logic;
|
signal tx_n : std_logic;
|
||||||
signal tx_active : std_logic;
|
|
||||||
signal tx_header : mac_header_fields;
|
|
||||||
signal carrier_detect : std_logic;
|
|
||||||
signal rx_error : std_logic;
|
|
||||||
signal rx_p : std_logic;
|
|
||||||
signal tx_p : std_logic;
|
|
||||||
signal tx_n : std_logic;
|
|
||||||
|
|
||||||
signal rx_mac_data : byte;
|
signal rx_mac_data : byte;
|
||||||
signal rx_mac_valid : std_logic;
|
signal rx_mac_valid : std_logic;
|
||||||
@ -48,6 +41,7 @@ architecture bench of bench_trashernet_mac is
|
|||||||
signal tx_mac_data_en : std_logic;
|
signal tx_mac_data_en : std_logic;
|
||||||
signal tx_mac_data_ack : std_logic;
|
signal tx_mac_data_ack : std_logic;
|
||||||
signal rx_header : mac_header_fields;
|
signal rx_header : mac_header_fields;
|
||||||
|
signal tx_header : mac_header_fields;
|
||||||
|
|
||||||
constant TEST_BENCH_LOOPBACK : boolean := true;
|
constant TEST_BENCH_LOOPBACK : boolean := true;
|
||||||
|
|
||||||
@ -58,40 +52,26 @@ begin
|
|||||||
F_CLK_PHY => 100000000
|
F_CLK_PHY => 100000000
|
||||||
)
|
)
|
||||||
port map(
|
port map(
|
||||||
clk => clk,
|
clk => clk,
|
||||||
phy_clk => phy_clk,
|
phy_clk => phy_clk,
|
||||||
rst => rst,
|
rst => rst,
|
||||||
rx_data => rx_data,
|
phy_out => phy_out,
|
||||||
rx_data_valid => rx_data_valid,
|
phy_in => phy_in,
|
||||||
rx_active => rx_active,
|
rx_p => rx_p,
|
||||||
tx_data => tx_data,
|
tx_p => tx_p,
|
||||||
tx_data_en => tx_data_en,
|
tx_n => tx_n
|
||||||
tx_data_ack => tx_data_ack,
|
|
||||||
tx_active => tx_active,
|
|
||||||
carrier_detect => carrier_detect,
|
|
||||||
rx_error => rx_error,
|
|
||||||
rx_p => rx_p,
|
|
||||||
tx_p => tx_p,
|
|
||||||
tx_n => tx_n
|
|
||||||
);
|
);
|
||||||
|
|
||||||
trashernet_mac_inst : entity trashernet.trashernet_mac
|
trashernet_mac_inst : entity trashernet.trashernet_mac
|
||||||
port map(
|
port map(
|
||||||
clk => clk,
|
clk => clk,
|
||||||
rst => rst,
|
rst => rst,
|
||||||
rx_data => rx_data,
|
phy_out => phy_out,
|
||||||
rx_data_valid => rx_data_valid,
|
phy_in => phy_in,
|
||||||
rx_active => rx_active,
|
|
||||||
tx_data => tx_data,
|
|
||||||
tx_data_en => tx_data_en,
|
|
||||||
tx_data_ack => tx_data_ack,
|
|
||||||
tx_active => tx_active,
|
|
||||||
carrier_detect => carrier_detect,
|
|
||||||
rx_error => rx_error,
|
|
||||||
rx_header => rx_header,
|
rx_header => rx_header,
|
||||||
|
rx_mac_header_rcv => rx_mac_header_rcv,
|
||||||
rx_mac_data => rx_mac_data,
|
rx_mac_data => rx_mac_data,
|
||||||
rx_mac_valid => rx_mac_valid,
|
rx_mac_valid => rx_mac_valid,
|
||||||
rx_mac_header_rcv => rx_mac_header_rcv,
|
|
||||||
rx_mac_crc_ok => rx_mac_crc_ok,
|
rx_mac_crc_ok => rx_mac_crc_ok,
|
||||||
rx_mac_crc_error => rx_mac_crc_error,
|
rx_mac_crc_error => rx_mac_crc_error,
|
||||||
tx_header => tx_header,
|
tx_header => tx_header,
|
||||||
@ -164,8 +144,8 @@ begin
|
|||||||
receiver : process is
|
receiver : process is
|
||||||
begin
|
begin
|
||||||
wait until rising_edge(clk);
|
wait until rising_edge(clk);
|
||||||
if rx_data_valid then
|
if phy_out.rx_data_valid then
|
||||||
report "[PHY] RX byte: " & to_hstring(rx_data);
|
report "[PHY] RX byte: " & to_hstring(phy_out.rx_data);
|
||||||
end if;
|
end if;
|
||||||
if rx_mac_valid then
|
if rx_mac_valid then
|
||||||
report "[MAC] RX byte: " & to_hstring(rx_mac_data);
|
report "[MAC] RX byte: " & to_hstring(rx_mac_data);
|
||||||
|
@ -25,18 +25,12 @@ architecture bench of bench_trashernet_phy is
|
|||||||
signal clk : std_logic;
|
signal clk : std_logic;
|
||||||
signal phy_clk : std_logic;
|
signal phy_clk : std_logic;
|
||||||
signal rst : std_logic;
|
signal rst : std_logic;
|
||||||
signal rx_data : std_logic_vector(7 downto 0);
|
signal phy_out : phy_out_t;
|
||||||
signal rx_data_valid : std_logic;
|
signal phy_in : phy_in_t;
|
||||||
signal rx_active : std_logic;
|
signal rx_p : std_logic;
|
||||||
signal tx_data : std_logic_vector(7 downto 0);
|
signal tx_p : std_logic;
|
||||||
signal tx_data_en : std_logic;
|
signal tx_n : std_logic;
|
||||||
signal tx_data_ack : std_logic;
|
|
||||||
signal carrier_detect : std_logic;
|
|
||||||
signal rx_error : std_logic;
|
|
||||||
signal rx_p : std_logic;
|
|
||||||
signal tx_p : std_logic;
|
|
||||||
signal tx_active : std_logic;
|
|
||||||
signal tx_n : std_logic;
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
trashernet_phy_cdc_inst : entity trashernet.trashernet_phy_cdc
|
trashernet_phy_cdc_inst : entity trashernet.trashernet_phy_cdc
|
||||||
@ -45,21 +39,14 @@ begin
|
|||||||
F_CLK_PHY => 100000000
|
F_CLK_PHY => 100000000
|
||||||
)
|
)
|
||||||
port map(
|
port map(
|
||||||
clk => clk,
|
clk => clk,
|
||||||
phy_clk => phy_clk,
|
phy_clk => phy_clk,
|
||||||
rst => rst,
|
rst => rst,
|
||||||
rx_data => rx_data,
|
phy_out => phy_out,
|
||||||
rx_data_valid => rx_data_valid,
|
phy_in => phy_in,
|
||||||
rx_active => rx_active,
|
rx_p => rx_p,
|
||||||
tx_data => tx_data,
|
tx_p => tx_p,
|
||||||
tx_data_en => tx_data_en,
|
tx_n => tx_n
|
||||||
tx_data_ack => tx_data_ack,
|
|
||||||
tx_active => tx_active,
|
|
||||||
carrier_detect => carrier_detect,
|
|
||||||
rx_error => rx_error,
|
|
||||||
rx_p => rx_p,
|
|
||||||
tx_p => tx_p,
|
|
||||||
tx_n => tx_n
|
|
||||||
);
|
);
|
||||||
|
|
||||||
clock_driver : process
|
clock_driver : process
|
||||||
@ -96,8 +83,8 @@ begin
|
|||||||
receiver : process is
|
receiver : process is
|
||||||
begin
|
begin
|
||||||
wait until rising_edge(clk);
|
wait until rising_edge(clk);
|
||||||
if rx_data_valid then
|
if phy_out.rx_data_valid then
|
||||||
report "RX byte: " & to_hstring(rx_data);
|
report "RX byte: " & to_hstring(phy_out.rx_data);
|
||||||
end if;
|
end if;
|
||||||
end process receiver;
|
end process receiver;
|
||||||
|
|
||||||
|
@ -22,17 +22,8 @@ entity trashernet_mac is
|
|||||||
rst : in std_logic; -- Asynchronous reset
|
rst : in std_logic; -- Asynchronous reset
|
||||||
|
|
||||||
-- PHY signals
|
-- PHY signals
|
||||||
rx_data : in byte; -- RX Data
|
phy_out : in phy_out_t; -- PHY application IF (out of PHY)
|
||||||
rx_data_valid : in std_logic; -- RX Data valid
|
phy_in : out phy_in_t; -- PHY application IF (into PHY)
|
||||||
rx_active : in std_logic; -- RX of packet in progress
|
|
||||||
|
|
||||||
tx_data : out byte; -- TX Data
|
|
||||||
tx_data_en : out std_logic; -- Transmitter enable
|
|
||||||
tx_data_ack : in std_logic; -- Latched data_tx
|
|
||||||
tx_active : in std_logic; -- Transmitter active
|
|
||||||
|
|
||||||
carrier_detect : in std_logic; -- Carrier detected
|
|
||||||
rx_error : in std_logic; -- Receive error
|
|
||||||
|
|
||||||
-- MAC signals
|
-- MAC signals
|
||||||
rx_header : out mac_header_fields; -- RX MAC Header Data
|
rx_header : out mac_header_fields; -- RX MAC Header Data
|
||||||
@ -79,8 +70,8 @@ begin
|
|||||||
port map(
|
port map(
|
||||||
clk => clk,
|
clk => clk,
|
||||||
rst => rst,
|
rst => rst,
|
||||||
data => rx_data,
|
data => phy_out.rx_data,
|
||||||
data_valid => rx_data_valid,
|
data_valid => phy_out.rx_data_valid,
|
||||||
crc_clear => crc_clear,
|
crc_clear => crc_clear,
|
||||||
crc_out => crc
|
crc_out => crc
|
||||||
);
|
);
|
||||||
@ -106,8 +97,8 @@ begin
|
|||||||
|
|
||||||
case state is
|
case state is
|
||||||
when HEAD =>
|
when HEAD =>
|
||||||
if rx_data_valid then
|
if phy_out.rx_data_valid then
|
||||||
sr_head <= sr_head(sr_head'low + 1 to sr_head'high) & rx_data;
|
sr_head <= sr_head(sr_head'low + 1 to sr_head'high) & phy_out.rx_data;
|
||||||
if byte_count = (HEAD_LENGTH - 1) then
|
if byte_count = (HEAD_LENGTH - 1) then
|
||||||
state <= PAYLOAD;
|
state <= PAYLOAD;
|
||||||
byte_count <= 0;
|
byte_count <= 0;
|
||||||
@ -119,24 +110,24 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
when PAYLOAD =>
|
when PAYLOAD =>
|
||||||
if rx_data_valid then
|
if phy_out.rx_data_valid then
|
||||||
sr_payload <= sr_payload(sr_payload'low + 1 to sr_payload'high) & rx_data;
|
sr_payload <= sr_payload(sr_payload'low + 1 to sr_payload'high) & phy_out.rx_data;
|
||||||
if byte_count = CRC_LENGTH then
|
if byte_count = CRC_LENGTH then
|
||||||
rx_mac_valid <= '1';
|
rx_mac_valid <= '1';
|
||||||
else
|
else
|
||||||
byte_count <= byte_count + 1;
|
byte_count <= byte_count + 1;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
if not rx_active then
|
if not phy_out.rx_active then
|
||||||
rx_mac_crc_ok <= crc_ok;
|
rx_mac_crc_ok <= crc_ok;
|
||||||
rx_mac_crc_error <= not crc_ok;
|
rx_mac_crc_error <= not crc_ok;
|
||||||
end if;
|
end if;
|
||||||
if rx_error then
|
if phy_out.rx_error then
|
||||||
rx_mac_crc_error <= '1';
|
rx_mac_crc_error <= '1';
|
||||||
end if;
|
end if;
|
||||||
end case;
|
end case;
|
||||||
|
|
||||||
if (not rx_active) or rx_error then
|
if (not phy_out.rx_active) or phy_out.rx_error then
|
||||||
byte_count <= 0;
|
byte_count <= 0;
|
||||||
state <= HEAD;
|
state <= HEAD;
|
||||||
crc_clear <= '1';
|
crc_clear <= '1';
|
||||||
@ -173,7 +164,7 @@ begin
|
|||||||
port map(
|
port map(
|
||||||
clk => clk,
|
clk => clk,
|
||||||
rst => rst,
|
rst => rst,
|
||||||
data => tx_data,
|
data => phy_in.tx_data,
|
||||||
data_valid => crc_valid,
|
data_valid => crc_valid,
|
||||||
crc_clear => crc_clear,
|
crc_clear => crc_clear,
|
||||||
crc_out => crc
|
crc_out => crc
|
||||||
@ -188,7 +179,7 @@ begin
|
|||||||
tx_mac_data_ack <= '0';
|
tx_mac_data_ack <= '0';
|
||||||
crc_valid <= '0';
|
crc_valid <= '0';
|
||||||
|
|
||||||
if tx_data_ack then
|
if phy_out.tx_data_ack then
|
||||||
sr <= sr(sr'low + 1 to sr'high) & x"00";
|
sr <= sr(sr'low + 1 to sr'high) & x"00";
|
||||||
crc_valid <= '1';
|
crc_valid <= '1';
|
||||||
if byte_cnt /= 0 then
|
if byte_cnt /= 0 then
|
||||||
@ -197,14 +188,14 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
case tx_state is
|
case tx_state is
|
||||||
when IDLE =>
|
when IDLE =>
|
||||||
if not tx_active and tx_mac_data_en then
|
if not phy_out.tx_active and tx_mac_data_en then
|
||||||
sr(0 to 7) <= byte_vector'(0 to 6 => x"55", 7 => x"D5");
|
sr(0 to 7) <= byte_vector'(0 to 6 => x"55", 7 => x"D5");
|
||||||
byte_cnt <= 7;
|
byte_cnt <= 7;
|
||||||
tx_state <= HEADER;
|
tx_state <= HEADER;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
when HEADER =>
|
when HEADER =>
|
||||||
if (tx_data_ack = '1') and (byte_cnt = 0) then -- Sync Header TX complete
|
if (phy_out.tx_data_ack = '1') and (byte_cnt = 0) then -- Sync Header TX complete
|
||||||
sr <= tx_header.mac_destination & tx_header.mac_source & tx_header.mac_ethertype;
|
sr <= tx_header.mac_destination & tx_header.mac_source & tx_header.mac_ethertype;
|
||||||
crc_valid <= '1';
|
crc_valid <= '1';
|
||||||
byte_cnt <= BIT_CNT_MAX;
|
byte_cnt <= BIT_CNT_MAX;
|
||||||
@ -212,7 +203,7 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
|
|
||||||
when DATA =>
|
when DATA =>
|
||||||
if (tx_data_ack = '1') and (byte_cnt = 0) then -- MAC Header TX complete
|
if (phy_out.tx_data_ack = '1') and (byte_cnt = 0) then -- MAC Header TX complete
|
||||||
if tx_mac_data_en then
|
if tx_mac_data_en then
|
||||||
sr(0) <= tx_mac_data;
|
sr(0) <= tx_mac_data;
|
||||||
tx_mac_data_ack <= '1';
|
tx_mac_data_ack <= '1';
|
||||||
@ -224,15 +215,15 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
|
|
||||||
when TXCRC =>
|
when TXCRC =>
|
||||||
if (tx_data_ack = '1') and (byte_cnt = 0) then -- CRC TX complete
|
if (phy_out.tx_data_ack = '1') and (byte_cnt = 0) then -- CRC TX complete
|
||||||
tx_state <= IDLE;
|
tx_state <= IDLE;
|
||||||
end if;
|
end if;
|
||||||
end case;
|
end case;
|
||||||
end if;
|
end if;
|
||||||
end process tx_main;
|
end process tx_main;
|
||||||
tx_data_en <= '1' when tx_state /= IDLE else '0';
|
phy_in.tx_data_en <= '1' when tx_state /= IDLE else '0';
|
||||||
crc_clear <= '1' when tx_state = HEADER else '0';
|
crc_clear <= '1' when tx_state = HEADER else '0';
|
||||||
tx_data <= sr(sr'low);
|
phy_in.tx_data <= sr(sr'low);
|
||||||
end block tx;
|
end block tx;
|
||||||
|
|
||||||
end architecture rtl;
|
end architecture rtl;
|
||||||
|
@ -22,26 +22,17 @@ entity trashernet_phy is
|
|||||||
);
|
);
|
||||||
port(
|
port(
|
||||||
-- Global
|
-- Global
|
||||||
clk : in std_logic; -- Global clock
|
clk : in std_logic; -- Global clock
|
||||||
rst : in std_logic; -- Asynchronous reset
|
rst : in std_logic; -- Asynchronous reset
|
||||||
|
|
||||||
-- Eth
|
-- PHY application interface
|
||||||
rx_data : out byte; -- RX Data
|
phy_out : out phy_out_t; -- PHY application IF (out)
|
||||||
rx_data_valid : out std_logic; -- RX Data valid
|
phy_in : in phy_in_t; -- PHY application IF (in)
|
||||||
rx_active : out std_logic; -- RX of packet in progress
|
|
||||||
|
|
||||||
tx_data : in byte; -- TX Data
|
|
||||||
tx_data_en : in std_logic; -- Transmitter enable
|
|
||||||
tx_data_ack : out std_logic; -- Latched data_tx
|
|
||||||
tx_active : out std_logic; -- Transmission in progress
|
|
||||||
|
|
||||||
carrier_detect : out std_logic; -- Carrier detected
|
|
||||||
rx_error : out std_logic; -- Receive error
|
|
||||||
|
|
||||||
-- Ethernet physical signals
|
-- Ethernet physical signals
|
||||||
rx_p : in std_logic;
|
rx_p : in std_logic;
|
||||||
tx_p : out std_logic;
|
tx_p : out std_logic;
|
||||||
tx_n : out std_logic
|
tx_n : out std_logic
|
||||||
);
|
);
|
||||||
end entity trashernet_phy;
|
end entity trashernet_phy;
|
||||||
|
|
||||||
@ -69,7 +60,7 @@ begin
|
|||||||
signal nlp_timeout_cnt : integer range 0 to NLP_TIMEOUT_CNT_MAX;
|
signal nlp_timeout_cnt : integer range 0 to NLP_TIMEOUT_CNT_MAX;
|
||||||
begin
|
begin
|
||||||
-- Synchronize RX input
|
-- Synchronize RX input
|
||||||
synchronizer_inst : entity work.synchronizer
|
synchronizer_rxp_inst : entity work.synchronizer
|
||||||
port map(
|
port map(
|
||||||
clk => clk,
|
clk => clk,
|
||||||
rst => rst,
|
rst => rst,
|
||||||
@ -188,11 +179,11 @@ begin
|
|||||||
if rst then
|
if rst then
|
||||||
demanchestization_state <= SYNC;
|
demanchestization_state <= SYNC;
|
||||||
bit_stb <= '0';
|
bit_stb <= '0';
|
||||||
rx_active <= '0';
|
phy_out.rx_active <= '0';
|
||||||
rx_error <= '0';
|
phy_out.rx_error <= '0';
|
||||||
elsif rising_edge(clk) then
|
elsif rising_edge(clk) then
|
||||||
bit_stb <= '0';
|
bit_stb <= '0';
|
||||||
rx_error <= '0';
|
phy_out.rx_error <= '0';
|
||||||
|
|
||||||
if (bit_ev /= NONE) then
|
if (bit_ev /= NONE) then
|
||||||
case demanchestization_state is
|
case demanchestization_state is
|
||||||
@ -200,7 +191,7 @@ begin
|
|||||||
if (bit_ev = KEEP) then
|
if (bit_ev = KEEP) then
|
||||||
bit_value <= '1';
|
bit_value <= '1';
|
||||||
demanchestization_state <= DATA;
|
demanchestization_state <= DATA;
|
||||||
rx_active <= '1';
|
phy_out.rx_active <= '1';
|
||||||
end if;
|
end if;
|
||||||
when DATA => -- @suppress: Condition outside of case allows to exit this state
|
when DATA => -- @suppress: Condition outside of case allows to exit this state
|
||||||
bit_value <= not bit_value when bit_ev = TOGGLE else bit_value;
|
bit_value <= not bit_value when bit_ev = TOGGLE else bit_value;
|
||||||
@ -211,13 +202,13 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
|
|
||||||
if (bit_ev = ERROR) then
|
if (bit_ev = ERROR) then
|
||||||
rx_error <= '1';
|
phy_out.rx_error <= '1';
|
||||||
demanchestization_state <= ERROR;
|
demanchestization_state <= ERROR;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
if (not transition_activity) then
|
if (not transition_activity) then
|
||||||
demanchestization_state <= SYNC;
|
demanchestization_state <= SYNC;
|
||||||
rx_active <= '0';
|
phy_out.rx_active <= '0';
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process bit_recovery;
|
end process bit_recovery;
|
||||||
@ -227,17 +218,17 @@ begin
|
|||||||
bytizer : process(clk, rst) is
|
bytizer : process(clk, rst) is
|
||||||
begin
|
begin
|
||||||
if rst then
|
if rst then
|
||||||
rx_data_valid <= '0';
|
phy_out.rx_data_valid <= '0';
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
elsif rising_edge(clk) then
|
||||||
rx_data_valid <= '0';
|
phy_out.rx_data_valid <= '0';
|
||||||
|
|
||||||
if rx_active then
|
if phy_out.rx_active then
|
||||||
if (bit_stb) then
|
if (bit_stb) then
|
||||||
rx_data <= bit_value & rx_data(rx_data'high downto rx_data'low + 1);
|
phy_out.rx_data <= bit_value & phy_out.rx_data(phy_out.rx_data'high downto phy_out.rx_data'low + 1);
|
||||||
if (bit_cnt = 7) then
|
if (bit_cnt = 7) then
|
||||||
rx_data_valid <= '1';
|
phy_out.rx_data_valid <= '1';
|
||||||
bit_cnt <= 0;
|
bit_cnt <= 0;
|
||||||
else
|
else
|
||||||
bit_cnt <= bit_cnt + 1;
|
bit_cnt <= bit_cnt + 1;
|
||||||
end if;
|
end if;
|
||||||
@ -263,7 +254,7 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process nlp_timeout_p;
|
end process nlp_timeout_p;
|
||||||
carrier_detect <= '1' when nlp_timeout_cnt /= 0 else '0';
|
phy_out.carrier_detect <= '1' when nlp_timeout_cnt /= 0 else '0';
|
||||||
end block receiver;
|
end block receiver;
|
||||||
|
|
||||||
-- -------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------
|
||||||
@ -274,7 +265,7 @@ begin
|
|||||||
|
|
||||||
type tx_state_t is (IDLE, NLP, TX, IPG);
|
type tx_state_t is (IDLE, NLP, TX, IPG);
|
||||||
signal tx_state : tx_state_t;
|
signal tx_state : tx_state_t;
|
||||||
signal sr : std_logic_vector(tx_data'range);
|
signal sr : std_logic_vector(phy_in.tx_data'range);
|
||||||
signal bit_stage : std_logic;
|
signal bit_stage : std_logic;
|
||||||
|
|
||||||
constant BIT_CNT_MAX_NLP : integer := 16000 / 100; -- 16 ms (timebase 100 ns)
|
constant BIT_CNT_MAX_NLP : integer := 16000 / 100; -- 16 ms (timebase 100 ns)
|
||||||
@ -291,10 +282,10 @@ begin
|
|||||||
tx_state <= TX;
|
tx_state <= TX;
|
||||||
tx_mode <= ACTIVE;
|
tx_mode <= ACTIVE;
|
||||||
|
|
||||||
sr <= tx_data;
|
sr <= phy_in.tx_data;
|
||||||
bit_stage <= '0';
|
bit_stage <= '0';
|
||||||
bit_cnt <= BIT_CNT_MAX_DATA;
|
bit_cnt <= BIT_CNT_MAX_DATA;
|
||||||
tx_data_ack <= '1';
|
phy_out.tx_data_ack <= '1';
|
||||||
end procedure transmit_byte;
|
end procedure transmit_byte;
|
||||||
|
|
||||||
procedure transmit_ipg is
|
procedure transmit_ipg is
|
||||||
@ -325,13 +316,13 @@ begin
|
|||||||
|
|
||||||
begin
|
begin
|
||||||
if rst then
|
if rst then
|
||||||
tx_data_ack <= '0';
|
phy_out.tx_data_ack <= '0';
|
||||||
tx_stb_cnt <= TX_STB_CNT_MAX;
|
tx_stb_cnt <= TX_STB_CNT_MAX;
|
||||||
tx_mode <= OFF;
|
tx_mode <= OFF;
|
||||||
go_idle;
|
go_idle;
|
||||||
|
|
||||||
elsif rising_edge(clk) then
|
elsif rising_edge(clk) then
|
||||||
tx_data_ack <= '0';
|
phy_out.tx_data_ack <= '0';
|
||||||
|
|
||||||
if tx_stb_cnt = 0 then
|
if tx_stb_cnt = 0 then
|
||||||
tx_stb_cnt <= TX_STB_CNT_MAX;
|
tx_stb_cnt <= TX_STB_CNT_MAX;
|
||||||
@ -351,7 +342,7 @@ begin
|
|||||||
|
|
||||||
case tx_state is
|
case tx_state is
|
||||||
when IDLE =>
|
when IDLE =>
|
||||||
if tx_data_en then -- New packet to TX
|
if phy_in.tx_data_en then -- New packet to TX
|
||||||
transmit_byte;
|
transmit_byte;
|
||||||
bit_stage <= '1';
|
bit_stage <= '1';
|
||||||
tx_stb_cnt <= TX_STB_CNT_MAX; -- resync
|
tx_stb_cnt <= TX_STB_CNT_MAX; -- resync
|
||||||
@ -372,7 +363,7 @@ begin
|
|||||||
if (bit_stage = '1') then
|
if (bit_stage = '1') then
|
||||||
sr <= '0' & sr(sr'high downto sr'low + 1);
|
sr <= '0' & sr(sr'high downto sr'low + 1);
|
||||||
if bit_cnt = 0 then
|
if bit_cnt = 0 then
|
||||||
if tx_data_en then
|
if phy_in.tx_data_en then
|
||||||
transmit_byte;
|
transmit_byte;
|
||||||
else
|
else
|
||||||
transmit_ipg;
|
transmit_ipg;
|
||||||
@ -387,7 +378,7 @@ begin
|
|||||||
end case;
|
end case;
|
||||||
end if;
|
end if;
|
||||||
end process tx_main;
|
end process tx_main;
|
||||||
tx_active <= '1' when tx_state /= IDLE else '0';
|
phy_out.tx_active <= '1' when tx_state /= IDLE else '0';
|
||||||
|
|
||||||
driver : process(clk, rst) is
|
driver : process(clk, rst) is
|
||||||
begin
|
begin
|
||||||
|
@ -22,42 +22,26 @@ entity trashernet_phy_cdc is
|
|||||||
);
|
);
|
||||||
port(
|
port(
|
||||||
-- Global
|
-- Global
|
||||||
clk : in std_logic; -- Clock for internal interface
|
clk : in std_logic; -- Clock for internal interface
|
||||||
phy_clk : in std_logic; -- Clock for PHY (rx_p, tx_p)
|
phy_clk : in std_logic; -- Clock for PHY (rx_p, tx_p)
|
||||||
rst : in std_logic; -- Asynchronous reset
|
rst : in std_logic; -- Asynchronous reset
|
||||||
|
|
||||||
-- System interface
|
-- PHY application interface
|
||||||
rx_data : out byte; -- RX Data
|
phy_out : out phy_out_t; -- PHY application IF (out)
|
||||||
rx_data_valid : out std_logic; -- RX Data valid
|
phy_in : in phy_in_t; -- PHY application IF (in)
|
||||||
rx_active : out std_logic; -- RX of packet in progress
|
|
||||||
|
|
||||||
tx_data : in byte; -- TX Data
|
|
||||||
tx_data_en : in std_logic; -- Transmitter enable
|
|
||||||
tx_data_ack : out std_logic; -- Latched data_tx
|
|
||||||
tx_active : out std_logic; -- Transmission in progress
|
|
||||||
|
|
||||||
carrier_detect : out std_logic; -- Carrier detected
|
|
||||||
rx_error : out std_logic; -- Receive error
|
|
||||||
|
|
||||||
-- Ethernet physical signals
|
-- Ethernet physical signals
|
||||||
rx_p : in std_logic;
|
rx_p : in std_logic;
|
||||||
tx_p : out std_logic;
|
tx_p : out std_logic;
|
||||||
tx_n : out std_logic
|
tx_n : out std_logic
|
||||||
);
|
);
|
||||||
end entity trashernet_phy_cdc;
|
end entity trashernet_phy_cdc;
|
||||||
|
|
||||||
architecture RTL of trashernet_phy_cdc is
|
architecture rtl of trashernet_phy_cdc is
|
||||||
-- PHY signals
|
-- PHY signals
|
||||||
signal phy_rst : std_logic;
|
signal phy_rst : std_logic;
|
||||||
signal phy_rx_data : std_logic_vector(7 downto 0);
|
signal phy_phy_out : phy_out_t;
|
||||||
signal phy_rx_data_valid : std_logic;
|
signal phy_phy_in : phy_in_t;
|
||||||
signal phy_rx_active : std_logic;
|
|
||||||
signal phy_tx_data : std_logic_vector(7 downto 0);
|
|
||||||
signal phy_tx_data_en : std_logic;
|
|
||||||
signal phy_tx_data_ack : std_logic;
|
|
||||||
signal phy_carrier_detect : std_logic;
|
|
||||||
signal phy_rx_error : std_logic;
|
|
||||||
signal phy_tx_active : std_logic;
|
|
||||||
|
|
||||||
-- Helper signals
|
-- Helper signals
|
||||||
signal rx_data_valid_i : std_logic;
|
signal rx_data_valid_i : std_logic;
|
||||||
@ -80,20 +64,13 @@ begin
|
|||||||
F_CLK => F_CLK_PHY
|
F_CLK => F_CLK_PHY
|
||||||
)
|
)
|
||||||
port map(
|
port map(
|
||||||
clk => phy_clk,
|
clk => phy_clk,
|
||||||
rst => phy_rst,
|
rst => phy_rst,
|
||||||
rx_data => phy_rx_data,
|
phy_out => phy_phy_out,
|
||||||
rx_data_valid => phy_rx_data_valid,
|
phy_in => phy_phy_in,
|
||||||
rx_active => phy_rx_active,
|
rx_p => rx_p,
|
||||||
tx_data => phy_tx_data,
|
tx_p => tx_p,
|
||||||
tx_data_en => phy_tx_data_en,
|
tx_n => tx_n
|
||||||
tx_data_ack => phy_tx_data_ack,
|
|
||||||
tx_active => phy_tx_active,
|
|
||||||
carrier_detect => phy_carrier_detect,
|
|
||||||
rx_error => phy_rx_error,
|
|
||||||
rx_p => rx_p,
|
|
||||||
tx_p => tx_p,
|
|
||||||
tx_n => tx_n
|
|
||||||
);
|
);
|
||||||
|
|
||||||
synchronizer_txen_inst : entity work.synchronizer
|
synchronizer_txen_inst : entity work.synchronizer
|
||||||
@ -103,11 +80,11 @@ begin
|
|||||||
port map(
|
port map(
|
||||||
clk => phy_clk,
|
clk => phy_clk,
|
||||||
rst => phy_rst,
|
rst => phy_rst,
|
||||||
data_in => tx_data_en,
|
data_in => phy_in.tx_data_en,
|
||||||
data_out => phy_tx_data_en
|
data_out => phy_phy_in.tx_data_en
|
||||||
);
|
);
|
||||||
|
|
||||||
phy_tx_data <= tx_data; -- When tx_data_en is through the synchronizer, this should be stable (and in the other direction, it should only change when we don't read it anyways)
|
phy_phy_in.tx_data <= phy_in.tx_data; -- When tx_data_en is through the synchronizer, this should be stable (and in the other direction, it should only change when we don't read it anyways)
|
||||||
|
|
||||||
-- -------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------
|
||||||
-- Drives: System clock domain
|
-- Drives: System clock domain
|
||||||
@ -116,7 +93,7 @@ begin
|
|||||||
port map(
|
port map(
|
||||||
a_clk => phy_clk,
|
a_clk => phy_clk,
|
||||||
a_rst => phy_rst,
|
a_rst => phy_rst,
|
||||||
a_in => phy_rx_data_valid,
|
a_in => phy_phy_out.rx_data_valid,
|
||||||
b_clk => clk,
|
b_clk => clk,
|
||||||
b_rst => rst,
|
b_rst => rst,
|
||||||
b_out => rx_data_valid_i
|
b_out => rx_data_valid_i
|
||||||
@ -125,10 +102,10 @@ begin
|
|||||||
rxdvff : process(clk, rst) is
|
rxdvff : process(clk, rst) is
|
||||||
begin
|
begin
|
||||||
if rst then
|
if rst then
|
||||||
rx_data_valid <= '0';
|
phy_out.rx_data_valid <= '0';
|
||||||
elsif rising_edge(clk) then
|
elsif rising_edge(clk) then
|
||||||
rx_data_valid <= rx_data_valid_i;
|
phy_out.rx_data_valid <= rx_data_valid_i;
|
||||||
rx_data <= phy_rx_data; -- Data should be stable after the time it takes the _valid signal to go through the synchronizer
|
phy_out.rx_data <= phy_phy_out.rx_data; -- Data should be stable after the time it takes the _valid signal to go through the synchronizer
|
||||||
end if;
|
end if;
|
||||||
end process rxdvff;
|
end process rxdvff;
|
||||||
|
|
||||||
@ -136,44 +113,44 @@ begin
|
|||||||
port map(
|
port map(
|
||||||
a_clk => phy_clk,
|
a_clk => phy_clk,
|
||||||
a_rst => phy_rst,
|
a_rst => phy_rst,
|
||||||
a_in => phy_rx_error,
|
a_in => phy_phy_out.rx_error,
|
||||||
b_clk => clk,
|
b_clk => clk,
|
||||||
b_rst => rst,
|
b_rst => rst,
|
||||||
b_out => rx_error
|
b_out => phy_out.rx_error
|
||||||
);
|
);
|
||||||
|
|
||||||
synchronizer_rxa_inst : entity work.synchronizer
|
synchronizer_rxa_inst : entity work.synchronizer
|
||||||
port map(
|
port map(
|
||||||
clk => clk,
|
clk => clk,
|
||||||
rst => rst,
|
rst => rst,
|
||||||
data_in => phy_rx_active,
|
data_in => phy_phy_out.rx_active,
|
||||||
data_out => rx_active
|
data_out => phy_out.rx_active
|
||||||
);
|
);
|
||||||
|
|
||||||
cdc_strobe_txack_inst : entity work.cdc_strobe
|
cdc_strobe_txack_inst : entity work.cdc_strobe
|
||||||
port map(
|
port map(
|
||||||
a_clk => phy_clk,
|
a_clk => phy_clk,
|
||||||
a_rst => phy_rst,
|
a_rst => phy_rst,
|
||||||
a_in => phy_tx_data_ack,
|
a_in => phy_phy_out.tx_data_ack,
|
||||||
b_clk => clk,
|
b_clk => clk,
|
||||||
b_rst => rst,
|
b_rst => rst,
|
||||||
b_out => tx_data_ack
|
b_out => phy_out.tx_data_ack
|
||||||
);
|
);
|
||||||
|
|
||||||
synchronizer_crs_inst : entity work.synchronizer
|
synchronizer_crs_inst : entity work.synchronizer
|
||||||
port map(
|
port map(
|
||||||
clk => clk,
|
clk => clk,
|
||||||
rst => rst,
|
rst => rst,
|
||||||
data_in => phy_carrier_detect,
|
data_in => phy_phy_out.carrier_detect,
|
||||||
data_out => carrier_detect
|
data_out => phy_out.carrier_detect
|
||||||
);
|
);
|
||||||
|
|
||||||
synchronizer_txa_inst : entity work.synchronizer
|
synchronizer_txa_inst : entity work.synchronizer
|
||||||
port map(
|
port map(
|
||||||
clk => clk,
|
clk => clk,
|
||||||
rst => rst,
|
rst => rst,
|
||||||
data_in => phy_tx_active,
|
data_in => phy_phy_out.tx_active,
|
||||||
data_out => tx_active
|
data_out => phy_out.tx_active
|
||||||
);
|
);
|
||||||
|
|
||||||
end architecture RTL;
|
end architecture rtl;
|
||||||
|
@ -19,10 +19,27 @@ package trashernet_pkg is
|
|||||||
subtype ethertype_t is byte_vector(0 to 1);
|
subtype ethertype_t is byte_vector(0 to 1);
|
||||||
|
|
||||||
type mac_header_fields is record
|
type mac_header_fields is record
|
||||||
mac_destination : mac_addr_t; -- Destination MAC address
|
mac_destination : mac_addr_t; -- Destination MAC address
|
||||||
mac_source : mac_addr_t; -- Source MAC address
|
mac_source : mac_addr_t; -- Source MAC address
|
||||||
mac_ethertype : ethertype_t; -- Ethertype or length
|
mac_ethertype : ethertype_t; -- Ethertype or length
|
||||||
end record mac_header_fields;
|
end record mac_header_fields;
|
||||||
|
|
||||||
|
-- PHY interface
|
||||||
|
type phy_in_t is record
|
||||||
|
tx_data : byte; -- TX Data
|
||||||
|
tx_data_en : std_logic; -- Transmitter enable
|
||||||
|
end record phy_in_t;
|
||||||
|
type phy_out_t is record
|
||||||
|
rx_data : byte; -- RX Data
|
||||||
|
rx_data_valid : std_logic; -- RX Data valid
|
||||||
|
rx_active : std_logic; -- RX of packet in progress
|
||||||
|
|
||||||
|
tx_data_ack : std_logic; -- Latched data_tx
|
||||||
|
tx_active : std_logic; -- Transmission in progress
|
||||||
|
|
||||||
|
carrier_detect : std_logic; -- Carrier detected
|
||||||
|
rx_error : std_logic; -- Receive error
|
||||||
|
end record phy_out_t;
|
||||||
end package trashernet_pkg;
|
end package trashernet_pkg;
|
||||||
|
|
||||||
package body trashernet_pkg is
|
package body trashernet_pkg is
|
||||||
|
Loading…
Reference in New Issue
Block a user