----------------------------------------------------------------------------- -- UART Receiver Model (behavior modeling) -- -- by Weijun Zhang, 05/2001 ----------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; package my_package is FUNCTION parity(inputs: std_logic_vector(7 downto 0)) RETURN std_logic; end my_package; PACKAGE body my_package is FUNCTION parity(inputs: std_logic_vector(7 downto 0)) RETURN std_logic is variable temp: std_logic; begin temp:='0'; for i in 7 downto 0 loop temp:=temp xor inputs(i); end loop; return temp; end parity; end my_package; ----------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; use work.my_package.all; entity recei is port( RRC: in std_logic; MR: in std_logic; RRI: in std_logic; SFD: in std_logic; RRD: in std_logic; DRR: in std_logic; CRL: in std_logic; CTRLWORD: in std_logic_vector(4 downto 0); OE: out std_logic; PE: out std_logic; FE: out std_logic; DR: out std_logic; RBR: out std_logic_vector(7 downto 0) ); end recei; architecture behv of recei is constant reg_init: std_logic_vector(11 downto 0):="111111111111"; signal ctrl_word: std_logic_vector(4 downto 0); signal recei_reg: std_logic_vector(11 downto 0); signal rri_temp: std_logic; signal dr_sig,pe_sig,oe_sig,fe_sig: std_logic; signal rx_empty: boolean; signal rbr_temp: std_logic_vector(7 downto 0); begin P1: process(CRL,CTRLWORD) begin if CRL='1' then ctrl_word <= CTRLWORD; end if; end process; rri_temp <= RRI; P2: process variable cnt16: integer range 0 to 15; begin wait until RRC'event and RRC='1'; if MR='1' then -- initialize and wait to receive data... cnt16 := 0 ; -- Original state... rx_empty <= true; oe_sig<='0'; recei_reg <= reg_init; elsif (rx_empty and rri_temp='0') then cnt16 := 0; -- start reading the bit come in... rx_empty <= false; if dr_sig/='0' then oe_sig<='1'; elsif dr_sig='0' then oe_sig<='0'; end if; recei_reg <= reg_init; elsif (cnt16=7 and (not rx_empty))then recei_reg <= rri_temp & recei_reg(11 downto 1); cnt16 := cnt16 +1; elsif cnt16 = 15 then -- finish reading 1-bit of receipt cnt16 := 0; -- ready to read next.. else cnt16 := cnt16 + 1; end if; case ctrl_word(4 downto 1) is when "0001" => if (not rx_empty) and recei_reg(5)='0' then rx_empty <= true; if DRR='1' then dr_sig <= '1'; elsif DRR='0' then dr_sig <='0'; end if; elsif recei_reg(5)/='0' then dr_sig <= '0'; elsif (rx_empty) then if DRR='0' then dr_sig <= '0'; end if; end if; when "0000"|"0011" => if (not rx_empty) and recei_reg(4)='0' then rx_empty <= true; if DRR='1' then dr_sig <= '1'; elsif DRR='0' then dr_sig <='0'; end if; elsif recei_reg(4)/='0' then dr_sig <= '0'; elsif (rx_empty) then if DRR='0' then dr_sig <= '0'; end if; end if; when "0010" => if (not rx_empty) and recei_reg(3)='0' then rx_empty <= true; if DRR='1' then dr_sig <= '1'; elsif DRR='0' then dr_sig <='0'; end if; elsif recei_reg(3)/='0' then dr_sig <= '0'; elsif (rx_empty) then if DRR='0' then dr_sig <= '0'; end if; end if; when "0101" => if (not rx_empty) and recei_reg(4)='0' then rx_empty <= true; if DRR='1' then dr_sig <= '1'; elsif DRR='0' then dr_sig <='0'; end if; elsif recei_reg(4)/='0' then dr_sig <= '0'; elsif (rx_empty) then if DRR='0' then dr_sig <= '0'; end if; end if; when "0100"|"0111" => if (not rx_empty) and recei_reg(3)='0' then rx_empty <= true; if DRR='1' then dr_sig <= '1'; elsif DRR='0' then dr_sig <='0'; end if; elsif recei_reg(3)/='0' then dr_sig <= '0'; elsif (rx_empty) then if DRR='0' then dr_sig <= '0'; end if; end if; when "0110" => if (not rx_empty) and recei_reg(2)='0' then rx_empty <= true; if DRR='1' then dr_sig <= '1'; elsif DRR='0' then dr_sig <='0'; end if; elsif recei_reg(2)/='0' then dr_sig <= '0'; elsif (rx_empty) then if DRR='0' then dr_sig <= '0'; end if; end if; when "1001" => if (not rx_empty) and recei_reg(3)='0' then rx_empty <= true; if DRR='1' then dr_sig <= '1'; elsif DRR='0' then dr_sig <='0'; end if; elsif recei_reg(3)/='0' then dr_sig <= '0'; elsif (rx_empty) then if DRR='0' then dr_sig <= '0'; end if; end if; when "1000"|"1011" => if (not rx_empty) and recei_reg(2)='0' then rx_empty <= true; if DRR='1' then dr_sig <= '1'; elsif DRR='0' then dr_sig <='0'; end if; elsif recei_reg(2)/='0' then dr_sig <= '0'; elsif (rx_empty) then if DRR='0' then dr_sig <= '0'; end if; end if; when "1010" => if (not rx_empty) and recei_reg(1)='0' then rx_empty <= true; if DRR='1' then dr_sig <= '1'; elsif DRR='0' then dr_sig <='0'; end if; elsif recei_reg(1)/='0' then dr_sig <= '0'; elsif (rx_empty) then if DRR='0' then dr_sig <= '0'; end if; end if; when "1101" => if (not rx_empty) and recei_reg(2)='0' then rx_empty <= true; if DRR='1' then dr_sig <= '1'; elsif DRR='0' then dr_sig <='0'; end if; elsif recei_reg(2)/='0' then dr_sig <= '0'; elsif (rx_empty) then if DRR='0' then dr_sig <= '0'; end if; end if; when "1100"|"1111" => if (not rx_empty) and recei_reg(1)='0' then rx_empty <= true; if DRR='1' then dr_sig <= '1'; elsif DRR='0' then dr_sig <='0'; end if; elsif recei_reg(1)/='0' then dr_sig <= '0'; elsif (rx_empty) then if DRR='0' then dr_sig <= '0'; end if; end if; when others => if (not rx_empty) and recei_reg(0)='0' then rx_empty <= true; if DRR='1' then dr_sig <= '1'; elsif DRR='0' then dr_sig <='0'; end if; elsif recei_reg(0)/='0' then dr_sig <= '0'; elsif (rx_empty) then if DRR='0' then dr_sig <= '0'; end if; end if; end case; end process; P3: process(RRC,recei_reg,ctrl_word) begin case ctrl_word(4 downto 1) is when "0001" => rbr_temp <= "000" & recei_reg(10 downto 6); when "0000"|"0011" => rbr_temp <= "000" & recei_reg(9 downto 5); when "0010" => rbr_temp <= "000" & recei_reg(8 downto 4); when "0101" => rbr_temp <= "00" & recei_reg(10 downto 5); when "0100"|"0111" => rbr_temp <= "00" & recei_reg(9 downto 4); when "0110" => rbr_temp <= "00" & recei_reg(8 downto 3); when "1001" => rbr_temp <= '0' & recei_reg(10 downto 4); when "1000"|"1011" => rbr_temp <= '0' & recei_reg(9 downto 3); when "1010" => rbr_temp <= '0' & recei_reg(8 downto 2); when "1101" => rbr_temp <= recei_reg(10 downto 3); when "1100"|"1111" => rbr_temp <= recei_reg(9 downto 2); when others => rbr_temp <= recei_reg(8 downto 1); end case; end process; P4: process(dr_sig,ctrl_word,rbr_temp,recei_reg) begin if dr_sig='1' then if ctrl_word(0)='1' then -- even parity case if ctrl_word(1)='0' then if ctrl_word(2)='1' then if (parity(rbr_temp) xor recei_reg(9))='0' then pe_sig <='0'; else pe_sig <= '1'; end if; elsif ctrl_word(2)='0' then if (parity(rbr_temp) xor recei_reg(10))='0' then pe_sig <='0'; else pe_sig <= '1'; end if; end if; elsif ctrl_word(1)='1' then pe_sig <= '0'; end if; elsif ctrl_word(0)='0' then -- odd parity case if ctrl_word(1)='0' then if ctrl_word(2)='1' then if (parity(rbr_temp) xor recei_reg(9))='1' then pe_sig <='0'; else pe_sig <= '1'; end if; elsif ctrl_word(2)='0' then if (parity(rbr_temp) xor recei_reg(10))='1' then pe_sig <='0'; else pe_sig <= '1'; end if; end if; elsif ctrl_word(1)='1' then pe_sig <= '0'; end if; end if; if ctrl_word(2)='0' then if recei_reg(11)/='1' then fe_sig<='1'; else fe_sig<='0'; end if; elsif ctrl_word(2)='1' then if recei_reg(11)/='1' or recei_reg(10)/='1' then fe_sig<='1'; else fe_sig<='0'; end if; end if; else pe_sig <= '0'; fe_sig <= '0'; end if; end process; P5: process(SFD,rbr_temp,RRD,dr_sig,pe_sig,fe_sig,oe_sig) begin if RRD='1' then RBR <= "ZZZZZZZZ"; elsif RRD='0' then RBR <= rbr_temp; end if; if SFD='1' then -- tri-buffer for other outputs DR <= 'Z'; PE <= 'Z'; OE <= 'Z'; FE <= 'Z'; elsif SFD='0' then DR <= dr_sig; PE <= pe_sig; OE <= oe_sig; FE <= fe_sig; end if; end process; end behv;