--********************************************************************** -- This file contains some of the major examples used in Prof. Armstrong's -- book on modelling using VHDL. The code has not been analyzed or -- simulated. Thus, they should be used with care. -- -- The files in this archive are: -- -- i8212.v ieeexsyn.v intxcont.v loop.v -- mark2.v mark2xsy.v markxsys.v mesc.v -- one.v ram.v ram2.v ramx.v -- syntax.v syspac.v tslpac.v two.v -- uart.v wait.v -- -- The files are all concatenated below into this single file for download -- convenience. --******************************************************************** --******************************************************************** -- i8212.v use TSL.all,SYSTEM.all; entity I8212 is generic(GDEL,FFDEL,BUFDEL: TIME); port(DI: in WORD; DO: out WORD; NDS1,DS2,MD,STB,NCLR: in BIT; NINT: out BIT); end I8212; architecture BEHAVIOR of I8212 is signal S0,S1,S2,S3: BIT; signal SRQ: BIT; signal Q,Q1,Q2: WORD; begin B1: block(S1='1' and NCLR='1') begin Q1 <= guarded DI after FFDEL; Q2 <= "00000000" after FFDEL when (NCLR='0') else Q2; DO <= Q after BUFDEL when (S3='1') else "ZZZZZZZZ" after BUFDEL; end block B1; S0 <= not NDS1 and DS2 after GDEL; S1 <= (S0 and MD) or (STB and not MD) after (2*GDEL); S2 <= S0 nor not NCLR after GDEL; S3 <= S0 or MD after GDEL; SRQ <= '1' after FFDEL when (S2='0') else '0' after FFDEL when (S2='1') and not STB'STABLE and (STB='0') else SRQ; NINT <= not SRQ nor S0 after GDEL; end BEHAVIOR; --******************************************************************** --******************************************************************** -- ieeexsyn.v entity REG is generic (STRB_DEL,EN_DEL: TIME); port (DI: in BIT_VECTOR(1 to 8); STRB: in BIT; DS1: in BIT; NDS2: in BIT; DO: out BIT_VECTOR(1 to 8)); end REG; ------------------------------------------------------------ ------------------------------------------------------------ architecture NODAL of REG is signal DID: BIT_VECTOR(1 to 8); signal END_SIG: BIT; begin A: process(STRB) begin if (STRB='1') then DID <= DI after STRB_DEL; end if; end process A; B: process(DS1,NDS2) begin END_SIG <= DS1 and not NDS2 after EN_DEL; end process B; C: process(DID,END_SIG) begin if (END_SIG='1') then DO <= DID after ODEL; else DO <= "11111111" after ODEL; end if; end process C; end NODAL; ------------------------------------------------------- ------------------------------------------------------- architecture DATA_FLOW of REG is begin B1: block (STRB='1' and not STRB'STABLE) signal DID: BIT_VECTOR(1 to 8); signal END_SIG: BIT; begin DID <= guarded DI after STRB_DEL; --process A END_SIG <= DS1 and not NDS2 after EN_DEL; --process B DO <= DID after ODEL when END_SIG='1' else "11111111" after ODEL; end block B1; end DATA_FLOW; ---------------------------------------------------------- ---------------------------------------------------------- entity PAR_SER is generic (SUT,HT,PW,PER,ODEL: TIME); port (PI: in BIT_VECTOR(0 to 7); STRB: in BIT; SO: out BIT); end PAR_SER; ---------------------------------------------------------- ---------------------------------------------------------- architecture CHIP_LEVEL of PAR_SER is signal SH: BIT; signal SR: BIT_VECTOR(0 to 7); signal DONE: BIT; begin LOAD: process(STRB, DONE) variable PIDEL: BIT_VECTOR(0 to 7); variable STRB_FLAG: BOOLEAN := true; begin if STRB_FLAG then if STRB='1' and not STRB'STABLE then PIDEL := PI; wait for HT; assert PI'STABLE(SUT + HT) report "Setup or HOLD TIME FAILURE"; if PI'STABLE(SUT+HT) then SR <= PIDEL; SH <= '1'; STRB := false; end if; end if; end if; if DONE='1' and not DONE'STABLE then STRB_FLAG := true; else STRB_FLAG := false; end if; end process LOAD; SHIFT: process(SH) variable COUNT: INTEGER := 0; begin if SH ='1' then COUNT := 0; while COUNT < 8 loop SO <= SR(0) after ODEL; SR <= SR(1 to 7)&'1'; COUNT := COUNT + 1; wait for PER; end loop; DONE <= '1'; SH <= '0'; end if; end process SHIFT; end CHIP_LEVEL; ----------------------------------------------------------- ----------------------------------------------------------- entity CLOCK_GENERATOR is generic (PER: TIME); port (RUN: in BIT; CLK: out BIT); end CLOCK_GENERATOR; -------------------------------------------------------- -------------------------------------------------------- architecture IMPL_1 of CLOCK_GENERATOR is signal CLOCK: BIT; begin process (RUN,CLOCK) variable CLOCK_FLAG: BOOLEAN := true; begin if RUN='1' and not RUN'STABLE then CLOCK_FLAG := true; CLOCK <= transport '0' after PER/2; CLOCK <= transport '1' after PER; end if; if RUN='0' and not RUN'STABLE then CLOCK := false; end if; if CLOCK_FLAG then if CLOCK='1' and not CLOCK'STABLE then CLOCK <= transport '0' after PER/2; CLOCK <= transport '1' after PER; end if; CLK <= CLOCK; end if; end process; end IMPL_1; ----------------------------------------------------------- ----------------------------------------------------------- entity CONTROLLED_CTR is generic (SUT,MPW,ENCDEL,IENDEL,CLRDEL,CNTDEL,LIMDEL,COMPDEL: TIME); port (CLK,STRB: in BIT; CON: in BIT_VECTOR(0 to 3); DATA: in BIT_VECTOR(0 to 3); OUTPUT: out BIT_VECTOR(0 to 3)); begin assert STRB'STABLE or STRB='1' or DATA'STABLE(SUT) report "Setup time failure on DATA input."; assert STRB'STABLE or STRB='0' or CON'STABLE(SUT) report "Setup time failure on CON input."; assert STRB'STABLE or STRB='1' or STRB'DELAYED'STABLE(MPW) report "Pulse width failure on STRB."; end CONTROLLED_CTR; --------------------------------------------------------------- --------------------------------------------------------------- use COUNTER_PAC.all; architecture PROCESS_IMPL of CONTROLLED_CTR is signal ENIT,ENIT1,ENIT2: BIT; signal EN: BIT; signal CONSIG,LIM: BIT_VECTOR(0 to 3); signal OUT_TMP,OUT1,OUT2: BIT_VECTOR(0 to 3); begin DECODE: process(STRB) variable CONREG: BIT_VECTOR(0 to 1) := "00"; begin if STRB='1' then CONREG := CON; case CONREG is when "00" => CONSIG <= "1000" after ENCDEL; when "01" => CONSIG <= "0100" after ENCDEL; when "10" => CONSIG <= "0010" after ENCDEL; ENIT1 <= '1' after IENDEL; when "11" => CONSIG <= "0001" after ENCDEL; ENIT1 <= '1' after IENDEL; end case; end if; end process DECODE; LOAD_LIMIT: block(CONSIG(1)='1' and STRB='0' and not STRB'STABLE) begin LIM <= guarded DATA after LIMDEL; end block LOAD_LIMIT; CLEAR_CTR: block(CONSIG(0)='1' and not CONSIG(0)'STABLE) begin OUT1 <= guarded "0000" after CLRDEL; end block CLEAR_CTR; CNT_UP_OR_DOWN: process(CLK,EN) variable COUNT: BIT := '0'; variable CNT: BIT_VECTOR(0 to 3) := "0000"; variable CLK_FLAG: BOOLEAN := true; begin if CLK_FLAG then if CLK='1' and not CLK'STABLE then if CONSIG(2)='1' then CNT := INC(CNT); else if (CONSIG(3)='1') then CNT := DEC(CNT); end if; end if; end if; OUT2 <= CNT after CNTDEL; end if; if not EN'STABLE then if EN='1' then CLK_FLAG := true; else CLK_FLAG := false; end if; end if; end process CNT_UP_OR_DOWN; LIMIT_CHK: process(OUT_TMP,ENIT) begin if ENIT='1' and not ENIT'STABLE then EN <= '1' after COMPDEL; ENIT2 <= '0' after IENDEL; else if EN='1' and OUT_TMP=LIM then EN <= '0' after COMPDEL; end if; end if; end process LIMIT_CHK; MUX1: OUT_TMP <= OUT1 when not OUT1'QUIET else OUT2 when not OUT2'QUIET else OUT_TMP; MUX2: ENIT <= ENIT1 when not ENIT1'QUIET else ENIT2 when not ENIT2'QUIET else ENIT; OUTPUT <= OUT_TMP; end PROCESS_IMPL; --------------------------------------------------------- --------------------------------------------------------- --******************************************************************** --******************************************************************** -- intxcont.v use TSL.all,SYSTEM.all; entity INT_CONT is generic(INTDEL,ENCDEL,BUFFDEL: TIME); port(NINT1,NINT2,NINT3,NINT4,INTA: in BIT; INT: out BIT; OUTPUT: out WORD); end INT_CONT; architecture BEHAVIOR of INT_CONT is signal VECT: WORD; begin INT <= NINT1 nand NINT2 nand NINT3 nand NINT4 after INTDEL; VECTOR: process(NINT1,NINT2,NINT3,NINT4) begin if (NINT1='0') then VECT <= "00011100" after ENCDEL; elsif (NINT2='0') then VECT <= "00011101" after ENCDEL; elsif (NINT3='0') then VECT <= "00011110" after ENCDEL; elsif (NINT4='0') then VECT <= "00011111" after ENCDEL; end if; end process VECTOR; BUFF: process(VECT,INTA) variable VECT_FLAG: BOOLEAN := true; begin if VECT_FLAG then if not INTA'STABLE then if (INTA='1') then OUTPUT <= VECT after BUFFDEL; VECT_FLAG := true; else OUTPUT <= "ZZZZZZZZ" after BUFFDEL; VECT_FLAG := false; end if; else if INTA='1' then OUTPUT <= VECT after BUFFDEL; end if; end if; end if; end process BUFF; end BEHAVIOR; --******************************************************************** --******************************************************************** -- loop.v entity LOOP_CONS is port (X: in BIT; Y: out BIT); end LOOP_CONS; architecture VARIOUS_LOOP of LOOP_CONS is begin process (X) variable SUM,N: integer; begin --EXAMPLE 2.3: for I in 0 to 3 loop A(I) := 2**I; end loop; --EXAMPLE 2.4: SUM := 0; I := 1; SUM_INT: while I <= N loop SUM := SUM + I; end loop SUM_INT; -- EXAMPLE 2.5 SUM := 0; I := 1; SUM_INT: while I <= N loop next SUM_INT when I = 3; SUM := SUM + I; end loop SUM_INT; --EXAMPLE 2.6: SUM := 0; loop VAL(X); exit when X < 0; SUM := SUM + X; end loop; end process; end VARIOUS_LOOP; --******************************************************************** --******************************************************************** -- mark2.v use TSL.all,SYSTEM.all; entity MARK2 is generic(RDEL,WDEL,ODEL,MADEL,INTDEL,PER: TIME); port(DATA: inout WORD; MA: out ADDR; RUN,INT: in BIT; RD,WRITE,IO,RDS,RDP,RSS,WIS,WTP,INTA: out BIT); end MARK2; architecture BEHAVIOR of MARK2 is signal STOP,INTE,IOWAIT: BIT; signal STOPR,STOPE,INTER,INTEE,INTEI: BIT; signal IOWAITF,IOWAITE,IOWAITI: BIT; signal CLK,FETCH,EXECUTE,INTERUPT: BOOLEAN; signal PCF,PCI,PCE,PC: ADDR; signal IR: WORD; signal MAF,MAE,TEMP_MA: ADDR; signal BITVEC_MA: BIT_VECTOR(4 downto 0); begin CLK <= not CLK after PER; RUN_PROC: process(RUN) begin if RUN='1' then STOPR <= '0'; INTER <= '0'; else STOPR <= '1'; end if; end process RUN_PROC; STATE: block((STOP='0') and (IOWAIT='0') and not CLK'STABLE) begin FETCH <= guarded TRUE when (EXECUTE and (INTE='0' or INT='0' or INTERUPT)) else FALSE; EXECUTE <= guarded TRUE when FETCH else FALSE; INTERUPT <= guarded TRUE when EXECUTE and (INT='1' and INTE='1') else FALSE; end block STATE; FETCH_PROC: process begin wait on FETCH until FETCH; MAF <= PC after MADEL; RD <= '1' after ODEL; WRITE <= '0' after ODEL; IOWAITF <= '1'; wait for RDEL; IR <= DATA; RD <= '0' after ODEL; IOWAITF <= '0'; PCF <= ADD5(PC,"00001"); end process FETCH_PROC; EXECUTE_PROC: process variable ACC: WORD; begin wait on EXECUTE until EXECUTE; case (IR(2 downto 0)) is --decoding when "000" => PCE <= IR(7 downto 3); --jmp when "001" => ACC := ADD8(INVW(ACC),"00000001"); --tcm when "010" => MAE <= IR(7 downto 3); --lda RD <= '1' after ODEL; WRITE <= '0' after ODEL; IOWAITE <= '1'; wait for RDEL; RD <= '0' after ODEL; IOWAITE <= '0'; ACC := DATA; when "011" => DATA <= ACC; --sta MAE <= IR(7 downto 0) after MADEL; RD <= '0' after ODEL; WRITE <= '1' after ODEL; IOWAITE <= '1'; wait for WDEL; WRITE <= '0' after ODEL; IOWAITE <= '0'; when "100" => MAE <= IR(7 downto 3); --add RD <= '1' after ODEL; WRITE <= '0' after ODEL; IOWAITE <= '1'; wait for RDEL; RD <= '0' after ODEL; IOWAITE <= '0'; ACC := ADD8(ACC,DATA); when "101" => if IR(7)='1' then --eni INTEE <= '1'; else INTEE <= '0'; end if; when "110" => if ACC(7)='1' then --jpn PCE <= IR(7 downto 3); end if; when "111" => STOPE <= '1'; --stop end case; end process EXECUTE_PROC; INTERUPT_PROC: process begin wait on INTERUPT until INTERUPT and INTE='1'; INTEI <= '0'; INTA <= '1' after ODEL; IOWAITI <= '1'; wait for INTDEL; PCI <= VDAD(DATA); INTA <= '0' after ODEL; IOWAITI <= '0'; end process INTERUPT; ---- I/O Control Signal Decoding IO_DECODE: block(BITVEC_MA(4) and BITVEC_MA(3)) begin RDP <= guarded not BITVEC_MA(2) and not BITVEC_MA(1) and not BITVEC_MA(0) after ODEL; WTP <= guarded not BITVEC_MA(2) and not BITVEC_MA(1) and BITVEC_MA(0) after ODEL; RDS <= guarded not BITVEC_MA(2) and BITVEC_MA(1) and not BITVEC_MA(0) after ODEL; WTS <= guarded not BITVEC_MA(2) and BITVEC_MA(1) and BITVEC_MA(0) after ODEL; RSS <= guarded BITVEC_MA(2) and not BITVEC_MA(1) and not BITVEC_MA(0) after ODEL; WIS <= guarded BITVEC_MA(2) and not BITVEC_MA(1) and BITVEC_MA(1) after ODEL; end block IO_DECODE; IO <= BITVEC_MA(4) and BITVEC_MA(3) after ODEL; ---- Process OUTPUT Multplexing PC <= PCE when not PCE'QUITE else PCI when not PCI'QUITE else PCF when not PCF'QUITE else PC; STOP <= STOPR when not STOPR'QUITE else STOPE when not STOPE'QUITE else STOP; IOWAIT <= IOWAITF when not IOWAITF'QUITE else IOWAITE when not IOWAITE'QUITE else IOWAITI when not IOWAITI'QUITE else IOWAIT; INTE <= INTER when not INTER'QUITE else INTEE when not INTEE'QUITE else INTEI when not INTEI'QUITE else INTE; TEMP_MA <= MAF when not MAF'QUIET else MAE when not MAF'QUIET else TEMP_MA; MA <= TEMP_MA; BITVEC_MA <= TRIVEC_TO_BITVEC(TEMP_MA); end BEHAVIOR; --******************************************************************** --******************************************************************** -- mark2xsy.v use TSL.all,SYSTEM.all; entity MARK2_SYS is port (SYSOUT: out WORD; SYSIN: in WORD; SEROUT: out BIT; SERIN : in BIT; ISTRB: in BIT; RUN: in BIT); end MARK2_SYS; architecture CHIP_LEVEL of MARK2_SYS is component MARK2 generic (RDEL,WDEL,ODEL,MADEL,INTDEL,PER: TIME) port (DATA: inout WORD; MA: out ADDR; RUN,INT: in BIT; RD,WRITE,IO,RDS,RDP,WTS,WTP,INTA: out BIT); component RAM generic (RDEL,DIS: TIME) port (DATA: inout WORD; ADDR: in SYSTEM.ADDR; RD,WRITE,NCS: in BIT); component UART generic (CLK_PER,ODEL,INDEL,INTDEL: TIME) port (DATA: inout WORD; I,LOAD,READ: in BIT; O,NINTO,NINTI: out BIT); component I8212 generic (GDEL,FFDEL,BUFDEL: TIME) port (DI: in WORD; DO: out WORD; NDS1,DS2,MD,STB,NCLR: in BIT; NINT: out BIT); component INT_CONT generic (INTDEL,ENCDEL,BUFFDEL: TIME) port (NINT1,NINT2,NINT3,NINT4,INTA: in BIT; INT: out BIT; OUTPUT: out WORD); signal DATA_BUS: WORD; signal MA: SYSTEM.ADDR; signal RD,WRITE,RDS,RDP: BIT; signal WTS,WTP,IO: BIT; signal INT,INTA,NINT1,NINT2,NINT3: BIT; signal ZERO: BIT ; signal ONE: BIT; begin CPU: MARK2 generic map (150 ns, 100 ns, 50 ns, 150 ns, 500 ns) port map (DATA_BUS,MA,RUN,INT,RD,WRITE,IO,RDS,RDP,WTS,WTP,INTA); MEM: RAM generic map (100 ns, 30 ns) port map (DATA_BUS,MA,RD,WRITE,IO); SER: UART generic map (104 us, 20 ns, 30 ns, 30 ns) port map (DATA_BUS,SERIN,WTS,RDS,SEROUT,NINT3,NINT2); PARIN: I8212 generic map (20 ns, 30 ns, 20 ns) port map (SYSIN,DATA_BUS,ZERO,RDP,ZERO,ISTRB,ONE,NINT1); PAROUT: I8212 generic map (20 ns, 30 ns, 20 ns) port map (DATA_BUS,SYSOUT,ZERO,WTP,ONE,ZERO,ONE,open); SYSINT: INT_CONT generic map (20 ns, 30 ns, 20 ns) port map (NINT1,NINT2,NINT3,ONE,INTA,INT,DATA_BUS); ONE <= '1'; ZERO <= '0'; end CHIP_LEVEL; --******************************************************************** --******************************************************************** -- markxsys.v use TSL.all,SYSTEM.all; entity MARK2_SYS is port (SYSOUT: out WORD; SYSIN: in WORD; SEROUT: out BIT; SERIN : in BIT; ISTRB: in BIT; RUN: in BIT); end MARK2_SYS; architecture CHIP_LEVEL of MARK2_SYS is component MARK2 generic (RDEL,WDEL,ODEL,MADEL,INTDEL,PER: TIME) port (DATA: inout WORD; MA: out ADDR; RUN,INT: in BIT; RD,WRITE,IO,RDS,RDP,WTS,WTP,INTA: out BIT); component RAM generic (RDEL,DIS: TIME) port (DATA: inout WORD; ADDR: in SYSTEM.ADDR; RD,WRITE,NCS: in BIT); component UART generic (CLK_PER,ODEL,INDEL,INTDEL: TIME) port (DATA: inout WORD; I,LOAD,READ: in BIT; O,NINTO,NINTI: out BIT); component I8212 generic (GDEL,FFDEL,BUFDEL: TIME) port (DI: in WORD; DO: out WORD; NDS1,DS2,MD,STB,NCLR: in BIT; NINT: out BIT); component INT_CONT generic (INTDEL,ENCDEL,BUFFDEL: TIME) port (NINT1,NINT2,NINT3,NINT4,INTA: in BIT; INT: out BIT; OUTPUT: out WORD); signal DATA_BUS: WORD; signal MA: SYSTEM.ADDR; signal RD,WRITE,RDS,RDP: BIT; signal WTS,WTP,IO: BIT; signal INT,INTA,NINT1,NINT2,NINT3: BIT; signal ZERO: BIT ; signal ONE: BIT; begin CPU: MARK2 generic map (150 ns, 100 ns, 50 ns, 150 ns, 500 ns) port map (DATA_BUS,MA,RUN,INT,RD,WRITE,IO,RDS,RDP,WTS,WTP,INTA); MEM: RAM generic map (100 ns, 30 ns) port map (DATA_BUS,MA,RD,WRITE,IO); SER: UART generic map (104 us, 20 ns, 30 ns, 30 ns) port map (DATA_BUS,SERIN,WTS,RDS,SEROUT,NINT3,NINT2); PARIN: I8212 generic map (20 ns, 30 ns, 20 ns) port map (SYSIN,DATA_BUS,ZERO,RDP,ZERO,ISTRB,ONE,NINT1); PAROUT: I8212 generic map (20 ns, 30 ns, 20 ns) port map (DATA_BUS,SYSOUT,ZERO,WTP,ONE,ZERO,ONE,open); SYSINT: INT_CONT generic map (20 ns, 30 ns, 20 ns) port map (NINT1,NINT2,NINT3,ONE,INTA,INT,DATA_BUS); ONE <= '1'; ZERO <= '0'; end block B1; end CHIP_LEVEL; --******************************************************************** --******************************************************************** -- mesc.v entity A is port(P: in BIT; Q: out BIT); end A; entity B is port(R: in BIT; S: out BIT); end B; entity X is port(L: in BIT; M: out BIT); end X; architecture STRUCTURAL of X is signal S1: BIT; --Signal declared component A --Component declared port(P: in BIT; Q: out BIT); component B port(R: in BIT; S: out BIT); begin A1: A port map(L,S1); --Component Instantiation B1: B port map(S1,M); --Component Instantiation end STRUCTURAL; -- USE OF TYPE package body DATA_TYPES is type CONTROL is (C_AND,C_OR,C_XOR,ADD,SUB,TCOMP); type CONTROL is range 0 to 31; subtype CONTROL is INTEGER range 0 to 31; end DATA_TYPES; package body CONVERSION is function BIN_TO_INT (signal INPUT: BIT_VECTOR) return INTEGER is variable SUM: INTEGER := 0; begin for I in INPUT'LOW to INPUT'HIGH loop if (INPUT(I) = '1') then SUM := SUM + (2**I); end if; end loop; return SUM; end BIN_TO_INT; function INT_TO_BIN (signal INPUT: INTEGER; signal OUTPUT: BIT_VECTOR) return BIT_VECTOR is variable TEMP_OUT: BIT_VECTOR(7 downto 0); variable TEMP_A: INTEGER := 0; variable TEMP_B: INTEGER := 0; begin TEMP_A := INPUT; for I in OUTPUT'HIGH downto OUTPUT'LOW loop TEMP_B := TEMP_A/(2**I); TEMP_A := TEMP_A rem (2**I); if (TEMP_B = '1') then TEMP_OUT(I) := '1'; else TEMP_OUT(I) := '0'; end if; end loop; return TEMP_OUT; end INT_TO_BIN; end CONVERSION; --******************************************************************** --******************************************************************** -- one.v entity ONES_CNT is port (A: in BIT_VECTOR(0 to 2); C:out BIT_VECTOR(0 to 1)); end ONES_CNT; architecture PURE_BEHAVIOR of ONES_CNT is begin process(A) variable NUM: INTEGER range 0 to 3 :=0; begin for I in 0 to 2 loop if A(I) = '1' then NUM := NUM + 1; end if; end loop; case NUM is when 0 => C <= "00"; when 1 => C <= "01"; when 2 => C <= "10"; when 3 => C <= "11"; end case; end process; end PURE_BEHAVIOR; architecture TWO_LEVEL_MECH of ONES_CNT is begin C(1) <= (A(1) and A(0)) or (A(2) and A(0)) or (A(2) and A(1)); C(0) <= (A(2) and not A(1) and not A(0)) or (not A(2) and not A(1) and A(0)) or (A(2) and A(1) and A(0)) or (not A(2) and A(1) and not A(0)); end TWO_LEVEL_MECH; entity AND2 is port (I1,I2: in BIT; O: out BIT); end AND2; architecture BEHAVIOR of AND2 is begin O <= I1 and I2; end BEHAVIOR; entity OR3 is port (I1,I2,I3: in BIT; O: out BIT); end OR3; architecture BEHAVIOR of OR3 is begin O <= I1 or I2 or I3; end BEHAVIOR; entity MAJ3 is port (X: in BIT_VECTOR(0 to 2); Z: out BIT); end MAJ3; architecture AND_OR of MAJ3 is component AND2 port (I1,I2: in BIT; O: out BIT); component OR3 port (I1,I2,I3: in BIT; O: out BIT); signal A1,A2,A3: BIT; begin G1: AND2 port map (X(0),X(1),A1); G2: AND2 port map (X(0),X(2),A2); G3: AND3 port map (X(1),X(2),A3); G4: OR3 port map (A1,A2,A3,Z); end AND_OR; architecture STRUCTURAL of ONES_CNT is component MAJ3 port (X: in BIT_VECTOR(0 to 2); Z: out BIT); component OPAR3 port (X: in BIT_VECTOR(0 to 2); Z: out BIT); begin COMPONENT_1: MAJ3 port map (A,C(1)); COMPONENT_2: OPAR3 port map (A,C(0)); end STRUCTURAL; --******************************************************************** --******************************************************************** -- ram.v use TSL.all,SYSTEM.all; entity RAM is generic(RDEL,DIS: TIME); port (DATA: inout WORD; ADDR: in ADDR; RD,WRITE,NCS: in BIT); end RAM; architecture SIMPLE of RAM is begin process(NCS) type MEMORY is array(0 to 31) of WORD; variable MEM: MEMORY; begin if NCS='0' then if RD='1' then DATA <= MEM(INTVAL(ADDR)) after RDEL; elsif WRITE='1' then MEM(INTVAL(ADDR)) := DATA; end if; else DATA <= "ZZZZZZZZ" after DIS; end if; end process; end SIMPLE; --******************************************************************** --******************************************************************** -- ram2.v use TSL.all,SYSTEM.all; entity RAM2 is generic(DEC,WS,DDEL,RDEL,DIS: TIME); port (READ,WRITE,CS: in BIT; ADDR: in SYSTEM.ADDR; DATA: inout WORD); end RAM2; architecture REALISTIC of RAM2 is type MEMORY is array(0 to 31) of WORD; signal MEM: MEMORY; signal DDATA: WORD; signal DADDR: SYSTEM.ADDR; signal ADC,WSEL: BIT; begin DADDR <= ADDR after DEC; WSEL <= WRITE and CS after WS; DDATA <= DATA after DDEL; READ_PROC: process(DADDR,CS,READ) begin if CS='1' then if READ='1' then DATA <= MEM(INTVAL(DADDR)) after RDEL; end if; else if not CS'STABLE then DO <= "ZZZZZZZZ" after DIS; end if; end if; end process READ_PROC; WRITE_PROC: process(WSEL,DDATA,DADDR) begin if WSEL = '1' then MEM(INTVAL(DADDR)) := DDATA; end if; end process WRITE_PROC; end REALISTIC; --******************************************************************** --******************************************************************** -- ramx.v entity RAM is port (ADDR: in BIT_VECTOR(0 to 9); RW,CS: in BIT; DATA: out BIT_VECTOR(0 to 7)); end RAM; architecture SYNTAX_TEST of RAM is begin RAM: process(ADDR,RW,CS) type MEMORY is array(0 to 1023) of BIT_VECTTOR(0 to 7); variable MEM: static MEMORY; begin null; end process RAM; end SYNTAX_TEST; --******************************************************************** --******************************************************************** -- syntax.v entity TIMING is port (X,Y,Z: in INTEGER; B: out INTEGER); end TIMING; architecture PROCEDURAL of TIMING is begin LOGIC_BLOCK1: process(X,Y,Z) variable A: INTEGER; begin A := X * Y; B <= A + Z; end process LOGIC_BLOCK1; end PROCEDURAL; entity CL is port (X1, X2, X3: in BIT; F: out BIT); end CL; architecture DATA_FLOW of CL is begin T1 <= X1 and X2; F <= T1 or X3; end DATA_FLOW; architecture PROCESS_IMPL of CL is begin process (X1, X2, X3) variable T1: BIT; begin T1 := X1 and X2; F <= T1 or X3 after 100 ns; end process; end PROCESS_IMPL; entity ROM_DECODER is port (X1, X2, X3: in BIT; F: out BIT); end ROM_DECODER; architecture SIMPLE of ROM_DECODER is begin ROM: process(X1, X2, X3) type FUNC_VALUES is array(0 to 7) of BIT; variable MEM: FUNC_VALUES:="01010111"; begin F <= MEM(INTVAL(3, X1&X2&X3)) after 100 ns; end process ROM; end SIMPLE; entity ASYNC is port (X: in BIT; Y1,Y2: out BIT); end ASYNC; architecture ROM of ASYNC is begin process (X,Y1,Y2) type SQ_ARRAY is array(0 to 7, 0 to 1) of BIT; variable MEM: SQ_ARRAY:=(('0','0'),('1','1'),('0','0'), ('1','1'),('0','1'),('0','1'), ('1','0'),('1','0')); begin Y1 <= MEM(INTVAL(X & Y1 & Y2),0) after 50 ns; Y2 <= MEM(INTVAL(X & Y1 & Y2),1) after 50 ns; end process; end ROM; architecture MUX of CL is begin MUX: process (X1,X2,X3) begin case X1 & X2 &X3 is when "000"=> F <= '0' after TOTAL_DEL; when "001"=> F <= '1' after TOTAL_DEL; when "010"=> F <= '0' after TOTAL_DEL; when "011"=> F <= '1' after TOTAL_DEL; when "100"=> F <= '0' after TOTAL_DEL; when "101"=> F <= '1' after TOTAL_DEL; when "110"=> F <= '1' after TOTAL_DEL; when "111"=> F <= '1' after TOTAL_DEL; end case; end process MUX; with X1 & X2 & X3 select F <= '0' after TOTAL_DEL when "000", '1' after TOTAL_DEL when "001", '0' after TOTAL_DEL when "010", '1' after TOTAL_DEL when "011", '0' after TOTAL_DEL when "100", '1' after TOTAL_DEL when "101", '1' after TOTAL_DEL when "110", '1' after TOTAL_DEL when "111"; end MUX; entity COUNTER is port (CON: in BIT; Z: out BIT_VECTOR(0 to 3)); end COUNTER; architecture HUFFMAN of COUNTER is signal CLK: BIT; begin process(CLK,CON) variable COUNT: BIT_VECTOR(0 to 3); begin CLK <= transport '0' after CLOCK_WIDTH/2; CLK <= transport '1' after CLOCK_WIDTH; if ((CLK='1') and not CLK'STABLE) then if (CON='1') then COUNT := INC(COUNT); Z <= COUNT after COUNT_DEL; end if; end if; end process; Z <= COUNT; end HUFFMAN; entity DFF is port (CLK: in BIT; D: in BIT; Q: out BIT); end DFF; architecture LEVEL_SENS of DFF is begin D_LATCH: block(CLK='1' or CLR='0') begin Q <= '0' when CLR='1' else Q; Q <= guarded D; end block D_LATCH; end LEVEL_SENS; architecture EDGE_TRIG of DFF is begin EDGE_TRIGGERED_D: block(CLK='1' and not CLK'STABLE and CLR='0') begin Q <= '0' when CLR='1' else Q; Q <= guarded D; end block EDGE_TRIGGERED_D; end EDGE_TRIG; entity MEALY_MACHINE is port (CLOCK,INPUT: in BIT; OUTPUT: out BIT); end MEALY_MACHINE; architecture STATE_SEQUENCE of MEALY_MACHINE is begin B1: block(CLOCK='1' and not CLOCK'STABLE) type STATE is (STATE0,STATE1,STATE2); type RES_TYPE is array (INTEGER range <>) of STATE; function STATE_RES_FUNC( signal INPUT: RES_TYPE ) return STATE is variable RESOLVED_VALUE: STATE; begin for I in INPUT'LOW to INPUT'HIGH loop RESLOVED_VALUE := INPUT(I); exit; end loop; return RESOLVED_VALUE; end STATE_RES_FUNC; signal STATE_REG: STATE_RES_FUNC STATE register; begin -- state 0 STATE_REG <= guarded STATE1 when STATE_REG=STATE0 and INPUT='0' else STATE2 when STATE_REG=STATE0 and INPUT='1' else off; -- state 1 STATE_REG <= guarded STATE1 when STATE_REG=STATE1 and INPUT='0' else STATE2 when STATE_REG=STATE1 and INPUT='1' else off; -- state 2 STATE_REG <= guarded STATE1 when STATE_REG=STATE2 and INPUT='0' else STATE2 when STATE_REG=STATE2 and INPUT='1' else off; -- output OUTPUT <= '0' when STATE_REG=STATE0 else '1' when STATE_REG=STATE1 and INPUT='0' else '0' when STATE_REG=STATE1 and INPUT='1' else '0' when STATE_REG=STATE2 and INPUT='0' else '1' when STATE_REG=STATE2 and INPUT='1' else null; end block B1; end STATE_SEQUENCE; architecture WAIT_CHK of NOTHING is begin process(X,Y) begin wait for 100 ns; wait on X,Y; wait until (Z='0'); wait on X,Y until (Z=0) for 100 ns; end process; process begin null; WAIT on X,Y,Z; end process; process begin for I in 1 to NUM_CLK loop CLK <= transport '1' after CLK_PERIOD/2; CLK <= transport '0' after CLK_PERIOD; wait for CLK_PERIOD; end loop; end process; end WAIT_CHK; --******************************************************************** --******************************************************************** -- syspac.v use TSL.all; package body SYSTEM is subtype WORD is TSV(7 downto 0); subtype ADDR is TSV(4 downto 0); function ADD8(signal A: WORD; signal B: WORD) return WORD is variable CARRY: MVL := '0'; variable S: TSV(1 to 3); variable NUM: INTEGER range 0 to 3 := 0; variable SUM: WORD; begin for I in 0 to 7 loop S:=A(I) & B(I) & CARRY; for K in 1 to 3 loop if S(K)='1' then NUM := NUM + 1; end if; end loop; case NUM is when 0 => SUM(I) := '0'; CARRY := '0'; when 1 => SUM(I) := '1'; CARRY := '0'; when 2 => SUM(I) := '0'; CARRY := '1'; when 3 => SUM(I) := '1'; CARRY := '1'; end case; end loop; return SUM; end ADD8; function ADD5(signal A: ADDR; signal B: ADDR) return ADDR is variable CARRY: MVL := '0'; variable S: TSV(1 to 3); variable NUM: INTEGER range 0 to 3 := 0; variable SUM: ADDR; begin for I in 0 to 3 loop S:=A(I) & B(I) & CARRY; for K in 1 to 3 loop if S(K)='1' then NUM := NUM + 1; end if; end loop; case NUM is when 0 => SUM(I) := '0'; CARRY := '0'; when 1 => SUM(I) := '1'; CARRY := '0'; when 2 => SUM(I) := '0'; CARRY := '1'; when 3 => SUM(I) := '1'; CARRY := '1'; end case; end loop; return SUM; end ADD5; function INVW(signal X: WORD) return WORD is variable TEMP: WORD; begin for I in 0 to 7 loop if X(I) = '0' then TEMP(I) := '1'; elsif X(I) = '1' then TEMP(I) := '0'; else assert X(I) /= 'Z' report "Internal Data= to Z, set = to 1"; TEMP(I) := '1'; end if; end loop; return TEMP; end INVW; function INTVAL (signal VAL: TSV) return INTEGER is variable SUM: INTEGER := 0; begin for N in VAL'LOW to VAL'HIGH loop if VAL(N) = '1' then SUM := SUM + (2**N); end if; end loop; return SUM; end INTVAL; function VDAD(signal DATA: WORD) return ADDR is variable ADDRESS: ADDR; begin ADDRESS := DATA(4 downto 0); return ADDRESS; end VDAD; end SYSTEM; --******************************************************************** --******************************************************************** -- tslpac.v package body TSL is type MVL is ('0','1','Z'); type TSA is array (INTEGER RANGE <>) of MVL; function BUSFUNC(INPUT: TSA) return MVL is variable RESOLVED_VALUE: MVL := 'Z'; begin for I in INPUT'LOW to INPUT'HIGH loop if INPUT(I) /= 'Z' then RESOLVED_VALUE := INPUT(I); exit; end if; end loop; return RESOLVED_VALUE; end BUSFUNC; subtype TSL is BUSFUNC MVL; type TSV is array(INTEGER range <>) of TSL; function TRISTATE_TO_BIT(INPUT: MVL) return BIT is constant TIE_OFF: BIT := '1'; begin case INPUT is when 'Z' => return TIE_OFF; when '0' => return '0'; when '1' => return '1'; end case; end TRISTATE_TO_BIT; function BIT_TO_TRISTATE (INPUT: BIT) return MVL is type INDEX is array (BIT) of MVL; constant TSL_VALUE: INDEX :="01"; begin return TSL_VALUE(INPUT); end BIT_TO_TRISTATE; function BITVEC_TO_TRIVEC(INPUT: BIT_VECTOR) return TSV is variable CONVERTED_VALUE: TSV(7 downto 0); begin for I in INPUT'LOW to INPUT'HIGH loop CONVERTED_VALUE(I) := BIT_TO_TRISTATE(INPUT(I)); end loop; return CONVERTED_VALUE; end BITVEC_TO_TRIVEC; function TRIVEC_TO_BITVEC(INPUT: TSV) return BIT_VECTOR is variable CONVERTED_VALUE: BIT_VECTOR(7 downto 0); begin for I in INPUT'LOW to INPUT'HIGH loop CONVERTED_VALUE(I) := TRISTATE_TO_BIT(INPUT(I)); end loop; return CONVERTED_VALUE; end TRIVEC_TO_BITVEC; end TSL; --******************************************************************** --******************************************************************** -- two.v package TYPE_DECL is type MVL is ('0','1','Z'); type INDEX is range 0 to 9; type VOLTAGE is range 0 to 10.0; type BIT_VECTOR is array (NATURAL range <>) of BIT; type INT_ARRAY is array(99 downto 0) of INTEGER; type DATE is record DAY : INTEGER range 1 to 31; MONTH: MONTH_NAME; YEAR: INTEGER range 0 to 3000; end record; subtype ADDRESS is BIT_VECTOR(0 to 15); subtype DATA is BIT_VECTOR(0 to 15); type X_INT is range 1 to 50; type Y_INT is range 1 to 30; subtype Z_INT is X_INT range 1 to 30; subtype BVECT3 is BIT_VECTOR(0 to 2); subtype BVECT2 is BIT_VECTOR(0 to 1); constant TIEOFF: MVL := '1'; constant OVFL_MSG: STRING(1 to 20) :="Accumulator Overflow"; constant OVFL_MSG: STRING := "Accumulator Overflow"; constant INT_VECTOR: BIT_VECTOR(0 to 7) := "00001000"; constant COEFF: REAL := 4.217; type MEMORY is array(0 to 1023) of BIT_VECTOR(0 to 7); function MAJ3(signal X,Y,Z: BIT) return BIT; procedure ONES_AND_ZEROS_CNT (variable X: in BIT_VECTOR(0 to 2); variable N_ONES, N_ZEROS: out BIT_VECTOR(0 to 1)); end TYPE_DECL; package body TYPE_DECL is function MAJ3(signal X,Y,Z: BIT) return BIT is begin return (X and Y) or (X and Z) or (Y and Z); end MAJ3; procedure ONES_AND_ZERO_CNT (variable X: in BIT_VECTOR(0 to 2); variable N_ONES,N_ZEROS: out BIT_VECTOR(0 to 1)) is variable NUM1: INTEGER range 0 to 3 := 0; variable NUM0: INTEGER range 0 to 3 := 0; begin for I in 0 to 2 loop if A(I)='1' then NUM1 := NUM1 + 1; else NUM0 := NUM0 + 1; end if; end loop; case NUM1 is when 0 => N_ONES := "00"; when 1 => N_ONES := "01"; when 2 => N_ONES := "10"; when 3 => N_ONES := "11"; end case; case NUM0 is when 0 => N_ZEROS := "00"; when 1 => N_ZEROS := "01"; when 2 => N_ZEROS := "10"; when 3 => N_ZEROS := "11"; end case; end ONES_AND_ZEROS_CNT; end TYPE_DECL; --******************************************************************** --******************************************************************** -- uart.v use TSL.all,SYSTEM.all; entity UART is generic(CLK_PER,ODEL,INDEL,INTDEL: TIME); port(DATA: inout WORD; I: in BIT; LOAD,READ: in BIT; O,NINTO,NINTI: out BIT); end UART; architecture BEHAVIOR of UART is signal ICLK,OCLK,ISTRT: BIT; signal NINTI1,NINTI2,TEMP_NINTI: BIT; signal IREG: BIT_VECTOR(7 downto 0); begin OUTPUT: process(LOAD,OCLK) variable OCNTR: INTEGER; variable OREG: BIT_VECTOR(7 downto 0); begin if not LOAD'STABLE and LOAD='1' then OREG := TRIVEC_TO_BITVEC(DATA); OCNTR := 7; O <= '0' after ODEL; OCLK <= not OCLK after CLK_PER; end if; if not OCLK'STABLE then if OCNTR /= -1 then O <= OREG(OCNTR) after ODEL; OCNTR := OCNTR-1; OCLK <= not OCLK after CLK_PER; else OCNTR := 7; O <= '1' after ODEL; NINTO <= '0' after INTDEL; end if; end if; end process OUTPUT; INPUT: process(I,ISTRT,ICLK) variable ICNTR: INTEGER; variable VDAV: WORD := "00000000"; variable I_FLAG: BOOLEAN := true; begin if I_FLAG then if not I'STABLE and I='0' then ISTRT <= '1' after CLK_PER/2; end if; end if; if not ISTRT'STABLE and I='1' then if I='0' and I'STABLE(CLK_PER/2) then I_FLAG := false; ISTRT <= '0'; ICNTR := 7; IREG(ICNTR) := 1; ICLK <= not ICLK after CLK_PER; end if; end if; if not ICLK'STABLE then if ICNTR /= -1 then IREG(ICNTR) := I; ICNTR := ICNTR-1; ICLK <= not ICLK after CLK_PER; else NINTI1 <= '0' after INTDEL; I_FLAG := true; end if; end if; end process INPUT; READ: process (READ,DAVIN) begin if not READ'STABLE then if READ='1' then DATA <= BITVEC_TO_TRIVEC(IREG) after INDEL; NINTI2 <= '1' after INTDEL; else DATA <= "ZZZZZZZZ" after INDEL; end if; end if; end process READ; MUX: TEMP_NINTI <= NINTI1 when not NINTI1'QUIET else NINTI2 when not NINTI2'QUIET else TEMP_NINTI; NINTI <= TEMP_NINTI; end BEHAVIOR; --******************************************************************** --******************************************************************** -- wait.v architecture WAIT_CHK of NOTHING is begin process(X,Y) begin wait for 100 ns; wait on X,Y; wait until (Z='0'); wait on X,Y until (Z=0) for 100 ns; end process; process begin null; WAIT on X,Y,Z; end process; process begin for I in 1 to NUM_CLK loop CLK <= transport '1' after CLK_PERIOD/2; CLK <= transport '0' after CLK_PERIOD; wait for CLK_PERIOD; end loop; end process; end WAIT_CHK; --********************************************************************