📄 internet.vhd
字号:
-- | Source IP Address |
-- | |
-- --------------------------------------------------------------------------------------------
-- | Destination IP Address |
-- | |
-- --------------------------------------------------------------------------------------------
-- | Options (if any - ignored) | Padding |
-- | | (if needed) |
-- --------------------------------------------------------------------------------------------
-- | Data |
-- | |
-- --------------------------------------------------------------------------------------------
-- | .... |
-- | |
-- --------------------------------------------------------------------------------------------
--
-- * - in 32 bit words
process (presState, returnState, cnt, frameDataLatch, datagramLen, headerLen, dataLen, newFrame, wrCnt,
complete, frameType, checksum, targetIP, bufferSelectSig, targetIdent,
position0, position1, ident0, ident1, fragmentOffset, moreFragments, timeout0, timeout1,
endFrame, newFrameByte, frameValid)
begin
-- signal defaults
wrRAM <= '0';
wrData <= (others => '0');
wrAddr <= (others => '0');
datagramSize <= (others => '0');
incCnt <= '0';
rstCnt <= '0';
incWrCnt <= '0';
rstWrCnt <= '0';
newDataGram <= '0';
-- the following two signals remember their previous value if not reassigned
nextHeaderLen <= headerLen;
nextDatagramLen <= datagramLen;
doWrite <= '0';
getNewByte <= '0';
latchFrameData <= '0';
shiftInSourceIP <= '0';
shiftInTargetIP <= '0';
latchProtocol <= '0';
newHeader <= '0';
newByte <= '0';
inByte <= (others => '0');
latchMoreFragments <= '0';
shiftInFragmentOffset <= '0';
shiftInIdentification <= '0';
nextBufferSelect <= bufferSelectSig;
latchIdent <= '0';
resetIdent <= '0';
updatePosition <= '0';
resetPosition <= '0';
resetTimeout <= '0';
case presState is
when stIdle =>
-- wait for the arrival of a new frame that has a frameType of 1
if newFrame = '0' or frameType = '0' then
nextState <= stIdle;
else
-- reset the counters for the next datagram
rstCnt <= '1';
rstWrCnt <= '1';
newHeader <= '1';
nextState <= stGetHeaderLen;
-- get header length and version information
getNewByte <= '1';
end if;
when stGetHeaderLen =>
-- check ip version
if frameDataLatch (7 downto 4) /= 4 then
nextState <= stIdle;
else
nextState <= stGetHeaderByte;
-- send data to checksum machine
inByte <= frameDataLatch;
newByte <= '1';
-- get the header length in bytes, rather than 32-bit words
nextHeaderLen <= frameDataLatch (3 downto 0) & "00";
end if;
when stGetHeaderByte =>
-- if we've finished getting the headers and processing them, start on the data
-- once finished, refragmenting will come next
if cnt = headerLen then
-- only operate on data meant for us, or broadcast data
if checksum = 0 and (targetIP = DEVICE_IP or targetIP = x"FFFFFFFF") then
-- determine which buffer should be used to handle the data
if ident0 = targetIdent and timeout0 /= FULLTIME then
-- the ident matches and the timeout counter has not expired
nextBufferSelect <= '0';
-- accept the frame if its offset matches what we think it should be
-- this drops out of order and duplicate frames.
if position0 = fragmentOffset & "000" then
nextState <= stGetDataByte;
else
nextState <= stIdle;
end if;
elsif ident1 = targetIdent and timeout1 /= FULLTIME then
-- the ident matches and the timeout counter has not expired
nextBufferSelect <= '1';
-- accept the frame if its offset matches what we think it should be
-- this drops out of order and duplicate frames.
if position1 = fragmentOffset & "000" then
nextState <= stGetDataByte;
else
nextState <= stIdle;
end if;
elsif (ident0 = 0 or timeout0 = FULLTIME) and fragmentOffset = 0 then
-- The ident doesn't match either of the buffers so check if buffer 0
-- is free. If ident = 0 or the timeout has expired then the buffer is free
-- This must be the first fragment if it is to go here so also check the offset
nextState <= stGetDataByte;
nextBufferSelect <= '0';
elsif (ident1 = 0 or timeout1 = FULLTIME) and fragmentOffset = 0 then
-- The ident doesn't match either of the buffers so check if buffer 1
-- is free. If ident = 0 or the timeout has expired then the buffer is free
-- This must be the first fragment if it is to go here so also check the offset
nextState <= stGetDataByte;
nextBufferSelect <= '1';
else
nextState <= stIdle;
end if;
else
-- ignore frame as it wasn't for us
nextState <= stIdle;
end if;
-- otherwise get the next header byte from RAM
else
nextState <= stStoreHeaderByte;
getNewByte <= '1';
end if;
when stStoreHeaderByte =>
nextState <= stGetHeaderByte;
-- operate on each value of the header received according to count
-- count will be one higher than the last byte received, as it is incremented
-- at the same time as the data is streamed in, so
-- when the data is seen to be available, count should also be one higher
-- Send data to checksum process
newByte <= '1';
inByte <= frameDataLatch;
-- Operate on data in the header
case cnt(4 downto 0) is
when "00011" =>
nextDatagramLen (10 downto 8) <= frameDataLatch (2 downto 0);
when "00100" =>
nextDatagramLen (7 downto 0) <= frameDataLatch;
when "00101" | "00110" =>
shiftInIdentification <= '1';
when "00111" =>
shiftInFragmentOffset <= '1';
latchMoreFragments <= '1';
when "01000" =>
shiftInFragmentOffset <= '1';
when "01010" =>
latchProtocol <= '1';
when "01101" | "01110" | "01111" | "10000" =>
shiftInSourceIP <= '1';
when "10001" | "10010" | "10011" | "10100" =>
shiftInTargetIP <= '1';
when others =>
end case;
when stGetDataByte =>
-- if we haven't finished receiving the data, then
if cnt /= datagramLen then
nextState <= stSetupWriteDataByte;
-- read an IP data byte from the data stream...
getNewByte <= '1';
elsif endFrame = '1' and frameValid = '1' then
-- this means that the frame is finished and was valid
-- so update the buffer data and go to final state
nextState <= stCompleteFragment;
resetTimeout <= '1'; -- start/restart timer
latchIdent <= '1'; -- allocate buffer to data
if fragmentOffset = 0 then -- check if this is the first fragment
resetPosition <= '1'; -- give position initial value
else
updatePosition <= '1'; -- or add to the amount of data stored
end if;
elsif endFrame = '1' then
-- the frame is complete but not valid so ignore it
nextState <= stIdle;
else
-- the frame is not complete so keep looping until it is
nextState <= stGetDataByte;
end if;
when stSetupWriteDataByte =>
nextState <= stGetDataByte;
--Set up to write the byte that was read in stGetDataByte to RAM
doWrite <= '1';
wrData <= frameDataLatch;
when stCompleteFragment =>
-- Signal the transport protocols if the datagram is finished
-- or await next frame.
nextState <= stIdle;
if moreFragments = '0' then
-- Last frame so :
newDatagram <= '1'; -- notify higher protocols it's ready
resetIdent <= '1'; -- free buffer for next time
if bufferSelectSig = '0' then -- output datagram size from correct buffer
datagramSize <= position0;
else
datagramSize <= position1;
end if;
end if;
when stDoWrite =>
-- Wait for RAM write request to be serviced
if complete = '0' then
-- keep signals asserted until complete is high
nextState <= stDoWrite;
wrRAM <= '1';
-- The address is based on the fragment offset and buffer
if bufferSelectSig = '0' then
wrAddr <= "001" & (wrCnt + (fragmentOffset & "000"));
else
wrAddr <= "010" & (wrCnt + (fragmentOffset & "000"));
end if;
wrData <= frameDataLatch;
else
-- when write is finished, go to returnState
nextState <= returnState;
incWrCnt <= '1';
end if;
when stGetNewByte =>
if newFrameByte = '0' then
-- wait for new byte to arrive
nextState <= stgetNewByte;
else
-- latch new byte and go to returnState
nextState <= returnState;
incCnt <= '1';
latchFrameData <= '1';
end if;
when others =>
end case;
end process;
-- Perform 2's complement to one's complement conversion, and invert output
checksumInt <= checksumLong(15 downto 0) + checksumLong(16);
checksum <= NOT checksumInt;
process (clk,rstn)
begin
if rstn = '0' then
checkState <= stMSB;
latchMSB <= (others => '0');
checkSumLong <= (others => '0');
lastNewByte <= '0';
elsif clk'event and clk = '1' then
-- this is used to check only for positive transitions
lastNewByte <= newByte;
case checkState is
when stMSB =>
if newHeader = '1' then
-- reset calculation
checkState <= stMSB;
checkSumLong <= (others => '0');
elsif newByte = '1' and lastNewByte = '0' then
-- latch MSB of 16 bit data
checkState <= stLSB;
latchMSB <= inByte;
else
checkState <= stMSB;
end if;
when stLSB =>
if newHeader = '1' then
-- reset calculation
checkState <= stMSB;
checkSumLong <= (others => '0');
elsif newByte = '1' and lastnewByte = '0' then
-- add with 2's complement arithmetic (convert to 1's above)
checkState <= stMSB;
checkSumLong <= ('0' & checkSumInt) + ('0' & latchMSB & inByte);
else
checkState <= stLSB;
end if;
when others =>
checkState <= stMSB;
end case;
end if;
end process;
end internet_arch;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -