library ieee; 
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity modMCounter is
    generic (
            M : integer := 5; -- count from 0 to M-1
            N : integer := 3   -- N bits required to count upto M i.e. 2**N >= M
    );
    
    port(
            clk, reset : in std_logic;
            complete_tick : out std_logic;
            count : out std_logic_vector(N-1 downto 0)
    );
end modMCounter;
architecture arch of modMCounter is
    signal count_reg, count_next : unsigned(N-1 downto 0);
begin
    process(clk, reset)
    begin
        if reset = '1' then 
            count_reg <= (others=>'0');
        elsif   clk'event and clk='1' then
            count_reg <= count_next;
        else  -- note that else block is not required
            count_reg <= count_reg;
        end if;
    end process;
    
    -- set count_next to 0 when maximum count is reached i.e. (M-1)
    -- otherwise increase the count
    count_next <= (others=>'0') when count_reg=(M-1) else (count_reg+1);
    
    -- Generate 'tick' on each maximum count
    complete_tick <= '1' when count_reg = (M-1) else '0';
    
    count <= std_logic_vector(count_reg); -- assign value to output port
end arch;

이 코드는 모듈로 카운터를 구현한 코드입니다. 

이 모듈러 카운터는 특정 범위 내에서 지정한 간격으로 카운트를하는 카운터로, 카운트가 최댓값에 도달하면 다시 0부터 시작합니다. 이 코드는 0부터 M-1까지 카운트하며, N비트가 필요합니다.

이 도뮬은 총 4개의 포트로 구성이됩니다. clk와 reset은 각각 카운터를 증가시키는 클록 신호와 카운터를 초기화하는 리셋 신호입니다. 

compelete_tick은 카운트가 M-1에 도달할때마다 '1'신호가 출력되는 출력 포트입니다. count는 현재 카운트 값이 출력되는 포트로,N비트의 벡터로 구성이됩니다.

clk와 reset 신호에 대한 process가 정의되어 있으며, reset이 '1'일 경우 count_reg가 0으로 초기화됩니다. clk의 edge가 감지되면 count_next 신호가 count_reg로 할당됩니다. 그 외의 경우는 count_reg를 유지합니다.

count_next는 현재 카운트 값이 M-1에 도달하면 0으로 리셋됩니다. 그렇지 않은 경우에는 카운트 값을 1씩 증가시킵니다. complete_tick은 count_reg가 M-1일 때 '1'로 할당되며, 그렇지 않은 경우에는 '0'으로 유지됩니다.

count는 count_reg 값을 N 비트의 벡터로 변환하여 출력합니다.

 

다음은 이 모듈로 카운터의 테스트벤치 코드입니다.

library ieee; 
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity modMCounter_tb is
end modMCounter_tb;


architecture arch of modMCounter_tb is
    constant M : integer := 3;  -- count upto 2 (i.e. 0 to 2)
    constant N : integer := 4;
    constant T : time := 100 ns; 

    signal clk, reset : std_logic;  -- input
    signal complete_tick : std_logic; -- output
    signal count : std_logic_vector(N-1 downto 0);  -- output

    -- total samples to store in file
    constant num_of_clocks : integer := 30; 
    signal i : integer := 0; -- loop variable
    begin

    modMCounter_unit : entity work.modMCounter
        generic map (M => M, N => N)
        port map (clk=>clk, reset=>reset, complete_tick=>complete_tick,
                    count=>count);

    -- reset = 1 for first clock cycle and then 0
    reset <= '1', '0' after T/2;

    -- continuous clock
    process 
    begin
        clk <= '0';
        wait for T/2;
        clk <= '1';
        wait for T/2;

        -- run 30 clocks
        if (i = num_of_clocks) then
           wait;
        else
            i <= i + 1;
        end if;
    end process;
end arch;

테스트벤치에서 사용되는 입력 신호는 clk와 reset입니다. clk는 일정한 주기로 반복되는 신호이며, reset은 모듈의 초기화를 수행하는데 사용됩니다.
테스트벤치에서 사용되는 출력 신호는 complete_tick과 count입니다. complete_tick은 모듈이 최대 카운트 값을 도달했을 때 생성되는 신호입니다. count는 현재 카운트 값을 나타내는 N비트 이진수 신호입니다.
테스트벤치는 시뮬레이션 시간을 T만큼 주기적으로 반복하면서, 모듈을 호출하고, 모듈이 제공하는 출력값을 파일에 저장합니다. 출력값은 이진수 형태로 저장됩니다.
테스트벤치는 초기에 reset 신호를 설정하고, 일정 주기마다 clk 신호를 생성하면서 모듈을 호출하고, 출력값을 저장하며, 시뮬레이션 시간이 끝날 때까지 반복됩니다.

'Computer_logic' 카테고리의 다른 글

Testbench  (0) 2023.04.06
Mealy & Moore VHDL code  (0) 2023.04.05
Mealy FSM & Moore FSM  (0) 2023.04.05
TCP Congestion control  (0) 2022.11.09
FLOW control  (0) 2022.11.09

이 테스트벤치는 디지털 회로를 시뮬레이션하고 검증하기 위한 코드입니다. 디지털 회로는 하드웨어 자체적으로 테스트하기 어려운 경우가 많아서, 테스트벤치를 작성하여 시뮬레이션을 수행하고 회로의 동작을 확인합니다.

또한 입력 신호를 생성하고, 이를 디지털 회로에 적용하여 출력 신호를 측정하고 검증합니다. 이를 위해 테스트벤치는 주어진 입력에 대한 예상 출력을 정의하고, 디지털 회로가 예상 출력과 동일한지를 확인합니다.

테스트벤치

library ieee;
use ieee.std_logic_1164.all;

entity half_adder is 
  port (a, b : in std_logic;
        sum, carry : out std_logic
    );
end half_adder;

architecture arch of half_adder is
begin
  sum <= a xor b;
  carry <= a and b;
end arch;

이코드는 하프에더의 vhdl code입니다. 두개의 입력(a,b)과 두개의 출력(sum,carry)을 가지고있습니다.

sum은 xor연산자를 이용하여 계산되며, carry는 and연산자를 이용하여 계산됩니다.

 

다음은 이 하프에더의 테스트 벤치 코드입니다.

library ieee;
use ieee.std_logic_1164.all;


entity half_adder_simple_tb is
end half_adder_simple_tb;

architecture tb of half_adder_simple_tb is
    signal a, b : std_logic;  -- inputs 
    signal sum, carry : std_logic;  -- outputs
	 
begin
    -- connecting testbench signals with half_adder.vhd
    UUT : entity work.half_adder port map (a => a, b => b, sum => sum, carry => carry); 
	 -- half_adder and the TB must be in the same directory
	 
   STIM: process 
      constant period: time := 50 ns;
    begin
         a <= '0';
         b <= '0';
         wait for period;
         assert ((sum = '0') and (carry = '0'))  -- expected output
         -- error will be reported if sum or carry is not 0
         report "test failed for input combination 00" severity error;
         a <= '0';
         b <= '1';
         wait for period;
         assert ((sum = '1') and (carry = '0'))
         report "test failed for input combination 01" severity error;

         a <= '1';
         b <= '0';
         wait for period;
         assert ((sum = '1') and (carry = '0'))
         report "test failed for input combination 10" severity error;

         a <= '1';
         b <= '1';
         wait for period;
         assert ((sum = '0') and (carry = '1'))
         report "test failed for input combination 11" severity error;

         -- Fail test
         a <= '0';
         b <= '1';
         wait for period;
         assert ((sum = '0') and (carry = '1'))
         report "test failed for input combination 01 (fail test)" severity error;

         wait; -- indefinitely suspend process
    end process;
end tb ;

이 테스트벤치코드는 half_adder.vhd 파일에서 정의된 half_adder라는 이름의 엔티티를 테스트합니다.

이 테스트 벤치에서는 입력신호 a,b와 출력신호 sum,carry를 정의합니다. 

UUT라는 이름으로 half_adder엔티티를 인스턴스화 하고, 이를 테스트벤치의 입력과 출력신호와 연결합니다.

이것을 통하여 입력신호를 half_adder로 전달하고, 출력 신호를 테스트벤치로 가져올 수 있습니다.

 

STIM프로세스는 테스트벤치의 핵심입니다. 이 프로세스는 입력신호 a,b에 값을 할당하고, 이를 half_adder에 전달하여 출력신호 sum,carry를 측정합니다. 이후 예상 출력값과 실제 출력값이 일치하는지 확인하기 위해 assert문을 사용합니다.

여기서는 입력신호 a,b가 00,01,10,11순서로 변화하며, 각각의 대해 예상 출력값을 assert문으로 검증합니다.

그리고 fail test를 실행하여 예상출력값과 다른 경우의 assert문도 확인합니다.

'Computer_logic' 카테고리의 다른 글

Modulo M counter  (0) 2023.04.06
Mealy & Moore VHDL code  (0) 2023.04.05
Mealy FSM & Moore FSM  (0) 2023.04.05
TCP Congestion control  (0) 2022.11.09
FLOW control  (0) 2022.11.09

무어머신입니다 헿

USE ieee.std_logic_1164.all ;

ENTITY simple IS
	PORT (	clock   : IN STD_LOGIC ;
                     resetn  : IN STD_LOGIC ;
                     w          : IN STD_LOGIC ;
			 z          : OUT STD_LOGIC ) ;
END simple ;

ARCHITECTURE Behavior OF simple IS
	TYPE State_type IS (A, B, C) ;
	SIGNAL y : State_type ;
BEGIN
	PROCESS ( resetn, clock )
	BEGIN
		IF resetn = '0' THEN
			y <= A ;
		ELSIF (Clock'EVENT AND Clock = '1') THEN
        CASE y IS
				WHEN A =>
					IF w = '0' THEN 
						y <= A ;
					ELSE 
						y <= B ;
					END IF ;
				WHEN B =>
					IF w = '0' THEN
						y <= A ;
					ELSE
						y <= C ;
					END IF ;
				WHEN C =>
					IF w = '0' THEN
						y <= A ;
					ELSE
						y <= C ;
					END IF ;
			END CASE ;
            END IF ;
	   END PROCESS ;
	
         z <= '1' WHEN y = C ELSE '0' ;

END Behavior ;

무어머신 VHDL code해석을 진행해보도록 하겠습니다......

우선 환경 설정을 해주고 clock과 reset을 선언해주고 w라는 인풋과 z라는 인풋을 선언해줍니다.

그리고 스테이트들을 선언을 해줍니다.

y는 현재 상태를 저장하는 신호로 초기상태 'A'로 설정됩니다.

PROCESS블록에서는 clock과 resetn의 신호를 감지하고이에따라 동작을 제어합니다.

만약 resetn의 신호가 0이면 y는 초기상태의 A로 설정됩니다.

만약 현재 스테이트가 A라면 인풋으로 0이 들어온다면 현재상태 A인 그대로 있으며 그게 아니라면 스테이트는 B로 설정이 됩니다. 만약 현재 상태가 B라면 인풋으로 0이 들어온다면 스테이트는 A로 바뀔것이며 그게 아니라면 스테이트는 C로 바뀔것입니다. 만약 현재 상태가 C라면 인풋으로0이 들어온다면 스테이트는 A로 바뀔것이며 그게아니라면 C로 바뀔것입니다.

아웃풋의 설정을 보면 현재 스테이트가 C일때만 아웃풋이 1이고 그게 아니라면 0을 출력하도록 되어있습니다.

 

이것은 밀리머신입니다.

LIBRARY ieee ;
USE ieee.std_logic_1164.all ;

ENTITY Mealy IS
	PORT ( 	clock     : IN 		STD_LOGIC ;
                     resetn   : IN 		STD_LOGIC ;
                     w 		: IN 		STD_LOGIC ;
			z      	: OUT 	STD_LOGIC ) ;
END Mealy ;

ARCHITECTURE Behavior OF Mealy IS
	TYPE State_type IS (A, B) ;
	SIGNAL y : State_type ;
BEGIN
	PROCESS ( resetn, clock )
	BEGIN
		IF resetn = '0' THEN
			y <= A ;
		ELSIF (clock'EVENT AND clock = '1') THEN
        CASE y IS
			       WHEN A =>
			              IF w = '0' THEN 
                                                  y <= A ;
				ELSE 
                                                  y <= B ;
				END IF ;
			        WHEN B =>
				IF w = '0' THEN 
                                                   y <= A ;
				ELSE 
                                                   y <= B ;
			        	END IF ;
			END CASE ;
            END IF ;
	END PROCESS ;

	WITH y SELECT
		z <= w WHEN B,
              z <= ‘0’  WHEN others;

END Behavior ;

이 밀리머신도 아까의 무어머신과 동일하게 설정과 스테이트 인풋과 아웃풋의 설정 그리고 특정 스테이트의 인풋값에 따라서 스테이트의 변화를 다 설정을 해줍니다. 그리고 마지막에 아웃풋을 결정하는 코드에서 만약 스테이트가 B라면 아웃풋으로 인풋값을 넣고 만약 아니라면 아웃풋값에 0을 넣어줍니다.

'Computer_logic' 카테고리의 다른 글

Modulo M counter  (0) 2023.04.06
Testbench  (0) 2023.04.06
Mealy FSM & Moore FSM  (0) 2023.04.05
TCP Congestion control  (0) 2022.11.09
FLOW control  (0) 2022.11.09

Finite State Machines(유한상태기계)는 주어진 입력에 따라 사전 정의된 동작을 수행하는 자동화된 기계입니다. FSM은 입력이 발생할 때 현재 상태에서 다음 상태로 전환하고, 출력을 생성합니다. FSM은 상태, 입력 및 출력에 대한 추상화된 모델을 사용하여 디지털 논리 회로 설계를 기술하는 데 자주 사용됩니다.

 

FSM은 두 가지 종류가 있습니다. Mealy 모델과 Moore 모델입니다. Mealy 모델에서는 상태 전이와 출력 값이 입력 및 현재 상태에 따라 결정됩니다. 반면에 Moore 모델에서는 상태 전이와 출력 값이 현재 상태에만 의존합니다. 각각의 모델은 특정 문제를 해결하기 위해 사용됩니다.

 

무어 모델은 상태 전이와 출력 값이 서로 독립적입니다. 즉, FSM의 현재 상태만으로 출력 값을 결정합니다. 따라서 무어 모델에서는 출력 값이 현재 상태에 대한 함수로 표현됩니다. 예를 들어, 현재 상태가 "정지"일 때 "정지" 라는 출력을 내보냅니다. 무어 모델은 출력 값이 안정적이며, 회로 구성이 단순하며 구현이 쉬워서 자주 사용됩니다.

 

밀리 모델은 상태 전이와 출력 값이 입력 값에 따라 결정됩니다. 따라서 밀리 모델에서는 출력 값이 입력 값과 현재 상태에 대한 함수로 표현됩니다. 예를 들어, 입력 값이 "1"이면 현재 상태에 따라 "1" 또는 "0"을 출력합니다. 밀리 모델은 출력 값이 동적이며, 상태 전이에 대한 피드백을 받아 반응성을 높일 수 있습니다. 하지만 회로 구성이 복잡하며, 디자인이 어렵습니다.

 

이 사진은 무어머신입니다.
이 사진은 밀리머신입니다.
이 타이밍 다이어그램은 입력받은 input에 따라 무어머신과 밀리머신의 스테이트와 출력값을 나타낸것입니다.

이 타이밍 다이어그램을 통하여 무어머신과 밀리머신의 state는 인풋에 따라서 즉각적으로 변하지만 출력값은 밀리머신은인풋값이 0으로 떨어짐과 동시에 바로 아웃풋으로 1이 출력되는것을 볼수있고 그에 반하여 무어머신은 클락에 동기화하여 스테이트가 변한 직후에 아웃풋이 변하는걸 관찰할 수 있습니다.

 

다음은 무어머신과 밀리머신의 쿼터스의 vhdl을 통한 코드작성입니다.

이것은 무어머신입니다.

TYPE state IS (S0, S1, S2);
SIGNAL Moore_state: state;

U_Moore: PROCESS (clock, reset)
BEGIN
	IF(reset = ‘1’) THEN
		Moore_state <= S0;
	ELSIF (clock = ‘1’ AND clock’event) THEN
		CASE Moore_state IS
			WHEN S0 =>
			  IF input = ‘1’ THEN
                    Moore_state <= S1; 
                ELSE
                   Moore_state <= S0;
                END IF;
            WHEN S1 =>
			  IF input = ‘0’ THEN 
                                     Moore_state <= S2; 
                              ELSE
                                     Moore_state <= S1; 
                              END IF;
	                  WHEN S2 =>
			  IF input = ‘0’ THEN
                                     Moore_state <= S0; 
			  ELSE 
                                     Moore_state <= S1; 
                              END IF;
		END CASE;
	END IF;
END PROCESS;

Output <= ‘1’ WHEN Moore_state = S2 ELSE ‘0’;

위 코드를 잘 보면 state의 상태들을 제시하고 clock과 reset을 동기화 해주었습니다.

만약 reset이 1이라면 초기 스테이트인 S0로 이동하도록 해주었으며, CLOCK이 1이면 무어머신의 현재 스테이트가 S0라면 인풋값으로 1이들어오면 스테이트는 S1로 설정이되게하고, 그게아니라면 S0으로 설정이되게 하였습니다. 

만약 현재 스테이트가 S1이라면 인풋값으로 0이 들어온다면 스테이트를 S2로 설정을 해주고 그게 아니라면 S1으로 설정을 하게 하였습니다.

만약 현재 스테이트가 S2라면 인풋값으로 0이 들어오면 스테이트를 S0로 옮겨지게 설정을 해주고 그게 아니라면 S1으로 설정을 해주게 하였으며 맨 밑 코드에 나와있는것처럼 아웃풋 설정은 무어머신의 현재 스테이트가 S2라면 1을 출력하고 그게 아니라면 0을 출력하게 설정이 된걸 볼 수 있습니다.

 

이것은 밀리머신입니다.

TYPE state IS (S0, S1);
SIGNAL Mealy_state: state;

U_Mealy: PROCESS(clock, reset)
BEGIN
	IF(reset = ‘1’) THEN
		Mealy_state <= S0;
	ELSIF (clock = ‘1’ AND clock’event) THEN
		CASE Mealy_state IS
		    WHEN S0 =>
	            IF input = ‘1’ THEN 
                     Mealy_state <= S1; 
                ELSE
                     Mealy_state <= S0;
                END IF;
            WHEN S1 =>
			  IF input = ‘0’ THEN
                                     Mealy_state <= S0; 
                               ELSE
                                     Mealy_state <= S1;
                               END IF;
		END CASE;
	END IF;
END PROCESS;

Output <= ‘1’ WHEN (Mealy_state = S1 AND input = ‘0’) ELSE ‘0’;

이 밀리머신을 구현한 VHDL코드를 보면 알겠듯이 아까 무어머신과는 동일하게 스테이트 설정을 해주고 스테이트 이동도 인풋에 따라서 비슷하게 구현이 되었습니다. 근데 여기에서 마지막에 아웃풋을 설정해주는 코드를 유심히보면 알겠지만

현재 스테이트의 값과 다음 인풋에 따라서 아웃풋이 결정된다는걸 알수있습니다. 

만약 현재의 밀리머신의 스테이트값이 S1이고 인풋이 0이라면 바로 아웃풋은 1이고 그게 아니라면 0이라고 해석이됩니다.

다음은 좀 더 자세하게 무어머신과 밀리머신의 VHDL코드에 대하여 알아보도록 하겠습니다.

'Computer_logic' 카테고리의 다른 글

Testbench  (0) 2023.04.06
Mealy & Moore VHDL code  (0) 2023.04.05
TCP Congestion control  (0) 2022.11.09
FLOW control  (0) 2022.11.09
TCP에러컨트롤  (0) 2022.11.09

TCP는 에러컨트롤 플로우컨트롤 컨제스천 컨트롤 3가지의 컨트롤이있음

CONGESTION CONTROL이란 CWND값을 결정하는 과정임 

첫번째는 네트워크 컨제스천을 감지해야함

두번째는 그걸바탕으로CWND계산해야함

버퍼가 꽉차면 전송된 시그널이 없어지는데 이걸 패킷로스라고함. <-이게 문제야! 목적지까지 너무 오래걸리고 심지어 없어짐.

근데 이걸 어캐 감지함???

크게 3가지 솔루션

1. 컨제스천이 발생하면 딜레이가 됨

2. 더 나아가서는 패킷로스가 일어남 

3. 중간에 있는중계기가 능동적으로 컨제스천이 발생한걸 알려줌(Explict Marks) <- 데이터 패킷에 컨제스천 발생했음이라고 쓰는 방법있음!

근데 이 3번 방법은 tcp에서 사용어려움 why? 앤드 투 앤드 프로토콜이기때문 중계기에 tcp가 안올라감

그래서 1 2 번 두개가 가능성이 있는 솔루션임.

그래서 1번으로 만약 패킷로스가 발생하면 컨제스천이다 라고 여기고, cwnd사이즈를 줄여주는 방식으로 할것임.

이게 결론적으로 tcp가 하는 일임! 패킷로스를 감지하면 cwnd를 줄인다.

근데 이 패킷로스를 어캐감지행?? 

쉽게말하면 1001번 패킷을 보냈는데 거기에대한 애크가 안오는 경우 1001번 패킷이 로스됐다고 생각함.

여기서 다시 집어보자면 윈도우는 한번에 보낼수있는 데이터이고 한번에 보낸다는 의미는 리시버에서 애크가 안와도 보낼수있는 최대 데이터의 양!

만약 cwnd의 크기가 1000이라고 치자! 여기서 패킷로스가 발생하면 이때 cwnd값은 뭘로하면 좋을까? TCP는 반으로 쫙줄임 500으로 함.

statistical multiplexing이란? 평균적인 인풋속도가 아웃풋 속도를 넘지 않는다는 평균 개념이 들어간 통계적인 멀티플렉싱이라고 함!

여러개의 인풋이 하나의 아웃풋으로 뭉치는 부분이 있는데 이런 인터넷의 구조상 호스트가 여러군데에서 오는 데이터가 하나로 몰리는 경우가 발생하고 이런 링크가 혼잡을 유발함!(컨제스천) 일시적으로 많아지면 버퍼가 쌓이고 이게 컨제스천이고 심하면 패킷로스가 발생하게됨

일시적인 컨제스천은 버퍼 스페이스를 늘리는 것으로 해결이된다.

그치만! 컨제스천이 길어진다면 소스에서 전송률을 낮춰야하는 상황이 발생한다.

 

이렇게 인풋이 계속 올라가면 아웃풋도 일정한만큼 올라가다가 한계치에 다다르게되면 더이상 올라가지않음 

 

 

여기 보면 컨제스천이 발생하지 않는 상황에서는 인풋rate가 올라가는 만큼 아웃풋도 올라간다 근데 점점 인풋이 더 증가할수록 아웃풋이 증가하는 비율은 점차 줄어들고 결국엔 급격하게 떨어져서 throughput이 0으로간다(0에수렴함 = 네트워크가 망가짐 그래서 저 동그라미 친부분을 왔다갔다하도록 해줘여함) 이때 throughput은 시간당 전송 성공률을 뜻한다

근데 어떻게해야 저수준에서만 왔다갔다함?

첫번째 방법은 end - end congestion control

로스나 딜레이를 관찰한 앤드시스템이 컨제스천을 유추하고 이를바탕으로 인풋속도를 조절하게 함

 

2번째 방법은 네트워크가 적극적으로 개입하는거

중계기가 자기가 컨제스천이 발생하면 그걸 엔드호스트에 적극적으로 알림! 그러면 그얘기를듣고 엔드호스트는 인풋 rate를 낮춰주는데 이방법은 tcp에서 채택하기 어려움 이유는 아까 말했져?

 

TCP에서는 Additive increase라고 하는걸 하는데 이게 뭐냐면 만약에 내가 최초의 cwnd가 500으로 시작했다 근데 내가 데이터를 보내고 애크를받았어 그럼 501로 늘리고 또 데이터를 보냈는데 애크를 받았어 그럼 502로 늘리고 이렇게 애크를 받을때마다 1씩 cwnd를 늘리는게 저거임! 

이렇게 처음에 1로 cwnd를  하면 애크받으면 1씩 늘리면서 해주는게 저거임

근데 만약에 이렇게 올리다가 컨제스천이 발생해서 패킷로스가 일어났다? 그럼 반으로 줄이는 거임 예를들어서 계속 애크받고 그러다보니까 cwnd가 510까지 갔다 근데 패킷로스가 발생했어 그러면 반을 줄여서 cwnd가 255가 되는거임 또 쭉 증가시키다가 로스 발생하면 또 반으로 줄이고 이런식으로 진행함.

이렇게 톱니마냥 진행함

이런식으로 진행하는게 1번 TCP

근데 이방식이 좋을까? 저렇게 CWND값을 올려서 저꼴난건데 반으로 줄이는게 좋은건가?

그래서 2번 TCP를 Tahoe라고 부르는데 얘는 cwnd를 로스가 발생하면 1로 줄임 근데 이러면 컨제스천은 해소가되는데

또 cwnd올리는데에 시간이  오래걸려 1부터 다시 증가해야하니까 그래서 1로 줄이는 대신 문제가없으면 이걸 cwnd사이즈를 빨리 키우자 함그래서 슬로우하게 스타트하지만 이걸 적당히 슬로우하게 해서 1다음에 2 다음에 4다음에 8이런식으로 증가하게함 긍까 애크가 하나오면 1+1해서 2보내고 그럼 애크2개오자나 그러면 2+2해서 다음 4보내고 또 4+4해서 8보내고 이런식으로 증가하게함(exponential growth)

 이 TCP 2번째 버전인 Tahoe는 현재 cwnd값의 2분의1을 threshold라고 저장해두고 그다음에 cwnd는 1로세팅하고 1부터는 저 threshold값 까지 exponential growth방식으로 증가하게 한다.

여기서 3dupACK가 와도 패킷로스라고 보고 또 1로 줄임!

 

TCP 3번인 Reno는 만약에 패킷 로스가 발생하면 현재의 cwnd의 2분의1을 threshold라고 일단 정하고 이 로스가 타임아웃에관한 것이라면 tcp2번 tahoe처럼 처리하고  3dup ACK에 의한 것이라면 1번 TCP처럼 함.

TCP 3번은 이런식으로 동작함! 두개를 상황에따라 다르게 합친것임 ㅎㅎ

 

TCP vegas도 있는데 이건 구현하기 어려워서 아직 구현 안됨 ㅋㅋ

 

 

 

'Computer_logic' 카테고리의 다른 글

Mealy & Moore VHDL code  (0) 2023.04.05
Mealy FSM & Moore FSM  (0) 2023.04.05
FLOW control  (0) 2022.11.09
TCP에러컨트롤  (0) 2022.11.09
propagation delay & transmission delay  (0) 2022.11.08

rwnd : 리시브 윈도우 값을 리시버가 결정함 

소켓은: 어플리케이션이 네트워크 서비스를 이용하기 위한 통로

버퍼중 센더가 보낸 데이터를 저장할수있는 공간을 rwnd라고함

센더는 리시브 윈도우값을 받은 이후에 애크를 받기 전까지 리시브 윈도우 사이즈 만큼만 최대한 보내는것

예를들어 301~400 ....해서 1000까지 보내면 LBS는 1000이되고 LBA(LastByteAcked)는 300이 되는거임

그러면 1000에서 300을뺀 700바이트가 in-flight하다고함 근데 이것이 rwnd보다 크면 안된다는 뜻임.

 

congetion control(엔드 호스트가 주체가되는 컨제스처 컨트롤)

TCP는 애크가 안오면(보낸 세그먼트가 로스가되거나, 애크가 에러가 발생하는것) 컨제스처라고 생각함

컨제스천이 발생하면 버퍼가 꽉차서 로스가 발생하여서 컨제스천이 발생한다고 생각하심. 딱 이정도로만 정리!

 

여기서 이 윈도우 사이즈는 리시브 윈도우 사이즈임

애크넘버부터 시작해서 윈도우 사이즈만큼 한번에 받을수있다

애크넘버가 301이고 윈도우 사이즈가 700이면 1000번바이트까지 받을수있음

'Computer_logic' 카테고리의 다른 글

Mealy & Moore VHDL code  (0) 2023.04.05
Mealy FSM & Moore FSM  (0) 2023.04.05
TCP Congestion control  (0) 2022.11.09
TCP에러컨트롤  (0) 2022.11.09
propagation delay & transmission delay  (0) 2022.11.08

센더가 프레임을 하나 보내고 거기에 별 이상이없으면 리시버가 ack를 하나보냄 그 애크를 확인한후 다음 프레임을 보냄

그리고 그 보낸 프레임도 이상이없으면 애크를 다시 보냄

이때 프레임을 보내고 애크가 올때 까지 스탑하고 웨이트한다고(웨이트 트레이닝? 내가 제일 좋아하는건디 ㅋ) 해서 이런 방식의 프로토콜을 스탑엔 웨이트 ARQ라고함(기본적인 에러컨트롤 프로토콜)

몇번 세그먼트에 에러가 있다는걸 정확하게 알 수 없기 때문에 이런식으로함.

프레임에 에러가 있다면 리시버가 애크를 보내지 않는 방식으로 에러가 있다는것을 알림.

프레임마다 고유의 식별자를 붙혀야함.(식별자 두개만 있으면됨)

리시버가 두개의 식별자를 통해 다 알수있음

애크가 안오면 프레임을 재전송하게됨. 

프레임에서 식별자 0 을 보내면 리시버가 받고 다음 포인터인 1로 받을거다라고 포인팅을 한 후에 애크를 주면 (애크를 1로 보내면 0은 잘받았고 다음번엔 1로 받을걸 기대한다는 것)  애크를 받은 후에 포인터를 1로 바꿈 만약 프레임이 1로 보낼때 1이 오류가 나면 리시버는 해독을 중지 그럼 타이머가 동작하여 일정시간되면 프레임 재전송함 다시 1로 보냄 근데 이번엔 오류가 없으면 다시 애크를 0 으로 보내고 프레임은 포인터를 0으로바꾸고 0으로 프레임을 보내는 식으로 동작함.

근데 여기서 애크가 로스트가 된다면 다시 프레임에서는 원래 보냈던 0을 다시 보내겠지? 그럼 애크가 로스트가 났구나라고 유추할수있음 그래서 또받은 프레임은 DISCARD하고 다시 애크를 보냄 이것이 동작원리!

근데 여기서 보면 저 구간을 하나의 시간이라고 보면 프레임을 보낸 시간은 굉장히 작음 거의 놀고있다는 뜻임 효율이 안좋앙 효율을 좋게하기 위해선 프레임 렝스를 길게하는것도 하나의 방법임 근데 이 프레임 렝스가 너무 길면 무슨 문제가 있냐면 뭔 문제가 있데....

 

센더는 포인터 두개로 작동 프레임 하나가 준비되면 센드 넥스트포인터는 다음 포인터로 이동 센더는 바로 프레임 보냄 이때 프레임 번호는 버퍼의 번호 0을 찍어서보냄 

리시버도 하나의 포인터 가짐 센더가 데이터를 보내면 여기다 저장할거임 이라고 굳게 결심함. 프레임 0의 리시브가 완료되어서 리시버0에 저장이되고 애크를 보냄과 동시에 리시버N을 옆으로 이동 

애크의 수신이 완료된 시점에서는 센더에서 0번에 저장된 데이터가 지워지고 퍼스트 포인터가 오른쪽으로 옮겨짐 

 이 사진에서 회색으로 칠해진 저 칸을 뜻하는 두 선은 윈도우라고하는데 한번에 보낼수있는 프레임의 갯수를 알려줌

갑자기 보낼 데이터가 많아지면 애크를 기다리지 않고 1~7번까지 프레임으로 다보냄 이것이 GO BACK N 프로토콜임

애크가 오는 순서대로 윈도우가 오른쪽으로 슬라이딩됨.

사진에 있는 상황은 3개의 프레임을 보낸상황이고 애크2가 누락된 상황인데 여기서 애크3이 애크2와3을 합친역할을 해줘서 커버 쳐줌 즉 애크3을 받음으로써 프레임 12가 잘받은걸 확인할수있음

 

한번에 보낼수있는 프레임의 수는 2의M승-1개임

최악의 경우는 프레임은 다 잘갔는데 애크가 죄다 망가진 경우! 그런 경우에 우리가 다 프레임을 한번에 보내면 에러남

 

왜 GO BACK N ARQ인 이유?

만약 프레임 1부터7까지 쭉보냈는데 프레임 1에 에러가 나면 그럼 이 리시버는 아무짓도 안하게 설계가됨.

근데 프레임 2가 와도 아무짓도안함 리시버는 프레임1이올때까지 계속 기다림 그래서 1~7다 보내도 애크 하나도 못받고 타임아웃발생하면 프레임 1부터 죄다 다시 보내야함 그래서 GOBACKN임 1번으로 다시 돌아가 이느낌임!

 

TCP에러 컨트롤은 고백N에 기반을 두지만 좀 다름 

비슷한점은

네거티브애크가 없음

만약 1프레임에 대해 애크가없어도 계속 쭉쭉보냄

타임아웃을 통해 잃은걸 찾음

 

다른점은

1번이 올때까지 기다렸다가 순차적으로 보냄

버퍼를 세밀하게 운영 하면서 2번프레임이 들어왔는데 걔의 시작 바이트 넘버가있으면 1번 프레임의 바이트길이는 이정도였겠구나 추론하여서 그만큼 띄워놓고 2번프레임을 그자리에 써놓음(바이트 오리엔티드 넘버링을한다)

TCP는 아이디가 많음 가용한 버퍼스페이스가 제한되지않음(가변적인 버퍼스페이스 사용)

 

애크를 보내는건 두가지 의미가있음

1.니가 보낸 세그먼트를 잘받았다

2. 그걸 내가 잘 처리 완료했다

 

잘받았는데 애크를 안주는경우는 아직 상위레이어로 올리지않아서

 

TCP round trip time, timeout

타임아웃시간을 정하는 핵심 원리는? RTT란 무엇이며 이걸 통하여 시간을 정함

프레임을 보내면 애크를 보내오잖아? 그 애크를 받을때까지의 텀을 RTT(라운드 트립 타임)이라고함

근데 이 RTT는 그때마다 다름 그래서 이걸 어떻게 보정해주지? RTT의 마지막값을 타임아웃으로 정할까?

아니다 여러개를 샘플링해서 최근 RTT를 샘플링해서 평균구함 다만 산술 평균이 아니라 웨이티드 에버리지 구함

최근값에 좀 더 비중을 둠. 최근값이 좀 더 좋잖여~ 거기에 여유분을 더하는데 추정된 RTT에 여유분을 더하는데

타임아웃시간은 추정된 ERTT(추정된 RTT)+여유분

그래서 RTT보다 제법 크게 타임아웃이 결정이됨 하지만 핵심은 RTT에 기반을 둠

 

TCP의 또다른 특징은 

여기서 301을 제대로 받지못하면 DUPLICATE 애크를 보냄 이 듀플이케이트 애크가 NAK(네거티브 애크)같은거임

301못받았다고 야무지게 3번정도 보냄 기대하지않은 넘버들어올때마다 301을 원하니까301을 계속 달라고 보냄

한 3번정도 보내면301 보내줌 이렇게 3개의 듀플리케이티드 애크를 통해 빠르게 재전송을 하는것을 Fast retransmission이라고 함.

두개의 프레임마다 하나의 애크를보냄 이걸 딜레이드 애크라고함

 

윈도우(아까 에러처리할때 배웠징?)의 크기를 조절하는게 tcp에서 해주는중요한일

윈도우로 전송속도제어가능 

윈도우의 크기는 한번에 보낼수있는 세그먼트의 수를 의미 

이때 c는 가상의 파이프가 최대로 보낼수있는 양을 뜻한(최대전송량)

이 c는 정해져있는값 RTT도 정해져있는값 X를 크게하면 전송속도가 빨라짐 작게하면 느려짐

X가 너무 작으면 효율떨어짐 근데 너무 크면 에러가 발생하면 재전송하게되고 여유가 없어서 문제생김 그래서 이 X를 적당한 크기로 정해주는걸 윈도우 컨트롤 이라함 그걸로 우리는 트랜스미션레이트를 컨트롤 할수있음.

센더에서 리시버까지 가상의 파이프를 얼마나 채울것인가!! 적당하게 채우는게 핵심

TCP는 컨트롤을 3개를 하는데 FLOW컨트롤 Congestion 컨트롤 에러컨트롤 근데 여기서 

플로우 컨트롤과 콘제스쳐컨트롤을 한방에 정리할거임!

 

플로우컨트롤:

리시버가 오버로드(처리용량을 넘어서 일을 너무 많이주는것)(쉽게 얘기하면 오래된 스마트폰에 데이터를 많이 넣어주면 버벅거리는것)하는걸 방지하는것 but, 어떻게? 방지하는 주체는 리시버임 리시버가 주체적으로 컨트롤함 센더한테 리시브윈도우(rwnd)(리시버에 가용한 버퍼의 크기)를 알려주는 방법으로 컨트롤함

 

컨제스쳐컨트롤:

네트워크(센더와 리시버 사이의 세그먼트가 지나가는 길 사이에있는 중계장비나 링크를 다 합친 엔티티)가 오버로드하는걸 방지함. 오버로드되는 이유는 외부에서 인풋으로 너무많이 몰리면 오버로드됨. 어떻게 이걸 방지할까?

네트워크의 오버로드 여부를 센더가 결정을함 네트워크가 오버로드 되있다 라고 결론 내리면 콘제스쳐윈도우(cwnd)라고하는 윈도우값을 줄이고 문제없는거라고 결론을 내리면 윈도우값 늘림 윈도우를 늘이고 줄임에따라 데이터보냄 윈도우값크면 많이보내고 적으면 적게보내고 

리시브 윈도우와 컨제스쳐윈도우는 서로 독립적으로 운용을 함.

리시브 윈도우는 리시버 상태에따라 커졌다 작아졌다하고 컨제스쳐윈도우는 네트워크 상태에따라 커졌다 작아졌다 하니까 당연한 말임! 

그런데 TCP가 실제로 사용하는 윈도우는 딱 하나임

min(cwnd,rwnd)값으로 결정이됨 그래서 저 윈도우 사이즈를 w라고하면 w에 맞춰서 세그먼트 한번에 보냄 네트워크는 널널한데 리시버가 버벅대면 w줄여서 안좋은상황에맞춰서 보냄 이것이 TCP윈도우 컨트롤의 핵심임.

 

'Computer_logic' 카테고리의 다른 글

Mealy & Moore VHDL code  (0) 2023.04.05
Mealy FSM & Moore FSM  (0) 2023.04.05
TCP Congestion control  (0) 2022.11.09
FLOW control  (0) 2022.11.09
propagation delay & transmission delay  (0) 2022.11.08

트랜스 미션 딜레이:

쉽게 얘기해서 계수구를 예를 들자면 계수구에서 물이 빠져나갈때 계수구의 넓이와 물의 양이 이 트랜스미션 딜레이를 좌우함. 계수구에서 물이 다 빠져 나가는 시간.

 

프로파게이션 딜레이:

쉽게 얘기해서 계수구를 빠져나간 물이 서울에서 대전까지 갈때 도달한 시간을 의미함

위 이미지에서 트랜스 미션 딜레이는 t2 - t1임 

또한 전체를 보내는 시간은 t4 - t1 ( 프로파게이션 딜레이 + 트랜스 미션 딜레이)

정리,

트랜스미션 딜레이는 프레임의 크기와 링크의 속도에 의해 좌우되고, 프로파게이션 딜레이는 거리와 일반적인 구리선로에서의 속도에 의해 좌우됨

 

 

 

 

'Computer_logic' 카테고리의 다른 글

Mealy & Moore VHDL code  (0) 2023.04.05
Mealy FSM & Moore FSM  (0) 2023.04.05
TCP Congestion control  (0) 2022.11.09
FLOW control  (0) 2022.11.09
TCP에러컨트롤  (0) 2022.11.09

+ Recent posts