diff --git a/bench/bench_trashernet_mac.vhd b/bench/bench_trashernet_mac.vhd index e1e71e9..4e7cdfe 100644 --- a/bench/bench_trashernet_mac.vhd +++ b/bench/bench_trashernet_mac.vhd @@ -22,22 +22,15 @@ entity bench_trashernet_mac is end entity bench_trashernet_mac; architecture bench of bench_trashernet_mac is - signal clk : std_logic; - signal phy_clk : std_logic; - signal rst : std_logic; - signal rx_data : std_logic_vector(7 downto 0); - signal rx_data_valid : std_logic; - signal rx_active : std_logic; - signal tx_data : std_logic_vector(7 downto 0); - signal tx_data_en : std_logic; - signal tx_data_ack : 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 clk : std_logic; + signal phy_clk : std_logic; + signal rst : std_logic; + + signal phy_out : phy_out_t; + signal phy_in : phy_in_t; + signal rx_p : std_logic; + signal tx_p : std_logic; + signal tx_n : std_logic; signal rx_mac_data : byte; 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_ack : std_logic; signal rx_header : mac_header_fields; + signal tx_header : mac_header_fields; constant TEST_BENCH_LOOPBACK : boolean := true; @@ -58,40 +52,26 @@ begin F_CLK_PHY => 100000000 ) port map( - clk => clk, - phy_clk => phy_clk, - rst => rst, - rx_data => rx_data, - rx_data_valid => rx_data_valid, - 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_p => rx_p, - tx_p => tx_p, - tx_n => tx_n + clk => clk, + phy_clk => phy_clk, + rst => rst, + phy_out => phy_out, + phy_in => phy_in, + rx_p => rx_p, + tx_p => tx_p, + tx_n => tx_n ); trashernet_mac_inst : entity trashernet.trashernet_mac port map( clk => clk, rst => rst, - rx_data => rx_data, - rx_data_valid => rx_data_valid, - 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, + phy_out => phy_out, + phy_in => phy_in, rx_header => rx_header, + rx_mac_header_rcv => rx_mac_header_rcv, rx_mac_data => rx_mac_data, 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_error => rx_mac_crc_error, tx_header => tx_header, @@ -164,8 +144,8 @@ begin receiver : process is begin wait until rising_edge(clk); - if rx_data_valid then - report "[PHY] RX byte: " & to_hstring(rx_data); + if phy_out.rx_data_valid then + report "[PHY] RX byte: " & to_hstring(phy_out.rx_data); end if; if rx_mac_valid then report "[MAC] RX byte: " & to_hstring(rx_mac_data); diff --git a/bench/bench_trashernet_phy.vhd b/bench/bench_trashernet_phy.vhd index 9980691..33129ba 100644 --- a/bench/bench_trashernet_phy.vhd +++ b/bench/bench_trashernet_phy.vhd @@ -25,18 +25,12 @@ architecture bench of bench_trashernet_phy is signal clk : std_logic; signal phy_clk : std_logic; signal rst : std_logic; - signal rx_data : std_logic_vector(7 downto 0); - signal rx_data_valid : std_logic; - signal rx_active : std_logic; - signal tx_data : std_logic_vector(7 downto 0); - signal tx_data_en : 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; + signal phy_out : phy_out_t; + signal phy_in : phy_in_t; + signal rx_p : std_logic; + signal tx_p : std_logic; + signal tx_n : std_logic; + begin trashernet_phy_cdc_inst : entity trashernet.trashernet_phy_cdc @@ -45,21 +39,14 @@ begin F_CLK_PHY => 100000000 ) port map( - clk => clk, - phy_clk => phy_clk, - rst => rst, - rx_data => rx_data, - rx_data_valid => rx_data_valid, - 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_p => rx_p, - tx_p => tx_p, - tx_n => tx_n + clk => clk, + phy_clk => phy_clk, + rst => rst, + phy_out => phy_out, + phy_in => phy_in, + rx_p => rx_p, + tx_p => tx_p, + tx_n => tx_n ); clock_driver : process @@ -96,8 +83,8 @@ begin receiver : process is begin wait until rising_edge(clk); - if rx_data_valid then - report "RX byte: " & to_hstring(rx_data); + if phy_out.rx_data_valid then + report "RX byte: " & to_hstring(phy_out.rx_data); end if; end process receiver; diff --git a/trashernet/trashernet_mac.vhd b/trashernet/trashernet_mac.vhd index 8d3de68..549108b 100644 --- a/trashernet/trashernet_mac.vhd +++ b/trashernet/trashernet_mac.vhd @@ -22,17 +22,8 @@ entity trashernet_mac is rst : in std_logic; -- Asynchronous reset -- PHY signals - rx_data : in byte; -- RX Data - rx_data_valid : in std_logic; -- RX Data valid - 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 + phy_out : in phy_out_t; -- PHY application IF (out of PHY) + phy_in : out phy_in_t; -- PHY application IF (into PHY) -- MAC signals rx_header : out mac_header_fields; -- RX MAC Header Data @@ -79,8 +70,8 @@ begin port map( clk => clk, rst => rst, - data => rx_data, - data_valid => rx_data_valid, + data => phy_out.rx_data, + data_valid => phy_out.rx_data_valid, crc_clear => crc_clear, crc_out => crc ); @@ -106,8 +97,8 @@ begin case state is when HEAD => - if rx_data_valid then - sr_head <= sr_head(sr_head'low + 1 to sr_head'high) & rx_data; + if phy_out.rx_data_valid then + sr_head <= sr_head(sr_head'low + 1 to sr_head'high) & phy_out.rx_data; if byte_count = (HEAD_LENGTH - 1) then state <= PAYLOAD; byte_count <= 0; @@ -119,24 +110,24 @@ begin end if; end if; when PAYLOAD => - if rx_data_valid then - sr_payload <= sr_payload(sr_payload'low + 1 to sr_payload'high) & rx_data; + if phy_out.rx_data_valid then + sr_payload <= sr_payload(sr_payload'low + 1 to sr_payload'high) & phy_out.rx_data; if byte_count = CRC_LENGTH then rx_mac_valid <= '1'; else byte_count <= byte_count + 1; 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_error <= not crc_ok; end if; - if rx_error then + if phy_out.rx_error then rx_mac_crc_error <= '1'; end if; 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; state <= HEAD; crc_clear <= '1'; @@ -173,7 +164,7 @@ begin port map( clk => clk, rst => rst, - data => tx_data, + data => phy_in.tx_data, data_valid => crc_valid, crc_clear => crc_clear, crc_out => crc @@ -188,7 +179,7 @@ begin tx_mac_data_ack <= '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"; crc_valid <= '1'; if byte_cnt /= 0 then @@ -197,14 +188,14 @@ begin end if; case tx_state is 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"); byte_cnt <= 7; tx_state <= HEADER; end if; 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; crc_valid <= '1'; byte_cnt <= BIT_CNT_MAX; @@ -212,7 +203,7 @@ begin end if; 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 sr(0) <= tx_mac_data; tx_mac_data_ack <= '1'; @@ -224,15 +215,15 @@ begin end if; 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; end if; end case; end if; end process tx_main; - tx_data_en <= '1' when tx_state /= IDLE else '0'; - crc_clear <= '1' when tx_state = HEADER else '0'; - tx_data <= sr(sr'low); + phy_in.tx_data_en <= '1' when tx_state /= IDLE else '0'; + crc_clear <= '1' when tx_state = HEADER else '0'; + phy_in.tx_data <= sr(sr'low); end block tx; end architecture rtl; diff --git a/trashernet/trashernet_phy.vhd b/trashernet/trashernet_phy.vhd index f928eed..333c459 100644 --- a/trashernet/trashernet_phy.vhd +++ b/trashernet/trashernet_phy.vhd @@ -22,26 +22,17 @@ entity trashernet_phy is ); port( -- Global - clk : in std_logic; -- Global clock - rst : in std_logic; -- Asynchronous reset + clk : in std_logic; -- Global clock + rst : in std_logic; -- Asynchronous reset - -- Eth - rx_data : out byte; -- RX Data - rx_data_valid : out std_logic; -- RX Data valid - 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 + -- PHY application interface + phy_out : out phy_out_t; -- PHY application IF (out) + phy_in : in phy_in_t; -- PHY application IF (in) -- Ethernet physical signals - rx_p : in std_logic; - tx_p : out std_logic; - tx_n : out std_logic + rx_p : in std_logic; + tx_p : out std_logic; + tx_n : out std_logic ); end entity trashernet_phy; @@ -69,7 +60,7 @@ begin signal nlp_timeout_cnt : integer range 0 to NLP_TIMEOUT_CNT_MAX; begin -- Synchronize RX input - synchronizer_inst : entity work.synchronizer + synchronizer_rxp_inst : entity work.synchronizer port map( clk => clk, rst => rst, @@ -188,11 +179,11 @@ begin if rst then demanchestization_state <= SYNC; bit_stb <= '0'; - rx_active <= '0'; - rx_error <= '0'; + phy_out.rx_active <= '0'; + phy_out.rx_error <= '0'; elsif rising_edge(clk) then - bit_stb <= '0'; - rx_error <= '0'; + bit_stb <= '0'; + phy_out.rx_error <= '0'; if (bit_ev /= NONE) then case demanchestization_state is @@ -200,7 +191,7 @@ begin if (bit_ev = KEEP) then bit_value <= '1'; demanchestization_state <= DATA; - rx_active <= '1'; + phy_out.rx_active <= '1'; end if; when DATA => -- @suppress: Condition outside of case allows to exit this state bit_value <= not bit_value when bit_ev = TOGGLE else bit_value; @@ -211,13 +202,13 @@ begin end if; if (bit_ev = ERROR) then - rx_error <= '1'; + phy_out.rx_error <= '1'; demanchestization_state <= ERROR; end if; if (not transition_activity) then demanchestization_state <= SYNC; - rx_active <= '0'; + phy_out.rx_active <= '0'; end if; end if; end process bit_recovery; @@ -227,17 +218,17 @@ begin bytizer : process(clk, rst) is begin if rst then - rx_data_valid <= '0'; + phy_out.rx_data_valid <= '0'; 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 - 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 - rx_data_valid <= '1'; - bit_cnt <= 0; + phy_out.rx_data_valid <= '1'; + bit_cnt <= 0; else bit_cnt <= bit_cnt + 1; end if; @@ -263,7 +254,7 @@ begin end if; end if; 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; -- ------------------------------------------------------------------------- @@ -274,7 +265,7 @@ begin type tx_state_t is (IDLE, NLP, TX, IPG); 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; constant BIT_CNT_MAX_NLP : integer := 16000 / 100; -- 16 ms (timebase 100 ns) @@ -291,10 +282,10 @@ begin tx_state <= TX; tx_mode <= ACTIVE; - sr <= tx_data; - bit_stage <= '0'; - bit_cnt <= BIT_CNT_MAX_DATA; - tx_data_ack <= '1'; + sr <= phy_in.tx_data; + bit_stage <= '0'; + bit_cnt <= BIT_CNT_MAX_DATA; + phy_out.tx_data_ack <= '1'; end procedure transmit_byte; procedure transmit_ipg is @@ -325,13 +316,13 @@ begin begin if rst then - tx_data_ack <= '0'; - tx_stb_cnt <= TX_STB_CNT_MAX; - tx_mode <= OFF; + phy_out.tx_data_ack <= '0'; + tx_stb_cnt <= TX_STB_CNT_MAX; + tx_mode <= OFF; go_idle; elsif rising_edge(clk) then - tx_data_ack <= '0'; + phy_out.tx_data_ack <= '0'; if tx_stb_cnt = 0 then tx_stb_cnt <= TX_STB_CNT_MAX; @@ -351,7 +342,7 @@ begin case tx_state is when IDLE => - if tx_data_en then -- New packet to TX + if phy_in.tx_data_en then -- New packet to TX transmit_byte; bit_stage <= '1'; tx_stb_cnt <= TX_STB_CNT_MAX; -- resync @@ -372,7 +363,7 @@ begin if (bit_stage = '1') then sr <= '0' & sr(sr'high downto sr'low + 1); if bit_cnt = 0 then - if tx_data_en then + if phy_in.tx_data_en then transmit_byte; else transmit_ipg; @@ -387,7 +378,7 @@ begin end case; end if; 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 begin diff --git a/trashernet/trashernet_phy_cdc.vhd b/trashernet/trashernet_phy_cdc.vhd index 1a470d4..10cd778 100644 --- a/trashernet/trashernet_phy_cdc.vhd +++ b/trashernet/trashernet_phy_cdc.vhd @@ -22,42 +22,26 @@ entity trashernet_phy_cdc is ); port( -- Global - clk : in std_logic; -- Clock for internal interface - phy_clk : in std_logic; -- Clock for PHY (rx_p, tx_p) - rst : in std_logic; -- Asynchronous reset + clk : in std_logic; -- Clock for internal interface + phy_clk : in std_logic; -- Clock for PHY (rx_p, tx_p) + rst : in std_logic; -- Asynchronous reset - -- System interface - rx_data : out byte; -- RX Data - rx_data_valid : out std_logic; -- RX Data valid - 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 + -- PHY application interface + phy_out : out phy_out_t; -- PHY application IF (out) + phy_in : in phy_in_t; -- PHY application IF (in) -- Ethernet physical signals - rx_p : in std_logic; - tx_p : out std_logic; - tx_n : out std_logic + rx_p : in std_logic; + tx_p : out std_logic; + tx_n : out std_logic ); end entity trashernet_phy_cdc; -architecture RTL of trashernet_phy_cdc is +architecture rtl of trashernet_phy_cdc is -- PHY signals - signal phy_rst : std_logic; - signal phy_rx_data : std_logic_vector(7 downto 0); - signal phy_rx_data_valid : std_logic; - 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; + signal phy_rst : std_logic; + signal phy_phy_out : phy_out_t; + signal phy_phy_in : phy_in_t; -- Helper signals signal rx_data_valid_i : std_logic; @@ -80,20 +64,13 @@ begin F_CLK => F_CLK_PHY ) port map( - clk => phy_clk, - rst => phy_rst, - rx_data => phy_rx_data, - rx_data_valid => phy_rx_data_valid, - rx_active => phy_rx_active, - tx_data => phy_tx_data, - tx_data_en => phy_tx_data_en, - 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 + clk => phy_clk, + rst => phy_rst, + phy_out => phy_phy_out, + phy_in => phy_phy_in, + rx_p => rx_p, + tx_p => tx_p, + tx_n => tx_n ); synchronizer_txen_inst : entity work.synchronizer @@ -103,11 +80,11 @@ begin port map( clk => phy_clk, rst => phy_rst, - data_in => tx_data_en, - data_out => phy_tx_data_en + data_in => phy_in.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 @@ -116,7 +93,7 @@ begin port map( a_clk => phy_clk, a_rst => phy_rst, - a_in => phy_rx_data_valid, + a_in => phy_phy_out.rx_data_valid, b_clk => clk, b_rst => rst, b_out => rx_data_valid_i @@ -125,10 +102,10 @@ begin rxdvff : process(clk, rst) is begin if rst then - rx_data_valid <= '0'; + phy_out.rx_data_valid <= '0'; elsif rising_edge(clk) then - 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_valid <= rx_data_valid_i; + 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 process rxdvff; @@ -136,44 +113,44 @@ begin port map( a_clk => phy_clk, a_rst => phy_rst, - a_in => phy_rx_error, + a_in => phy_phy_out.rx_error, b_clk => clk, b_rst => rst, - b_out => rx_error + b_out => phy_out.rx_error ); synchronizer_rxa_inst : entity work.synchronizer port map( clk => clk, rst => rst, - data_in => phy_rx_active, - data_out => rx_active + data_in => phy_phy_out.rx_active, + data_out => phy_out.rx_active ); cdc_strobe_txack_inst : entity work.cdc_strobe port map( a_clk => phy_clk, a_rst => phy_rst, - a_in => phy_tx_data_ack, + a_in => phy_phy_out.tx_data_ack, b_clk => clk, b_rst => rst, - b_out => tx_data_ack + b_out => phy_out.tx_data_ack ); synchronizer_crs_inst : entity work.synchronizer port map( clk => clk, rst => rst, - data_in => phy_carrier_detect, - data_out => carrier_detect + data_in => phy_phy_out.carrier_detect, + data_out => phy_out.carrier_detect ); synchronizer_txa_inst : entity work.synchronizer port map( clk => clk, rst => rst, - data_in => phy_tx_active, - data_out => tx_active + data_in => phy_phy_out.tx_active, + data_out => phy_out.tx_active ); -end architecture RTL; +end architecture rtl; diff --git a/trashernet/trashernet_pkg.vhd b/trashernet/trashernet_pkg.vhd index 41cec21..e88af23 100644 --- a/trashernet/trashernet_pkg.vhd +++ b/trashernet/trashernet_pkg.vhd @@ -19,10 +19,27 @@ package trashernet_pkg is subtype ethertype_t is byte_vector(0 to 1); type mac_header_fields is record - mac_destination : mac_addr_t; -- Destination MAC address - mac_source : mac_addr_t; -- Source MAC address - mac_ethertype : ethertype_t; -- Ethertype or length + mac_destination : mac_addr_t; -- Destination MAC address + mac_source : mac_addr_t; -- Source MAC address + mac_ethertype : ethertype_t; -- Ethertype or length 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; package body trashernet_pkg is