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;
댓글
댓글 쓰기