Line 186... |
Line 186... |
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Entity for RioSerial.
|
-- Entity for RioSerial.
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
entity RioSerial is
|
entity RioSerial is
|
generic(
|
generic(
|
TIMEOUT_WIDTH : natural;
|
TIMEOUT_WIDTH : natural := 20;
|
NUMBER_WORDS : natural range 1 to 4 := 1);
|
NUMBER_WORDS : natural range 1 to 4 := 1);
|
port(
|
port(
|
-- System signals.
|
-- System signals.
|
clk : in std_logic;
|
clk : in std_logic;
|
areset_n : in std_logic;
|
areset_n : in std_logic;
|
Line 565... |
Line 565... |
constant NUMBER_STATUS_TRANSMIT : natural := 15;
|
constant NUMBER_STATUS_TRANSMIT : natural := 15;
|
constant NUMBER_LINK_RESPONSE_RETRIES : natural := 2;
|
constant NUMBER_LINK_RESPONSE_RETRIES : natural := 2;
|
|
|
component RioTransmitterCore is
|
component RioTransmitterCore is
|
generic(
|
generic(
|
TIMEOUT_WIDTH : natural;
|
|
NUMBER_WORDS : natural range 1 to 4 := 1);
|
NUMBER_WORDS : natural range 1 to 4 := 1);
|
port(
|
port(
|
-- System signals.
|
-- System signals.
|
clk : in std_logic;
|
clk : in std_logic;
|
areset_n : in std_logic;
|
areset_n : in std_logic;
|
|
|
-- Status signals used for maintenance.
|
-- Status signals used for maintenance.
|
portLinkTimeout_i : in std_logic_vector(TIMEOUT_WIDTH-1 downto 0);
|
|
portEnable_i : in std_logic;
|
portEnable_i : in std_logic;
|
|
|
-- Port output interface.
|
-- Port output interface.
|
portInitialized_i : in std_logic;
|
portInitialized_i : in std_logic;
|
txFull_i : in std_logic;
|
txFull_i : in std_logic;
|
Line 598... |
Line 596... |
-- Internal signalling from the receiver part.
|
-- Internal signalling from the receiver part.
|
linkInitialized_o : out std_logic;
|
linkInitialized_o : out std_logic;
|
linkInitialized_i : in std_logic;
|
linkInitialized_i : in std_logic;
|
ackIdStatus_i : in std_logic_vector(4 downto 0);
|
ackIdStatus_i : in std_logic_vector(4 downto 0);
|
|
|
-- The current time used for timeout calculations.
|
|
timeCurrent_i : in std_logic_vector(TIMEOUT_WIDTH downto 0);
|
|
|
|
-- Internal core variables for cascading.
|
-- Internal core variables for cascading.
|
timeSentWrite_o : out std_logic;
|
timeSentSet_o : out std_logic;
|
timeSentWriteAddress_o : out std_logic_vector(4 downto 0);
|
timeSentReset_o : out std_logic;
|
timeSentWriteData_o : out std_logic_vector(TIMEOUT_WIDTH downto 0);
|
timeSentExpired_i : in std_logic;
|
timeSentReadAddress_o : out std_logic_vector(4 downto 0);
|
|
timeSentReadData_i : in std_logic_vector(TIMEOUT_WIDTH downto 0);
|
|
operational_i : in std_logic;
|
operational_i : in std_logic;
|
operational_o : out std_logic;
|
operational_o : out std_logic;
|
ackId_i : in std_logic_vector(4 downto 0);
|
ackId_i : in std_logic_vector(4 downto 0);
|
ackId_o : out std_logic_vector(4 downto 0);
|
ackId_o : out std_logic_vector(4 downto 0);
|
bufferStatus_i : in std_logic_vector(4 downto 0);
|
bufferStatus_i : in std_logic_vector(4 downto 0);
|
Line 667... |
Line 660... |
addressB_i : in std_logic_vector(ADDRESS_WIDTH-1 downto 0);
|
addressB_i : in std_logic_vector(ADDRESS_WIDTH-1 downto 0);
|
dataB_o : out std_logic_vector(DATA_WIDTH-1 downto 0));
|
dataB_o : out std_logic_vector(DATA_WIDTH-1 downto 0));
|
end component;
|
end component;
|
|
|
signal timeCurrent : std_logic_vector(TIMEOUT_WIDTH downto 0);
|
signal timeCurrent : std_logic_vector(TIMEOUT_WIDTH downto 0);
|
signal timeSentWrite : std_logic;
|
signal timeSentElapsed : unsigned(TIMEOUT_WIDTH downto 0);
|
|
signal timeSentDelta : unsigned(TIMEOUT_WIDTH downto 0);
|
|
signal timeSentExpired : std_logic;
|
|
signal timeSentSet : std_logic;
|
|
signal timeSentReset : std_logic;
|
|
|
|
signal timeSentEnable : std_logic;
|
signal timeSentWriteAddress : std_logic_vector(4 downto 0);
|
signal timeSentWriteAddress : std_logic_vector(4 downto 0);
|
signal timeSentWriteData : std_logic_vector(TIMEOUT_WIDTH downto 0);
|
|
signal timeSentReadAddress : std_logic_vector(4 downto 0);
|
signal timeSentReadAddress : std_logic_vector(4 downto 0);
|
signal timeSentReadData : std_logic_vector(TIMEOUT_WIDTH downto 0);
|
signal timeSentReadData : std_logic_vector(TIMEOUT_WIDTH downto 0);
|
|
|
signal operationalCurrent, operationalNext : std_logic;
|
signal operationalCurrent, operationalNext : std_logic;
|
signal ackIdCurrent, ackIdNext : std_logic_vector(4 downto 0);
|
signal ackIdCurrent, ackIdNext : std_logic_vector(4 downto 0);
|
Line 699... |
Line 697... |
elsif (clk'event and clk = '1') then
|
elsif (clk'event and clk = '1') then
|
timeCurrent <= std_logic_vector(unsigned(timeCurrent) + 1);
|
timeCurrent <= std_logic_vector(unsigned(timeCurrent) + 1);
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
|
timeSentElapsed <= unsigned(timeCurrent) - unsigned(timeSentReadData);
|
|
timeSentDelta <= unsigned('0' & portLinkTimeout_i) - timeSentElapsed;
|
|
timeSentExpired <= timeSentDelta(TIMEOUT_WIDTH);
|
|
|
|
timeSentEnable <= (not txFull_i) and (timeSentSet or timeSentReset);
|
|
timeSentWriteAddress <= ackIdWindowCurrent when timeSentSet = '1' else
|
|
ackIdCurrent;
|
|
timeSentReadAddress <= ackIdCurrent;
|
|
|
TimeoutMemory: MemorySimpleDualPortAsync
|
TimeoutMemory: MemorySimpleDualPortAsync
|
generic map(ADDRESS_WIDTH=>5, DATA_WIDTH=>TIMEOUT_WIDTH+1, INIT_VALUE=>'0')
|
generic map(ADDRESS_WIDTH=>5, DATA_WIDTH=>TIMEOUT_WIDTH+1, INIT_VALUE=>'0')
|
port map(
|
port map(
|
clkA_i=>clk, enableA_i=>timeSentWrite,
|
clkA_i=>clk, enableA_i=>timeSentEnable,
|
addressA_i=>timeSentWriteAddress, dataA_i=>timeSentWriteData,
|
addressA_i=>timeSentWriteAddress, dataA_i=>timeCurrent,
|
addressB_i=>timeSentReadAddress, dataB_o=>timeSentReadData);
|
addressB_i=>timeSentReadAddress, dataB_o=>timeSentReadData);
|
|
|
process(areset_n, clk)
|
process(areset_n, clk)
|
begin
|
begin
|
if (areset_n = '0') then
|
if (areset_n = '0') then
|
Line 724... |
Line 731... |
frameWordCounterCurrent <= (others=>'0');
|
frameWordCounterCurrent <= (others=>'0');
|
frameContentCurrent <= (others=>'0');
|
frameContentCurrent <= (others=>'0');
|
counterCurrent <= (others=>'0');
|
counterCurrent <= (others=>'0');
|
symbolsTransmittedCurrent <= (others=>'0');
|
symbolsTransmittedCurrent <= (others=>'0');
|
elsif (clk'event and clk = '1') then
|
elsif (clk'event and clk = '1') then
|
|
if (txFull_i = '0') then
|
operationalCurrent <= operationalNext;
|
operationalCurrent <= operationalNext;
|
ackIdCurrent <= ackIdNext;
|
ackIdCurrent <= ackIdNext;
|
bufferStatusCurrent <= bufferStatusNext;
|
bufferStatusCurrent <= bufferStatusNext;
|
statusReceivedCurrent <= statusReceivedNext;
|
statusReceivedCurrent <= statusReceivedNext;
|
numberSentLinkRequestsCurrent <= numberSentLinkRequestsNext;
|
numberSentLinkRequestsCurrent <= numberSentLinkRequestsNext;
|
Line 739... |
Line 747... |
frameWordCounterCurrent <= frameWordCounterNext;
|
frameWordCounterCurrent <= frameWordCounterNext;
|
frameContentCurrent <= frameContentNext;
|
frameContentCurrent <= frameContentNext;
|
counterCurrent <= counterNext;
|
counterCurrent <= counterNext;
|
symbolsTransmittedCurrent <= symbolsTransmittedNext;
|
symbolsTransmittedCurrent <= symbolsTransmittedNext;
|
end if;
|
end if;
|
|
end if;
|
end process;
|
end process;
|
|
|
TxCore: RioTransmitterCore
|
TxCore: RioTransmitterCore
|
generic map(TIMEOUT_WIDTH=>TIMEOUT_WIDTH,
|
generic map(NUMBER_WORDS=>NUMBER_WORDS)
|
NUMBER_WORDS=>NUMBER_WORDS)
|
|
port map(
|
port map(
|
clk=>clk, areset_n=>areset_n,
|
clk=>clk, areset_n=>areset_n,
|
portLinkTimeout_i=>portLinkTimeout_i, portEnable_i=>portEnable_i,
|
portEnable_i=>portEnable_i,
|
portInitialized_i=>portInitialized_i,
|
portInitialized_i=>portInitialized_i,
|
txFull_i=>txFull_i, txWrite_o=>txWrite_o, txType_o=>txType_o, txData_o=>txData_o,
|
txFull_i=>txFull_i, txWrite_o=>txWrite_o, txType_o=>txType_o, txData_o=>txData_o,
|
txControlEmpty_i=>txControlEmpty_i,
|
txControlEmpty_i=>txControlEmpty_i,
|
txControlSymbol_i=>txControlSymbol_i,
|
txControlSymbol_i=>txControlSymbol_i,
|
txControlUpdate_o=>txControlUpdate_o,
|
txControlUpdate_o=>txControlUpdate_o,
|
Line 759... |
Line 767... |
rxControlUpdate_o=>rxControlUpdate_o,
|
rxControlUpdate_o=>rxControlUpdate_o,
|
linkInitialized_o=>linkInitialized_o,
|
linkInitialized_o=>linkInitialized_o,
|
linkInitialized_i=>linkInitialized_i,
|
linkInitialized_i=>linkInitialized_i,
|
ackIdStatus_i=>ackIdStatus_i,
|
ackIdStatus_i=>ackIdStatus_i,
|
|
|
timeCurrent_i=>timeCurrent,
|
timeSentSet_o=>timeSentSet,
|
timeSentWrite_o=>timeSentWrite,
|
timeSentReset_o=>timeSentReset,
|
timeSentWriteAddress_o=>timeSentWriteAddress,
|
timeSentExpired_i=>timeSentExpired,
|
timeSentWriteData_o=>timeSentWriteData,
|
|
timeSentReadAddress_o=>timeSentReadAddress,
|
|
timeSentReadData_i=>timeSentReadData,
|
|
|
|
operational_i=>operationalCurrent, operational_o=>operationalNext,
|
operational_i=>operationalCurrent, operational_o=>operationalNext,
|
ackId_i=>ackIdCurrent, ackId_o=>ackIdNext,
|
ackId_i=>ackIdCurrent, ackId_o=>ackIdNext,
|
bufferStatus_i=>bufferStatusCurrent, bufferStatus_o=>bufferStatusNext,
|
bufferStatus_i=>bufferStatusCurrent, bufferStatus_o=>bufferStatusNext,
|
statusReceived_i=>statusReceivedCurrent, statusReceived_o=>statusReceivedNext,
|
statusReceived_i=>statusReceivedCurrent, statusReceived_o=>statusReceivedNext,
|
Line 811... |
Line 816... |
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Entity for RioTransmitterCore.
|
-- Entity for RioTransmitterCore.
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
entity RioTransmitterCore is
|
entity RioTransmitterCore is
|
generic(
|
generic(
|
TIMEOUT_WIDTH : natural;
|
|
NUMBER_WORDS : natural range 1 to 4 := 1);
|
NUMBER_WORDS : natural range 1 to 4 := 1);
|
port(
|
port(
|
-- System signals.
|
-- System signals.
|
clk : in std_logic;
|
clk : in std_logic;
|
areset_n : in std_logic;
|
areset_n : in std_logic;
|
|
|
-- Status signals used for maintenance.
|
-- Status signals used for maintenance.
|
portLinkTimeout_i : in std_logic_vector(TIMEOUT_WIDTH-1 downto 0);
|
|
portEnable_i : in std_logic;
|
portEnable_i : in std_logic;
|
|
|
-- Port output interface.
|
-- Port output interface.
|
portInitialized_i : in std_logic;
|
portInitialized_i : in std_logic;
|
txFull_i : in std_logic;
|
txFull_i : in std_logic;
|
Line 844... |
Line 847... |
-- Internal signalling from the receiver part.
|
-- Internal signalling from the receiver part.
|
linkInitialized_o : out std_logic;
|
linkInitialized_o : out std_logic;
|
linkInitialized_i : in std_logic;
|
linkInitialized_i : in std_logic;
|
ackIdStatus_i : in std_logic_vector(4 downto 0);
|
ackIdStatus_i : in std_logic_vector(4 downto 0);
|
|
|
-- The current time used for timeout calculations.
|
|
timeCurrent_i : in std_logic_vector(TIMEOUT_WIDTH downto 0);
|
|
|
|
-- Internal core variables for cascading.
|
-- Internal core variables for cascading.
|
timeSentWrite_o : out std_logic;
|
timeSentSet_o : out std_logic;
|
timeSentWriteAddress_o : out std_logic_vector(4 downto 0);
|
timeSentReset_o : out std_logic;
|
timeSentWriteData_o : out std_logic_vector(TIMEOUT_WIDTH downto 0);
|
timeSentExpired_i : in std_logic;
|
timeSentReadAddress_o : out std_logic_vector(4 downto 0);
|
|
timeSentReadData_i : in std_logic_vector(TIMEOUT_WIDTH downto 0);
|
|
|
|
operational_i : in std_logic;
|
operational_i : in std_logic;
|
operational_o : out std_logic;
|
operational_o : out std_logic;
|
ackId_i : in std_logic_vector(4 downto 0);
|
ackId_i : in std_logic_vector(4 downto 0);
|
ackId_o : out std_logic_vector(4 downto 0);
|
ackId_o : out std_logic_vector(4 downto 0);
|
Line 902... |
Line 900... |
|
|
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Architecture for RioTransmitterCore.
|
-- Architecture for RioTransmitterCore.
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
|
-- REMARK: Check that all _o except channel variables are registered...
|
architecture RioTransmitterCoreImpl of RioTransmitterCore is
|
architecture RioTransmitterCoreImpl of RioTransmitterCore is
|
|
|
constant NUMBER_STATUS_TRANSMIT : std_logic_vector := "1111";
|
constant NUMBER_STATUS_TRANSMIT : std_logic_vector := "1111";
|
constant NUMBER_LINK_RESPONSE_RETRIES : std_logic_vector := "10";
|
constant NUMBER_LINK_RESPONSE_RETRIES : std_logic_vector := "10";
|
|
|
Line 920... |
Line 919... |
port(
|
port(
|
d_i : in std_logic_vector(18 downto 0);
|
d_i : in std_logic_vector(18 downto 0);
|
crc_o : out std_logic_vector(4 downto 0));
|
crc_o : out std_logic_vector(4 downto 0));
|
end component;
|
end component;
|
|
|
signal timeSentUpdate : std_logic;
|
signal txControlUpdateOut : std_logic;
|
signal timeElapsed : unsigned(TIMEOUT_WIDTH downto 0);
|
|
signal timeDelta : unsigned(TIMEOUT_WIDTH downto 0);
|
|
signal timeExpired : std_logic;
|
|
|
|
signal sendRestartFromRetry, sendRestartFromRetryOut : std_logic;
|
signal sendRestartFromRetry, sendRestartFromRetryOut : std_logic;
|
signal sendLinkRequest, sendLinkRequestOut : std_logic;
|
signal sendLinkRequest, sendLinkRequestOut : std_logic;
|
|
|
|
signal readFrameOut : std_logic;
|
|
signal readFrameRestartOut : std_logic;
|
|
signal readWindowResetOut : std_logic;
|
|
signal readWindowNextOut : std_logic;
|
|
signal readContentOut : std_logic;
|
signal symbolControlRestartOut, symbolControlRestart : std_logic;
|
signal symbolControlRestartOut, symbolControlRestart : std_logic;
|
signal symbolControlLinkRequestOut, symbolControlLinkRequest : std_logic;
|
signal symbolControlLinkRequestOut, symbolControlLinkRequest : std_logic;
|
signal symbolControlStartOut, symbolControlStart : std_logic;
|
signal symbolControlStartOut, symbolControlStart : std_logic;
|
signal symbolControlEndOut, symbolControlEnd : std_logic;
|
signal symbolControlEndOut, symbolControlEnd : std_logic;
|
signal symbolDataOut, symbolData : std_logic;
|
signal symbolDataOut, symbolData : std_logic;
|
signal symbolDataContentOut, symbolDataContent : std_logic_vector(31 downto 0);
|
signal symbolDataContentOut, symbolDataContent : std_logic_vector(31 downto 0);
|
|
|
|
signal rxControlUpdateOut : std_logic;
|
signal symbolControlStype1 : std_logic;
|
signal symbolControlStype1 : std_logic;
|
signal controlValidOut, controlValid : std_logic;
|
signal controlValidOut, controlValid : std_logic;
|
signal stype0Out, stype0 : std_logic_vector(2 downto 0);
|
signal stype0Out, stype0 : std_logic_vector(2 downto 0);
|
signal parameter0Out, parameter0 : std_logic_vector(4 downto 0);
|
signal parameter0Out, parameter0 : std_logic_vector(4 downto 0);
|
signal parameter1Out, parameter1 : std_logic_vector(4 downto 0);
|
signal parameter1Out, parameter1 : std_logic_vector(4 downto 0);
|
Line 979... |
Line 980... |
-- Receive stuff from link-partner and timeout supervision.
|
-- Receive stuff from link-partner and timeout supervision.
|
-- Input: ackId, ackIdWindow, timeoutExpired
|
-- Input: ackId, ackIdWindow, timeoutExpired
|
-- Output: sendLinkRequest, sendRestartFromRetry, ackId,
|
-- Output: sendLinkRequest, sendRestartFromRetry, ackId,
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
|
|
timeSentReadAddress_o <= ackId_i;
|
|
timeElapsed <= unsigned(timeCurrent_i) - unsigned(timeSentReadData_i);
|
|
timeDelta <= unsigned('0' & portLinkTimeout_i) - timeElapsed;
|
|
timeExpired <= timeDelta(TIMEOUT_WIDTH);
|
|
|
|
process(clk, areset_n)
|
process(clk, areset_n)
|
begin
|
begin
|
if (areset_n = '0') then
|
if (areset_n = '0') then
|
|
txControlUpdate_o <= '0';
|
|
readFrame_o <= '0';
|
|
|
sendRestartFromRetry <= '0';
|
sendRestartFromRetry <= '0';
|
sendLinkRequest <= '0';
|
sendLinkRequest <= '0';
|
elsif (clk'event and clk = '1') then
|
elsif (clk'event and clk = '1') then
|
|
txControlUpdate_o <= '0';
|
|
readFrame_o <= '0';
|
|
|
|
if (txFull_i = '0') then
|
|
txControlUpdate_o <= txControlUpdateOut;
|
|
readFrame_o <= readFrameOut;
|
|
|
sendRestartFromRetry <= sendRestartFromRetryOut;
|
sendRestartFromRetry <= sendRestartFromRetryOut;
|
sendLinkRequest <= sendLinkRequestOut;
|
sendLinkRequest <= sendLinkRequestOut;
|
end if;
|
end if;
|
|
end if;
|
end process;
|
end process;
|
|
|
-- REMARK: Reset statusReceived at startup...
|
|
process(outputErrorStopped_i, recoverActive_i, recoverCounter_i,
|
process(outputErrorStopped_i, recoverActive_i, recoverCounter_i,
|
ackId_i, bufferStatus_i, statusReceived_i,
|
ackId_i, ackIdWindow_i, bufferStatus_i, statusReceived_i,
|
numberSentLinkRequests_i,
|
numberSentLinkRequests_i,
|
txFull_i, operational_i,
|
operational_i,
|
txControlEmpty_i, txControlStype0,
|
txControlEmpty_i, txControlStype0,
|
txControlParameter0, txControlParameter1)
|
txControlParameter0, txControlParameter1,
|
|
timeSentExpired_i)
|
begin
|
begin
|
txControlUpdate_o <= '0';
|
|
outputErrorStopped_o <= outputErrorStopped_i;
|
outputErrorStopped_o <= outputErrorStopped_i;
|
recoverActive_o <= recoverActive_i;
|
recoverActive_o <= recoverActive_i;
|
recoverCounter_o <= recoverCounter_i;
|
recoverCounter_o <= recoverCounter_i;
|
ackId_o <= ackId_i;
|
ackId_o <= ackId_i;
|
bufferStatus_o <= bufferStatus_i;
|
bufferStatus_o <= bufferStatus_i;
|
statusReceived_o <= statusReceived_i;
|
statusReceived_o <= statusReceived_i;
|
numberSentLinkRequests_o <= numberSentLinkRequests_i;
|
numberSentLinkRequests_o <= numberSentLinkRequests_i;
|
|
|
readFrame_o <= '0';
|
timeSentReset_o <= '0';
|
|
txControlUpdateOut <= '0';
|
|
readFrameOut <= '0';
|
|
|
sendRestartFromRetryOut <= '0';
|
sendRestartFromRetryOut <= '0';
|
sendLinkRequestOut <= '0';
|
sendLinkRequestOut <= '0';
|
|
|
if (recoverActive_i = '1') then
|
if (recoverActive_i = '1') then
|
if (ackId_i /= recoverCounter_i) then
|
if (ackId_i /= recoverCounter_i) then
|
ackId_o <= std_logic_vector(unsigned(ackId_i) + 1);
|
ackId_o <= std_logic_vector(unsigned(ackId_i) + 1);
|
|
readFrameOut <= '1';
|
else
|
else
|
recoverActive_o <= '0';
|
recoverActive_o <= '0';
|
outputErrorStopped_o <= '0';
|
outputErrorStopped_o <= '0';
|
end if;
|
end if;
|
else
|
else
|
if (txFull_i = '0') then
|
|
if (operational_i = '0') then
|
if (operational_i = '0') then
|
if (txControlEmpty_i = '0') then
|
if (txControlEmpty_i = '0') then
|
if (txControlStype0 = STYPE0_STATUS) then
|
if (txControlStype0 = STYPE0_STATUS) then
|
-- A status-control symbol has been received.
|
-- A status-control symbol has been received.
|
ackId_o <= txControlParameter0;
|
ackId_o <= txControlParameter0;
|
bufferStatus_o <= txControlParameter1;
|
bufferStatus_o <= txControlParameter1;
|
statusReceived_o <= '1';
|
statusReceived_o <= '1';
|
else
|
else
|
-- Discard all other received symbols in this state.
|
-- Discard all other received symbols in this state.
|
end if;
|
end if;
|
txControlUpdate_o <= '1';
|
txControlUpdateOut <= '1';
|
end if;
|
end if;
|
else
|
else
|
|
-- Operational mode.
|
|
|
|
-- Make sure to reset the status received flag.
|
|
statusReceived_o <= '0';
|
|
|
-- Check if the oldest frame timeout has expired.
|
-- Check if the oldest frame timeout has expired.
|
|
-- REMARK: Two link-requests are transmitted when a timeout occurrs...
|
if ((ackId_i /= ackIdWindow_i) and
|
if ((ackId_i /= ackIdWindow_i) and
|
(timeExpired = '1')) then
|
(timeSentExpired_i = '1')) then
|
-- There has been a timeout on a transmitted frame.
|
-- There has been a timeout on a transmitted frame.
|
|
|
|
-- Reset the timeout to expire when the transmitted link-request has
|
|
-- timed out instead.
|
|
timeSentReset_o <= '1';
|
|
|
if (outputErrorStopped_i = '1') then
|
if (outputErrorStopped_i = '1') then
|
-- Count the number of retransmissions and abort if
|
-- Count the number of retransmissions and abort if
|
-- no reply has been received for too many times.
|
-- no reply has been received for too many times.
|
if (unsigned(numberSentLinkRequests_i) /= 0) then
|
if (unsigned(numberSentLinkRequests_i) /= 0) then
|
-- Not sent link-request too many times.
|
-- Not sent link-request too many times.
|
Line 1096... |
Line 1114... |
(ackId_i = txControlParameter0)) then
|
(ackId_i = txControlParameter0)) then
|
-- The packet-accepted is expected and the ackId is the expected.
|
-- The packet-accepted is expected and the ackId is the expected.
|
-- The frame has been accepted by the link partner.
|
-- The frame has been accepted by the link partner.
|
|
|
-- Update to a new buffer and increment the ackId.
|
-- Update to a new buffer and increment the ackId.
|
readFrame_o <= '1';
|
readFrameOut <= '1';
|
ackId_o <= std_logic_vector(unsigned(ackId_i) + 1);
|
ackId_o <= std_logic_vector(unsigned(ackId_i) + 1);
|
else
|
else
|
-- Unexpected packet-accepted or packet-accepted for
|
-- Unexpected packet-accepted or packet-accepted for
|
-- unexpected ackId.
|
-- unexpected ackId.
|
sendLinkRequestOut <= '1';
|
sendLinkRequestOut <= '1';
|
Line 1175... |
Line 1193... |
when others =>
|
when others =>
|
null;
|
null;
|
end case;
|
end case;
|
|
|
-- Indicate the control symbol has been processed.
|
-- Indicate the control symbol has been processed.
|
txControlUpdate_o <= '1';
|
txControlUpdateOut <= '1';
|
end if;
|
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
Line 1196... |
Line 1213... |
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
|
|
process(clk, areset_n)
|
process(clk, areset_n)
|
begin
|
begin
|
if (areset_n = '0') then
|
if (areset_n = '0') then
|
|
readFrameRestart_o <= '0';
|
|
readWindowReset_o <= '0';
|
|
readWindowNext_o <= '0';
|
|
readContent_o <= '0';
|
|
|
symbolControlRestart <= '0';
|
symbolControlRestart <= '0';
|
symbolControlLinkRequest <= '0';
|
symbolControlLinkRequest <= '0';
|
symbolControlStart <= '0';
|
symbolControlStart <= '0';
|
symbolControlEnd <= '0';
|
symbolControlEnd <= '0';
|
symbolData <= '0';
|
symbolData <= '0';
|
symbolDataContent <= (others => '0');
|
symbolDataContent <= (others => '0');
|
elsif (clk'event and clk = '1') then
|
elsif (clk'event and clk = '1') then
|
|
readFrameRestart_o <= '0';
|
|
readWindowReset_o <= '0';
|
|
readWindowNext_o <= '0';
|
|
readContent_o <= '0';
|
|
|
|
if (txFull_i = '0') then
|
|
readFrameRestart_o <= readFrameRestartOut;
|
|
readWindowReset_o <= readWindowResetOut;
|
|
readWindowNext_o <= readWindowNextOut;
|
|
readContent_o <= readContentOut;
|
|
|
symbolControlRestart <= symbolControlRestartOut;
|
symbolControlRestart <= symbolControlRestartOut;
|
symbolControlLinkRequest <= symbolControlLinkRequestOut;
|
symbolControlLinkRequest <= symbolControlLinkRequestOut;
|
symbolControlStart <= symbolControlStartOut;
|
symbolControlStart <= symbolControlStartOut;
|
symbolControlEnd <= symbolControlEndOut;
|
symbolControlEnd <= symbolControlEndOut;
|
symbolData <= symbolDataOut;
|
symbolData <= symbolDataOut;
|
symbolDataContent <= symbolDataContentOut;
|
symbolDataContent <= symbolDataContentOut;
|
end if;
|
end if;
|
|
end if;
|
end process;
|
end process;
|
|
|
-- This process decide which stype1-part of a control symbols to send as well
|
-- This process decide which stype1-part of a control symbols to send as well
|
-- as all data symbols.
|
-- as all data symbols.
|
process(frameState_i, frameWordCounter_i, frameContent_i, ackIdWindow_i, timeCurrent_i,
|
process(readWindowEmpty_i, bufferStatus_i,
|
|
recoverActive_i, recoverCounter_i, ackId_i, operational_i, outputErrorStopped_i, portEnable_i, readContentData_i, readContentWords_i, readContentEnd_i,
|
|
frameState_i, frameWordCounter_i, frameContent_i,
|
|
ackIdWindow_i,
|
sendRestartFromRetry, sendLinkRequest)
|
sendRestartFromRetry, sendLinkRequest)
|
begin
|
begin
|
readFrame_o <= '0';
|
readFrameRestartOut <= '0';
|
readFrameRestart_o <= '0';
|
readWindowResetOut <= '0';
|
readWindowReset_o <= '0';
|
readWindowNextOut <= '0';
|
readWindowNext_o <= '0';
|
readContentOut <= '0';
|
readContent_o <= '0';
|
|
|
|
frameState_o <= frameState_i;
|
frameState_o <= frameState_i;
|
frameWordCounter_o <= frameWordCounter_i;
|
frameWordCounter_o <= frameWordCounter_i;
|
frameContent_o <= frameContent_i;
|
frameContent_o <= frameContent_i;
|
ackIdWindow_o <= ackIdWindow_i;
|
ackIdWindow_o <= ackIdWindow_i;
|
|
|
timeSentWrite_o <= '0';
|
timeSentSet_o <= '0';
|
timeSentWriteAddress_o <= ackIdWindow_i;
|
|
timeSentWriteData_o <= timeCurrent_i;
|
|
|
|
symbolControlRestartOut <= '0';
|
symbolControlRestartOut <= '0';
|
symbolControlLinkRequestOut <= '0';
|
symbolControlLinkRequestOut <= '0';
|
symbolControlStartOut <= '0';
|
symbolControlStartOut <= '0';
|
symbolControlEndOut <= '0';
|
symbolControlEndOut <= '0';
|
Line 1245... |
Line 1279... |
-- REMARK: Make sure idle is generated when this state is active...
|
-- REMARK: Make sure idle is generated when this state is active...
|
ackIdWindow_o <= recoverCounter_i;
|
ackIdWindow_o <= recoverCounter_i;
|
frameState_o <= FRAME_START;
|
frameState_o <= FRAME_START;
|
|
|
if (ackId_i /= recoverCounter_i) then
|
if (ackId_i /= recoverCounter_i) then
|
readFrame_o <= '1';
|
-- REMARK: Discard packets; readFrameOut <= '1';
|
else
|
else
|
readWindowReset_o <= '1';
|
readWindowResetOut <= '1';
|
end if;
|
end if;
|
else
|
else
|
if (txFull_i = '0') then
|
|
if (operational_i = '0') then
|
if (operational_i = '0') then
|
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
-- This state is entered at startup. A port that is not initialized
|
-- This state is entered at startup. A port that is not initialized
|
-- should only transmit idle sequences.
|
-- should only transmit idle sequences.
|
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
|
|
-- Initialize framing before entering the operational state.
|
-- Initialize framing before entering the operational state.
|
-- REMARK: Only do this when the portInitialized becomes asserted???
|
-- REMARK: Only do this when the portInitialized becomes asserted???
|
frameState_o <= FRAME_START;
|
frameState_o <= FRAME_START;
|
ackIdWindow_o <= ackId_i;
|
ackIdWindow_o <= ackId_i;
|
readWindowReset_o <= '1';
|
readWindowResetOut <= '1';
|
else
|
else
|
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
-- This state is the operational state. It relays frames and handle
|
-- This state is the operational state. It relays frames and handle
|
-- flow control.
|
-- flow control.
|
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
Line 1275... |
Line 1308... |
-- of the frame.
|
-- of the frame.
|
symbolControlRestartOut <= '1';
|
symbolControlRestartOut <= '1';
|
|
|
-- Make sure there wont be any timeout before the frame is
|
-- Make sure there wont be any timeout before the frame is
|
-- starting to be retransmitted.
|
-- starting to be retransmitted.
|
timeSentWrite_o <= '1';
|
timeSentSet_o <= '1';
|
|
|
-- Restart the frame transmission.
|
-- Restart the frame transmission.
|
ackIdWindow_o <= ackId_i;
|
ackIdWindow_o <= ackId_i;
|
frameState_o <= FRAME_START;
|
frameState_o <= FRAME_START;
|
readWindowReset_o <= '1';
|
readWindowResetOut <= '1';
|
end if;
|
end if;
|
|
|
if (sendLinkRequest = '1') then
|
if (sendLinkRequest = '1') then
|
-- Dont restart the packet transmission since we do not yet know which
|
-- Dont restart the packet transmission since we do not yet know which
|
-- packets that was successfully received by our link partner.
|
-- packets that was successfully received by our link partner.
|
|
|
-- Send a link-request symbol.
|
-- Send a link-request symbol.
|
symbolControlLinkRequestOut <= '1';
|
symbolControlLinkRequestOut <= '1';
|
|
|
-- Write the current timer value.
|
-- Write the current timer value.
|
timeSentWrite_o <= '1';
|
timeSentSet_o <= '1';
|
end if;
|
end if;
|
|
|
if ((sendRestartFromRetry = '0') and (sendLinkRequest = '0') and
|
if ((sendRestartFromRetry = '0') and (sendLinkRequest = '0') and
|
(outputErrorStopped_i = '0')) then
|
(outputErrorStopped_i = '0')) then
|
-- Check if a frame transfer is in progress.
|
-- Check if a frame transfer is in progress.
|
Line 1324... |
Line 1357... |
-- transmission of the frame.
|
-- transmission of the frame.
|
frameState_o <= FRAME_CHECK;
|
frameState_o <= FRAME_CHECK;
|
|
|
-- Update the output from the frame buffer to contain the
|
-- Update the output from the frame buffer to contain the
|
-- data when it is read later.
|
-- data when it is read later.
|
readContent_o <= '1';
|
readContentOut <= '1';
|
end if;
|
end if;
|
|
|
when FRAME_CHECK =>
|
when FRAME_CHECK =>
|
-------------------------------------------------------
|
-------------------------------------------------------
|
-- Check if we are allowed to transmit this packet.
|
-- Check if we are allowed to transmit this packet.
|
-------------------------------------------------------
|
-------------------------------------------------------
|
|
-- REMARK: Merge this state with the one above or it will be
|
|
-- impossible to send packet back-to-back...
|
|
|
-- Check if this packet is allowed to be transmitted.
|
-- Check if this packet is allowed to be transmitted.
|
if ((portEnable_i = '1') or
|
if ((portEnable_i = '1') or
|
(readContentData_i(19 downto 16) = FTYPE_MAINTENANCE_CLASS)) then
|
(readContentData_i(19 downto 16) = FTYPE_MAINTENANCE_CLASS)) then
|
-- The packet may be transmitted.
|
-- The packet may be transmitted.
|
Line 1342... |
Line 1377... |
-- Indicate that a control symbol has been sent to start the
|
-- Indicate that a control symbol has been sent to start the
|
-- transmission of the frame.
|
-- transmission of the frame.
|
frameState_o <= FRAME_ACKID;
|
frameState_o <= FRAME_ACKID;
|
frameWordCounter_o <= readContentWords_i;
|
frameWordCounter_o <= readContentWords_i;
|
frameContent_o <= readContentData_i;
|
frameContent_o <= readContentData_i;
|
|
readContentOut <= '1';
|
|
|
-- Send a control symbol to start the packet and a status to
|
-- Send a control symbol to start the packet and a status to
|
-- complete the symbol.
|
-- complete the symbol.
|
symbolControlStartOut <= '1';
|
symbolControlStartOut <= '1';
|
else
|
else
|
Line 1355... |
Line 1391... |
-- Check that there are no outstanding packets that
|
-- Check that there are no outstanding packets that
|
-- has not been acknowledged.
|
-- has not been acknowledged.
|
if(unsigned(ackIdWindow_i) = unsigned(ackId_i)) then
|
if(unsigned(ackIdWindow_i) = unsigned(ackId_i)) then
|
-- No unacknowledged packets.
|
-- No unacknowledged packets.
|
-- It is now safe to remove the unallowed frame.
|
-- It is now safe to remove the unallowed frame.
|
readFrame_o <= '1';
|
-- REMARK: Discard packets; readFrameOut <= '1';
|
|
|
-- Go back and send a new frame.
|
-- Go back and send a new frame.
|
frameState_o <= FRAME_START;
|
frameState_o <= FRAME_START;
|
end if;
|
end if;
|
end if;
|
end if;
|
Line 1373... |
Line 1409... |
-- Write a new data symbol and fill in our ackId on the
|
-- Write a new data symbol and fill in our ackId on the
|
-- packet.
|
-- packet.
|
symbolDataOut <= '1';
|
symbolDataOut <= '1';
|
symbolDataContentOut <=
|
symbolDataContentOut <=
|
std_logic_vector(ackIdWindow_i) & "0" &
|
std_logic_vector(ackIdWindow_i) & "0" &
|
frameContent_i((32*NUMBER_WORDS)-1 downto (32*(NUMBER_WORDS-1))-1);
|
frameContent_i((32*NUMBER_WORDS)-7 downto (32*(NUMBER_WORDS-1)));
|
|
|
|
-- REMARK: Code frameWordCounter as 0=1 or 1=1???
|
if (unsigned(frameWordCounter_i) /= 0) then
|
if (unsigned(frameWordCounter_i) /= 0) then
|
frameWordCounter_o <=
|
frameWordCounter_o <=
|
std_logic_vector(unsigned(frameWordCounter_i) - 1);
|
std_logic_vector(unsigned(frameWordCounter_i) - 1);
|
frameContent_o <=
|
frameContent_o <=
|
frameContent_i((32*(NUMBER_WORDS-1))-1 downto 0) & x"0000";
|
frameContent_i((32*(NUMBER_WORDS-1))-1 downto 0) & x"00000000";
|
else
|
else
|
readContent_o <= '1';
|
|
frameWordCounter_o <= readContentWords_i;
|
frameWordCounter_o <= readContentWords_i;
|
frameContent_o <= readContentData_i;
|
frameContent_o <= readContentData_i;
|
|
readContentOut <= '1';
|
end if;
|
end if;
|
|
|
-- Continue to send the rest of the body of the packet.
|
-- Continue to send the rest of the body of the packet.
|
frameState_o <= FRAME_BODY;
|
frameState_o <= FRAME_BODY;
|
|
|
Line 1405... |
Line 1442... |
-- packet...
|
-- packet...
|
|
|
-- Write a new data symbol.
|
-- Write a new data symbol.
|
symbolDataOut <= '1';
|
symbolDataOut <= '1';
|
symbolDataContentOut <=
|
symbolDataContentOut <=
|
frameContent_i((32*NUMBER_WORDS)-1 downto (32*(NUMBER_WORDS-1))-1);
|
frameContent_i((32*NUMBER_WORDS)-1 downto (32*(NUMBER_WORDS-1)));
|
|
|
if (unsigned(frameWordCounter_i) /= 0) then
|
if (unsigned(frameWordCounter_i) /= 0) then
|
frameWordCounter_o <=
|
frameWordCounter_o <=
|
std_logic_vector(unsigned(frameWordCounter_i) - 1);
|
std_logic_vector(unsigned(frameWordCounter_i) - 1);
|
frameContent_o <=
|
frameContent_o <=
|
frameContent_i((32*(NUMBER_WORDS-1))-1 downto 0) & x"0000";
|
frameContent_i((32*(NUMBER_WORDS-1))-1 downto 0) & x"00000000";
|
else
|
else
|
-- Check if the frame is ending.
|
-- Check if the frame is ending.
|
if (readContentEnd_i = '1') then
|
if (readContentEnd_i = '1') then
|
-- The frame is ending.
|
-- The frame is ending.
|
|
|
-- Update the window to the next frame.
|
-- Update the window to the next frame.
|
-- It takes one tick for the output from the frame
|
-- It takes one tick for the output from the frame
|
-- buffer to get updated.
|
-- buffer to get updated.
|
readWindowNext_o <= '1';
|
readWindowNextOut <= '1';
|
|
|
-- Proceed to check if there is another frame to start
|
-- Proceed to check if there is another frame to start
|
-- with directly.
|
-- with directly.
|
frameState_o <= FRAME_END;
|
frameState_o <= FRAME_END;
|
else
|
else
|
readContent_o <= '1';
|
|
frameWordCounter_o <= readContentWords_i;
|
frameWordCounter_o <= readContentWords_i;
|
frameContent_o <= readContentData_i;
|
frameContent_o <= readContentData_i;
|
|
readContentOut <= '1';
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
when FRAME_END =>
|
when FRAME_END =>
|
---------------------------------------------------------------
|
---------------------------------------------------------------
|
Line 1451... |
Line 1488... |
|
|
-- Update the window ackId.
|
-- Update the window ackId.
|
ackIdWindow_o <= std_logic_vector(unsigned(ackIdWindow_i) + 1);
|
ackIdWindow_o <= std_logic_vector(unsigned(ackIdWindow_i) + 1);
|
|
|
-- Start timeout supervision for transmitted frame.
|
-- Start timeout supervision for transmitted frame.
|
timeSentWrite_o <= '1';
|
timeSentSet_o <= '1';
|
|
|
-- Start a new frame the next time.
|
-- Start a new frame the next time.
|
frameState_o <= FRAME_START;
|
frameState_o <= FRAME_START;
|
|
|
when others =>
|
when others =>
|
Line 1466... |
Line 1503... |
|
|
end case;
|
end case;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
end process;
|
end process;
|
|
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
-- N-1
|
-- N-1
|
-- Create the stype0 and stype1 part of a control symbol.
|
-- Create the stype0 and stype1 part of a control symbol.
|
Line 1486... |
Line 1522... |
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
|
|
process(clk, areset_n)
|
process(clk, areset_n)
|
begin
|
begin
|
if (areset_n = '0') then
|
if (areset_n = '0') then
|
|
rxControlUpdate_o <= '0';
|
|
|
controlValid <= '0';
|
controlValid <= '0';
|
stype0 <= (others=>'0');
|
stype0 <= (others=>'0');
|
parameter0 <= (others=>'0');
|
parameter0 <= (others=>'0');
|
parameter1 <= (others=>'0');
|
parameter1 <= (others=>'0');
|
stype1 <= STYPE1_NOP;
|
stype1 <= STYPE1_NOP;
|
cmd <= (others=>'0');
|
cmd <= (others=>'0');
|
dataValid <= '0';
|
dataValid <= '0';
|
dataContent <= (others=>'0');
|
dataContent <= (others=>'0');
|
elsif (clk'event and clk = '1') then
|
elsif (clk'event and clk = '1') then
|
if (txFull_i = '0') then
|
if (txFull_i = '0') then
|
|
rxControlUpdate_o <= rxControlUpdateOut;
|
|
|
controlValid <= controlValidOut;
|
controlValid <= controlValidOut;
|
stype0 <= stype0Out;
|
stype0 <= stype0Out;
|
parameter0 <= parameter0Out;
|
parameter0 <= parameter0Out;
|
parameter1 <= parameter1Out;
|
parameter1 <= parameter1Out;
|
stype1 <= STYPE1_NOP;
|
stype1 <= STYPE1_NOP;
|
Line 1526... |
Line 1566... |
|
|
symbolControlStype1 <=
|
symbolControlStype1 <=
|
symbolControlRestart or symbolControlLinkRequest or
|
symbolControlRestart or symbolControlLinkRequest or
|
symbolControlStart or symbolControlEnd;
|
symbolControlStart or symbolControlEnd;
|
|
|
process(txFull_i, linkInitialized_i, ackIdStatus_i, portInitialized_i,
|
process(linkInitialized_i, ackIdStatus_i, portInitialized_i,
|
operational_i, counter_i, statusReceived_i, symbolsTransmitted_i)
|
operational_i, counter_i, statusReceived_i, symbolsTransmitted_i,
|
|
rxControlEmpty_i,
|
|
symbolControlStype1, symbolData,
|
|
rxControlStype0, rxControlParameter0, rxControlParameter1)
|
begin
|
begin
|
operational_o <= operational_i;
|
operational_o <= operational_i;
|
counter_o <= counter_i;
|
counter_o <= counter_i;
|
symbolsTransmitted_o <= symbolsTransmitted_i;
|
symbolsTransmitted_o <= symbolsTransmitted_i;
|
rxControlUpdate_o <= '0';
|
rxControlUpdateOut <= '0';
|
|
|
controlValidOut <= '0';
|
controlValidOut <= '0';
|
stype0Out <= STYPE0_STATUS;
|
stype0Out <= STYPE0_STATUS;
|
parameter0Out <= ackIdStatus_i;
|
parameter0Out <= ackIdStatus_i;
|
parameter1Out <= "11111";
|
parameter1Out <= "11111";
|
|
|
-- Check if there is room for more in the outbound fifo.
|
|
if (txFull_i = '0') then
|
|
-- The outbound fifo needs to be filled.
|
|
|
|
-- Check the operational state.
|
-- Check the operational state.
|
if (operational_i = '0') then
|
if (operational_i = '0') then
|
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
-- This state is entered at startup. A port that is not initialized
|
-- This state is entered at startup. A port that is not initialized
|
-- should only transmit idle sequences.
|
-- should only transmit idle sequences.
|
Line 1623... |
Line 1662... |
-- receiver or too many idle symbols has been sent.
|
-- receiver or too many idle symbols has been sent.
|
|
|
-- Force the sending of a status containing the bufferStatus.
|
-- Force the sending of a status containing the bufferStatus.
|
controlValidOut <= '1';
|
controlValidOut <= '1';
|
symbolsTransmitted_o <= (others=>'0');
|
symbolsTransmitted_o <= (others=>'0');
|
elsif ((symbolControlStype1 = '1') and (rxControlEmpty_i = '0')) then
|
elsif ((symbolData = '0') and (rxControlEmpty_i = '0')) then
|
-- A control symbol is about to be sent and there is a pending
|
-- A control symbol is about to be sent and there is a pending
|
-- symbol from the receiver.
|
-- symbol from the receiver.
|
|
|
-- Remove the symbol from the fifo.
|
-- Remove the symbol from the fifo.
|
rxControlUpdate_o <= '1';
|
rxControlUpdateOut <= '1';
|
|
|
-- Send the receiver symbol.
|
-- Send the receiver symbol.
|
controlValidOut <= '1';
|
controlValidOut <= '1';
|
stype0Out <= rxControlStype0;
|
stype0Out <= rxControlStype0;
|
parameter0Out <= rxControlParameter0;
|
parameter0Out <= rxControlParameter0;
|
Line 1657... |
Line 1696... |
-- The port is not initialized anymore.
|
-- The port is not initialized anymore.
|
-- Change the operational state.
|
-- Change the operational state.
|
operational_o <= '0';
|
operational_o <= '0';
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
end process;
|
end process;
|
|
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
-- N pipeline stage.
|
-- N pipeline stage.
|
-- Make all symbols ready for transmission, i.e. calculate the CRC5 on
|
-- Make all symbols ready for transmission, i.e. calculate the CRC5 on
|