---------------------------------------------------------------------------- -- UART Transmitter 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 trans is port( TRC: in std_logic; MR: in std_logic; TBRL: in std_logic; SFD: in std_logic; CRL: in std_logic; CTRLWORD: in std_logic_vector(4 downto 0); TBR: in std_logic_vector(7 downto 0); TRE: out std_logic; TBRE: out std_logic; TRO: out std_logic ); end trans; ------------------------------------------------------------------------ architecture behv of trans is constant C0: unsigned(4 downto 0):="00001"; constant CI: unsigned(4 downto 0):="01000"; constant CM: unsigned(4 downto 0):="10000"; constant MM: unsigned(3 downto 0):="1111"; signal trans_reg: std_logic_vector(11 downto 0); signal trans_reg_temp: std_logic_vector(11 downto 0); signal TBR_sig: std_logic_vector(7 downto 0); signal old_tbr_sig: std_logic_vector(7 downto 0); signal delay: std_logic_vector(0 downto 0); signal go: std_logic; signal t_pari: std_logic; signal clk: std_logic; signal i: unsigned(3 downto 0); signal ctrl_word: std_logic_vector(4 downto 0); begin --P0: process(MR,TRC,i,TBR) -- generate 16* clock --begin -- if MR='1' then -- i<="00000"; -- elsif TRC='1' and TRC'event then -- i<=i+C0; -- if i=CI then -- clk<='1'; -- elsif i=CM then -- i<="00000"; -- clk<='0'; -- end if; -- end if; --end process; P1: process(CRL,CTRLWORD) -- load control word here begin if CRL='1' then ctrl_word<=CTRLWORD; end if; end process; -- this process make out the transmit register according to control word. P2: process(clk,ctrl_word,MR,TBR,TBRL,TBR_sig,t_pari) begin if (MR='1') then TBR_sig<="11111111"; t_pari <= '0'; trans_reg_temp <= "1111" & TBR_sig; else if TBRL='0' then TBR_sig <= TBR; t_pari <= parity(TBR); -- call function and compute the parity end if; case ctrl_word is when "00000"|"00001" => if t_pari='0' then -- odd parity trans_reg_temp <= "111" & "11" & '1' & TBR_sig(4 downto 0) & '0'; elsif t_pari='1' then -- even parity trans_reg_temp <= "111" & "11" & '0' & TBR_sig(4 downto 0) & '0'; end if; when "00010"|"00011" => if t_pari='0' then -- odd parity trans_reg_temp <= "111" & "11" & '0' & TBR_sig(4 downto 0) & '0'; elsif t_pari='1' then -- even parity trans_reg_temp <= "111" & "11" & '1' & TBR_sig(4 downto 0) & '0'; end if; when "00100"|"00110"|"00101"|"00111" => -- no parity trans_reg_temp <= "1111" & "11" & TBR_sig(4 downto 0) & '0'; when "01000"|"01001" => if t_pari='0' then -- odd parity trans_reg_temp <= "11" & "11" & '1' & TBR_sig(5 downto 0) & '0'; elsif t_pari='1' then -- even parity trans_reg_temp <= "11" & "11" & '0' & TBR_sig(5 downto 0) & '0'; end if; when "01010"|"01011" => if t_pari='0' then -- odd parity trans_reg_temp <= "11" & "11" & '0' & TBR_sig(5 downto 0) & '0'; elsif t_pari='1' then -- even parity trans_reg_temp <= "11" & "11" & '1' & TBR_sig(5 downto 0) & '0'; end if; when "01100"|"01110"|"01101"|"01111" => -- no parity trans_reg_temp <= "111" & "11" & TBR_sig(5 downto 0) & '0'; when "10000"|"10001" => if t_pari='0' then -- odd parity trans_reg_temp <= '1' & "11" & '1' & TBR_sig(6 downto 0) & '0'; elsif t_pari='1' then -- even parity trans_reg_temp <= '1' & "11" & '0' & TBR_sig(6 downto 0) & '0'; end if; when "10010"|"10011" => if t_pari='0' then -- odd parity trans_reg_temp <= '1' & "11" & '0' & TBR_sig(6 downto 0) & '0'; elsif t_pari='1' then -- even parity trans_reg_temp <= '1' & "11" & '1' & TBR_sig(6 downto 0) & '0'; end if; when "10100"|"10110"|"10101"|"10111" => -- no parity trans_reg_temp <= "11" & "11" & TBR_sig(6 downto 0) & '0'; when "11000"|"11001" => if t_pari='0' then -- odd parity trans_reg_temp <= "11" & '1' & TBR_sig(7 downto 0) & '0'; elsif t_pari='1' then -- even parity trans_reg_temp <= "11" & '0' & TBR_sig(7 downto 0) & '0'; end if; when "11010"|"11011" => if t_pari='0' then -- odd parity trans_reg_temp <= "11" & '0' & TBR_sig(7 downto 0) & '0'; elsif t_pari='1' then -- even parity trans_reg_temp <= "11" & '1' & TBR_sig(7 downto 0) & '0'; end if; when others => -- no parity trans_reg_temp <= '1' & "11" & TBR_sig(7 downto 0) & '0'; end case; end if; end process; -- P3 describes the whole transmission procedure P3: process variable cnt: integer range 0 to 12; variable cnt_limit: integer range 0 to 12; begin wait until TRC'event and TRC='1'; if MR='1' then old_tbr_sig <= "11111111"; delay<="0"; go<='0'; i <= "0000"; else if (i=MM) then i<="0000"; if(go='0') then delay<="0"; cnt := 12; TRE <= '1'; if (old_tbr_sig=TBR_sig) then go <= '0'; elsif (old_tbr_sig/=TBR_sig) then go <='1'; end if; trans_reg <= "111111111111"; elsif (go='1' and delay="0") then go<='1'; cnt:=0; delay<=delay+1; TRE <= '1'; trans_reg <= "111111111111"; elsif (go='1' and delay="1" and cnt=0) then go <= '1'; cnt:=cnt+1; delay<=delay+0; old_tbr_sig<=TBR_sig; TRE<='0'; trans_reg <= trans_reg_temp; elsif (go='1' and delay="1" and cnt/=0) then trans_reg <= '1' & trans_reg(11 downto 1); case ctrl_word(4 downto 2) is when "000" => if ctrl_word(0)='0' then cnt_limit := 8; elsif ctrl_word(0)='1' then cnt_limit :=9; end if; when "001" => if ctrl_word(0)='0' then cnt_limit := 7; elsif ctrl_word(0)='1' then cnt_limit :=8; end if; when "010" => if ctrl_word(0)='0' then cnt_limit := 9; elsif ctrl_word(0)='1' then cnt_limit :=10; end if; when "011" => if ctrl_word(0)='0' then cnt_limit := 8; elsif ctrl_word(0)='1' then cnt_limit :=9; end if; when "100" => if ctrl_word(0)='0' then cnt_limit := 10; elsif ctrl_word(0)='1' then cnt_limit :=11; end if; when "101" => if ctrl_word(0)='0' then cnt_limit := 9; elsif ctrl_word(0)='1' then cnt_limit :=10; end if; when "110" => if ctrl_word(0)='0' then cnt_limit :=11; elsif ctrl_word(0)='1' then cnt_limit :=12; end if; when "111" => if ctrl_word(0)='0' then cnt_limit :=10; elsif ctrl_word(0)='1' then cnt_limit :=11; end if; when others => end case; if cnt/=cnt_limit then go <= '1'; delay<=delay+0; cnt:=cnt+1; TRE<='0'; elsif cnt=cnt_limit then go <= '0'; delay<="0"; TRE<='1'; end if; end if; if SFD='1' then TBRE <= 'Z'; elsif SFD='0' then if (cnt=0 or cnt=1) then TBRE <= '0'; else TBRE <= '1'; end if; end if; else i<=i+1; end if; end if; end process; -- this cocurrent statement handles the serial output of Transmitter tro <= trans_reg(0); end behv;