FPGA 실습(5)


5. Manchester Code

 맨체스터 코드는 앞절에서 설명한 SDLC의 NRZ 모드에서 별도의 클럭을 사용하지 않고 데이터에서 클럭을 추출하기 위해 사용하며, 멘체스터 코드의 코딩 방식은 다음 그림과 같다.


5.1. 송신부(Encoder)

송신부는 앞의 그림에서 살펴본 바와 같이 CLK과 NRZ를 XOR을 취해서 출력하면 된다.

그런데 CLK과 NRZ를 XOR을 취하면 서로의 위상차로 인해 glitch가 발생할 수 있으므로 전송 속도보다 아주 빠른 클럭으로 래치해서 출력하는 것이 좋다.


5.2. 수신부(Decoder)

수신부는 입력되는 맨체스터 코드로부터 데이터와 클럭을 추출하여 출력하여야 한다. 먼저 전송속도보다 아주 빠른 클럭을 이용하여 전송속도에 맞는 클럭을 생성하기 위한 카운터를 구동하여 기본적인 클럭을 생성한다. 예를 들어 전송 속도가 1Mbps인데 회로에서 사용하는 클럭이 128MHz 클럭이라고 한다면 카운터 값이 63이 된뒤 다시 0으로 돌아가도록 구성하여 카운 터값이 0일 때 반전이 일어나도록 하여 1MHz의 클럭을 생성한다. 그리고 입력되는 데이터를 전송속도 보다 아주 빠른 클럭(예: 128MHz)으로 래치를 해서 rising edge와 falling edge를 검출하고 rinsing edge나 falling edge에서 앞에서 언급한 카운터를 0으로 셋팅하여 주기를 맞춘다. 그리고 클럭 주기의 1/2되는 지점에서 sample 클럭을 생성하여 sample 클럭에서 입력되는 데이터를 래치하여 이전데이터와 비교한다. sample 데이터가 b’01이면 1로 디코딩하고 데이터가 b’10이면 0으로 디코딩하며 출력 클럭을 반전시킨다. 만일 데이터가 b’00이거나 b’11이면 디코딩하지 않으며 출력 클럭을 그대로 유지 한다. 이렇게 하면 입력되는 데이터로부터 데이터와 클럭을 추출하여 NRZ 데이터를 출력할 수 있다. 다음 그림은 Loopback되는 맨체스터코드로부터 NRZ 데이터와 출력 클럭을 시험 한 결과이다.


다음은 맨체스터 코드의 VHDL 모델이다.

- Encoder

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_arith.ALL;

use IEEE.STD_LOGIC_unsigned.ALL;


entity me1 is

Port ( 

rstb : in std_logic;

      din : in std_logic;

c128m : in std_logic;

tclk : in std_logic;

clko : out std_logic;

dout : out std_logic

);

end me1;

architecture Behavioral of me1 is

signal dind : std_logic;

signal doutd : std_logic;

constant delay : time := 1 ns;


begin

clko <= tclk;

process(rstb, tclk)

begin

if(rstb <= '0') then

dind <= '0' after delay;

elsif tclk'event and tclk = '1' then

dind <= din after delay;

end if;

end process;

process(c128m)

begin

if(rising_edge(c128m)) then

if(rstb = '0') then

doutd <= '0' after delay;

else

doutd <= dind xor tclk after delay;

end if;

end if;

end process;

dout <= doutd;

end Behavioral;


- Decoder

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_arith.ALL;

use IEEE.STD_LOGIC_unsigned.ALL;


entity md1 is

Port (

rstb : in std_logic;

c128m : in std_logic;

    din : in std_logic;

clko : out std_logic;

dout : out std_logic;

sclko : out std_logic;

dino : out std_logic_vector(1 downto 0)

  );

end md1;

architecture Behavioral of md1 is

    signal dind : std_logic_vector(1 downto 0);

    signal dindd : std_logic_vector(1 downto 0);

signal clkod : std_logic_vector(3 downto 0);

signal posi : std_logic;

signal nega : std_logic;

signal dcnt : std_logic_vector(7 downto 0);

signal drefd : std_logic_vector(7 downto 0);

signal doutd : std_logic;

signal clkodo : std_logic;

constant delay : time := 1 ns;

constant refbaud : std_logic_vector(7 downto 0) := x"3f";

begin

process(c128m)

begin

if(rising_edge(c128m)) then

if(rstb = '0') then

dind <= (others => '0') after delay;

clkod <= "0000" after delay;

dcnt <= (others => '0') after delay;

posi <= '0' after delay;

nega <= '0' after delay;

doutd <= '0' after delay;

dindd <= "00" after delay;

clkodo <= '0' after delay;

drefd <= refbaud after delay;

else

dind <= dind(0) & din after delay;

posi <= dind(0) and not dind(1) after delay;

nega <= not dind(0) and dind(1) after delay;

if((posi or nega) = '1') then

dcnt <= (others => '0') after delay;

else

if(dcnt = drefd) then

dcnt <= (others => '0') after delay;

else

dcnt <= dcnt + 1 after delay;

end if;

end if;

if(dcnt = '0'&drefd(7 downto 1)) then

clkod(0) <= '1' after delay;

else

clkod(0) <= '0' after delay;

end if;

clkod(3 downto 1) <= clkod(2 downto 0) after delay;

if(clkod(0) = '1') then

dindd <= dindd(0) & din after delay;

else

dindd <= dindd after delay;

end if;

if(clkod(1) = '1') then

if((dindd = "00") or (dindd = "11")) then

clkodo <= '0' after delay;

else

clkodo <= not clkodo after delay;

end if;

end if;

if(clkod(3) = '1' and clkodo = '1') then

if(dindd = "01") then

doutd <= '1' after delay;

elsif(dindd = "10") then

doutd <= '0' after delay;

else

doutd <= doutd after delay;

end if;

else

doutd <= doutd after delay;

end if;

end if;

end if;

end process;

clko <= not clkodo;

dout <= doutd;

sclko <= clkod(3) and clkodo;

dino <= dindd;

end Behavioral;


- Top Module

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_arith.ALL;

use IEEE.STD_LOGIC_unsigned.ALL;


entity man is

Port (

    rstb : in std_logic;

c128m : in std_logic;

tclki : in std_logic;

tdin : in std_logic;

tdout : out std_logic;

tclk : out std_logic;

rdin : in std_logic;

rdout : out std_logic;

rclk : out std_logic;

loopback   : in std_logic;

sclko : out std_logic;

dino : out std_logic_vector(1 downto 0)

);

end man;

architecture Behavioral of man is

component me1 is

port(

rstb : in std_logic;

din : in std_logic;

c128m : in std_logic;

tclk : in std_logic;

rdin : in std_logic;

rdout : out std_logic;

rclk : out std_logic;

loopback   : in std_logic;

sclko : out std_logic;

dino : out std_logic_vector(1 downto 0)

);

end man;


architecture Behavioral of man is

component me1 is

port(

rstb : in std_logic;

din : in std_logic;

c128m : in std_logic;

tclk : in std_logic;

clko : out std_logic;

dout : out std_logic

); end component;

component md1 is

port(

rstb : in std_logic;

c128m : in std_logic;

din : in std_logic;

clko : out std_logic;

dout : out std_logic;

sclko : out std_logic;

dino : out std_logic_vector(1 downto 0)

); end component;

signal txd : std_logic;

signal rxd : std_logic;

begin

enc : me1

port map(

rstb => rstb,

din => tdin,

c128m => c128m,

tclk => tclki,

clko => tclk,

dout => txd

);

dec : md1

port map(

rstb => rstb,

c128m => c128m,

din => rxd,

clko => rclk,

dout => rdout,

sclko => sclko,

dino => dino

);

    tdout <= txd;

    rxd <= txd when(loopback = '1') else rdin;

end Behavioral;


댓글

이 블로그의 인기 게시물