-------------------------------------------------------------------------- -------------------------------------------------------------------------- -- File Name : i8251.v -- Author(s) : Guruprasad and S. Datta -- Affiliation : Laboratory for Digital Design Environments -- Department of Electrical & Computer Engineering -- University of Cincinnati -- Date Created : June 1991 -- Introduction : Behavioral description of Intel's I8251 serial -- IO chip, written in a synthesizable subset of -- VHDL. -- Source : Original source is an ISPS description written -- by John A. Nestor, Illinois. Inst. of Tech. -- (Taken from the High-Level Benchmarks Repository) -- -- Modified For Synthesis by Jay(anta) Roy, University of Cincinnati. -- Date Modified : Sept, 91. -- -- Disclaimer : This comes with absolutely no guarantees of any -- kind (just stating the obvious ...) -- -- Acknowledgement : The Distributed Synthesis Systems research at -- the Laboratory for Digital Design Environments, -- University of Cincinnati, is sponsored in part -- by the Defense Advanced Research Projects Agency -- under order number 7056 monitored by the Federal -- Bureau of Investigation under contract number -- J-FBI-89-094. -- -------------------------------------------------------------------------- -------------------------------------------------------------------------- --use STD.TEXTIO.all; use work.functions.all; entity intel is port(reset,wrl,rdl,csl,cd,esd : in Bit; ctsl,rxd,rxdset,rxdrdy,rrdyclr1 : in Bit; tdata,temp : in Bit_Vector(7 downto 0)); end intel; architecture intel of intel is signal ehset : bit; signal ehclr : bit; signal ehclr1 : bit; signal sync1 : bit_vector(7 downto 0); signal sync2 : bit_vector(7 downto 0); signal data : bit_vector(7 downto 0); signal rstint : bit; signal mode : bit_vector(7 downto 0); signal control : bit_vector(7 downto 0); signal status : bit_vector(7 downto 0); alias status_6 : bit is status(6); alias status_5 : bit is status(5); alias status_4 : bit is status(4); alias status_3 : bit is status(3); alias status_2 : bit is status(2); signal xdata : bit_vector(7 downto 0); alias xdata_7 : bit is xdata(7); alias xdata_6 : bit is xdata(6); alias xdata_5 : bit is xdata(5); alias xdata_4 : bit is xdata(4); alias xdata_3 : bit is xdata(3); alias xdata_2 : bit is xdata(2); alias xdata_1 : bit is xdata(1); alias xdata_0 : bit is xdata(0); signal xgoset : bit; signal rdata : bit_vector(7 downto 0); signal rrdy : bit; signal rrdyclr : bit; signal syncmode : bit; signal errclr : bit; signal nbits : bit_vector(1 downto 0); alias nbits_1 : bit is nbits(1); alias nbits_0 : bit is nbits(0); signal nsbits : bit_vector(1 downto 0); alias nsbits_1 : bit is nsbits(1); alias nsbits_0 : bit is nsbits(0); signal pen : bit; signal ep : bit; signal sbrk : bit; signal txen : bit; signal xgo : bit; signal xgoclr : bit; --signal xdhalf : time; --signal xdrdy : time; signal txd : bit; signal txe : bit; signal rrdyset : bit; signal rxe : bit; signal brate : bit_vector(1 downto 0); alias brate_1 : bit is brate(1); alias brate_0 : bit is brate(0); signal eh : bit; signal feset : bit; signal oeset : bit; signal peset : bit; signal pe : bit; signal oe : bit; signal fe : bit; signal syndet : bit; signal rxrdy : bit; signal scs : bit; signal txdata : bit_vector(7 downto 0); begin -- ************************************************************************** -- -- Process main describes interface between pins and the inside of the chip. -- -- ************************************************************************** main : process --variable L : Line; begin wait for 1fs; rstint <= '1'; xgoset <= '0'; errclr <= '0'; -- xdrdy <= 2ns; -- xdhalf <= 1ns; wait for 1ns; -- program mode wait until csl = '0' and wrl = '0' and cd = '1'; mode <= temp; wait for 1fs; --writeline(OUTPUT,L); --write(L,STRING'("MODE PROGRAMMED =")); --write(L,mode); --writeline(OUTPUT,L); -- resolve the mode word if mode(0) = '0' and mode(1) = '0' then syncmode <= '1'; nbits_0 <= mode(2); nbits_1 <= mode(3); pen <= mode(4); ep <= mode(5); scs <= mode(7); else syncmode <= '0'; brate_0 <= mode(0); brate_1 <= mode(1); nbits_0 <= mode(2); nbits_1 <= mode(3); pen <= mode(4); ep <= mode(5); nsbits_0 <= mode(6); nsbits_1 <= mode(7); end if; wait for 1fs; rstint <= '0'; wait for 1ns; -- get sync charecters if needed if syncmode = '1' then -- sync1 wait until csl = '0' and wrl = '0' and cd = '1'; sync1 <= temp; wait for 1fs; if scs = '0' then -- sync2 if needed wait for 1fs; wait until csl = '0' and wrl = '0' and cd = '1'; sync2 <= temp; wait for 2ns; end if; --write(L,STRING'("SYNC1 =")); --write(L,sync1); --writeline(OUTPUT,L); --write(L,STRING'("SYNC2 =")); --write(L,sync2); --writeline(OUTPUT,L); end if; -- endlessly monitor the control pins loop wait for 1ns; -- read data if csl = '0' and wrl = '1' and rdl = '0' and cd = '0' then data <= rdata; wait until rdl = '0'; rrdyclr <= '1'; wait for 1fs; rrdyclr <= '0'; wait for 1fs; elsif csl = '0' and wrl = '1' and rdl = '0' and cd = '1' then -- read status status_2 <= txe; status_3 <= pe; status_4 <= oe; status_5 <= fe; status_6 <= syndet; data <= status; wait for 1fs; --write(L,STRING'("READING STATUS")); --write(L,data); --writeline(OUTPUT,L); wait until rdl = '1'; elsif csl = '0' and wrl = '0' and rdl = '1' and cd = '0' then -- load tx buffer txdata <= temp; wait for 1fs; xgoset <= '1'; wait for 1fs; xgoset <= '0'; --write(L,STRING'("LOADING TX BUFFER ")); --write(L,txdata); --writeline(OUTPUT,L); elsif csl = '0' and wrl = '0' and rdl = '1' and cd = '1' then -- --write command word wait for 1fs; control <= temp; wait for 1fs; txen <= control(0); rxe <= control(2); sbrk <= control(3); errclr <= control(4); rstint <= control(6); if control(7) = '1' then ehset <= '1'; wait for 1fs; ehset <= '0'; else ehclr <= '1'; wait for 1fs; ehclr <= '0'; end if; wait for 1fs; --write(L,STRING'("READING CONTROL = ")); --write(L,control); --writeline(OUTPUT,L); rstint <= '0'; wait for 1fs; end if; end loop; end process; -- ************************************************************************** -- -- transmitter -- -- ************************************************************************** tx:process variable xcount : bit_vector(2 downto 0); alias xcount_2 : bit is xcount(2); alias xcount_1 : bit is xcount(1); alias xcount_0 : bit is xcount(0); variable syncflg : bit; variable par : bit; variable cntint : integer; --variable L : Line; begin syncflg := '0'; txd <= '1'; txe <= '0'; xgoclr <= '0'; -- forever if tx buffer not empty and tx enabled transmit loop while txen = '1' and ctsl = '0' loop wait for 1ns; -- if send break if sbrk = '1' and syncmode = '0' then --write(L,STRING'("SENDING BREAK")); --writeline(OUTPUT,L); txd <= '0'; wait for 1fs; wait until sbrk = '0' or txen = '0' or ctsl= '0'; txd <= '1'; wait for 1fs; end if; if syncmode = '1' then --write(L,STRING'("SYNCRONOUS TRANSMIT")); --writeline(OUTPUT,L); if xgo = '0' then -- Load sync chars txe <= '1'; if syncflg = '0' then xdata <= sync1; syncflg := '1'; elsif syncflg = '1' then xdata <= sync2; syncflg := '0'; end if; elsif xgo = '1' then -- Load data xdata <= txdata; xgoclr <= '1'; wait for 1fs; xgoclr <= '0'; end if; elsif syncmode = '0' then --write(L,STRING'("ASYNCRONOUS TRANSMIT")); --writeline(OUTPUT,L); if xgo = '0' then txe <= '1'; end if; while xgo = '0' loop wait for 1ns; end loop; xdata <= txdata; wait for 1fs; xgoclr <= '1'; wait for 1fs; xgoclr <= '0'; end if; -- calculate charecter length xcount_2 := '1'; xcount_1 := nbits_1; xcount_0 := nbits_0; txe <= '0'; wait for 1fs; if syncmode = '0' then -- wait for xdrdy; wait for 2ns; txd <= '0'; wait for 1fs; --write(L,STRING'("TRANSMITTING START BIT ")); --writeline(OUTPUT,L); --write(L,STRING'("TXD = ")); --write(L,txd); --writeline(OUTPUT,L); end if; -- initialize parity checker if pen = '1' then if ep = '0' then par := '1'; elsif ep = '1' then par := '0'; end if; end if; cntint := bits_to_int(xcount); --write(L,STRING'("TRANSMITTING DATA")); --writeline(OUTPUT,L); while cntint+1 > 0 loop -- wait for xdrdy; wait for 2ns; -- output LSB on to TXD pin (perform right shift on xdata) txd <= xdata_0; wait for 1fs; --write(L,STRING'("TXD =")); --write(L,txd); --writeline(OUTPUT,L); if txd = '1' then par := not par; end if; xdata_0 <= xdata_1; xdata_1 <= xdata_2; xdata_2 <= xdata_3; xdata_3 <= xdata_4; xdata_4 <= xdata_5; xdata_5 <= xdata_6; xdata_6 <= xdata_6; xdata_7 <= '1'; wait for 1fs; cntint := cntint - 1; end loop; wait for 1fs; if pen = '1' then -- wait for xdrdy; wait for 2ns; txd <= par; wait for 1fs; --write(L,STRING'("TRANSMITTING PARITY BIT")); --writeline(OUTPUT,L); --write(L,STRING'("TXD =")); --write(L,txd); --writeline(OUTPUT,L); -- wait for xdrdy; wait for 2ns; end if; if syncmode = '0' then -- wait for xdrdy; wait for 2ns; txd <= '1'; -- wait for xdrdy; wait for 2ns; --write(L,STRING'("TRANSMITTING FIRST STOP BIT")); --writeline(OUTPUT,L); --write(L,STRING'("TXD =")); --write(L,txd); --writeline(OUTPUT,L); if nsbits_1 = '1' then -- wait for xdrdy; wait for 2ns; --write(L,STRING'("TRANSMITTING SECOND STOP BIT")); --writeline(OUTPUT,L); --write(L,STRING'("TXD =")); --write(L,txd); --writeline(OUTPUT,L); else -- wait for xdhalf; wait for 1ns; --write(L,STRING'("TRANSMITTING HALF A STOP BIT")); --writeline(OUTPUT,L); --write(L,STRING'("TXD =")); --write(L,txd); --writeline(OUTPUT,L); end if; end if; end loop; wait for 1ns; end loop; end process; -- *************************************************************************** -- -- receiver -- -- *************************************************************************** rx: process variable rcount : bit_vector(3 downto 0); alias rcount_0 : bit is rcount(0); alias rcount_1 : bit is rcount(1); alias rcount_2 : bit is rcount(2); variable ldata : bit_vector(7 downto 0); alias ldata_7 : bit is ldata(7); alias ldata_6 : bit is ldata(6); alias ldata_5 : bit is ldata(5); alias ldata_4 : bit is ldata(4); alias ldata_3 : bit is ldata(3); alias ldata_2 : bit is ldata(2); alias ldata_1 : bit is ldata(1); alias ldata_0 : bit is ldata(0); variable par : bit; variable strt: bit; variable synok : bit; variable cntint : integer; --variable L : Line; begin rxrdy <= '0'; feset <= '0'; oeset <= '0'; peset <= '0'; rrdyset <= '0'; syndet <= '0'; wait for 1fs; wait until rstint = '0'; if syncmode = '0' then -- receive asynchronously loop wait until rxe = '1'; --write(L,STRING'("ASYNCRONOUS RECEIVE")); --writeline(OUTPUT,L); strt := '0'; -- detect start bit and check by sampling at middle of the bit while strt = '0' loop wait until rxd = '0'; -- wait for xdrdy/2; wait for 1ns; if rxd = '0' then strt := '1'; end if; end loop; --write(L,STRING'("START BIT DETECTED")); --writeline(OUTPUT,L); rcount_2 := '1'; rcount_1 := nbits_1; rcount_0 := nbits_0; ldata := "00000000"; -- initialize parity checker if pen = '1' then if ep = '0' then par := '1'; elsif ep = '1' then par := '0'; end if; end if; -- receive data cntint := bits_to_int(rcount); while cntint+1 > 0 loop -- wait for xdrdy; wait for 2ns; -- perform right shift on ldata ldata_0 := ldata_1; ldata_1 := ldata_2; ldata_2 := ldata_3; ldata_3 := ldata_4; ldata_4 := ldata_5; ldata_5 := ldata_6; ldata_6 := ldata_7; ldata_7 := rxd; --write(L,STRING'("RXD = ")); --write(L,rxd); --writeline(OUTPUT,L); cntint := cntint - 1; if rxd = '1' then par := not par; end if; end loop; -- receive parity bit if pen = '1' then --write(L,STRING'("RECEIVING PARITY BIT ")); --writeline(OUTPUT,L); -- wait for xdrdy; wait for 2ns; --write(L,STRING'("RXD = ")); --write(L,rxd); --writeline(OUTPUT,L); if not (par = rxd) then peset <= '1'; end if; end if; peset <= '0'; -- check for framing error -- wait for xdrdy; wait for 2ns; --write(L,STRING'("RECEIVING STOP BITS")); --writeline(OUTPUT,L); --write(L,STRING'("RXD = ")); --write(L,rxd); --writeline(OUTPUT,L); if rxd = '0' then feset <= '1'; if ldata = "00000000" then syndet <= '1'; end if; end if; feset <= '0'; -- check for overrun error if rrdy = '1' then oeset <= '1'; end if; rdata <= ldata; rrdyset <= '1'; wait for 1fs; rrdyset <= '0'; oeset <= '0'; end loop; elsif syncmode = '1' then wait until eh = '1'; --write(L,STRING'("SYNCRONOUS RECEIVE")); --writeline(OUTPUT,L); loop if eh = '1' then -- enter haunt mode while synok = '0' loop if esd = '1' then wait until syndet = '1'; synok := '1'; else ldata := "11111111"; -- wait for xdrdy/2; wait for 1ns; -- lookout for sync1 while not (ldata = sync1) loop -- wait for xdrdy; wait for 2ns; -- perform right shift on ldata ldata_0 := ldata_1; ldata_1 := ldata_2; ldata_2 := ldata_3; ldata_3 := ldata_4; ldata_4 := ldata_5; ldata_5 := ldata_6; ldata_6 := ldata_7; ldata_7 := rxd; --write(L,STRING'("RXD = ")); --write(L,rxd); --writeline(OUTPUT,L); end loop; --write(L,STRING'("SYNC1 DETECTED")); --writeline(OUTPUT,L); synok := '1'; -- get sync2 if programmed if scs = '0' then synok := '0'; rcount_2 := '1'; rcount_1 := nbits_1; rcount_0 := nbits_0; cntint := bits_to_int(rcount); while cntint+1 > 0 loop -- wait for xdrdy; wait for 2ns; -- perform right shift on ldata ldata_0 := ldata_1; ldata_1 := ldata_2; ldata_2 := ldata_3; ldata_3 := ldata_4; ldata_4 := ldata_5; ldata_5 := ldata_6; ldata_6 := ldata_7; ldata_7 := rxd; cntint := cntint - 1; end loop; if ldata = sync2 then synok := '1'; ehclr1 <= '1'; wait for 1fs; ehclr1 <= '0'; end if; end if; end if; end loop; end if; -- sync detected start assembling data rcount_2 := '1'; rcount_1 := nbits_1; rcount_0 := nbits_0; rdata <= "00000000"; cntint := bits_to_int(rcount); while cntint+1 > 0 loop -- wait for xdrdy; wait for 2ns; -- perform right shift of ldata ldata_0 := ldata_1; ldata_1 := ldata_2; ldata_2 := ldata_3; ldata_3 := ldata_4; ldata_4 := ldata_5; ldata_5 := ldata_6; ldata_6 := ldata_7; ldata_7 := rxd; --write(L,STRING'("RXD = ")); --write(L,rxd); --writeline(OUTPUT,L); cntint := cntint - 1; end loop; -- check for overrun error if rrdy = '1' then oeset <= '1'; end if; rdata <= ldata; wait for 1fs; rrdyset <= '1'; wait for 1fs; rrdyset <= '0'; oeset <= '0'; end loop; end if; end process; -- ************************************************************************** -- -- synchronization flip flops -- -- ************************************************************************** xgoff : process --variable L : Line; begin if xgo = '0' then wait until xgoset = '1'; xgo <= '1'; else wait until xgoclr = '1'; xgo <= '0'; end if; wait for 1fs; end process; peff : process --variable L : Line; begin pe <= mode(4); if pe = '0' then wait until peset = '1'; pe <= '1'; else wait until errclr = '1'; pe <= '0'; end if; wait for 1fs; end process; oeff : process --variable L : Line; begin if oe = '0' then wait until oeset = '1'; oe <= '1'; else wait until errclr = '1'; oe <= '0'; end if; wait for 1fs; end process; feff : process --variable L : Line; begin if fe = '0' then wait until feset = '1'; fe <= '1'; else wait until errclr = '1'; fe <= '0'; end if; wait for 1fs; end process; ehff : process --variable L : Line; begin if eh = '0' then wait until ehset = '1'; eh <= '1'; else wait until ehclr = '1' or ehclr1 = '1'; eh <= '0'; end if; wait for 1fs; end process; rrdyff : process --variable L : Line; begin if rrdy = '0' then wait until rrdyset = '1'; rrdy <= '1'; else wait until rrdyclr = '1' or rrdyclr1 = '1'; rrdy <= '0'; end if; wait for 1fs; end process; end intel;