--===========================================================================-- -- Design units : HDLC decoder (Entity and architecture) -- -- File name : hdlcdec.vhd -- -- Purpose : HDLC decode (bitstuffing and flag detection) -- write data to ram, add frame length -- -- Note : -- -- Limitations : -- -- Errors : -- -- Library : -- -- Dependencies : -- -- Author : Juergen Hasch, hasch@t-online.de -- Meisenstr. 23 -- 73066 Uhingen -- Germany -- -- Synthesis : Xilinx Foundation 1.4 ------------------------------------------------------------------------------- -- Revision list -- Version Author Date Changes -- 1.0 JH 28 Dec 97 File created -- 1.1 JH 19 Apr 98 included rx controller -- 1.2 JH 24 May 98 simplified hdlc decoding -- 1.3 JH 31 Jul 98 partial redesign ------------------------------------------------------------------------------- Library ieee; Use ieee.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; entity hdlcdec is port( mclk: in std_logic; -- master clock (64*bit clock) frameavl: out std_logic; -- frame available wrreq: buffer std_logic; -- ram write request wrok: in std_logic; -- write finished dataout: out std_logic_vector(7 downto 0); -- data output rxaddr: buffer std_logic_vector(11 downto 0); -- ram address eppaddr: in std_logic_vector(11 downto 0); -- epp read address dcd: in std_logic; -- dcd signal from dpll data_in: in std_logic; -- data input clock: in std_logic; -- bit clock dcd_clr: buffer std_logic); -- clear dcd for 8 received ones end hdlcdec; architecture behaviour of HDLCDEC is signal crc: std_logic; -- 1 for rx crc ok signal flag_received: std_logic; -- hdlc flag received signal abort_received: std_logic; -- hdlc abort received signal raw_shift: std_logic_vector(7 downto 0); -- shift register for raw data signal X: std_logic_vector(15 downto 0); -- crc shift register signal address: std_logic_vector(11 downto 0); -- msb frame start pointer signal rx_counter: std_logic_vector(8 downto 0); -- received bytes in frame, truncates more than 512 byte signal bit_counter: std_logic_vector(2 downto 0); -- count until one rx byte complete signal disable_transfer: std_logic; signal crc_shift : std_logic_vector( 7 downto 0); signal tmp: std_logic; begin frameavl <= '1' when ( (address+1) = eppaddr) else '0'; -- frame available flag -- -- shift in serial rx data -- process(dcd,clock,data_in,flag_received,bit_counter) begin if (clock'event and clock='1') then dataout <= raw_shift; raw_shift(7) <= data_in; raw_shift(6) <= raw_shift(7); raw_shift(5) <= raw_shift(6); raw_shift(4) <= raw_shift(5); raw_shift(3) <= raw_shift(4); raw_shift(2) <= raw_shift(3); raw_shift(1) <= raw_shift(2); raw_shift(0) <= raw_shift(1); end if; end process; -- -- check for HDLC flag ( 6 ones, 2 zeroes) -- process(raw_shift,mclk) begin if(mclk='1' and mclk'event) then if ( raw_shift = "01111110") then flag_received <= '1'; else flag_received <= '0'; end if; end if; end process; -- -- check for ABORT flag (7 ones, 1 zero) -- process(raw_shift,mclk) begin if(mclk='1' and mclk'event) then if ( raw_shift = "11111110") then abort_received <= '1'; else abort_received <= '0'; end if; end if; end process; -- -- check for 8 trailing ones (illegal state, clear DCD) -- process(raw_shift,mclk) begin if(mclk='1' and mclk'event) then if ( raw_shift = "11111111" and dcd_clr <='0') then dcd_clr <= '1'; else dcd_clr <= '0'; end if; end if; end process; -- -- compute CRC -- process(clock,data_in,raw_shift,flag_received) begin if (flag_received = '1') then X <= (others => '1'); elsif (clock'event and clock='1') then if (not(raw_shift(7 downto 3)="11111") ) then -- remove bitstuffing for 5 trailing ones tmp <= data_in; --raw_shift(3); X(0) <= tmp xor X(15); X(1) <= X(0); X(2) <= X(1); X(3) <= X(2); X(4) <= X(3); X(5) <= X(4) xor tmp xor X(15); X(6) <= X(5); X(7) <= X(6); X(8) <= X(7); X(9) <= X(8); X(10) <= X(9); X(11) <= X(10); X(12) <= X(11) xor tmp xor X(15); X(13) <= X(12); X(14) <= X(13); X(15) <= X(14); end if; end if; end process; -- -- compare crc register to crc value of a correct received frame -- process(X,clock,dcd,mclk,wrok) begin if ( dcd='0') then crc <= '0'; elsif (clock'event and clock='1' ) then if X = "0001110100001111" then crc_shift(0) <= '1'; else crc_shift(0) <= '0'; end if; crc <= crc_shift(5); crc_shift(7) <= crc_shift(6); crc_shift(6) <= crc_shift(5); crc_shift(5) <= crc_shift(4); crc_shift(4) <= crc_shift(3); crc_shift(3) <= crc_shift(2); crc_shift(2) <= crc_shift(1); crc_shift(1) <= crc_shift(0); end if; end process; -- -- received bits counter (count from 0..7) -- process(clock,flag_received) begin -- if (flag_received = '1') then -- bit_counter <= (others => '0'); if (clock'event and clock='1') then if (flag_received = '1') then bit_counter <= (others => '0'); else bit_counter <= bit_counter+1; end if; end if; end process; -- -- initiate transfer to ram -- process(bit_counter,disable_transfer,clock) begin if (disable_transfer='1') then wrreq <= '0'; elsif (clock'event and clock='0' ) then if (bit_counter = 0 ) then wrreq <='1'; else wrreq <='0'; end if; end if; end process; -- -- stop transfer to ram -- process(wrok,mclk,dcd) begin if (dcd='0') then disable_transfer <='1'; -- no data transfer when no rx signal elsif (mclk'event and mclk='1' ) then disable_transfer <= wrok; -- stop transfer as soon as ram controller acknowledges end if; end process; -- -- increase frame byte counter -- process(clock,rx_counter,flag_received,bit_counter) begin -- if (flag_received='1') then -- rx_counter <= (others => '0'); if (clock'event and clock='1' ) then if (flag_received = '1') then rx_counter <= (others => '0'); elsif (bit_counter=0) then rx_counter <= rx_counter+1; end if; end if; end process; -- -- set rx address -- process(mclk,address,rx_counter) begin if (mclk'event and mclk='1' ) then -- rxaddr <= (address(11 downto 9) & ( address(8 downto 0) + rx_counter)); rxaddr <= address + rx_counter; end if; end process; -- -- calculate new address after frame received -- process(clock,crc,flag_received) begin if (clock'event and clock='1' ) then if (flag_received ='1' and crc = '1') then address <= rxaddr; end if; end if; end process; end behaviour; --========================= End of hdlc_dec ================================--